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.
DO NOT DELETE ANY LOCAL OR REMOTE FILES WITHOUT ASKING ME TO CONFIRM!
📋 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.5:/fs/1000/nfs/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