Docker Services Deployment (LXC)

Core services stack on Proxmox LXC.

📝 Note: Paperless & Stirling-PDF run on Pop!_OS for GPU acceleration.


Overview

Services on LXC

ServicePurposeRAMPort
PortainerContainer management256MB9000
Uptime KumaStatus monitoring256MB3001
VaultwardenPassword manager256MB8080
HomepageService dashboard128MB3000
n8nWorkflow automation512MB5678
Calibre-webEbook library256MB8083
IT-ToolsDeveloper utilities128MB8082
Actual BudgetFinancial planning256MB5006

Total estimate: ~2GB RAM

Services on Pop!_OS (GPU)

ServicePurposePort
Paperless-ngxDocument OCR8000
Stirling-PDFPDF processing8081
PlexMedia server32400

See: Pop!_OS Docker Setup


Part 1: Proxmox LXC Setup

Create the LXC

  1. Proxmox UI → Create CT

  2. Settings:

    • Template: Debian 12 or Ubuntu 22.04
    • Hostname: docker-services
    • RAM: 4GB
    • Cores: 2
    • Disk: 32GB
    • Network: Static IP (e.g., 192.168.1.20)
  3. Enable nesting (required for Docker):

# On Proxmox host
pct set <vmid> -features nesting=1

Install Docker

# Enter container
pct enter <vmid>
 
# Update
apt update && apt upgrade -y
 
# Install Docker
curl -fsSL https://get.docker.com | sh
 
# Install Compose
apt install docker-compose-plugin -y
 
# Verify
docker --version
docker compose version

Part 2: Directory Structure

mkdir -p /opt/docker/{portainer,uptime-kuma,vaultwarden,homepage/config,n8n,calibre-web/{config,books},it-tools,actual}
cd /opt/docker

Part 3: Docker Compose

Create /opt/docker/docker-compose.yml:

version: "3.8"
 
services:
  # ===================
  # PORTAINER
  # ===================
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9000:9000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./portainer:/data
 
  # ===================
  # UPTIME KUMA
  # ===================
  uptime-kuma:
    image: louislam/uptime-kuma:latest
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - ./uptime-kuma:/app/data
 
  # ===================
  # VAULTWARDEN
  # ===================
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    ports:
      - "8080:80"
    environment:
      - WEBSOCKET_ENABLED=true
    volumes:
      - ./vaultwarden:/data
 
  # ===================
  # HOMEPAGE
  # ===================
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - ./homepage/config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
 
  # ===================
  # N8N
  # ===================
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=CHANGE_ME
      - GENERIC_TIMEZONE=America/Chicago
    volumes:
      - ./n8n:/home/node/.n8n
 
  # ===================
  # CALIBRE-WEB
  # ===================
  calibre-web:
    image: lscr.io/linuxserver/calibre-web:latest
    container_name: calibre-web
    restart: unless-stopped
    ports:
      - "8083:8083"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Chicago
    volumes:
      - ./calibre-web/config:/config
      - ./calibre-web/books:/books
 
  # ===================
  # IT-TOOLS
  # ===================
  it-tools:
    image: corentinth/it-tools:latest
    container_name: it-tools
    restart: unless-stopped
    ports:
      - "8082:80"
 
  # ===================
  # ACTUAL BUDGET
  # ===================
  actual:
    image: actualbudget/actual-server:latest
    container_name: actual
    restart: unless-stopped
    ports:
      - "5006:5006"
    volumes:
      - ./actual:/data

Part 4: Deploy

cd /opt/docker
 
# Pull images
docker compose pull
 
# Start
docker compose up -d
 
# Check
docker compose ps

Part 5: Access URLs

Assuming LXC IP is 192.168.1.20:

ServiceURLDefault Creds
Portainer:9000Create on first visit
Uptime Kuma:3001Create on first visit
Vaultwarden:8080Create account
Homepage:3000Config file
n8n:5678admin / CHANGE_ME
Calibre-web:8083admin / admin123
IT-Tools:8082None
Actual Budget:5006Create on first visit

Part 6: Homepage Config

Create /opt/docker/homepage/config/services.yaml:

- Infrastructure:
    - Proxmox:
        href: https://192.168.1.144:8006
        icon: proxmox.png
        description: Hypervisor
    - Pi-hole:
        href: http://192.168.1.50/admin
        icon: pi-hole.png
        description: DNS
    - NPM:
        href: http://192.168.1.10:81
        icon: nginx-proxy-manager.png
        description: Reverse Proxy
 
- Management:
    - Portainer:
        href: http://192.168.1.20:9000
        icon: portainer.png
        description: Containers
    - Uptime Kuma:
        href: http://192.168.1.20:3001
        icon: uptime-kuma.png
        description: Monitoring
    - Vaultwarden:
        href: http://192.168.1.20:8080
        icon: bitwarden.png
        description: Passwords
 
- Productivity:
    - n8n:
        href: http://192.168.1.20:5678
        icon: n8n.png
        description: Automation
    - Paperless:
        href: http://192.168.1.156:8000
        icon: paperless-ngx.png
        description: Documents
    - Actual:
        href: http://192.168.1.20:5006
        icon: actual.png
        description: Budget
 
- Tools:
    - IT-Tools:
        href: http://192.168.1.20:8082
        icon: it-tools.png
        description: Dev Utils
    - Stirling PDF:
        href: http://192.168.1.156:8081
        icon: stirling-pdf.png
        description: PDF Tools
    - Calibre:
        href: http://192.168.1.20:8083
        icon: calibre-web.png
        description: Ebooks
 
- Media:
    - Plex:
        href: https://plex.shdwnet.org
        icon: plex.png
        description: Media
 
- External:
    - Notes:
        href: https://notes.shdwnet.org
        icon: obsidian.png
        description: Knowledge Base

Post-Deployment

Change Passwords!

  • n8n: Edit N8N_BASIC_AUTH_PASSWORD in compose
  • Calibre-web: Change default admin password

Backups

# Backup everything
tar -czvf docker-backup-$(date +%Y%m%d).tar.gz /opt/docker

Reverse Proxy (NPM)

Add proxy hosts for external access:

  • vault.shdwnet.org → 192.168.1.20:8080
  • n8n.shdwnet.org → 192.168.1.20:5678