diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index ecc6949d..0978217f 100755 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -6,12 +6,23 @@ - **Use `/update-knowledge` command**: Or edit this file directly to add learnings ## Execution Environment (CRITICAL) -- **File operations** (Read, Edit, Write, Glob, Grep): Run locally at `/Volumes/wizard/code/infra` -- **Git commands**: Run locally (git status, git log, git diff, etc.) -- **ALL other commands**: Use the remote executor relay (kubectl, terraform, helm, python, etc.) +- **Prefer running commands directly first** - only use remote executor as fallback if local execution fails -### Remote Command Execution (ALWAYS USE THIS) -For any command that is not file editing or git, use the file-based relay: +### Commands that work LOCALLY (macOS) +- **File operations**: Read, Edit, Write, Glob, Grep tools +- **Git commands**: git status, git log, git diff, git add, git commit, git reset, etc. +- **Basic shell**: ls, cat, head, tail, find, grep, etc. + +### Commands that REQUIRE REMOTE EXECUTOR +- **terraform**: apply, plan, init, state - needs cluster access +- **kubectl**: all k8s commands - needs cluster access +- **helm**: chart operations - needs cluster access +- **docker**: container operations on remote hosts +- **ssh**: connections to infrastructure nodes +- **Any command interacting with**: Proxmox, Kubernetes cluster, NFS server, other infrastructure + +### Remote Command Execution (FALLBACK) +For commands that fail locally, use the file-based relay: **To execute a remote command:** ```bash @@ -151,6 +162,7 @@ Edge/Aux (tier 3-4): - Use `GIT_OPTIONAL_LOCKS=0` prefix if git hangs - **Local SSH is blocked** - use remote executor to push: `echo "git push origin master" > .claude/cmd_input.txt` - Always commit only specific files you changed, not everything +- **ALWAYS ask user before pushing to remote** - never push without explicit confirmation ## Prometheus Alerts - Alert rules are in `modules/kubernetes/monitoring/prometheus_chart_values.tpl` diff --git a/.claude/commands/add-service.md b/.claude/commands/add-service.md new file mode 100755 index 00000000..482a2a4d --- /dev/null +++ b/.claude/commands/add-service.md @@ -0,0 +1,16 @@ +# Add New Service + +Help create a new Kubernetes service module. + +Service name: $ARGUMENTS + +Steps: +1. Create directory at modules/kubernetes// +2. Create main.tf with: + - Namespace resource + - Deployment with appropriate container + - Service resource + - Ingress with TLS and standard annotations +3. Use existing patterns from similar services +4. Add module reference in main.tf +5. Update .claude/CLAUDE.md with new service version diff --git a/.claude/commands/kubectl.md b/.claude/commands/kubectl.md new file mode 100755 index 00000000..344ec707 --- /dev/null +++ b/.claude/commands/kubectl.md @@ -0,0 +1,16 @@ +# Kubectl Command + +Run kubectl commands on the cluster via the remote executor. + +Use the remote executor relay: +```bash +echo "kubectl $ARGUMENTS" > /System/Volumes/Data/mnt/code/infra/.claude/cmd_input.txt +sleep 2 && cat /System/Volumes/Data/mnt/code/infra/.claude/cmd_status.txt +cat /System/Volumes/Data/mnt/code/infra/.claude/cmd_output.txt +``` + +Examples: +- `/kubectl get pods -A` - List all pods +- `/kubectl get pods -n immich` - List pods in immich namespace +- `/kubectl logs -n immich deploy/immich-server` - View logs +- `/kubectl describe pod -n monitoring ` - Describe a pod diff --git a/.claude/commands/list-services.md b/.claude/commands/list-services.md new file mode 100755 index 00000000..6dd54ecd --- /dev/null +++ b/.claude/commands/list-services.md @@ -0,0 +1,11 @@ +# List All Services + +List all Kubernetes services deployed in this infrastructure. + +```bash +ls -1 /System/Volumes/Data/mnt/code/infra/modules/kubernetes/ +``` + +Provide a summary of the services, grouped by category if possible (media, monitoring, productivity, etc.). + +Note: This command runs locally since it only reads the filesystem. diff --git a/.claude/commands/service-version.md b/.claude/commands/service-version.md new file mode 100755 index 00000000..861d750a --- /dev/null +++ b/.claude/commands/service-version.md @@ -0,0 +1,10 @@ +# Check Service Version + +Find the version of a specific service deployed in this infrastructure. + +Search for the service name in modules/kubernetes/ and extract: +1. The image version/tag being used +2. Any version variables defined +3. The Helm chart version if applicable + +Service to check: $ARGUMENTS diff --git a/.claude/commands/tf-apply.md b/.claude/commands/tf-apply.md new file mode 100755 index 00000000..40691f2f --- /dev/null +++ b/.claude/commands/tf-apply.md @@ -0,0 +1,13 @@ +# Terraform Apply + +Run terraform apply to deploy infrastructure changes via the remote executor. + +Use the remote executor relay: +```bash +echo "terraform apply -target=module.kubernetes_cluster.module. -auto-approve" > /System/Volumes/Data/mnt/code/infra/.claude/cmd_input.txt +sleep 2 && cat /System/Volumes/Data/mnt/code/infra/.claude/cmd_status.txt +# Wait for done:N status, then read output +cat /System/Volumes/Data/mnt/code/infra/.claude/cmd_output.txt +``` + +ALWAYS use -target to speed up execution. Monitor the output and report any errors or successful completions. diff --git a/.claude/commands/tf-plan.md b/.claude/commands/tf-plan.md new file mode 100755 index 00000000..d0d35a98 --- /dev/null +++ b/.claude/commands/tf-plan.md @@ -0,0 +1,13 @@ +# Terraform Plan + +Run terraform plan to preview infrastructure changes via the remote executor. + +Use the remote executor relay: +```bash +echo "terraform plan -target=module.kubernetes_cluster.module." > /System/Volumes/Data/mnt/code/infra/.claude/cmd_input.txt +sleep 2 && cat /System/Volumes/Data/mnt/code/infra/.claude/cmd_status.txt +# Wait for done:N status, then read output +cat /System/Volumes/Data/mnt/code/infra/.claude/cmd_output.txt +``` + +ALWAYS use -target to speed up execution. Summarize the planned changes, highlighting any resources being destroyed or recreated. diff --git a/.claude/commands/update-knowledge.md b/.claude/commands/update-knowledge.md new file mode 100755 index 00000000..dd2345dc --- /dev/null +++ b/.claude/commands/update-knowledge.md @@ -0,0 +1,12 @@ +# Update Knowledge Base + +Update the .claude/CLAUDE.md knowledge file with new learnings. + +Add or update information based on recent discoveries about: +- Service versions +- Infrastructure patterns +- Important configurations +- Useful commands +- Troubleshooting notes + +Context to add: $ARGUMENTS diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100755 index 00000000..cf2d6fdd --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,12 @@ +{ + "project": { + "name": "Home Infrastructure", + "type": "terraform", + "description": "Kubernetes cluster on Proxmox with self-hosted services" + }, + "permissions": { + "allow": [ + "Bash(ssh:*)" + ] + } +} diff --git a/main.tf b/main.tf index 0f826048..509fb6f9 100644 --- a/main.tf +++ b/main.tf @@ -77,6 +77,7 @@ variable "crowdsec_dash_machine_id" { type = string } variable "crowdsec_dash_machine_password" { type = string } variable "vaultwarden_smtp_password" {} variable "resume_database_url" {} +variable "resume_database_password" {} variable "resume_redis_url" {} variable "frigate_valchedrym_camera_credentials" { default = "" } variable "paperless_db_password" {} @@ -485,8 +486,9 @@ module "kubernetes_cluster" { vaultwarden_smtp_password = var.vaultwarden_smtp_password - resume_redis_url = var.resume_redis_url - resume_database_url = var.resume_database_url + resume_redis_url = var.resume_redis_url + resume_database_password = var.resume_database_password + resume_database_url = var.resume_database_url frigate_valchedrym_camera_credentials = var.frigate_valchedrym_camera_credentials diff --git a/modules/kubernetes/main.tf b/modules/kubernetes/main.tf index 1dcbd6a6..121276b4 100644 --- a/modules/kubernetes/main.tf +++ b/modules/kubernetes/main.tf @@ -61,6 +61,7 @@ variable "crowdsec_dash_machine_id" { type = string } variable "crowdsec_dash_machine_password" { type = string } variable "vaultwarden_smtp_password" {} variable "resume_database_url" {} +variable "resume_database_password" {} variable "resume_redis_url" {} variable "frigate_valchedrym_camera_credentials" { default = "" } variable "paperless_db_password" {} @@ -575,6 +576,7 @@ module "crowdsec" { # tls_secret_name = var.tls_secret_name # redis_url = var.resume_redis_url # database_url = var.resume_database_url +# db_password = var.resume_database_password # } module "uptime-kuma" { diff --git a/modules/kubernetes/resume/main.tf b/modules/kubernetes/resume/main.tf index f4f6cba1..cf3fd0ef 100644 --- a/modules/kubernetes/resume/main.tf +++ b/modules/kubernetes/resume/main.tf @@ -1,6 +1,8 @@ -variable "tls_secret_name" {} -variable "database_url" {} -variable "redis_url" {} +variable "tls_secret_name" { type = string } +variable "tier" { type = string } +variable "database_url" { type = string } +variable "redis_url" { type = string } +variable "db_password" { type = string } module "tls_secret" { source = "../setup_tls_secret" @@ -14,12 +16,18 @@ resource "kubernetes_namespace" "resume" { } } +resource "random_string" "random" { + length = 32 + lower = true +} + resource "kubernetes_deployment" "resume" { metadata { name = "resume" namespace = kubernetes_namespace.resume.metadata[0].name labels = { - app = "resume" + app = "resume" + tier = var.tier } annotations = { "reloader.stakater.com/search" = "true" @@ -58,9 +66,34 @@ resource "kubernetes_deployment" "resume" { name = "PUBLIC_SERVER_URL" value = "https://resume.viktorbarzin.me" } + + env { + name = "POSTGRES_HOST" + value = "postgresql.dbaas.svc.cluster.local" + } + env { + name = "POSTGRES_DB" + value = "resume" + } + env { + name = "POSTGRES_USER" + value = "resume" + } + env { + name = "POSTGRES_PASSWORD" + value = var.db_password + } env { name = "JWT_SECRET" - value = "kek" + value = random_string.random.result + } + env { + name = "AUTH_SECRET" + value = random_string.random.result + } + env { + name = "SECRET_KEY" + value = random_string.random.result } env { name = "JWT_EXPIRY_TIME" @@ -70,28 +103,46 @@ resource "kubernetes_deployment" "resume" { name = "STORAGE_ENDPOINT" value = "https://resume.viktorbarzin.me" } - env { - name = "STORAGE_PORT" - value = 443 - } // There's a tone of these... I give up... // check https://github.com/AmruthPillai/Reactive-Resume/blob/main/.env.example port { container_port = 3000 } - # volume_mount { - # name = "config" - # mount_path = "/app/public/" - # } + port { + container_port = 3100 + } } - # volume { - # name = "config" - # config_map { - # name = "config" - # } - # } } } } } + + +resource "kubernetes_service" "resume" { + metadata { + name = "resume" + namespace = kubernetes_namespace.resume.metadata[0].name + labels = { + "app" = "resume" + } + } + + spec { + selector = { + app = "resume" + } + port { + name = "http" + port = 80 + target_port = 3000 + } + } +} + +module "ingress" { + source = "../ingress_factory" + namespace = kubernetes_namespace.resume.metadata[0].name + name = "resume" + tls_secret_name = var.tls_secret_name +} diff --git a/modules/kubernetes/reverse_proxy/factory/main.tf b/modules/kubernetes/reverse_proxy/factory/main.tf index a80407f5..5e758246 100644 --- a/modules/kubernetes/reverse_proxy/factory/main.tf +++ b/modules/kubernetes/reverse_proxy/factory/main.tf @@ -85,6 +85,16 @@ resource "kubernetes_ingress_v1" "proxied-ingress" { "nginx.ingress.kubernetes.io/auth-response-headers" : var.protected ? "Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid" : null "nginx.ingress.kubernetes.io/auth-snippet" : var.protected ? "proxy_set_header X-Forwarded-Host $http_host;" : null + # # 2. Local Basic Auth Config + # nginx.ingress.kubernetes.io/auth-type: basic + # nginx.ingress.kubernetes.io/auth-secret: emergency-basic-auth + # nginx.ingress.kubernetes.io/auth-realm: "Authentik Down - Use Emergency Login" + + # # 3. The Fallback Magic + # nginx.ingress.kubernetes.io/configuration-snippet: | + # satisfy any; + # allow all; + "nginx.ingress.kubernetes.io/proxy-body-size" : var.max_body_size "nginx.ingress.kubernetes.io/use-proxy-protocol" : var.use_proxy_protocol "nginx.ingress.kubernetes.io/proxy-connect-timeout" : var.proxy_timeout diff --git a/terraform.tfvars b/terraform.tfvars index ffaa6945..573346fd 100644 Binary files a/terraform.tfvars and b/terraform.tfvars differ