v0.1.2: Multi-server architecture + security cleanup

- Implement multi-server Traefik + Sablier architecture
- Add label-based automatic service discovery
- Create separate Sablier stack deployment
- Add remote server deployment workflow (Option 3)
- Add 9 new functions for multi-server management
- Remove deprecated config-templates folder
- Replace hardcoded private data with placeholders
- Update backup timestamp format to YY_MM_DD_hh_mm
- Add markup.yml to .gitignore

Breaking changes:
- Removed Sablier from core docker-compose.yml (now separate stack)
- Config templates moved from config-templates/ to docker-compose/core/
- REQUIRED_VARS now dynamic based on deployment type
This commit is contained in:
Kelin
2026-02-04 19:36:18 -05:00
parent 75e66586d1
commit 73cb274160
94 changed files with 2343 additions and 12845 deletions

View File

@@ -3,10 +3,10 @@
###############################################################
users:
kelin:
displayname: "kelin"
password: "$argon2id$v=19$m=65536,t=3,p=4$e97MzVuvteD5VfHT+Kw9Ew$NnK63ABYKRm5d8nWG7Z8dbRBJfhhHjaf71zQ354KSN4"
email: kelinshomelab@gmail.com
admin:
displayname: "admin"
password: "generate-with-openssl-rand-hex-64"
email: admin@example.com
groups:
- admins
- users

View File

@@ -15,8 +15,8 @@ services:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- SUBDOMAINS=kelinreij
- TOKEN=41ef7faa-fc93-41d2-a32f-340fd2b75b2f
- SUBDOMAINS=yourdomain
- TOKEN=your-duckdns-token
volumes:
- ./duckdns/config:/config
networks:
@@ -29,7 +29,7 @@ services:
restart: unless-stopped
command: ['--configFile=/config/traefik.yml']
environment:
- DUCKDNS_TOKEN=41ef7faa-fc93-41d2-a32f-340fd2b75b2f
- DUCKDNS_TOKEN=your-duckdns-token
ports:
- 80:80
- 443:443
@@ -48,7 +48,7 @@ services:
- 'homelab.category=core'
- 'homelab.description=Reverse proxy and SSL termination'
- 'traefik.enable=true'
- 'traefik.http.routers.traefik.rule=Host(`traefik.kelinreij.duckdns.org`)'
- 'traefik.http.routers.traefik.rule=Host(`traefik.yourdomain.duckdns.org`)'
- 'traefik.http.routers.traefik.entrypoints=websecure'
- 'traefik.http.routers.traefik.tls.certresolver=letsencrypt'
- 'traefik.http.routers.traefik.middlewares=authelia@docker'
@@ -56,7 +56,7 @@ services:
authelia:
# Single sign-on authentication service - must always run for user authentication
image: authelia/authelia:4.37.5
image: authelia/authelia:latest
container_name: authelia
restart: unless-stopped
environment:
@@ -80,54 +80,23 @@ services:
# If Traefik is on a remote server: these labels are NOT USED;
# configure external yml files in /traefik/dynamic folder instead.
- 'traefik.enable=true'
- 'traefik.http.routers.authelia.rule=Host(`auth.kelinreij.duckdns.org`)'
- 'traefik.http.routers.authelia.rule=Host(`auth.yourdomain.duckdns.org`)'
- 'traefik.http.routers.authelia.entrypoints=websecure'
- 'traefik.http.routers.authelia.tls.certresolver=letsencrypt'
- 'traefik.http.routers.authelia.service=authelia'
- 'traefik.http.services.authelia.loadbalancer.server.port=9091'
# Authelia forward auth middleware configuration
- 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.kelinreij.duckdns.org/'
- 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.yourdomain.duckdns.org/'
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=X-Secret'
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true'
# Sablier - Lazy loading service for Docker containers
# Controls startup/shutdown of lazy-loaded services, must always run
# REQUIREMENTS FOR DOCKER API ACCESS:
# 1. Docker daemon must be configured to listen on TCP port 2376 with TLS
# 2. DOCKER_HOST environment variable must point to accessible Docker API endpoint
# 3. Firewall must allow TCP connections to Docker API port (2376)
# 4. TLS certificates must be mounted and environment variables set
# 5. Ensure dockerproxy service is running and accessible
sablier-service:
image: sablierapp/sablier:latest
container_name: sablier-service
restart: unless-stopped
networks:
- traefik-network
environment:
- SABLIER_PROVIDER=docker
- SABLIER_DOCKER_API_VERSION=1.51
- SABLIER_DOCKER_NETWORK=traefik-network
- SABLIER_LOG_LEVEL=debug
- DOCKER_HOST=tcp://192.168.4.11:2376
- DOCKER_TLS_VERIFY=1
- DOCKER_CERT_PATH=/certs
volumes:
- ./shared-ca:/certs:ro
ports:
- 10000:10000
labels:
# Service metadata
- 'homelab.category=core'
- 'homelab.description=Lazy loading service for Docker containers'
networks:
traefik-network:
external: true
x-dockge:
urls:
- https://auth.kelinreij.duckdns.org
- http://192.168.4.11:9091
- https://traefik.kelinreij.duckdns.org
- http://192.168.4.11:8080
- https://auth.yourdomain.duckdns.org
- http://192.168.1.100:9091
- https://traefik.yourdomain.duckdns.org
- http://192.168.1.100:8080

View File

@@ -27,7 +27,7 @@ entryPoints:
certificatesResolvers:
letsencrypt:
acme:
email: kelinshomelab@gmail.com # Your email for Let's Encrypt notifications
email: admin@example.com # Your email for Let's Encrypt notifications
caServer: https://acme-v02.api.letsencrypt.org/directory # Use staging for testing
storage: /letsencrypt/acme.json
# DNS challenge - For wildcard certificates (*.yourdomain.duckdns.org)

View File

@@ -0,0 +1,78 @@
# Sablier Stack
This stack deploys [Sablier](https://github.com/acouvreur/sablier), a service that provides lazy loading (on-demand startup) for Docker containers.
## Overview
Sablier monitors Docker containers and can automatically start them when they receive traffic through Traefik, then stop them after a period of inactivity. This is useful for:
- Reducing resource usage on servers with limited RAM/CPU
- Managing seasonal or infrequently-used services
- Extending the capacity of small servers (like Raspberry Pi)
## Multi-Server Architecture
Each server in your homelab should have its own Sablier instance:
- **Core Server**: Manages lazy loading for core services
- **Remote Servers**: Each runs Sablier to control local containers
Sablier only connects to the local Docker socket (`/var/run/docker.sock`) on its own server.
## Features
- **Web Dashboard**: Access at `https://sablier.yourdomain.duckdns.org`
- **Protected by Authelia**: SSO authentication required
- **Local Control**: Only manages containers on the same server
- **Traefik Integration**: Uses Traefik middlewares for automatic container startup
## Usage
### Enable Lazy Loading on a Container
Add these labels to any service in your docker-compose files:
```yaml
services:
myservice:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.myservice.rule=Host(`myservice.yourdomain.duckdns.org`)"
- "traefik.http.routers.myservice.entrypoints=websecure"
- "traefik.http.routers.myservice.tls=true"
- "traefik.http.routers.myservice.middlewares=sablier-myservice@docker"
# Sablier middleware configuration
- "traefik.http.middlewares.sablier-myservice.plugin.sablier.names=myservice"
- "traefik.http.middlewares.sablier-myservice.plugin.sablier.sablierUrl=http://sablier:10000"
- "traefik.http.middlewares.sablier-myservice.plugin.sablier.sessionDuration=5m"
```
### Configuration Options
- `names`: Container name(s) to manage (comma-separated for multiple)
- `sablierUrl`: URL of the Sablier service (use `http://sablier:10000` for local)
- `sessionDuration`: How long to keep the container running after last request (e.g., `5m`, `1h`)
## Deployment
This stack is automatically deployed:
- On the **core server** after core infrastructure deployment
- On **remote servers** during remote server setup
Manual deployment:
```bash
cd /opt/stacks/sablier
docker compose up -d
```
## Resources
- CPU: ~10-20 MB RAM per instance
- Storage: Minimal (~50 MB)
- Network: Internal Docker network only
## Documentation
- [Sablier GitHub](https://github.com/acouvreur/sablier)
- [Sablier Documentation](https://acouvreur.github.io/sablier/)
- [Traefik Plugin Configuration](https://doc.traefik.io/traefik/plugins/sablier/)

View File

@@ -0,0 +1,24 @@
services:
sablier:
image: acouvreur/sablier:1.7.0
container_name: sablier
restart: unless-stopped
networks:
- traefik-network
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.sablier.rule=Host(`sablier.{{DUCKDNS_DOMAIN}}`)"
- "traefik.http.routers.sablier.entrypoints=websecure"
- "traefik.http.routers.sablier.tls=true"
- "traefik.http.routers.sablier.tls.certresolver=letsencrypt"
- "traefik.http.routers.sablier.middlewares=authelia@file"
- "traefik.http.services.sablier.loadbalancer.server.port=10000"
command:
- start
- --provider.name=docker
networks:
traefik-network:
external: true