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

@@ -215,3 +215,130 @@ run_cmd() {
fi
fi
}
# =============================================
# MULTI-SERVER FUNCTIONS
# =============================================
# Detect server role based on deployed stacks
detect_server_role() {
debug_log "Detecting server role"
if [ -d "/opt/stacks/core" ] && [ -f "/opt/stacks/core/docker-compose.yml" ]; then
echo "core"
debug_log "Detected role: core"
else
echo "remote"
debug_log "Detected role: remote"
fi
}
# Generate Traefik provider configuration for a remote Docker host
generate_traefik_provider_config() {
local server_ip="$1"
local server_hostname="$2"
local output_file="$3"
debug_log "Generating Traefik provider config for $server_hostname ($server_ip)"
if [ -z "$server_ip" ] || [ -z "$server_hostname" ] || [ -z "$output_file" ]; then
log_error "generate_traefik_provider_config requires server_ip, server_hostname, and output_file"
return 1
fi
cat > "$output_file" <<EOF
# Traefik Docker Provider for Remote Server: $server_hostname
# Auto-generated by EZ-Homelab
# Last updated: $(date '+%Y-%m-%d %H:%M:%S')
providers:
docker:
endpoint: "tcp://${server_ip}:2376"
exposedByDefault: false
network: traefik-network
watch: true
tls:
ca: /shared-ca/ca.pem
cert: /shared-ca/cert.pem
key: /shared-ca/key.pem
insecureSkipVerify: false
# Server-specific constraints
defaultRule: "Host(\`{{ normalize .Name }}.${DUCKDNS_DOMAIN}\`)"
EOF
log_success "Generated Traefik provider config: $output_file"
debug_log "Provider config written to $output_file"
}
# Generate Sablier middleware configuration for remote server
generate_sablier_middleware_config() {
local server_hostname="$1"
local server_ip="$2"
local output_file="$3"
debug_log "Generating Sablier middleware config for $server_hostname ($server_ip)"
if [ -z "$server_hostname" ] || [ -z "$server_ip" ] || [ -z "$output_file" ]; then
log_error "generate_sablier_middleware_config requires server_hostname, server_ip, and output_file"
return 1
fi
cat > "$output_file" <<EOF
# Sablier Middleware for Remote Server: $server_hostname
# Auto-generated by EZ-Homelab
# Last updated: $(date '+%Y-%m-%d %H:%M:%S')
#
# This middleware enables lazy loading for services on $server_hostname
# Each server has its own Sablier instance managing local containers
http:
middlewares:
sablier-${server_hostname}:
plugin:
sablier:
sablierUrl: "http://${server_ip}:10000"
sessionDuration: "5m"
dynamic:
theme: "hacker-terminal"
EOF
log_success "Generated Sablier middleware config: $output_file"
debug_log "Sablier middleware config written to $output_file"
}
# Register remote server with core Traefik
add_remote_server_to_traefik() {
local server_ip="$1"
local server_hostname="$2"
debug_log "Registering remote server $server_hostname with core Traefik"
if [ -z "$server_ip" ] || [ -z "$server_hostname" ]; then
log_error "add_remote_server_to_traefik requires server_ip and server_hostname"
return 1
fi
# Check if core stack exists
if [ ! -d "/opt/stacks/core" ]; then
log_error "Core stack not found at /opt/stacks/core - cannot register remote server"
return 1
fi
local traefik_dynamic_dir="/opt/stacks/core/traefik/dynamic"
# Create dynamic directory if it doesn't exist
if [ ! -d "$traefik_dynamic_dir" ]; then
log_info "Creating Traefik dynamic config directory"
mkdir -p "$traefik_dynamic_dir"
fi
# Generate provider configuration
local provider_file="${traefik_dynamic_dir}/docker-provider-${server_hostname}.yml"
generate_traefik_provider_config "$server_ip" "$server_hostname" "$provider_file"
# Generate Sablier middleware configuration
local sablier_file="${traefik_dynamic_dir}/sablier-middleware-${server_hostname}.yml"
generate_sablier_middleware_config "$server_hostname" "$server_ip" "$sablier_file"
log_success "Registered remote server $server_hostname with core Traefik"
log_info "Traefik will auto-reload configurations within 2 seconds"
}