Files
homelab-optimized/docs/admin/deployment.md
Gitea Mirror Bot c7c622ba48
Some checks failed
Documentation / Build Docusaurus (push) Failing after 8s
Documentation / Deploy to GitHub Pages (push) Has been skipped
Sanitized mirror from private repository - 2026-03-15 05:23:45 UTC
2026-03-15 05:23:45 +00:00

12 KiB
Raw Blame History

🚀 Service Deployment Guide

🟡 Intermediate Guide

This guide covers how to deploy new services in the homelab infrastructure, following established patterns and best practices used across all 176 Docker Compose configurations.

🎯 Deployment Philosophy

🏗️ Infrastructure as Code

  • All services are defined in Docker Compose files
  • Configuration is version-controlled in Git
  • Ansible automates deployment and management
  • Consistent patterns across all services

🔄 Deployment Workflow

Development → Testing → Staging → Production
     ↓           ↓         ↓          ↓
   Local PC → Test VM → Staging → Live Host

📋 Pre-Deployment Checklist

Before You Start

  • Identify the appropriate host for your service
  • Check resource requirements (CPU, RAM, storage)
  • Verify network port availability
  • Review security implications
  • Plan data persistence strategy
  • Consider backup requirements

🎯 Host Selection Criteria

Host Type Best For Avoid For
Synology NAS Always-on services, media, storage CPU-intensive tasks
Proxmox VMs Isolated workloads, testing Resource-constrained apps
Physical Hosts AI/ML, gaming, high-performance Simple utilities
Edge Devices IoT, networking, lightweight apps Heavy databases

🐳 Docker Compose Patterns

📝 Standard Template

Every service follows this basic structure:

version: '3.9'

services:
  service-name:
    image: official/image:latest
    container_name: Service-Name
    hostname: service-hostname
    
    # Security hardening
    security_opt:
      - no-new-privileges:true
    user: 1026:100  # Synology user mapping (adjust per host)
    read_only: true  # For stateless services
    
    # Health monitoring
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    
    # Restart policy
    restart: on-failure:5
    
    # Resource limits
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'
        reservations:
          memory: 256M
    
    # Networking
    networks:
      - service-network
    ports:
      - "8080:80"
    
    # Data persistence
    volumes:
      - /volume1/docker/service:/data:rw
      - /etc/localtime:/etc/localtime:ro
    
    # Configuration
    environment:
      - TZ=America/Los_Angeles
      - PUID=1026
      - PGID=100
    env_file:
      - .env
    
    # Dependencies
    depends_on:
      database:
        condition: service_healthy

  # Supporting services (database, cache, etc.)
  database:
    image: postgres:15
    container_name: Service-DB
    # ... similar configuration

networks:
  service-network:
    name: service-network
    ipam:
      config:
        - subnet: 192.168.x.0/24

volumes:
  service-data:
    driver: local

🔧 Host-Specific Adaptations

Synology NAS (Atlantis, Calypso, Setillo)

# User mapping for Synology
user: 1026:100

# Volume paths
volumes:
  - /volume1/docker/service:/data:rw
  - /volume1/media:/media:ro

# Memory limits (conservative)
deploy:
  resources:
    limits:
      memory: 1G

Proxmox VMs (Homelab, Chicago, Bulgaria)

# Standard Linux user
user: 1000:1000

# Volume paths
volumes:
  - ./data:/data:rw
  - /etc/localtime:/etc/localtime:ro

# More generous resources
deploy:
  resources:
    limits:
      memory: 4G
      cpus: '2.0'

Physical Hosts (Anubis, Guava)

# GPU access (if needed)
runtime: nvidia
environment:
  - NVIDIA_VISIBLE_DEVICES=all

# High-performance settings
deploy:
  resources:
    limits:
      memory: 16G
      cpus: '8.0'

📁 Directory Structure

🗂️ Standard Layout

/workspace/homelab/
├── HostName/
│   ├── service-name/
│   │   ├── docker-compose.yml
│   │   ├── .env
│   │   ├── config/
│   │   └── README.md
│   └── service-name.yml  # Simple services
├── docs/
└── ansible/

📝 File Naming Conventions

  • Simple services: service-name.yml
  • Complex services: service-name/docker-compose.yml
  • Environment files: .env or stack.env
  • Configuration: config/ directory

🔐 Security Best Practices

🛡️ Container Security

# Security hardening
security_opt:
  - no-new-privileges:true
  - apparmor:docker-default
  - seccomp:unconfined  # Only if needed

# User namespaces
user: 1026:100  # Non-root user

# Read-only filesystem
read_only: true
tmpfs:
  - /tmp
  - /var/tmp

# Capability dropping
cap_drop:
  - ALL
cap_add:
  - CHOWN  # Only add what's needed

🔑 Secrets Management

# Use Docker secrets for sensitive data
secrets:
  db_password:
    "REDACTED_PASSWORD" ./secrets/db_password.txt

services:
  app:
    secrets:
      - db_password
    environment:
      - DB_PASSWORD_FILE=/run/secrets/db_password

🌐 Network Security

# Custom networks for isolation
networks:
  frontend:
    internal: false  # Internet access
  backend:
    internal: true   # No internet access
    
services:
  web:
    networks:
      - frontend
      - backend
  database:
    networks:
      - backend  # Database isolated from internet

📊 Monitoring Integration

📈 Health Checks

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 60s

🏷️ Prometheus Labels

labels:
  - "prometheus.io/scrape=true"
  - "prometheus.io/port=8080"
  - "prometheus.io/path=/metrics"
  - "service.category=media"
  - "service.tier=production"

📊 Logging Configuration

logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"
    labels: "service,environment"

🚀 Deployment Process

1 Local Development

# Create service directory
mkdir -p ~/homelab-dev/new-service
cd ~/homelab-dev/new-service

# Create docker-compose.yml
cat > docker-compose.yml << 'EOF'
# Your service configuration
EOF

# Test locally
docker-compose up -d
docker-compose logs -f

2 Testing & Validation

# Health check
curl -f http://localhost:8080/health

# Resource usage
docker stats

# Security scan
docker scout cves

# Cleanup
docker-compose down -v

3 Repository Integration

# Add to homelab repository
cp -r ~/homelab-dev/new-service /workspace/homelab/TargetHost/

# Update documentation
echo "## New Service" >> /workspace/homelab/TargetHost/README.md

# Commit changes
git add .
git commit -m "Add new-service to TargetHost"

4 Ansible Deployment

# Deploy using Ansible
cd /workspace/homelab/ansible
ansible-playbook -i inventory.ini deploy-service.yml \
  --extra-vars "target_host=atlantis service_name=new-service"

# Verify deployment
ansible atlantis -i inventory.ini -m shell \
  -a "docker ps | grep new-service"

🔧 Service-Specific Patterns

🎬 Media Services

# Common media service pattern
services:
  media-service:
    image: linuxserver/service:latest
    environment:
      - PUID=1026
      - PGID=100
      - TZ=America/Los_Angeles
    volumes:
      - /volume1/docker/service:/config
      - /volume1/media:/media:ro
      - /volume1/downloads:/downloads:rw
    ports:
      - "8080:8080"

🗄️ Database Services

# Database with backup integration
services:
  database:
    image: postgres:15
    environment:
      - POSTGRES_DB=appdb
      - POSTGRES_USER=appuser
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./backups:/backups
    secrets:
      - db_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]

🌐 Web Services

# Web service with reverse proxy
services:
  web-app:
    image: nginx:alpine
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.webapp.rule=Host(`app.example.com`)"
      - "traefik.http.services.webapp.loadbalancer.server.port=80"
    volumes:
      - ./html:/usr/share/nginx/html:ro

📋 Deployment Checklist

Pre-Deployment

  • Service configuration reviewed
  • Resource requirements calculated
  • Security settings applied
  • Health checks configured
  • Backup strategy planned
  • Monitoring integration added

During Deployment

  • Service starts successfully
  • Health checks pass
  • Logs show no errors
  • Network connectivity verified
  • Resource usage within limits
  • Security scan completed

Post-Deployment

  • Service accessible via intended URLs
  • Monitoring alerts configured
  • Backup jobs scheduled
  • Documentation updated
  • Team notified of new service
  • Performance baseline established

🚨 Troubleshooting Deployment Issues

🔍 Common Problems

Container Won't Start

# Check logs
docker-compose logs service-name

# Check resource constraints
docker stats

# Verify image availability
docker pull image:tag

# Check port conflicts
netstat -tulpn | grep :8080

Permission Issues

# Fix ownership (Synology)
sudo chown -R 1026:100 /volume1/docker/service

# Fix permissions
sudo chmod -R 755 /volume1/docker/service

Network Issues

# Check network connectivity
docker exec service-name ping google.com

# Verify DNS resolution
docker exec service-name nslookup service-name

# Check port binding
docker port service-name

Resource Constraints

# Check memory usage
docker stats --no-stream

# Check disk space
df -h

# Monitor resource limits
docker exec service-name cat /sys/fs/cgroup/memory/memory.limit_in_bytes

🔄 Update & Maintenance

📦 Container Updates

# Update single service
docker-compose pull
docker-compose up -d

# Update with Watchtower (automated)
# Watchtower handles updates automatically for tagged containers

🔧 Configuration Changes

# Apply configuration changes
docker-compose down
# Edit configuration files
docker-compose up -d

# Rolling updates (zero downtime)
docker-compose up -d --no-deps service-name

🗄️ Database Migrations

# Backup before migration
docker exec db-container pg_dump -U user dbname > backup.sql

# Run migrations
docker-compose exec app python manage.py migrate

# Verify migration
docker-compose exec app python manage.py showmigrations

📊 Performance Optimization

Resource Tuning

# Optimize for your workload
deploy:
  resources:
    limits:
      memory: 2G      # Set based on actual usage
      cpus: '1.0'     # Adjust for CPU requirements
    reservations:
      memory: 512M    # Guarantee minimum resources

🗄️ Storage Optimization

# Use appropriate volume types
volumes:
  # Fast storage for databases
  - /volume1/ssd/db:/var/lib/postgresql/data
  
  # Slower storage for archives
  - /volume1/hdd/archives:/archives:ro
  
  # Temporary storage
  - type: tmpfs
    target: /tmp
    tmpfs:
      size: 100M

🌐 Network Optimization

# Optimize network settings
networks:
  app-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-app
      com.docker.network.driver.mtu: 1500

📋 Next Steps


Remember: Start simple, test thoroughly, and iterate based on real-world usage. Every service in this homelab started with this basic deployment pattern.