- 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
286 lines
8.8 KiB
Markdown
286 lines
8.8 KiB
Markdown
# Multi-Server Implementation - COMPLETED
|
|
|
|
**Implementation Date:** February 4, 2026
|
|
**Status:** ✅ COMPLETE - All changes implemented and validated
|
|
|
|
---
|
|
|
|
## Implementation Summary
|
|
|
|
Successfully implemented multi-server Traefik + Sablier architecture for EZ-Homelab. The system now supports:
|
|
|
|
1. **Label-based automatic service discovery** - No manual YAML editing required
|
|
2. **Multi-server Docker provider** - Traefik discovers containers on remote servers via TLS
|
|
3. **Per-server Sablier instances** - Each server controls local lazy loading independently
|
|
4. **Unified domain management** - All services under one DuckDNS wildcard domain
|
|
5. **Secure Docker TLS** - Shared CA certificates for multi-server communication
|
|
|
|
---
|
|
|
|
## Changes Implemented
|
|
|
|
### 1. File Structure Changes
|
|
|
|
#### Deleted:
|
|
- ✅ `config-templates/` folder (deprecated)
|
|
|
|
#### Created:
|
|
- ✅ `docker-compose/sablier/` - New standalone Sablier stack
|
|
- `docker-compose.yml` - Sablier container with local Docker socket
|
|
- `README.md` - Complete documentation
|
|
|
|
#### Modified:
|
|
- ✅ `docker-compose/core/docker-compose.yml` - Removed embedded Sablier service
|
|
- ✅ `scripts/common.sh` - Added 4 new multi-server functions
|
|
- ✅ `scripts/ez-homelab.sh` - Added 5 new functions + updated workflow
|
|
- ✅ `.env.example` - Already contained REMOTE_SERVER_* variables
|
|
|
|
---
|
|
|
|
### 2. New Functions Added
|
|
|
|
#### common.sh (4 functions)
|
|
```bash
|
|
detect_server_role() # Detects if server is core or remote
|
|
generate_traefik_provider_config() # Creates Docker provider config for remote server
|
|
generate_sablier_middleware_config() # Creates Sablier middleware for remote server
|
|
add_remote_server_to_traefik() # Registers remote server with core Traefik
|
|
```
|
|
|
|
#### ez-homelab.sh (5 functions)
|
|
```bash
|
|
check_docker_installed() # Pre-flight check for Docker
|
|
set_required_vars_for_deployment() # Dynamic REQUIRED_VARS based on deployment type
|
|
deploy_remote_server() # Complete remote server deployment workflow
|
|
register_remote_server_with_core() # SSH to core server for registration
|
|
deploy_sablier_stack() # Deploy Sablier stack (used by both core and remote)
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Workflow Changes
|
|
|
|
#### main() Function Updates:
|
|
- ✅ Added Docker pre-check before Options 2 and 3
|
|
- ✅ Calls `set_required_vars_for_deployment()` dynamically
|
|
- ✅ Option 2: Sets `REQUIRED_VARS` for core deployment
|
|
- ✅ Option 3: Sets `REQUIRED_VARS` for remote deployment, calls `deploy_remote_server()`
|
|
|
|
#### deploy_core() Function Updates:
|
|
- ✅ Automatically deploys Sablier stack after core deployment
|
|
- ✅ Updated config paths from `config-templates/*` to `docker-compose/core/*`
|
|
- ✅ Fixed backup timestamp format: `YY_MM_DD_hh_mm`
|
|
|
|
#### Backup Logic Verification:
|
|
- ✅ Backups correctly create from `/opt/stacks/core/` (deployed location, not repo)
|
|
- ✅ Format: `traefik.backup.26_02_04_14_30/`
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
### Core Server (Option 2)
|
|
```
|
|
Core Server
|
|
├── Traefik (discovers all servers)
|
|
│ ├── Local Docker provider (this server)
|
|
│ ├── Remote Docker provider (auto-registered)
|
|
│ └── Dynamic configs in /opt/stacks/core/traefik/dynamic/
|
|
├── Authelia (SSO for all servers)
|
|
├── DuckDNS (wildcard domain)
|
|
└── Sablier (manages local lazy loading)
|
|
```
|
|
|
|
### Remote Server (Option 3)
|
|
```
|
|
Remote Server
|
|
├── Docker API (TLS port 2376)
|
|
│ └── Shares CA with core server
|
|
├── Sablier (manages local lazy loading)
|
|
└── Services with Traefik labels
|
|
└── Auto-discovered by core Traefik
|
|
```
|
|
|
|
### Service Discovery Flow
|
|
```
|
|
1. Remote server deployed → Docker TLS configured → Sablier deployed
|
|
2. Remote server registers with core → Creates Traefik provider config
|
|
3. Traefik polls remote Docker API → Discovers labeled containers
|
|
4. User accesses https://service.domain.duckdns.org
|
|
5. Core Traefik routes to remote service
|
|
6. SSL certificate issued by core Traefik
|
|
```
|
|
|
|
---
|
|
|
|
## Required Variables by Deployment Type
|
|
|
|
### Core Deployment (Option 2):
|
|
```bash
|
|
SERVER_IP
|
|
SERVER_HOSTNAME
|
|
DUCKDNS_SUBDOMAINS
|
|
DUCKDNS_TOKEN
|
|
DOMAIN
|
|
DEFAULT_USER
|
|
DEFAULT_PASSWORD
|
|
DEFAULT_EMAIL
|
|
```
|
|
|
|
### Remote Deployment (Option 3):
|
|
```bash
|
|
SERVER_IP # This remote server
|
|
SERVER_HOSTNAME # This remote server
|
|
DUCKDNS_DOMAIN # Shared domain
|
|
DEFAULT_USER # Local user
|
|
REMOTE_SERVER_IP # Core server IP
|
|
REMOTE_SERVER_HOSTNAME # Core server hostname
|
|
REMOTE_SERVER_USER # Core server SSH user
|
|
```
|
|
|
|
---
|
|
|
|
## Testing Checklist
|
|
|
|
### Pre-Implementation Tests:
|
|
- ✅ Bash syntax validation (`bash -n scripts/*.sh`)
|
|
- ✅ Docker Compose syntax validation
|
|
- ✅ No errors in VS Code
|
|
|
|
### Post-Implementation Tests Required:
|
|
- ⏳ Deploy core server (Option 2)
|
|
- ⏳ Verify Sablier stack auto-deployed
|
|
- ⏳ Verify shared CA generated
|
|
- ⏳ Deploy remote server (Option 3)
|
|
- ⏳ Verify Docker TLS configured
|
|
- ⏳ Verify registration with core
|
|
- ⏳ Deploy test service on remote with labels
|
|
- ⏳ Verify Traefik discovers service
|
|
- ⏳ Verify SSL certificate issued
|
|
- ⏳ Verify lazy loading works
|
|
|
|
---
|
|
|
|
## Key Implementation Details
|
|
|
|
### 1. Sablier Container Name
|
|
- Changed from `sablier-service` to `sablier` (consistent naming)
|
|
- Only connects to local Docker socket (no remote DOCKER_HOST)
|
|
- Each server runs independent Sablier instance
|
|
|
|
### 2. REQUIRED_VARS Mechanism
|
|
- Reused existing `validate_and_prompt_variables()` function
|
|
- Made REQUIRED_VARS dynamic via `set_required_vars_for_deployment()`
|
|
- No duplicate validation functions created
|
|
|
|
### 3. Docker Pre-Check
|
|
- Added `check_docker_installed()` before deployment options
|
|
- Prevents confusing errors during deployment
|
|
- Guides users to Option 1 if Docker missing
|
|
|
|
### 4. Traefik Provider Configuration
|
|
- Auto-generated in `/opt/stacks/core/traefik/dynamic/`
|
|
- Format: `docker-provider-{hostname}.yml`
|
|
- Traefik auto-reloads within 2 seconds
|
|
|
|
### 5. Remote Server Registration
|
|
- Uses SSH to run functions on core server
|
|
- Sources common.sh on core to access functions
|
|
- Creates provider and Sablier middleware configs
|
|
- Restarts Traefik to apply changes
|
|
|
|
---
|
|
|
|
## Files Modified Summary
|
|
|
|
| File | Lines Changed | Status |
|
|
|------|---------------|--------|
|
|
| `scripts/common.sh` | +130 | ✅ Complete |
|
|
| `scripts/ez-homelab.sh` | +200 | ✅ Complete |
|
|
| `docker-compose/core/docker-compose.yml` | -38 | ✅ Complete |
|
|
| `docker-compose/sablier/docker-compose.yml` | +19 | ✅ Created |
|
|
| `docker-compose/sablier/README.md` | +77 | ✅ Created |
|
|
| `config-templates/` | Entire folder | ✅ Deleted |
|
|
|
|
**Total Lines of Code:** ~430 lines added/modified
|
|
|
|
---
|
|
|
|
## Documentation Updates Needed
|
|
|
|
The following documentation should be updated:
|
|
- [ ] README.md - Add multi-server architecture section
|
|
- [ ] Quick reference guide - Update deployment options
|
|
- [ ] Troubleshooting guide - Add multi-server scenarios
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
1. **Test on Raspberry Pi 4** - Verify resource constraints handled properly
|
|
2. **Create example service** - Document label structure for remote services
|
|
3. **Update RoadMap.md** - Mark investigation items as complete
|
|
4. **Performance testing** - Verify timeout handling on Pi 4
|
|
|
|
---
|
|
|
|
## Notes for Future Maintenance
|
|
|
|
### Adding New Remote Server:
|
|
1. Run Option 3 on new server
|
|
2. Script automatically registers with core
|
|
3. Deploy services with proper labels
|
|
|
|
### Removing Remote Server:
|
|
1. Delete provider config: `/opt/stacks/core/traefik/dynamic/docker-provider-{hostname}.yml`
|
|
2. Delete Sablier config: `/opt/stacks/core/traefik/dynamic/sablier-middleware-{hostname}.yml`
|
|
3. Traefik auto-reloads
|
|
|
|
### Debugging:
|
|
- Check Traefik logs: `docker logs traefik`
|
|
- Check dynamic configs: `/opt/stacks/core/traefik/dynamic/`
|
|
- Verify Docker TLS: `docker -H tcp://remote-ip:2376 --tlsverify ps`
|
|
- Check Sablier logs: `docker logs sablier`
|
|
|
|
---
|
|
|
|
## Implementation Validation
|
|
|
|
### Syntax Checks:
|
|
```bash
|
|
✅ bash -n scripts/ez-homelab.sh
|
|
✅ bash -n scripts/common.sh
|
|
✅ docker compose -f docker-compose/core/docker-compose.yml config -q
|
|
✅ docker compose -f docker-compose/sablier/docker-compose.yml config -q
|
|
```
|
|
|
|
### Code Quality:
|
|
- ✅ No VS Code errors/warnings
|
|
- ✅ Follows existing code patterns
|
|
- ✅ Reuses existing functions appropriately
|
|
- ✅ Proper error handling
|
|
- ✅ Debug logging included
|
|
- ✅ User-friendly messages
|
|
|
|
---
|
|
|
|
## Success Criteria - ALL MET ✅
|
|
|
|
- [x] Sablier in separate stack (not embedded in core)
|
|
- [x] Container named "sablier" (not "sablier-service")
|
|
- [x] No prompt_for_server_role() function (unnecessary)
|
|
- [x] Reused existing validate_and_prompt_variables()
|
|
- [x] Dynamic REQUIRED_VARS based on deployment type
|
|
- [x] Compose changes in repo files (not script overrides)
|
|
- [x] Backup from /opt/stacks/ (not repo)
|
|
- [x] Timestamp format: YY_MM_DD_hh_mm
|
|
- [x] Docker pre-check before deployment
|
|
- [x] Config-templates folder deleted
|
|
- [x] All functions properly documented
|
|
|
|
---
|
|
|
|
**Implementation Complete!** 🎉
|
|
|
|
Ready for deployment testing on target hardware (Raspberry Pi 4 4GB).
|