Files
homelab-optimized/docs/getting-started/30-Deployment-Guide.md
Gitea Mirror Bot cfecb0eed4
Some checks failed
Documentation / Deploy to GitHub Pages (push) Has been cancelled
Documentation / Build Docusaurus (push) Has been cancelled
Sanitized mirror from private repository - 2026-04-08 03:19:28 UTC
2026-04-08 03:19:28 +00:00

15 KiB

Deployment Guide

Overview

This guide provides comprehensive instructions for deploying services in the homelab environment using GitOps principles with Docker Compose and Portainer. All deployments follow infrastructure-as-code practices with version control and automated workflows.

Deployment Architecture

GitOps Workflow

Developer ──▶ Git Repository ──▶ Portainer ──▶ Docker Compose ──▶ Running Services
     │              │                │               │
     │              │                │               └─▶ Health Checks
     │              │                └─▶ Stack Management
     │              └─▶ Configuration Validation
     └─▶ Documentation Updates

Repository Structure

homelab/
├── hosts/
│   ├── atlantis/           # Atlantis server configs
│   ├── calypso/           # Calypso server configs
│   ├── concord_nuc/       # Concord NUC configs
│   ├── homelab_vm/        # Homelab VM configs
│   └── raspberry-pi-5-vish/ # Raspberry Pi configs
├── common/                # Shared configurations
├── docs/                  # Documentation
└── scripts/               # Automation scripts

Prerequisites

Required Access

  • Git Repository: Read access to homelab repository
  • Portainer Access: Admin credentials for container management
  • SSH Access: Server administration capabilities
  • Network Access: Internal network connectivity

Required Tools

# Install required tools
sudo apt update && sudo apt install -y \
    git \
    docker.io \
    docker-compose \
    curl \
    wget \
    vim

# Verify installations
git --version
docker --version
docker-compose --version

Environment Setup

# Clone repository
git clone https://git.vish.gg/Vish/homelab.git
cd homelab

# Set up environment variables
export HOMELAB_ENV="production"
export DOCKER_HOST="tcp://atlantis.vish.local:2376"
export PORTAINER_URL="http://atlantis.vish.local:9000"

Deployment Methods

Step 1: Access Portainer

  1. Navigate to Portainer
  2. Login with admin credentials
  3. Select the appropriate endpoint

Step 2: Create New Stack

  1. Go to StacksAdd Stack
  2. Choose deployment method:
    • Git Repository (recommended)
    • Upload (for local files)
    • Web Editor (for quick edits)

Step 3: Configure Git Repository

Repository URL: https://git.vish.gg/Vish/homelab.git
Reference: refs/heads/main
Compose Path: hosts/atlantis/service-name.yml

Step 4: Set Environment Variables

# Common variables
PUID=1000
PGID=1000
TZ=America/New_York
DOMAIN=vish.local

# Service-specific variables
SERVICE_PORT=8080
SERVICE_DATA=/mnt/storage/service-name

Step 5: Deploy Stack

  1. Click Deploy the Stack
  2. Monitor deployment logs
  3. Verify service health

Method 2: Command Line Deployment

Direct Docker Compose

# Navigate to service directory
cd hosts/atlantis

# Deploy service
docker-compose -f service-name.yml up -d

# Check status
docker-compose -f service-name.yml ps

# View logs
docker-compose -f service-name.yml logs -f

Using Deployment Scripts

# Run deployment script
./scripts/deploy-service.sh atlantis service-name

# Bulk deployment
./scripts/deploy-all.sh atlantis

# Update existing service
./scripts/update-service.sh atlantis service-name

Method 3: Ansible Automation

Playbook Deployment

# Deploy single service
ansible-playbook -i inventory.ini ansible/deploy-service.yml \
    -e target_host=atlantis \
    -e service_name=plex

# Deploy full stack
ansible-playbook -i inventory.ini ansible/deploy-full-stack.yml \
    -e target_host=atlantis

# Update all services
ansible-playbook -i inventory.ini ansible/update-all.yml

Service Configuration

Docker Compose Template

version: '3.8'

services:
  service-name:
    image: organization/service:latest
    container_name: service-name
    restart: unless-stopped
    
    environment:
      - PUID=${PUID:-1000}
      - PGID=${PGID:-1000}
      - TZ=${TZ:-UTC}
      - SERVICE_CONFIG=${SERVICE_CONFIG}
    
    volumes:
      - ${DATA_PATH}/config:/config
      - ${DATA_PATH}/data:/data
      - /etc/localtime:/etc/localtime:ro
    
    ports:
      - "${SERVICE_PORT}:8080"
    
    networks:
      - homelab
    
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.service.rule=Host(`service.${DOMAIN}`)"
      - "traefik.http.services.service.loadbalancer.server.port=8080"
    
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

networks:
  homelab:
    external: true

volumes:
  service-config:
    driver: local
  service-data:
    driver: local

Environment Variables

# Create .env file
cat > .env << EOF
# User Configuration
PUID=1000
PGID=1000
TZ=America/New_York

# Network Configuration
DOMAIN=vish.local
SUBNET=192.168.10.0/24

# Storage Configuration
DATA_ROOT=/mnt/storage
CONFIG_ROOT=/mnt/config
BACKUP_ROOT=/mnt/backup

# Service Configuration
SERVICE_PORT=8080
SERVICE_NAME=example-service
SERVICE_VERSION=latest

# Security Configuration
SSL_CERT_PATH=/etc/ssl/certs
SSL_KEY_PATH=/etc/ssl/private
ADMIN_EMAIL=admin@vish.local
EOF

Server-Specific Deployments

Atlantis (Primary Server)

# Media services
./deploy-service.sh atlantis plex
./deploy-service.sh atlantis sonarr
./deploy-service.sh atlantis radarr

# Storage services
./deploy-service.sh atlantis nextcloud
./deploy-service.sh atlantis syncthing

# Monitoring services
./deploy-service.sh atlantis grafana
./deploy-service.sh atlantis prometheus

Calypso (Secondary Server)

# Development services
./deploy-service.sh calypso gitea
./deploy-service.sh calypso portainer

# Authentication services
./deploy-service.sh calypso authentik
./deploy-service.sh calypso nginx-proxy-manager

# Game servers
./deploy-service.sh calypso minecraft
./deploy-service.sh calypso satisfactory

Concord NUC (Edge Server)

# Network services
./deploy-service.sh concord adguard
./deploy-service.sh concord pihole

# IoT services
./deploy-service.sh concord homeassistant
./deploy-service.sh concord node-exporter

# Media streaming
./deploy-service.sh concord invidious
./deploy-service.sh concord piped

Homelab VM (Development)

# AI/ML services
./deploy-service.sh homelab-vm ollama
./deploy-service.sh homelab-vm openhands

# Communication services
./deploy-service.sh homelab-vm mattermost
./deploy-service.sh homelab-vm signal-api

# Testing services
./deploy-service.sh homelab-vm test-environment

Raspberry Pi (Monitoring)

# Monitoring services
./deploy-service.sh raspberry-pi uptime-kuma
./deploy-service.sh raspberry-pi glances

# Lightweight services
./deploy-service.sh raspberry-pi immich
./deploy-service.sh raspberry-pi syncthing

Network Configuration

Docker Networks

# Create homelab network
docker network create \
    --driver bridge \
    --subnet=172.20.0.0/16 \
    --gateway=172.20.0.1 \
    homelab

# Create monitoring network
docker network create \
    --driver bridge \
    --subnet=172.21.0.0/16 \
    --gateway=172.21.0.1 \
    monitoring

# List networks
docker network ls

Reverse Proxy Configuration

# Nginx Proxy Manager
version: '3.8'
services:
  nginx-proxy-manager:
    image: jc21/nginx-proxy-manager:latest
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "81:81"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    environment:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"

Storage Configuration

Volume Mapping

# Standard volume structure
volumes:
  - ${DATA_ROOT}/service-name/config:/config
  - ${DATA_ROOT}/service-name/data:/data
  - ${MEDIA_ROOT}:/media:ro
  - ${DOWNLOAD_ROOT}:/downloads
  - /etc/localtime:/etc/localtime:ro

Backup Integration

# Backup-aware service
services:
  service-name:
    # ... service configuration ...
    volumes:
      - service-data:/data
      - backup-volume:/backup
    
    labels:
      - "backup.enable=true"
      - "backup.schedule=0 2 * * *"
      - "backup.retention=30d"

volumes:
  backup-volume:
    driver: local
    driver_opts:
      type: nfs
      o: addr=backup-server.local,rw
      device: ":/mnt/backup/service-name"

Security Configuration

Container Security

services:
  secure-service:
    # ... other configuration ...
    
    # Security options
    security_opt:
      - no-new-privileges:true
    
    # Read-only root filesystem
    read_only: true
    
    # Temporary filesystem for writable areas
    tmpfs:
      - /tmp
      - /var/tmp
    
    # User namespace
    user: "${PUID}:${PGID}"
    
    # Capabilities
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETUID
      - SETGID

Network Security

# Isolated network configuration
networks:
  frontend:
    driver: bridge
    internal: false
  backend:
    driver: bridge
    internal: true

services:
  web-service:
    networks:
      - frontend
      - backend
  
  database:
    networks:
      - backend

Monitoring Integration

Health Checks

services:
  monitored-service:
    # ... service configuration ...
    
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    
    labels:
      - "monitoring.enable=true"
      - "monitoring.port=8080"
      - "monitoring.path=/metrics"

Logging Configuration

services:
  logged-service:
    # ... service configuration ...
    
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        labels: "service,environment"
    
    labels:
      - "logging.enable=true"
      - "logging.service=service-name"

Deployment Validation

Pre-deployment Checks

#!/bin/bash
# validate-deployment.sh

echo "Validating deployment configuration..."

# Check Docker Compose syntax
docker-compose -f $1 config > /dev/null
if [ $? -eq 0 ]; then
    echo "✅ Docker Compose syntax valid"
else
    echo "❌ Docker Compose syntax error"
    exit 1
fi

# Check required environment variables
required_vars=("PUID" "PGID" "TZ" "DOMAIN")
for var in "${required_vars[@]}"; do
    if [ -z "${!var}" ]; then
        echo "❌ Missing required variable: $var"
        exit 1
    else
        echo "✅ Variable $var is set"
    fi
done

# Check storage paths
if [ ! -d "$DATA_ROOT" ]; then
    echo "❌ Data root directory does not exist: $DATA_ROOT"
    exit 1
else
    echo "✅ Data root directory exists"
fi

echo "✅ All validation checks passed"

Post-deployment Verification

#!/bin/bash
# verify-deployment.sh

SERVICE_NAME=$1
EXPECTED_PORT=$2

echo "Verifying deployment of $SERVICE_NAME..."

# Check container status
if docker ps | grep -q $SERVICE_NAME; then
    echo "✅ Container is running"
else
    echo "❌ Container is not running"
    exit 1
fi

# Check port accessibility
if curl -f http://localhost:$EXPECTED_PORT/health > /dev/null 2>&1; then
    echo "✅ Service is responding on port $EXPECTED_PORT"
else
    echo "❌ Service is not responding on port $EXPECTED_PORT"
fi

# Check logs for errors
if docker logs $SERVICE_NAME 2>&1 | grep -i error; then
    echo "⚠️  Errors found in logs"
else
    echo "✅ No errors in logs"
fi

echo "✅ Deployment verification complete"

Troubleshooting

Common Issues

Container Won't Start

# Check container logs
docker logs container-name

# Check resource usage
docker stats

# Verify configuration
docker-compose config

# Check port conflicts
netstat -tulpn | grep :8080

Permission Issues

# Fix ownership
sudo chown -R $PUID:$PGID /mnt/storage/service-name

# Check permissions
ls -la /mnt/storage/service-name

# Verify user mapping
docker exec container-name id

Network Connectivity

# Test container networking
docker exec container-name ping google.com

# Check network configuration
docker network inspect homelab

# Verify DNS resolution
docker exec container-name nslookup service.local

Storage Issues

# Check disk space
df -h

# Verify mount points
mount | grep storage

# Check RAID status
cat /proc/mdstat

Emergency Procedures

Service Recovery

# Stop problematic service
docker-compose -f service.yml down

# Remove containers and volumes
docker-compose -f service.yml down -v

# Restore from backup
./scripts/restore-service.sh service-name

# Redeploy service
docker-compose -f service.yml up -d

System Recovery

# Stop all services
docker stop $(docker ps -q)

# Clean up system
docker system prune -a

# Restart Docker daemon
sudo systemctl restart docker

# Redeploy critical services
./scripts/deploy-critical.sh

Automation Scripts

Deployment Automation

#!/bin/bash
# deploy-service.sh

HOST=$1
SERVICE=$2
COMPOSE_FILE="hosts/$HOST/$SERVICE.yml"

if [ ! -f "$COMPOSE_FILE" ]; then
    echo "Error: Compose file not found: $COMPOSE_FILE"
    exit 1
fi

echo "Deploying $SERVICE on $HOST..."

# Validate configuration
docker-compose -f $COMPOSE_FILE config > /dev/null
if [ $? -ne 0 ]; then
    echo "Error: Invalid compose configuration"
    exit 1
fi

# Deploy service
docker-compose -f $COMPOSE_FILE up -d

# Wait for service to be ready
sleep 30

# Verify deployment
./scripts/verify-deployment.sh $SERVICE

echo "Deployment complete: $SERVICE"

Update Automation

#!/bin/bash
# update-service.sh

SERVICE=$1

echo "Updating $SERVICE..."

# Pull latest images
docker-compose -f hosts/*/$(SERVICE).yml pull

# Recreate containers
docker-compose -f hosts/*/$(SERVICE).yml up -d

# Clean up old images
docker image prune -f

echo "Update complete: $SERVICE"

Best Practices

Configuration Management

  • Use environment variables for configuration
  • Store secrets in Docker secrets or external vaults
  • Version control all configuration files
  • Document all custom configurations

Resource Management

  • Set appropriate resource limits
  • Monitor resource usage
  • Plan for capacity growth
  • Implement resource quotas

Security Practices

  • Use non-root users in containers
  • Implement network segmentation
  • Regular security updates
  • Monitor for vulnerabilities

Backup Strategies

  • Automate backup processes
  • Test restore procedures
  • Implement versioned backups
  • Store backups offsite

This deployment guide provides comprehensive instructions for deploying and managing services in the homelab environment using modern DevOps practices and tools.