12 KiB
AI Agent Context: Home Docker Infrastructure
Purpose: This document helps AI assistants (GitHub Copilot, Claude, ChatGPT, etc.) understand the repository structure, architecture, and context for better code assistance.
📋 Repository Overview
Name: home-docker (wahyd4/home-docker)
Purpose: Home media server and personal cloud infrastructure managed via Kubernetes (K3s) and Terraform
Architecture: Self-hosted Kubernetes cluster with NGINX Ingress, cert-manager, and various homelab applications
Primary Technologies: Kubernetes (K3s), Terraform, Docker, Helm, ArgoCD
🏗️ Infrastructure Architecture
Kubernetes Cluster Setup
- Distribution: K3s (lightweight Kubernetes)
- Control Plane: 192.168.1.2 (server-3)
- Container Runtime: containerd 2.0.5-k3s2
- Kubernetes Version: v1.33.3+k3s1
- OS: Ubuntu 24.04.3 LTS
- Network: 192.168.1.0/24 (local network)
Key Infrastructure Components
-
Ingress Controller: NGINX Ingress Controller (ingress-nginx namespace)
- NodePort on ports 80/443
- Handles all external traffic
- Integrated with cert-manager for TLS
- Domain *.junv.cc
-
Certificate Management: cert-manager
- Let's Encrypt integration (letsencrypt-prod ClusterIssuer)
- Automatic TLS certificate provisioning
- Email: me@junv.cc
-
GitOps: ArgoCD
- Continuous deployment from Git
- Web UI: https://argo.junv.cc
- Uses external Redis (redis-master.db.svc.cluster.local)
-
Security: Multi-layered protection
CrowdSec (Community threat intelligence):
- Monitors NGINX Ingress logs
- SSH monitoring (port 22422)
- System log analysis
- Enrolled in CrowdSec Console
- Storage: /mnt/k8s/crowdsec/ on server-3
fail2ban (Local intrusion prevention):
- SSH brute force protection (port 22422)
- Ban time: 1 hour (3600 seconds)
- Max retries: 5 attempts in 10 minutes
- Recidive jail: 24 hour ban for repeat offenders
- Ignores local network (192.168.1.0/24)
-
Monitoring: Prometheus + Grafana
- Metrics collection
- Custom dashboards
- ServiceMonitor for various services
📁 Directory Structure
Root Level Files
-
terraform/: Terraform configurations for infrastructure as code
main.tf: K3s cluster setup, SSH configurationargocd.tf: ArgoCD, cert-manager, NGINX Ingress deploymentcrowdsec.tf: CrowdSec security engine setupfail2ban.tf: fail2ban intrusion prevention setuppostgres.tf: PostgreSQL installation via SSHredis.tf: Redis installation via SSH
-
home-apps/: Home automation and productivity apps
ddns.yaml: Dynamic DNS clients (Cloudflare, Aliyun)n8n.yaml: Workflow automation platformsearxng.yaml: Privacy-respecting search enginehome.yaml: Home dashboard applicationserver-backup.yaml: Backup automation
-
apps/: General applications
passkey-auth.yaml: Authentication service
-
ai/: AI/ML applications
crawl4ai.yaml: AI web crawler
-
media/: Media server applications
alist.yaml: File listing servicejackett.yaml: Torrent indexermedia.yaml: Media server deploymentnextcloud-pv.yaml: Nextcloud persistent volumestatic-file.yaml: Static file server
-
db/: Database services
redis-values.yaml: Redis Helm valuesqdrant.yaml: Vector database for AI
-
archive/: Deprecated/archived configurations
- Legacy configurations no longer in active use
- Old services like Jellyfin, Plex, Metabase, etc.
Key Scripts
apply.sh: Manual kubectl apply commands (mostly deprecated in favor of Terraform)backup-k8s.sh: Kubernetes cluster backup scriptrestore-k8s.sh: Kubernetes cluster restorationk3s.sh: K3s installation and management notesfix_redis.sh: Redis troubleshooting script
🔧 Terraform Configuration
SSH Access Configuration
locals {
ssh_host = "192.168.1.2"
ssh_user = "junv"
ssh_port = 22422 # Custom SSH port
ssh_private_key = file("~/.ssh/id_ed25519")
}
Terraform Providers
- ssh (loafoe/ssh v2.6.0): Remote command execution
- kubernetes (hashicorp/kubernetes v2.27.0): K8s resource management
- helm (hashicorp/helm v2.12.1): Helm chart deployment
- kubectl (gavinbunney/kubectl v1.14.0): Raw K8s manifests
Storage Strategy
- Local Path Storage:
/mnt/k8s/on server-3 (192.168.1.2) - Storage Class:
local-path(K3s default) - Node Affinity: Resources pinned to
server-3hostname - Examples:
- CrowdSec:
/mnt/k8s/crowdsec/ - PostgreSQL:
/mnt/k8s/postgres/ - Redis:
/mnt/k8s/redis/
- CrowdSec:
🔐 Security & Access
SSH Configuration
- Port: 22422 (non-standard for security)
- Key: Ed25519 (~/.ssh/id_ed25519)
- User: junv
- Host: 192.168.1.2
Network Security
- Local Network: 192.168.1.0/24 (trusted)
- CrowdSec: Monitors external threats
- iptables: Previously attempted but removed due to kubectl connectivity issues
CrowdSec Configuration
-
Monitored Logs:
- NGINX Ingress Controller logs (container logs with poll_without_inotify)
- SSH attempts: /var/log/auth.log
- System logs: /var/log/kern.log, /var/log/syslog
-
Collections Installed:
- crowdsecurity/nginx
- crowdsecurity/base-http-scenarios
- crowdsecurity/linux
- crowdsecurity/sshd
- crowdsecurity/iptables
- crowdsecurity/endlessh
-
Enrollment: junv-home-k3s-cluster (enrolled in CrowdSec Console)
🚀 Common Operations
Terraform Workflow
cd terraform/
terraform init
terraform plan
terraform apply
Kubernetes Access
# Copy kubeconfig from server
scp -P 22422 junv@192.168.1.2:/etc/rancher/k3s/k3s.yaml ~/.kube/config
sed -i '' 's/127.0.0.1/192.168.1.2/g' ~/.kube/config
# Or use Terraform local
# Defined in main.tf as local.kubeconfig_cmd
CrowdSec Commands
# View metrics
kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli metrics
# List decisions (bans)
kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli decisions list
# List bouncers
kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli bouncers list
# Quick status view
./terraform/view_crowdsec.sh
fail2ban Commands
# View status
ssh -p 22422 junv@192.168.1.2 "sudo fail2ban-client status"
# SSH jail status
ssh -p 22422 junv@192.168.1.2 "sudo fail2ban-client status sshd"
# List banned IPs
ssh -p 22422 junv@192.168.1.2 "sudo fail2ban-client status sshd | grep 'Banned IP'"
# Unban an IP
ssh -p 22422 junv@192.168.1.2 "sudo fail2ban-client set sshd unbanip <IP>"
# Quick status view
./terraform/view_fail2ban.sh
Backup/Restore
# Backup cluster
./backup-k8s.sh
# Restore cluster
./restore-k8s.sh
📦 Helm Charts Used
| Chart | Repository | Version | Namespace | Purpose |
|---|---|---|---|---|
| crowdsec | https://crowdsecurity.github.io/helm-charts | 0.20.0 | crowdsec | Security engine |
| cert-manager | https://charts.jetstack.io | v1.17.2 | cert-manager | Certificate management |
| ingress-nginx | https://kubernetes.github.io/ingress-nginx | 4.10.5 | ingress-nginx | Ingress controller |
| argocd | https://argoproj.github.io/argo-helm | latest | argocd | GitOps CD |
| kube-prometheus-stack | prometheus-community | latest | default | Monitoring |
| redis | bitnami | latest | db | Cache/queue |
🗄️ Persistent Storage Locations
All persistent data stored on server-3 at 192.168.1.2:/mnt/k8s/
/mnt/k8s/
├── crowdsec/
│ ├── lapi-config/ (1Gi)
│ └── lapi-data/ (2Gi)
├── postgres/
├── redis/
└── [other services]
🌐 Domain Configuration
- Primary Domain: junv.cc
- Subdomains:
- argo.junv.cc (ArgoCD)
- [other services configured via Ingress resources]
🔍 Important Patterns & Conventions
Namespace Organization
crowdsec: Security monitoringingress-nginx: Ingress controllercert-manager: Certificate managementargocd: GitOps deploymenthome-apps: Home automation appsmedia: Media server appsdb: Database servicesdefault: Legacy prometheus/monitoring
Resource Naming
- PersistentVolumes:
{service}-{type}-pv(e.g.,crowdsec-lapi-config-pv) - Deployments: Usually match service name
- Secrets:
{service}-credentialsor{service}-{purpose}
Storage Classes
local-path: K3s default local storage (most common)nfs-client: NFS-based storage (if NFS provisioner installed)
⚠️ Known Issues & Fixes
Issue: iptables blocking kubectl
Problem: CrowdSec iptables rules blocked kubectl access to port 6443
Solution: Disabled iptables integration in crowdsec.tf (commented out ssh_resource.iptables_logging)
Status: CrowdSec still works via log analysis without iptables
Issue: Container log symlinks
Problem: CrowdSec warning about inotify polling with symlinked container logs
Solution: Added poll_without_inotify: true to NGINX Ingress acquisition config
Status: Resolved
Issue: SSH timeout during Terraform apply
Problem: SSH connection timeout when iptables rules were being applied Root Cause: iptables port scan detection was blocking Terraform's own SSH connections Solution: Removed iptables integration entirely
🔗 External Dependencies
- NFS Server: 192.168.1.4:/k8s (for NFS storage provisioner)
- External etcd Cluster:
- 192.168.1.6:2379
- 192.168.1.10:2379
- 192.168.1.11:2379
- CrowdSec Console: https://app.crowdsec.net
📝 Migration Notes
From Docker Compose to Kubernetes
- legacy-docker-compose/: Contains old Docker Compose configurations
- Most services migrated to Kubernetes YAML manifests
- Some services archived if no longer needed
From Manual kubectl to Terraform
- apply.sh: Contains legacy manual kubectl commands
- Gradually being replaced by Terraform resources
- Reference for secret creation and one-time setup tasks
🎯 Development Workflow
Adding a New Service
- Create YAML manifest in appropriate directory (home-apps/, media/, etc.)
- Define namespace, deployment, service, ingress
- If needs persistence: create PV/PVC with
/mnt/k8s/{service}/path - If needs TLS: add cert-manager annotations to Ingress
- If monitoring needed: add ServiceMonitor resource
- Consider adding to ArgoCD for GitOps deployment
Modifying Terraform Infrastructure
- Edit appropriate
.tffile interraform/ - Run
terraform planto preview changes - Run
terraform applyto apply changes - For SSH-based resources: ensure connectivity to 192.168.1.2:22422
Debugging
- Pod logs:
kubectl logs -n {namespace} {pod-name} - Pod shell:
kubectl exec -it -n {namespace} {pod-name} -- /bin/bash - Events:
kubectl get events -n {namespace} --sort-by='.lastTimestamp' - CrowdSec:
./terraform/view_crowdsec.sh
🤖 AI Assistant Guidelines
When assisting with this repository:
- Always consider the namespace - resources are organized by namespace
- Use Terraform when possible - prefer Terraform over manual kubectl
- Respect storage patterns - use
/mnt/k8s/{service}/for persistence - Check SSH port - always use port 22422, not default 22
- Local network trust - 192.168.1.0/24 is trusted, don't block it
- CrowdSec integration - avoid iptables, use log-based monitoring only
- Node affinity - resources should be pinned to "server-3" hostname
- Poll without inotify - use for container logs (symlinks)
- Ingress patterns - use cert-manager annotations for TLS
- Secret management - reference existing secrets in apply.sh for creation patterns
📚 Reference Documentation
- K3s Docs: https://docs.k3s.io/
- CrowdSec Docs: https://docs.crowdsec.net/
- NGINX Ingress: https://kubernetes.github.io/ingress-nginx/
- cert-manager: https://cert-manager.io/
- ArgoCD: https://argo-cd.readthedocs.io/
- Terraform Kubernetes Provider: https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs
🏷️ Tags & Keywords
kubernetes k3s terraform homelab nginx-ingress crowdsec argocd cert-manager prometheus grafana self-hosted infrastructure-as-code gitops security monitoring media-server home-automation
Last Updated: October 5, 2025 Maintainer: junv (wahyd4) Repository: https://github.com/wahyd4/home-docker