diff --git a/.env.example b/.env.example index 7519bb9..2ed0d44 100644 --- a/.env.example +++ b/.env.example @@ -37,6 +37,13 @@ AUTHELIA_STORAGE_ENCRYPTION_KEY=your-encryption-key-here-64-chars SMTP_USERNAME=your-email@example.com SMTP_PASSWORD=your-smtp-password +# Authentik SSO (optional - alternative to Authelia with web UI) +# Generate secrets with: openssl rand -hex 50 +AUTHENTIK_SECRET_KEY=your-authentik-secret-key-here-100-chars +AUTHENTIK_DB_USER=authentik +AUTHENTIK_DB_PASSWORD=changeme-authentik-db-password +AUTHENTIK_DB_NAME=authentik + # VPN Configuration (Surfshark) # Get WireGuard details from Surfshark dashboard SURFSHARK_PRIVATE_KEY=your-wireguard-private-key diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c8c757f..baed45e 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -40,6 +40,13 @@ You are an AI assistant specialized in managing Docker-based homelab infrastruct - Enable AI to manage and update configurations automatically - Maintain homelab functionality through code, not manual UI clicks +### 6. Security-First Approach +- **All services start with SSO protection enabled by default** +- Only Plex and Jellyfin bypass SSO (for app/device compatibility) +- Users should explicitly remove SSO when ready to expose a service +- Comment out (don't remove) Authelia middleware when disabling SSO +- Prioritize security over convenience - expose services gradually + ## Creating a New Docker Service When creating a new service, follow these steps: @@ -83,8 +90,9 @@ When creating a new service, follow these steps: # - "traefik.http.routers.service-name.rule=Host(`service.domain.com`)" # - "traefik.http.routers.service-name.entrypoints=websecure" # - "traefik.http.routers.service-name.tls.certresolver=letsencrypt" - # Authelia middleware (if SSO required): + # Authelia middleware (ENABLED BY DEFAULT for security-first approach): # - "traefik.http.routers.service-name.middlewares=authelia@docker" + # ONLY bypass SSO for Plex, Jellyfin, or services requiring direct app access volumes: service-data: diff --git a/docker-compose/infrastructure.yml b/docker-compose/infrastructure.yml index 8a7d752..12b8af9 100644 --- a/docker-compose/infrastructure.yml +++ b/docker-compose/infrastructure.yml @@ -182,9 +182,116 @@ services: - "traefik.http.routers.glances.middlewares=authelia@docker" - "traefik.http.services.glances.loadbalancer.server.port=61208" + # Authentik - Alternative SSO/Identity Provider with Web UI + # Access at: https://authentik.${DOMAIN} + # NOTE: Authelia is the default SSO. Deploy Authentik only if you need a web UI for user management + authentik-server: + image: ghcr.io/goauthentik/server:2024.2.0 + container_name: authentik-server + restart: unless-stopped + command: server + networks: + - homelab-network + - traefik-network + volumes: + - /opt/stacks/authentik/media:/media + - /opt/stacks/authentik/custom-templates:/templates + environment: + - AUTHENTIK_REDIS__HOST=authentik-redis + - AUTHENTIK_POSTGRESQL__HOST=authentik-db + - AUTHENTIK_POSTGRESQL__USER=${AUTHENTIK_DB_USER:-authentik} + - AUTHENTIK_POSTGRESQL__NAME=${AUTHENTIK_DB_NAME:-authentik} + - AUTHENTIK_POSTGRESQL__PASSWORD=${AUTHENTIK_DB_PASSWORD} + - AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY} + - AUTHENTIK_ERROR_REPORTING__ENABLED=false + labels: + - "homelab.category=infrastructure" + - "homelab.description=SSO/Identity provider with web UI (alternative to Authelia)" + - "traefik.enable=true" + - "traefik.http.routers.authentik.rule=Host(`authentik.${DOMAIN}`)" + - "traefik.http.routers.authentik.entrypoints=websecure" + - "traefik.http.routers.authentik.tls.certresolver=letsencrypt" + - "traefik.http.routers.authentik.middlewares=authelia@docker" + - "traefik.http.services.authentik.loadbalancer.server.port=9000" + depends_on: + - authentik-db + - authentik-redis + + # Authentik Worker - Background task processor + authentik-worker: + image: ghcr.io/goauthentik/server:2024.2.0 + container_name: authentik-worker + restart: unless-stopped + command: worker + networks: + - homelab-network + volumes: + - /opt/stacks/authentik/media:/media + - /opt/stacks/authentik/certs:/certs + - /opt/stacks/authentik/custom-templates:/templates + environment: + - AUTHENTIK_REDIS__HOST=authentik-redis + - AUTHENTIK_POSTGRESQL__HOST=authentik-db + - AUTHENTIK_POSTGRESQL__USER=${AUTHENTIK_DB_USER:-authentik} + - AUTHENTIK_POSTGRESQL__NAME=${AUTHENTIK_DB_NAME:-authentik} + - AUTHENTIK_POSTGRESQL__PASSWORD=${AUTHENTIK_DB_PASSWORD} + - AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY} + - AUTHENTIK_ERROR_REPORTING__ENABLED=false + labels: + - "homelab.category=infrastructure" + - "homelab.description=Authentik background worker" + depends_on: + - authentik-db + - authentik-redis + + # Authentik Database - PostgreSQL + authentik-db: + image: postgres:16-alpine + container_name: authentik-db + restart: unless-stopped + networks: + - homelab-network + volumes: + - authentik-db-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${AUTHENTIK_DB_USER:-authentik} + - POSTGRES_PASSWORD=${AUTHENTIK_DB_PASSWORD} + - POSTGRES_DB=${AUTHENTIK_DB_NAME:-authentik} + labels: + - "homelab.category=infrastructure" + - "homelab.description=Authentik database" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${AUTHENTIK_DB_USER:-authentik}"] + interval: 10s + timeout: 5s + retries: 5 + + # Authentik Redis - Cache and message queue + authentik-redis: + image: redis:7-alpine + container_name: authentik-redis + restart: unless-stopped + networks: + - homelab-network + volumes: + - authentik-redis-data:/data + command: --save 60 1 --loglevel warning + labels: + - "homelab.category=infrastructure" + - "homelab.description=Authentik cache and messaging" + healthcheck: + test: ["CMD-SHELL", "redis-cli ping | grep PONG"] + interval: 10s + timeout: 3s + retries: 5 + volumes: portainer-data: driver: local + authentik-db-data: + driver: local + authentik-redis-data: + driver: local networks: homelab-network: diff --git a/docker-compose/media-extended.yml b/docker-compose/media-extended.yml index 78997b6..7ee61cb 100644 --- a/docker-compose/media-extended.yml +++ b/docker-compose/media-extended.yml @@ -166,8 +166,8 @@ services: - "traefik.http.routers.jellyseerr.rule=Host(`jellyseerr.${DOMAIN}`)" - "traefik.http.routers.jellyseerr.entrypoints=websecure" - "traefik.http.routers.jellyseerr.tls.certresolver=letsencrypt" + - "traefik.http.routers.jellyseerr.middlewares=authelia@docker" - "traefik.http.services.jellyseerr.loadbalancer.server.port=5055" - # No Authelia - users should be able to request easily # FlareSolverr - Cloudflare bypass for Prowlarr # No web UI - used by Prowlarr diff --git a/docker-compose/monitoring.yml b/docker-compose/monitoring.yml index a4d67a3..f2e22c3 100644 --- a/docker-compose/monitoring.yml +++ b/docker-compose/monitoring.yml @@ -102,21 +102,27 @@ services: - "homelab.description=Container metrics and performance monitoring" # Uptime Kuma - Uptime monitoring - # Access at: http://server-ip:3001 + # Access at: https://status.${DOMAIN} uptime-kuma: - image: louislam/uptime-kuma:1.23.11 + image: louislam/uptime-kuma:1 container_name: uptime-kuma restart: unless-stopped networks: - monitoring-network - homelab-network - ports: - - "3001:3001" + - traefik-network volumes: - uptime-kuma-data:/app/data + - /var/run/docker.sock:/var/run/docker.sock:ro labels: - "homelab.category=monitoring" - "homelab.description=Service uptime monitoring and alerts" + - "traefik.enable=true" + - "traefik.http.routers.uptime-kuma.rule=Host(`status.${DOMAIN}`)" + - "traefik.http.routers.uptime-kuma.entrypoints=websecure" + - "traefik.http.routers.uptime-kuma.tls.certresolver=letsencrypt" + - "traefik.http.routers.uptime-kuma.middlewares=authelia@docker" + - "traefik.http.services.uptime-kuma.loadbalancer.server.port=3001" # Loki - Log aggregation # Access at: http://server-ip:3100 @@ -171,3 +177,5 @@ networks: driver: bridge homelab-network: external: true + traefik-network: + external: true diff --git a/docker-compose/utilities.yml b/docker-compose/utilities.yml index 95003ee..62acd9f 100644 --- a/docker-compose/utilities.yml +++ b/docker-compose/utilities.yml @@ -59,28 +59,6 @@ services: - "traefik.http.routers.duplicati.middlewares=authelia@docker" - "traefik.http.services.duplicati.loadbalancer.server.port=8200" - # Uptime Kuma - Status monitoring - # Access at: https://status.${DOMAIN} - uptime-kuma: - image: louislam/uptime-kuma:1 - container_name: uptime-kuma - restart: unless-stopped - networks: - - homelab-network - - traefik-network - volumes: - - /opt/stacks/uptime-kuma/data:/app/data - - /var/run/docker.sock:/var/run/docker.sock:ro - labels: - - "homelab.category=utilities" - - "homelab.description=Uptime monitoring and status page" - - "traefik.enable=true" - - "traefik.http.routers.uptime-kuma.rule=Host(`status.${DOMAIN}`)" - - "traefik.http.routers.uptime-kuma.entrypoints=websecure" - - "traefik.http.routers.uptime-kuma.tls.certresolver=letsencrypt" - - "traefik.http.services.uptime-kuma.loadbalancer.server.port=3001" - # No Authelia - public status page - # Code Server - VS Code in browser # Access at: https://code.${DOMAIN} code-server: diff --git a/docs/quick-reference.md b/docs/quick-reference.md index 2215f99..416808e 100644 --- a/docs/quick-reference.md +++ b/docs/quick-reference.md @@ -11,25 +11,53 @@ ### Service Management ```bash -# Start all services in a compose file -docker compose -f docker-compose/infrastructure.yml up -d +# Start all services in a compose file (from stack directory) +cd /opt/stacks/stack-name/ +docker compose up -d -# Start specific service -docker compose -f docker-compose/infrastructure.yml up -d service-name +# Start all services (from anywhere, using full path) +docker compose -f /opt/stacks/stack-name/docker-compose.yml up -d -# Stop all services -docker compose -f docker-compose/infrastructure.yml down +# Start specific service (from stack directory) +cd /opt/stacks/stack-name/ +docker compose up -d service-name -# Stop specific service -docker compose -f docker-compose/infrastructure.yml stop service-name +# Start specific service (from anywhere) +docker compose -f /opt/stacks/stack-name/docker-compose.yml up -d service-name -# Restart service -docker compose -f docker-compose/file.yml restart service-name +# Stop all services (from stack directory) +cd /opt/stacks/stack-name/ +docker compose down -# Remove service and volumes -docker compose -f docker-compose/file.yml down -v +# Stop all services (from anywhere) +docker compose -f /opt/stacks/stack-name/docker-compose.yml down + +# Stop specific service (from stack directory) +cd /opt/stacks/stack-name/ +docker compose stop service-name + +# Stop specific service (from anywhere) +docker compose -f /opt/stacks/stack-name/docker-compose.yml stop service-name + +# Restart service (from stack directory) +cd /opt/stacks/stack-name/ +docker compose restart service-name + +# Restart service (from anywhere) +docker compose -f /opt/stacks/stack-name/docker-compose.yml restart service-name + +# Remove service and volumes (from stack directory) +cd /opt/stacks/stack-name/ +docker compose down -v + +# Remove service and volumes (from anywhere) +docker compose -f /opt/stacks/stack-name/docker-compose.yml down -v ``` +**Note:** There's more than one way to manage containers - use whichever is most convenient: +- Navigate to `/opt/stacks/stack-name/` and use short commands +- Use full paths with `-f` flag from anywhere in the system + ### Monitoring ```bash diff --git a/docs/services-reference.md b/docs/services-reference.md index 36ce0ef..9ebf56a 100644 --- a/docs/services-reference.md +++ b/docs/services-reference.md @@ -11,9 +11,13 @@ This document provides a comprehensive overview of all 60+ pre-configured servic | ├─ Traefik | Reverse proxy + SSL | ✓ | /opt/stacks/core/traefik | traefik.${DOMAIN} | | ├─ Authelia | SSO authentication | - | /opt/stacks/core/authelia | auth.${DOMAIN} | | └─ Gluetun | VPN (Surfshark) | - | /opt/stacks/core/gluetun | No UI | -| **🔧 infrastructure** (7) | | | | | +| **🔧 infrastructure** (12) | | | | | | ├─ Dockge | Stack manager (PRIMARY) | ✓ | /opt/stacks/infrastructure | dockge.${DOMAIN} | | ├─ Portainer | Container management | ✓ | /opt/stacks/infrastructure | portainer.${DOMAIN} | +| ├─ Authentik Server | SSO with web UI | ✓ | /opt/stacks/authentik | authentik.${DOMAIN} | +| │ ├─ authentik-worker | Background tasks | - | /opt/stacks/authentik | No UI | +| │ ├─ authentik-db | PostgreSQL | - | /opt/stacks/authentik | No UI | +| │ └─ authentik-redis | Cache/messaging | - | /opt/stacks/authentik | No UI | | ├─ Pi-hole | DNS + Ad blocking | ✓ | /opt/stacks/infrastructure | pihole.${DOMAIN} | | ├─ Watchtower | Auto container updates | - | /opt/stacks/infrastructure | No UI | | ├─ Dozzle | Docker log viewer | ✓ | /opt/stacks/infrastructure | dozzle.${DOMAIN} | @@ -35,7 +39,7 @@ This document provides a comprehensive overview of all 60+ pre-configured servic | ├─ Lazy Librarian | Book automation | ✓ | /opt/stacks/media-ext, /mnt/media | lazylibrarian.${DOMAIN} | | ├─ Mylar3 | Comic manager | ✓ | /opt/stacks/media-ext, /mnt/media | mylar.${DOMAIN} | | ├─ Calibre-Web | Ebook reader | ✓ | /opt/stacks/media-ext, /mnt/media | calibre.${DOMAIN} | -| ├─ Jellyseerr | Media requests | ✗ | /opt/stacks/media-ext | jellyseerr.${DOMAIN} | +| ├─ Jellyseerr | Media requests | ✓ | /opt/stacks/media-ext | jellyseerr.${DOMAIN} | | ├─ FlareSolverr | Cloudflare bypass | - | /opt/stacks/media-ext | No UI | | ├─ Tdarr Server | Transcoding server | ✓ | /opt/stacks/media-ext, /mnt/transcode | tdarr.${DOMAIN} | | ├─ Tdarr Node | Transcoding worker | - | /mnt/transcode-cache | No UI | @@ -63,22 +67,21 @@ This document provides a comprehensive overview of all 60+ pre-configured servic | │ └─ mediawiki-db | MariaDB | - | /opt/stacks/productivity | No UI | | └─ Form.io | Form builder | ✓ | /opt/stacks/productivity | forms.${DOMAIN} | | └─ formio-mongo | MongoDB | - | /opt/stacks/productivity | No UI | -| **🛠️ utilities** (7) | | | | | +| **🛠️ utilities** (6) | | | | | | ├─ Backrest | Backup (restic) | ✓ | /opt/stacks/utilities, /mnt/backups | backrest.${DOMAIN} | | ├─ Duplicati | Encrypted backups | ✓ | /opt/stacks/utilities, /mnt/backups | duplicati.${DOMAIN} | -| ├─ Uptime Kuma | Status monitoring | ✗ | /opt/stacks/utilities | status.${DOMAIN} | | ├─ Code Server | VS Code in browser | ✓ | /opt/stacks/utilities | code.${DOMAIN} | | ├─ Form.io | Form platform | ✓ | /opt/stacks/utilities | forms.${DOMAIN} | | │ └─ formio-mongo | MongoDB | - | /opt/stacks/utilities | No UI | | └─ Authelia-Redis | Session storage | - | /opt/stacks/utilities | No UI | -| **📈 monitoring** (7) | | | | | +| **📈 monitoring** (8) | | | | | | ├─ Prometheus | Metrics collection | ✓ | /opt/stacks/monitoring | prometheus.${DOMAIN} | | ├─ Grafana | Visualization | ✓ | /opt/stacks/monitoring | grafana.${DOMAIN} | | ├─ Loki | Log aggregation | - | /opt/stacks/monitoring | Via Grafana | | ├─ Promtail | Log shipper | - | /opt/stacks/monitoring | No UI | | ├─ Node Exporter | Host metrics | - | /opt/stacks/monitoring | No UI | | ├─ cAdvisor | Container metrics | - | /opt/stacks/monitoring | Internal :8080 | -| └─ Uptime Kuma | Uptime monitoring | ✗ | /opt/stacks/monitoring | status.${DOMAIN} | +| └─ Uptime Kuma | Uptime monitoring | ✓ | /opt/stacks/monitoring | status.${DOMAIN} | | **👨‍💻 development** (6) | | | | | | ├─ GitLab CE | Git + CI/CD | ✓ | /opt/stacks/development, /mnt/git | gitlab.${DOMAIN} | | ├─ PostgreSQL | SQL database | - | /opt/stacks/development | Port 5432 | @@ -145,7 +148,7 @@ labels: ### To Disable SSO on a Service -Remove or comment out the middleware line: +Comment out (don't remove) the middleware line: ```yaml labels: @@ -153,19 +156,37 @@ labels: - "traefik.http.routers.servicename.rule=Host(`servicename.${DOMAIN}`)" - "traefik.http.routers.servicename.entrypoints=websecure" - "traefik.http.routers.servicename.tls.certresolver=letsencrypt" - # - "traefik.http.routers.servicename.middlewares=authelia@docker" # ← Commented out + # - "traefik.http.routers.servicename.middlewares=authelia@docker" # ← Commented out (not removed) - "traefik.http.services.servicename.loadbalancer.server.port=8080" ``` After making changes, redeploy the service: + ```bash +# From inside the stack directory cd /opt/stacks/stack-name/ docker compose up -d + +# Or from anywhere, using the full path +docker compose -f /opt/stacks/stack-name/docker-compose.yml up -d +``` + +**Stopping a Service:** + +```bash +# From inside the stack directory +cd /opt/stacks/stack-name/ +docker compose down + +# Or from anywhere, using the full path +docker compose -f /opt/stacks/stack-name/docker-compose.yml down ``` **Use Cases for Development/Production:** -- **Development**: Enable SSO to protect services during testing -- **Production**: Disable SSO for services that need direct app/API access (Plex, Jellyfin, etc.) +- **Security First**: All services start with SSO enabled by default for maximum security +- **Development**: Keep SSO enabled to protect services during testing +- **Production**: Disable SSO only for services needing direct app/API access (Plex, Jellyfin) +- **Gradual Exposure**: Comment out SSO only when ready to expose a service - **Quick Toggle**: AI assistant can modify these labels automatically when you ask ## Authelia Customization @@ -264,20 +285,27 @@ notifier: - `/opt/stacks/core/authelia/configuration.yml` - Main settings - `/opt/stacks/core/authelia/users_database.yml` - User accounts -This is **by design** and makes Authelia perfect for AI management: +This is **by design** and makes Authelia perfect for AI management and security-first approach: - AI can read and modify YAML files - Version control friendly - No UI clicks required - Infrastructure as code +- Secure by default **Web UI Available For:** - Login page: `https://auth.${DOMAIN}` - User profile: Change password, enroll 2FA - Device enrollment: Manage trusted devices -**Alternatives with Web UI:** -If you need a web UI for user management: -- **Authentik**: More complex but has full web UI +**Alternative with Web UI: Authentik** +If you need a web UI for user management, Authentik is included in the infrastructure stack: +- **Authentik**: Full-featured SSO with web UI for user/group management +- Access at: `https://authentik.${DOMAIN}` +- Includes PostgreSQL database and Redis cache +- More complex but offers GUI-based configuration +- Deploy only if you need web-based user management + +**Other Alternatives:** - **Keycloak**: Enterprise-grade SSO with web UI - **Authelia + LDAP**: Use LDAP with web management (phpLDAPadmin, etc.)