Compare commits

...

3 commits

14 changed files with 206 additions and 26 deletions

View file

@ -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`

16
.claude/commands/add-service.md Executable file
View file

@ -0,0 +1,16 @@
# Add New Service
Help create a new Kubernetes service module.
Service name: $ARGUMENTS
Steps:
1. Create directory at modules/kubernetes/<service-name>/
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

16
.claude/commands/kubectl.md Executable file
View file

@ -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 <pod>` - Describe a pod

View file

@ -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.

View file

@ -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

13
.claude/commands/tf-apply.md Executable file
View file

@ -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.<service> -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.

13
.claude/commands/tf-plan.md Executable file
View file

@ -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.<service>" > /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.

View file

@ -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

12
.claude/settings.json Executable file
View file

@ -0,0 +1,12 @@
{
"project": {
"name": "Home Infrastructure",
"type": "terraform",
"description": "Kubernetes cluster on Proxmox with self-hosted services"
},
"permissions": {
"allow": [
"Bash(ssh:*)"
]
}
}

View file

@ -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

View file

@ -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" {

View file

@ -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
}

View file

@ -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

Binary file not shown.