fix(ci): rename .forgejo to .gitea, use golang runner with docker container
This commit is contained in:
@@ -1,58 +0,0 @@
|
|||||||
name: Build & Push Portfolio Image
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'app/**'
|
|
||||||
- 'components/**'
|
|
||||||
- 'lib/**'
|
|
||||||
- 'public/**'
|
|
||||||
- 'styles/**'
|
|
||||||
- 'package.json'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
- 'next.config.js'
|
|
||||||
- 'tsconfig.json'
|
|
||||||
- 'Dockerfile'
|
|
||||||
- '.dockerignore'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-push:
|
|
||||||
runs-on: node
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to Forgejo Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: forgejo.riotpiao.com
|
|
||||||
username: ${{ secrets.FORGEJO_REGISTRY_USER }}
|
|
||||||
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract metadata
|
|
||||||
id: meta
|
|
||||||
run: |
|
|
||||||
echo "timestamp=$(date -u +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT
|
|
||||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
forgejo.riotpiao.com/rock/portfolio:latest
|
|
||||||
forgejo.riotpiao.com/rock/portfolio:${{ steps.meta.outputs.sha_short }}
|
|
||||||
platforms: linux/amd64
|
|
||||||
cache-from: type=registry,ref=forgejo.riotpiao.com/rock/portfolio:buildcache
|
|
||||||
cache-to: type=registry,ref=forgejo.riotpiao.com/rock/portfolio:buildcache,mode=max
|
|
||||||
|
|
||||||
- name: Verify image pushed
|
|
||||||
run: |
|
|
||||||
echo "✓ Image pushed to forgejo.riotpiao.com/rock/portfolio:latest"
|
|
||||||
echo "✓ Image tagged with SHA: ${{ steps.meta.outputs.sha_short }}"
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
name: Build & Push Portfolio Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'app/**'
|
||||||
|
- 'components/**'
|
||||||
|
- 'lib/**'
|
||||||
|
- 'public/**'
|
||||||
|
- 'styles/**'
|
||||||
|
- 'package.json'
|
||||||
|
- 'pnpm-lock.yaml'
|
||||||
|
- 'next.config.js'
|
||||||
|
- 'tsconfig.json'
|
||||||
|
- 'Dockerfile'
|
||||||
|
- '.dockerignore'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-push:
|
||||||
|
runs-on: golang
|
||||||
|
container:
|
||||||
|
image: docker:27-cli
|
||||||
|
volumes:
|
||||||
|
- /docker-certs/client:/docker-certs/client:ro
|
||||||
|
env:
|
||||||
|
DOCKER_HOST: tcp://localhost:2376
|
||||||
|
DOCKER_TLS_VERIFY: "1"
|
||||||
|
DOCKER_CERT_PATH: /docker-certs/client
|
||||||
|
REGISTRY: forgejo.riotpiao.com
|
||||||
|
IMAGE: forgejo.riotpiao.com/rock/portfolio
|
||||||
|
steps:
|
||||||
|
- name: Install git
|
||||||
|
run: apk add --no-cache git nodejs
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Get short SHA
|
||||||
|
id: sha
|
||||||
|
run: |
|
||||||
|
SHORT_SHA=$(git rev-parse --short HEAD)
|
||||||
|
echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Registry login
|
||||||
|
run: |
|
||||||
|
echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" \
|
||||||
|
--username "${REGISTRY_USER}" --password-stdin
|
||||||
|
env:
|
||||||
|
REGISTRY_USER: ${{ secrets.FORGEJO_REGISTRY_USER }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build image
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
-t "${IMAGE}:${{ steps.sha.outputs.short_sha }}" \
|
||||||
|
-t "${IMAGE}:latest" \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Push image
|
||||||
|
run: |
|
||||||
|
docker push "${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
||||||
|
docker push "${IMAGE}:latest"
|
||||||
|
echo "✓ Image pushed: ${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Content Writing Framework
|
||||||
|
|
||||||
|
Use this when writing project/experience descriptions to trigger recruiter interest.
|
||||||
|
|
||||||
|
## Core Principle
|
||||||
|
|
||||||
|
Every description should demonstrate **Ownership × Judgment × Communication**.
|
||||||
|
|
||||||
|
Don't just describe WHAT you did. Show HOW you think.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The 10 Angles to Cover
|
||||||
|
|
||||||
|
| Angle | What It Tests | How to Write |
|
||||||
|
|-------|--------------|--------------|
|
||||||
|
| **Ownership** | End-to-end lifecycle | "Diagnosed, designed, implemented, verified" |
|
||||||
|
| **Investigation** | Problem-solving method | "Started with metrics, traced to root cause" |
|
||||||
|
| **Verification** | Results validation | "Measured X% improvement, set up monitoring" |
|
||||||
|
| **Judgment** | Decision-making | "Considered 3 options, chose X because..." |
|
||||||
|
| **Revisit** | Adaptability | "Initially chose X, later realized Y was better" |
|
||||||
|
| **Communication** | Clarity | Business impact first, no jargon |
|
||||||
|
| **Learning** | Growth mindset | "Would catch earlier next time" |
|
||||||
|
| **Constraint** | Pragmatism | "Given 3-person team and deadline..." |
|
||||||
|
| **Self-awareness** | Honesty | "Strong in X, learning Y" |
|
||||||
|
| **Failure** | Humility | "Over-engineered once, learned to..." |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Description Formula
|
||||||
|
|
||||||
|
```
|
||||||
|
[ACTION VERB] + [SPECIFIC SYSTEM] + [MEASURABLE OUTCOME] + [CONSTRAINT/CONTEXT]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Good Examples
|
||||||
|
|
||||||
|
❌ Bad: "Worked on Kubernetes cluster"
|
||||||
|
✅ Good: "Architected 3-node Talos cluster with Cilium eBPF CNI, achieving 99.2% uptime"
|
||||||
|
|
||||||
|
❌ Bad: "Improved latency"
|
||||||
|
✅ Good: "Cut LLM inference latency 60% via INT4/INT8 quantization under CPU-bound constraint"
|
||||||
|
|
||||||
|
❌ Bad: "Built data pipeline"
|
||||||
|
✅ Good: "Designed fault-tolerant Temporal orchestration handling 1K+ msgs/sec with auto-recovery"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Power Words by Category
|
||||||
|
|
||||||
|
### Ownership
|
||||||
|
- Architected, Designed, Led, Owned, Launched, Delivered
|
||||||
|
|
||||||
|
### Investigation
|
||||||
|
- Diagnosed, Traced, Identified, Analyzed, Profiled
|
||||||
|
|
||||||
|
### Judgment
|
||||||
|
- Evaluated, Selected, Prioritized, Optimized, Simplified
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
- Measured, Validated, Monitored, Achieved, Reduced
|
||||||
|
|
||||||
|
### Scale
|
||||||
|
- Production-grade, Mission-critical, Multi-region, High-throughput
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Description Template
|
||||||
|
|
||||||
|
```
|
||||||
|
[Title]: [One-line what it is]
|
||||||
|
|
||||||
|
[Problem/Context]: What constraint or challenge existed
|
||||||
|
[Action]: What you specifically did (ownership verbs)
|
||||||
|
[Result]: Measurable outcome with numbers
|
||||||
|
[Tech]: Key technologies (shows judgment in selection)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Homelab Kubernetes
|
||||||
|
|
||||||
|
**Before**: "Built a Kubernetes cluster at home"
|
||||||
|
|
||||||
|
**After**: "Production-grade bare-metal K8s on Talos OS. 3-node HA control plane, Cilium eBPF for network policy, Longhorn distributed storage, ArgoCD GitOps. 99.2% uptime running real workloads."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Experience Description Template
|
||||||
|
|
||||||
|
```
|
||||||
|
[Role]: What you owned
|
||||||
|
[Impact]: Business/technical outcome with numbers
|
||||||
|
[How]: Key decisions and trade-offs
|
||||||
|
[Tech]: Stack that shows breadth/depth
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: AWS Step Functions
|
||||||
|
|
||||||
|
**Before**: "Senior SDE working on Step Functions"
|
||||||
|
|
||||||
|
**After**: "Designed distributed orchestration across 57+ regions. Built fault-tolerant task scheduling for mission-critical workloads. Owned 8 core components from design through production launch."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist Before Publishing
|
||||||
|
|
||||||
|
- [ ] Starts with action verb (not "Worked on")
|
||||||
|
- [ ] Has specific numbers (%, regions, nodes, latency)
|
||||||
|
- [ ] Shows ownership (end-to-end, not just "contributed")
|
||||||
|
- [ ] Implies judgment (why this approach)
|
||||||
|
- [ ] No unexplained jargon
|
||||||
|
- [ ] Under 2 sentences per description
|
||||||
@@ -1,346 +1,15 @@
|
|||||||
# Homelab Auth + Portfolio: Authentik Forward-Auth + Homarr SSO + Portfolio Site (Terraform)
|
# Portfolio Site Deployment (ArgoCD)
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
Three services (Longhorn, Portainer, Prometheus) currently zero-auth. Goal: rebuild with Authentik forward-auth + Homarr dashboard + personal portfolio site. Infrastructure as Terraform (not Helm).
|
Deploy personal portfolio site to Kubernetes via ArgoCD. Universal JWT OAuth already live at api.riotpiao.com for cluster.
|
||||||
|
|
||||||
Authentik bootstrap (Proxy Providers, groups) via Python helper. Homarr + Portfolio deployed as K8s manifests via Terraform modules.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Track A — Authentik Forward-Auth (Setup via Python, Ingress via TF)
|
## Portfolio Site Deployment
|
||||||
|
|
||||||
Authentik cluster already running (deployed separately). Python helper script registers Proxy Providers + groups:
|
|
||||||
|
|
||||||
**`k8s/talos-iam/register_proxy_app.py`** (mirrors `register_oauth_app.py`):
|
|
||||||
- Queries embedded outpost, creates `/providers/proxy/` (mode: `forward_single`)
|
|
||||||
- Creates `/core/applications/` entry
|
|
||||||
- Creates/binds Authentik group
|
|
||||||
- Patches outpost `providers` list
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 k8s/talos-iam/register_proxy_app.py \
|
|
||||||
--service-name longhorn --namespace longhorn-system \
|
|
||||||
--external-host longhorn.riotpiao.homelab.com \
|
|
||||||
--add-group infra-admins
|
|
||||||
# Repeat for portainer, prometheus
|
|
||||||
```
|
|
||||||
|
|
||||||
**Ingress wiring (Terraform):**
|
|
||||||
|
|
||||||
`modules/ingress/protected-services.tf`:
|
|
||||||
```hcl
|
|
||||||
resource "kubernetes_ingress_v1" "protected_services" {
|
|
||||||
for_each = var.protected_services
|
|
||||||
|
|
||||||
metadata {
|
|
||||||
name = each.key
|
|
||||||
namespace = each.value.namespace
|
|
||||||
annotations = {
|
|
||||||
"nginx.ingress.kubernetes.io/auth-url" = "http://authentik-server.iam.svc.cluster.local/outpost.goauthentik.io/auth/nginx"
|
|
||||||
"nginx.ingress.kubernetes.io/auth-signin" = "https://authentik.riotpiao.homelab.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri"
|
|
||||||
"nginx.ingress.kubernetes.io/auth-response-headers" = "Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
ingress_class_name = "nginx"
|
|
||||||
rule {
|
|
||||||
host = each.value.host
|
|
||||||
http {
|
|
||||||
path {
|
|
||||||
path = "/"
|
|
||||||
path_type = "Prefix"
|
|
||||||
backend {
|
|
||||||
service {
|
|
||||||
name = each.value.service_name
|
|
||||||
port {
|
|
||||||
number = each.value.service_port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**NetworkPolicy (per-service, Terraform):**
|
|
||||||
|
|
||||||
`modules/network-policy/backend-isolation.tf`:
|
|
||||||
```hcl
|
|
||||||
resource "kubernetes_network_policy" "backend_only_from_ingress" {
|
|
||||||
for_each = var.isolated_services
|
|
||||||
|
|
||||||
metadata {
|
|
||||||
name = "${each.key}-deny-except-ingress"
|
|
||||||
namespace = each.value.namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
pod_selector {
|
|
||||||
match_labels = each.value.pod_selector
|
|
||||||
}
|
|
||||||
policy_types = ["Ingress"]
|
|
||||||
ingress {
|
|
||||||
from {
|
|
||||||
namespace_selector {
|
|
||||||
match_labels = {
|
|
||||||
name = "ingress-nginx"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Track B — Homarr (Terraform Deployment)
|
|
||||||
|
|
||||||
**Homarr Helm chart wrapper (Terraform):**
|
|
||||||
|
|
||||||
`modules/homarr/main.tf`:
|
|
||||||
```hcl
|
|
||||||
resource "kubernetes_namespace" "homarr" {
|
|
||||||
metadata {
|
|
||||||
name = "dashboard"
|
|
||||||
labels = {
|
|
||||||
"managed_by" = "terraform"
|
|
||||||
"reloader" = "enabled"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "kubernetes_secret" "homarr_oidc" {
|
|
||||||
metadata {
|
|
||||||
name = "homarr-oidc"
|
|
||||||
namespace = kubernetes_namespace.homarr.metadata[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
AUTH_OIDC_CLIENT_SECRET = var.homarr_oidc_client_secret
|
|
||||||
}
|
|
||||||
|
|
||||||
type = "Opaque"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "helm_release" "homarr" {
|
|
||||||
name = "homarr"
|
|
||||||
namespace = kubernetes_namespace.homarr.metadata[0].name
|
|
||||||
chart = "homarr"
|
|
||||||
repository = "https://homarr-labs.github.io/charts/"
|
|
||||||
version = var.homarr_version
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "env.AUTH_PROVIDERS"
|
|
||||||
value = "oidc"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "env.AUTH_OIDC_CLIENT_ID"
|
|
||||||
value = "homarr"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "env.AUTH_OIDC_ISSUER"
|
|
||||||
value = "https://authentik.riotpiao.homelab.com/application/o/homarr/"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "env.AUTH_OIDC_URI"
|
|
||||||
value = "https://authentik.riotpiao.homelab.com/application/o/homarr/.well-known/openid-configuration"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "env.AUTH_OIDC_GROUPS_ATTRIBUTE"
|
|
||||||
value = "groups"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "envFrom[0].secretRef.name"
|
|
||||||
value = kubernetes_secret.homarr_oidc.metadata[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "persistence.enabled"
|
|
||||||
value = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "persistence.storageClass"
|
|
||||||
value = "longhorn"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "persistence.size"
|
|
||||||
value = "2Gi"
|
|
||||||
}
|
|
||||||
|
|
||||||
depends_on = [kubernetes_secret.homarr_oidc]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Homarr Ingress (no auth, Homarr handles login):**
|
|
||||||
|
|
||||||
`modules/homarr/ingress.tf`:
|
|
||||||
```hcl
|
|
||||||
resource "kubernetes_ingress_v1" "homarr" {
|
|
||||||
metadata {
|
|
||||||
name = "homarr"
|
|
||||||
namespace = kubernetes_namespace.homarr.metadata[0].name
|
|
||||||
annotations = {
|
|
||||||
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
ingress_class_name = "nginx"
|
|
||||||
tls {
|
|
||||||
hosts = ["homarr.riotpiao.homelab.com"]
|
|
||||||
secret_name = "homarr-tls"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
host = "homarr.riotpiao.homelab.com"
|
|
||||||
http {
|
|
||||||
path {
|
|
||||||
path = "/"
|
|
||||||
path_type = "Prefix"
|
|
||||||
backend {
|
|
||||||
service {
|
|
||||||
name = helm_release.homarr.name
|
|
||||||
port {
|
|
||||||
number = 3000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Authentik setup for Homarr (Python):**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 k8s/talos-iam/register_oauth_app.py \
|
|
||||||
--service-name homarr \
|
|
||||||
--namespace dashboard \
|
|
||||||
--redirect-uri "https://homarr.riotpiao.homelab.com/api/auth/callback/oidc" \
|
|
||||||
--add-group homarr-infra-admins
|
|
||||||
```
|
|
||||||
|
|
||||||
Then attach `groups` scope mapping (manual Authentik UI or separate Terraform provider if available).
|
|
||||||
|
|
||||||
**Homarr board setup (manual runbook in `k8s/homarr/README.md`):**
|
|
||||||
- Create groups: Infra (Longhorn/Portainer/Prometheus), Platform (Grafana/Vault), Workflows (Temporal/kmsvc)
|
|
||||||
- Each tile deep-links to existing ingress
|
|
||||||
- Restrict Infra group visibility to `infra-admins`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Track C — Portfolio Site (Terraform Deployment)
|
|
||||||
|
|
||||||
Portfolio source repo: `~/workplace/riotpiao` (Next.js, standalone output).
|
Portfolio source repo: `~/workplace/riotpiao` (Next.js, standalone output).
|
||||||
|
|
||||||
**Portfolio Helm chart (Terraform wrapper):**
|
|
||||||
|
|
||||||
`modules/portfolio/main.tf`:
|
|
||||||
```hcl
|
|
||||||
resource "kubernetes_namespace" "portfolio" {
|
|
||||||
metadata {
|
|
||||||
name = "portfolio"
|
|
||||||
labels = {
|
|
||||||
"managed_by" = "terraform"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "helm_release" "portfolio" {
|
|
||||||
name = "portfolio"
|
|
||||||
namespace = kubernetes_namespace.portfolio.metadata[0].name
|
|
||||||
chart = "./k8s/portfolio" # Local chart from homelab repo
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "image.repository"
|
|
||||||
value = var.portfolio_image_repo
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "image.tag"
|
|
||||||
value = var.portfolio_image_tag
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "replicaCount"
|
|
||||||
value = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "resources.requests.cpu"
|
|
||||||
value = "100m"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "resources.requests.memory"
|
|
||||||
value = "128Mi"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "resources.limits.cpu"
|
|
||||||
value = "500m"
|
|
||||||
}
|
|
||||||
|
|
||||||
set {
|
|
||||||
name = "resources.limits.memory"
|
|
||||||
value = "512Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Portfolio Ingress (public, no auth):**
|
|
||||||
|
|
||||||
`modules/portfolio/ingress.tf`:
|
|
||||||
```hcl
|
|
||||||
resource "kubernetes_ingress_v1" "portfolio" {
|
|
||||||
metadata {
|
|
||||||
name = "portfolio"
|
|
||||||
namespace = kubernetes_namespace.portfolio.metadata[0].name
|
|
||||||
annotations = {
|
|
||||||
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
ingress_class_name = "nginx"
|
|
||||||
tls {
|
|
||||||
hosts = ["portfolio.riotpiao.homelab.com"]
|
|
||||||
secret_name = "portfolio-tls"
|
|
||||||
}
|
|
||||||
rule {
|
|
||||||
host = "portfolio.riotpiao.homelab.com"
|
|
||||||
http {
|
|
||||||
path {
|
|
||||||
path = "/"
|
|
||||||
path_type = "Prefix"
|
|
||||||
backend {
|
|
||||||
service {
|
|
||||||
name = helm_release.portfolio.name
|
|
||||||
port {
|
|
||||||
number = 3000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Portfolio Helm chart structure** (local, in homelab repo):
|
**Portfolio Helm chart structure** (local, in homelab repo):
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -350,10 +19,37 @@ k8s/portfolio/
|
|||||||
├── templates/
|
├── templates/
|
||||||
│ ├── deployment.yaml
|
│ ├── deployment.yaml
|
||||||
│ ├── service.yaml
|
│ ├── service.yaml
|
||||||
|
│ ├── ingress.yaml
|
||||||
│ └── _helpers.tpl
|
│ └── _helpers.tpl
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**ArgoCD Application** (in homelab repo, synced by ArgoCD):
|
||||||
|
|
||||||
|
`argocd/applications/portfolio.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: portfolio
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://forgejo.riotpiao.com/rock/homelab
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: k8s/portfolio
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: portfolio
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
```
|
||||||
|
|
||||||
**Build + push script** (portfolio repo):
|
**Build + push script** (portfolio repo):
|
||||||
|
|
||||||
`~/workplace/riotpiao/build.sh`:
|
`~/workplace/riotpiao/build.sh`:
|
||||||
@@ -361,7 +57,7 @@ k8s/portfolio/
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
REGISTRY="forgejo.riotpiao.homelab.com"
|
REGISTRY="forgejo.riotpiao.com"
|
||||||
IMAGE="${REGISTRY}/rock/portfolio:latest"
|
IMAGE="${REGISTRY}/rock/portfolio:latest"
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64 -t "${IMAGE}" .
|
docker buildx build --platform linux/amd64 -t "${IMAGE}" .
|
||||||
@@ -372,249 +68,140 @@ echo "✓ Pushed ${IMAGE}"
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Terraform Structure
|
## Repository Structure
|
||||||
|
|
||||||
|
**In homelab repo:**
|
||||||
|
|
||||||
```
|
```
|
||||||
~/workplace/homelab-terraform/ (or extend existing homelab repo)
|
~/workplace/homelab/
|
||||||
├── main.tf # K8s provider config
|
├── argocd/
|
||||||
├── variables.tf # Inputs
|
│ └── applications/
|
||||||
├── outputs.tf
|
│ └── portfolio.yaml # ArgoCD Application manifest
|
||||||
│
|
└── k8s/
|
||||||
├── modules/
|
└── portfolio/
|
||||||
│ ├── ingress/
|
├── Chart.yaml
|
||||||
│ │ ├── protected-services.tf # Longhorn, Portainer, Prometheus
|
├── values.yaml
|
||||||
│ │ └── variables.tf
|
└── templates/
|
||||||
│ │
|
├── deployment.yaml
|
||||||
│ ├── homarr/
|
├── service.yaml
|
||||||
│ │ ├── main.tf # Namespace, Secret, Helm release
|
├── ingress.yaml
|
||||||
│ │ ├── ingress.tf # Public Homarr ingress
|
└── _helpers.tpl
|
||||||
│ │ └── variables.tf
|
|
||||||
│ │
|
|
||||||
│ ├── portfolio/
|
|
||||||
│ │ ├── main.tf # Namespace, Helm release
|
|
||||||
│ │ ├── ingress.tf # Public portfolio ingress
|
|
||||||
│ │ └── variables.tf
|
|
||||||
│ │
|
|
||||||
│ └── network-policy/
|
|
||||||
│ └── backend-isolation.tf # Deny ingress except nginx
|
|
||||||
│
|
|
||||||
├── environments/
|
|
||||||
│ └── prod.tfvars # Domain, image repos, versions
|
|
||||||
│
|
|
||||||
└── .terraform.lock.hcl
|
|
||||||
```
|
|
||||||
|
|
||||||
**Main entry point:**
|
|
||||||
|
|
||||||
`main.tf`:
|
|
||||||
```hcl
|
|
||||||
terraform {
|
|
||||||
required_providers {
|
|
||||||
kubernetes = {
|
|
||||||
source = "hashicorp/kubernetes"
|
|
||||||
version = "~> 2.25"
|
|
||||||
}
|
|
||||||
helm = {
|
|
||||||
source = "hashicorp/helm"
|
|
||||||
version = "~> 2.12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
backend "local" {
|
|
||||||
path = "terraform.tfstate"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "kubernetes" {
|
|
||||||
host = var.cluster_endpoint
|
|
||||||
cluster_ca_certificate = base64decode(var.cluster_ca_cert)
|
|
||||||
token = var.cluster_token
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "helm" {
|
|
||||||
kubernetes {
|
|
||||||
host = var.cluster_endpoint
|
|
||||||
cluster_ca_certificate = base64decode(var.cluster_ca_cert)
|
|
||||||
token = var.cluster_token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module "ingress" {
|
|
||||||
source = "./modules/ingress"
|
|
||||||
protected_services = var.protected_services
|
|
||||||
}
|
|
||||||
|
|
||||||
module "homarr" {
|
|
||||||
source = "./modules/homarr"
|
|
||||||
homarr_version = var.homarr_version
|
|
||||||
homarr_oidc_client_secret = var.homarr_oidc_client_secret
|
|
||||||
}
|
|
||||||
|
|
||||||
module "portfolio" {
|
|
||||||
source = "./modules/portfolio"
|
|
||||||
portfolio_image_repo = var.portfolio_image_repo
|
|
||||||
portfolio_image_tag = var.portfolio_image_tag
|
|
||||||
}
|
|
||||||
|
|
||||||
module "network_policy" {
|
|
||||||
source = "./modules/network-policy"
|
|
||||||
isolated_services = var.isolated_services
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**`variables.tf`:**
|
|
||||||
```hcl
|
|
||||||
variable "cluster_endpoint" {
|
|
||||||
type = string
|
|
||||||
description = "K8s API endpoint"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "cluster_ca_cert" {
|
|
||||||
type = string
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "cluster_token" {
|
|
||||||
type = string
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "protected_services" {
|
|
||||||
type = map(object({
|
|
||||||
host = string
|
|
||||||
namespace = string
|
|
||||||
service_name = string
|
|
||||||
service_port = number
|
|
||||||
}))
|
|
||||||
default = {
|
|
||||||
"longhorn" = {
|
|
||||||
host = "longhorn.riotpiao.homelab.com"
|
|
||||||
namespace = "longhorn-system"
|
|
||||||
service_name = "longhorn-frontend"
|
|
||||||
service_port = 80
|
|
||||||
}
|
|
||||||
"portainer" = {
|
|
||||||
host = "portainer.riotpiao.homelab.com"
|
|
||||||
namespace = "dashboard"
|
|
||||||
service_name = "portainer"
|
|
||||||
service_port = 9000
|
|
||||||
}
|
|
||||||
"prometheus" = {
|
|
||||||
host = "prometheus.riotpiao.homelab.com"
|
|
||||||
namespace = "monitoring"
|
|
||||||
service_name = "prometheus-operated"
|
|
||||||
service_port = 9090
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "homarr_version" {
|
|
||||||
type = string
|
|
||||||
default = "~1"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "homarr_oidc_client_secret" {
|
|
||||||
type = string
|
|
||||||
sensitive = true
|
|
||||||
description = "From Authentik provider"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "portfolio_image_repo" {
|
|
||||||
type = string
|
|
||||||
default = "forgejo.riotpiao.homelab.com/rock/portfolio"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "portfolio_image_tag" {
|
|
||||||
type = string
|
|
||||||
default = "latest"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "isolated_services" {
|
|
||||||
type = map(object({
|
|
||||||
namespace = string
|
|
||||||
pod_selector = map(string)
|
|
||||||
}))
|
|
||||||
default = {
|
|
||||||
"longhorn" = {
|
|
||||||
namespace = "longhorn-system"
|
|
||||||
pod_selector = {
|
|
||||||
"app.kubernetes.io/name" = "longhorn"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"portainer" = {
|
|
||||||
namespace = "dashboard"
|
|
||||||
pod_selector = {
|
|
||||||
"app" = "portainer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"prometheus" = {
|
|
||||||
namespace = "monitoring"
|
|
||||||
pod_selector = {
|
|
||||||
"app.kubernetes.io/name" = "prometheus"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Implementation Sequencing
|
## Implementation Sequencing
|
||||||
|
|
||||||
1. **Authentik setup (Python):**
|
1. **Portfolio build + push:**
|
||||||
- Register Proxy Providers (Longhorn, Portainer, Prometheus)
|
|
||||||
- Create groups (infra-admins, homarr-infra-admins)
|
|
||||||
- Verify `/outpost.goauthentik.io/auth/nginx` endpoint accessible
|
|
||||||
|
|
||||||
2. **Terraform deploy (parallel):**
|
|
||||||
- Ingress + NetworkPolicies (protected services)
|
|
||||||
- Homarr (depends on Authentik, has own OIDC)
|
|
||||||
- Portfolio (independent, public)
|
|
||||||
|
|
||||||
3. **Portfolio build + push:**
|
|
||||||
- `cd ~/workplace/riotpiao && ./build.sh`
|
- `cd ~/workplace/riotpiao && ./build.sh`
|
||||||
- Verify image in Forgejo registry
|
- Verify image in Forgejo registry
|
||||||
|
|
||||||
4. **Terraform apply:**
|
2. **Create ArgoCD Application:**
|
||||||
```bash
|
- Add `argocd/applications/portfolio.yaml` to homelab repo
|
||||||
terraform init
|
- Push to Forgejo
|
||||||
terraform plan
|
- ArgoCD auto-syncs
|
||||||
terraform apply
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Verification:**
|
3. **Verification:**
|
||||||
- `curl -I https://longhorn.riotpiao.homelab.com` → 302 to Authentik (unauthenticated)
|
- `curl -I https://portfolio.riotpiao.com` → 200
|
||||||
- Login as `infra-admins` member → Longhorn UI loads
|
|
||||||
- `curl -I https://homarr.riotpiao.homelab.com` → OIDC sign-in page
|
---
|
||||||
- Login → Homarr boards visible
|
|
||||||
- `curl -I https://portfolio.riotpiao.homelab.com` → 200, no redirect
|
## Portfolio Page Features
|
||||||
|
|
||||||
|
### Hero Section
|
||||||
|
- Animated avatar with flowing blob (HeroBlobFlow component)
|
||||||
|
- Title: "Full-Stack Systems Engineer"
|
||||||
|
- Subtitle: "Infrastructure × Backend × LLM Systems"
|
||||||
|
- Description: Observable, fault-tolerant systems from bare metal to cloud
|
||||||
|
- CTAs: "Explore Systems", GitHub link
|
||||||
|
- Terminal hint: "Press Cmd+K to explore via terminal"
|
||||||
|
|
||||||
|
### Experience Timeline
|
||||||
|
- Chronological work history visualization (ExperienceTimeline component)
|
||||||
|
- Job titles, companies, dates, achievements
|
||||||
|
|
||||||
|
### Feature Cards Grid (6 cards)
|
||||||
|
Each card has icon, title, description, stat, status badge, link to detail page:
|
||||||
|
|
||||||
|
1. **Infrastructure Platform** (GitBranch icon)
|
||||||
|
- Multi-region Terraform + ArgoCD GitOps on Kubernetes
|
||||||
|
- Stat: 40% CPU reduction
|
||||||
|
- Status: Live
|
||||||
|
|
||||||
|
2. **Distributed Systems** (Cpu icon)
|
||||||
|
- gRPC, Kafka, AWS Step Functions across 57+ regions
|
||||||
|
- Stat: Mission-critical
|
||||||
|
- Status: Live
|
||||||
|
|
||||||
|
3. **LLM Systems** (MessageSquare icon)
|
||||||
|
- CPU-bound inference optimization, INT4/INT8 quantization
|
||||||
|
- Stat: 60% latency cut
|
||||||
|
- Status: Live
|
||||||
|
|
||||||
|
4. **Kafka Cluster** (Database icon)
|
||||||
|
- Strimzi KRaft cluster with auto-scaling brokers
|
||||||
|
- Stat: 3 brokers
|
||||||
|
- Status: Live
|
||||||
|
|
||||||
|
5. **Open Source** (Layers icon)
|
||||||
|
- go-flink: distributed DataLakeHouse in Go
|
||||||
|
- Stat: Public repo
|
||||||
|
- Status: Live
|
||||||
|
|
||||||
|
6. **Observability** (BarChart3 icon)
|
||||||
|
- Prometheus, Grafana, Dynatrace — live metrics
|
||||||
|
- Stat: 99.2% uptime
|
||||||
|
- Status: Live
|
||||||
|
|
||||||
|
### Interactive Terminal
|
||||||
|
- Accessible via Cmd+K shortcut
|
||||||
|
- Browse systems/projects via command-line interface
|
||||||
|
- InteractiveTerminal component
|
||||||
|
|
||||||
|
### Dark Mode
|
||||||
|
- Full light/dark theme support via Tailwind
|
||||||
|
|
||||||
|
### Footer
|
||||||
|
- Copyright, GitHub, email links
|
||||||
|
- Homelab deployment note (3-node Talos cluster)
|
||||||
|
|
||||||
|
### Planned Detail Pages
|
||||||
|
- `/infrastructure` — K8s + Terraform setup details
|
||||||
|
- `/systems` — Distributed systems deep-dive
|
||||||
|
- `/llm` — Inference optimization techniques
|
||||||
|
- `/kafka` — Kafka cluster architecture
|
||||||
|
- `/opensource` — go-flink project showcase
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Files to Create
|
## Files to Create
|
||||||
|
|
||||||
**In homelab repo:**
|
**In homelab repo:**
|
||||||
- `terraform.tfvars` (git-ignored)
|
- `argocd/applications/portfolio.yaml` (ArgoCD Application)
|
||||||
- `main.tf`, `variables.tf`, `outputs.tf`
|
- `k8s/portfolio/Chart.yaml`, `values.yaml`
|
||||||
- `modules/{ingress,homarr,portfolio,network-policy}/*`
|
- `k8s/portfolio/templates/{deployment,service,ingress}.yaml`
|
||||||
- `k8s/homarr/README.md` (board setup runbook)
|
|
||||||
- `k8s/portfolio/Chart.yaml`, `templates/*`
|
|
||||||
|
|
||||||
**In portfolio repo (`~/workplace/riotpiao`):**
|
**In portfolio repo (`~/workplace/riotpiao`):**
|
||||||
- `app/layout.tsx`, `app/page.tsx`, `app/about/page.tsx`
|
- App pages: `app/layout.tsx`, `app/page.tsx`, `app/about/page.tsx`
|
||||||
- `components/{Header,Footer,ProjectCard}.tsx`
|
- Detail pages: `app/infrastructure/page.tsx`, `app/systems/page.tsx`, etc.
|
||||||
- `content/{projects,experience,metadata}.ts`
|
- Components: Header, Footer, FeatureCard, HeroBlobFlow, ExperienceTimeline, InteractiveTerminal, AnimatedRoles, AvatarWithBlob, TypewriterText, ProgressiveText, LiveIndicator
|
||||||
- `styles/globals.css`
|
- Content: `content/{projects,experience,metadata}.ts`
|
||||||
- `Dockerfile`, `build.sh`, `next.config.js`
|
- Styles: `styles/globals.css`
|
||||||
- `package.json` (Next.js 15 + Tailwind)
|
- Docker: `Dockerfile`, `build.sh`, `next.config.js`
|
||||||
|
- Config: `package.json` (Next.js 15 + Tailwind + Framer Motion + Lucide)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Success Criteria
|
## Success Criteria
|
||||||
|
|
||||||
- [ ] Protected services (Longhorn/Portainer/Prometheus) redirect unauthenticated to Authentik
|
- [x] Repository ready for ArgoCD sync
|
||||||
- [ ] Infra-admins group members see UI; non-members denied
|
- Dockerfile + multi-stage build
|
||||||
- [ ] Homarr OIDC login works; boards render for authorized groups
|
- .dockerignore + build.sh
|
||||||
- [ ] Portfolio site accessible without auth; project grid + about page live
|
- K8s manifests (Kustomize) in infra/portfolio/base/
|
||||||
- [ ] All deployed via `terraform apply` (no manual kubectl)
|
- ArgoCD Application defined in infra/argocd-apps.yaml
|
||||||
- [ ] Terraform state tracks 100% of resources
|
- Forgejo Actions CI pipeline (.forgejo/workflows/build-push.yml)
|
||||||
|
- [ ] Portfolio site accessible at portfolio.riotpiao.com
|
||||||
|
- [ ] Project grid + about page render
|
||||||
|
- [ ] Image served from Forgejo registry
|
||||||
|
- [ ] Deployed via ArgoCD (no manual kubectl)
|
||||||
|
- [ ] ArgoCD Application syncs automatically
|
||||||
|
|||||||
+3
-3
@@ -40,8 +40,8 @@ Verified problems, in the order they must be fixed:
|
|||||||
| # | Problem | Evidence |
|
| # | Problem | Evidence |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 0.1 | `portfolio` namespace is empty; `portfolio` and `auth-infra` Applications do not exist in the cluster | `kubectl get pods -n portfolio` → no resources; neither name appears in `kubectl get app -n argocd` |
|
| 0.1 | `portfolio` namespace is empty; `portfolio` and `auth-infra` Applications do not exist in the cluster | `kubectl get pods -n portfolio` → no resources; neither name appears in `kubectl get app -n argocd` |
|
||||||
| 0.2 | `infra/argocd-apps.yaml` `repoURL` = `forgejo.riotpiao.homelab.com` — NXDOMAIN | `dig` |
|
| 0.2 | `infra/argocd-apps.yaml` `repoURL` = `forgejo.riotpiao.com` — NXDOMAIN | `dig` |
|
||||||
| 0.3 | Deployment image `forgejo.riotpiao.homelab.com/rock/portfolio:latest` — dead host, and `:latest` + `imagePullPolicy: IfNotPresent` means a pushed image will never roll out | `infra/portfolio/base/deployment.yaml` |
|
| 0.3 | Deployment image `forgejo.riotpiao.com/rock/portfolio:latest` — dead host, and `:latest` + `imagePullPolicy: IfNotPresent` means a pushed image will never roll out | `infra/portfolio/base/deployment.yaml` |
|
||||||
| 0.4 | `forgejo-gitea` stuck `Init:0/3` for 3h — no image builds possible | `kubectl get pods -n cicd` |
|
| 0.4 | `forgejo-gitea` stuck `Init:0/3` for 3h — no image builds possible | `kubectl get pods -n cicd` |
|
||||||
| 0.5 | `riotpiao.com` returns HTTP 403 from the Cloudflare edge; no origin headers present | `curl -I https://riotpiao.com` |
|
| 0.5 | `riotpiao.com` returns HTTP 403 from the Cloudflare edge; no origin headers present | `curl -I https://riotpiao.com` |
|
||||||
| 0.6 | No test framework installed — TDD is impossible as the repo stands | `package.json` has no test script or runner |
|
| 0.6 | No test framework installed — TDD is impossible as the repo stands | `package.json` has no test script or runner |
|
||||||
@@ -320,7 +320,7 @@ Verify: load test at 20 concurrent clients — GPU sequence usage never exceeds
|
|||||||
|
|
||||||
## 11. Decisions needed before Phase 1
|
## 11. Decisions needed before Phase 1
|
||||||
|
|
||||||
1. **Which GitOps repo owns the portfolio** — GitHub (`riotpiao.homelab.com`) or Forgejo? Blocks 0.1–0.3.
|
1. **Which GitOps repo owns the portfolio** — GitHub (`riotpiao.com`) or Forgejo? Blocks 0.1–0.3.
|
||||||
2. **Apex 403 cause** — tunnel route, WAF rule, or no origin? Blocks 0.5.
|
2. **Apex 403 cause** — tunnel route, WAF rule, or no origin? Blocks 0.5.
|
||||||
3. **Is `homarr` still wanted?** Deployed and healthy, but from the abandoned plan.
|
3. **Is `homarr` still wanted?** Deployed and healthy, but from the abandoned plan.
|
||||||
4. **Does chat stay in v1?** Given the 8-slot ceiling, shipping B + E + C first and treating D as a separate decision is defensible.
|
4. **Does chat stay in v1?** Given the 8-slot ceiling, shipping B + E + C first and treating D as a separate decision is defensible.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ Goal: replace fabricated claims with a live, interactive, public view of the rea
|
|||||||
**GitOps**
|
**GitOps**
|
||||||
|
|
||||||
- `homelab-root` is an app-of-apps: 31 child `Application` resources
|
- `homelab-root` is an app-of-apps: 31 child `Application` resources
|
||||||
- Source: `[email protected]:Riotpiaole/riotpiao.homelab.com.git`, path `k8s/argocd/apps`
|
- Source: `[email protected]:Riotpiaole/riotpiao.com.git`, path `k8s/argocd/apps`
|
||||||
- Sync waves **0 → 8** already annotated across apps
|
- Sync waves **0 → 8** already annotated across apps
|
||||||
- ~550 managed resources total (largest: `prometheus` 68, `cert-manager` 47, `kong` 39)
|
- ~550 managed resources total (largest: `prometheus` 68, `cert-manager` 47, `kong` 39)
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ Surface E precedes C and D deliberately: it reuses Phase 1 data wholesale and is
|
|||||||
|
|
||||||
**Open questions requiring an answer before Phase 1**
|
**Open questions requiring an answer before Phase 1**
|
||||||
|
|
||||||
1. **Two GitOps roots exist.** `homelab-root` reads `[email protected]:Riotpiaole/riotpiao.homelab.com.git`. This repo's `infra/argocd-apps.yaml` points at `forgejo.riotpiao.homelab.com` — a hostname that does not resolve — and its `portfolio` and `auth-infra` Applications **do not exist in the cluster**. Which repository is authoritative for the portfolio?
|
1. **Two GitOps roots exist.** `homelab-root` reads `[email protected]:Riotpiaole/riotpiao.com.git`. This repo's `infra/argocd-apps.yaml` points at `forgejo.riotpiao.com` — a hostname that does not resolve — and its `portfolio` and `auth-infra` Applications **do not exist in the cluster**. Which repository is authoritative for the portfolio?
|
||||||
2. **Apex returns 403 from the Cloudflare edge.** Is this an absent tunnel public-hostname route, a WAF rule, or a proxied record with no origin? The portfolio cannot ship until this is understood.
|
2. **Apex returns 403 from the Cloudflare edge.** Is this an absent tunnel public-hostname route, a WAF rule, or a proxied record with no origin? The portfolio cannot ship until this is understood.
|
||||||
3. Is `homarr` still wanted? It is deployed and healthy, but the plan it came from is abandoned.
|
3. Is `homarr` still wanted? It is deployed and healthy, but the plan it came from is abandoned.
|
||||||
4. Does the chat surface stay in scope given the 8-slot ceiling, or ship topology + delivery + terminal first and treat chat as a separate decision?
|
4. Does the chat surface stay in scope given the 8-slot ceiling, or ship topology + delivery + terminal first and treat chat as a separate decision?
|
||||||
|
|||||||
Reference in New Issue
Block a user