Files
homelab-configs/caddy-kopia-reverse-proxy.md
T
jgitta 821f954200 Add Caddy reverse proxy configuration and Kopia backup documentation
- Create INFRASTRUCTURE-COMPLETE.md: Comprehensive infrastructure overview
  * Network architecture and DNS configuration
  * Storage architecture for Nextcloud (1.4TB warm storage via LVM)
  * Kopia backup setup with Backblaze B2 integration
  * Caddy reverse proxy configuration (CT 202)
  * Security configuration and capacity planning

- Add Caddy reverse proxy configurations:
  * caddy-kopia-integration.md: Integration steps for CT 202
  * caddy-kopia-reverse-proxy.md: Complete configuration reference
  * caddy/Caddyfile: Production-ready configuration
  * caddy/docker-compose.yml: Docker deployment spec

- Add Kopia backup documentation:
  * kopia-nextcloud-backblaze-setup.md: Complete Kopia setup guide
  * Backup strategy, retention policies, and restore procedures

- Update related documentation with consolidated references

Status: Infrastructure documented and ready for deployment
2026-04-27 11:46:47 -05:00

8.4 KiB

Caddy Reverse Proxy Configuration for Kopia

Date: April 27, 2026
Status: Configuration Ready for Deployment
Purpose: HTTPS reverse proxy for kopia.jgitta.com → siklos:51515


Overview

This guide configures Caddy as a reverse proxy to expose Kopia Web UI securely at https://kopia.jgitta.com with:

  • Automatic HTTPS/TLS termination
  • Domain-based routing from jgitta.com
  • Transparent proxy to http://192.168.88.27:51515
  • Security headers and best practices

Current Setup

Component Location Details
Kopia Web UI siklos (192.168.88.27:51515) Running in Docker container
DNS Record MikroTik (192.168.88.1) kopia.jgitta.com → 192.168.88.27
Reverse Proxy Caddy (to be deployed) siklos @ port 443 (HTTPS)
Internal Network 192.168.88.0/24 Private LAN (jgitta.com)

Caddy Configuration

File Location

/srv/docker/caddy/Caddyfile

Configuration Content

# Kopia Web UI Reverse Proxy
kopia.jgitta.com {
    # Reverse proxy to Kopia Web UI
    reverse_proxy 127.0.0.1:51515 {
        # Pass original headers
        header_upstream X-Forwarded-Proto {scheme}
        header_upstream X-Forwarded-Host {http.request.host}
        header_upstream X-Forwarded-For {http.request.remote.host}
        
        # WebSocket support (Kopia uses WebSockets)
        header_upstream Connection {http.request.header.Connection}
        header_upstream Upgrade {http.request.header.Upgrade}
    }
    
    # Security headers
    header {
        # Browser security
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        X-XSS-Protection "1; mode=block"
        
        # HTTPS enforcement
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        
        # Cache control
        Cache-Control "public, max-age=3600"
    }
    
    # Logging
    log {
        output stdout
        format json
    }
    
    # Enable TLS (automatic via Let's Encrypt for public domains, self-signed for internal)
    tls internal
}

# Optional: Redirect HTTP to HTTPS
http://kopia.jgitta.com {
    redir https://kopia.jgitta.com{uri} permanent
}

Docker Compose for Caddy

Location

/srv/docker/caddy/docker-compose.yml

Configuration

version: '3.8'

services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    
    ports:
      - "80:80"
      - "443:443"
    
    volumes:
      # Caddyfile configuration
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      
      # Persistent data (certificates, config)
      - caddy_data:/data
      - caddy_config:/config
      
      # Logs
      - ./logs:/var/log/caddy
    
    environment:
      # For internal TLS, Caddy will use self-signed certificates
      # For public domains, configure DNS for Let's Encrypt validation
      CADDY_ACME_CA: "https://acme-v02.api.letsencrypt.org/directory"
    
    networks:
      - docker_network
    
    labels:
      com.example.description: "Caddy reverse proxy for homelab services"
    
    # Health check
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

volumes:
  caddy_data:
  caddy_config:

networks:
  docker_network:
    driver: bridge

Deployment Steps

Step 1: Create Directory Structure

# SSH to siklos
ssh jgitta@192.168.88.27

# Create Caddy directory if it doesn't exist
sudo mkdir -p /srv/docker/caddy/logs

# Set permissions
sudo chmod 755 /srv/docker/caddy

Step 2: Create Caddyfile

# Create the Caddyfile with the configuration above
sudo tee /srv/docker/caddy/Caddyfile > /dev/null << 'EOF'
# [Insert Caddyfile content from above]
EOF

# Verify syntax
sudo docker run --rm -v /srv/docker/caddy/Caddyfile:/etc/caddy/Caddyfile caddy validate

Step 3: Create Docker Compose

# Create docker-compose.yml
sudo tee /srv/docker/caddy/docker-compose.yml > /dev/null << 'EOF'
# [Insert docker-compose.yml content from above]
EOF

Step 4: Start Caddy Service

cd /srv/docker/caddy

# Start the container
sudo docker-compose up -d

# Verify it's running
sudo docker-compose ps

# Check logs
sudo docker-compose logs -f caddy

Step 5: Verify Configuration

# Test connectivity from siklos
curl -k https://kopia.jgitta.com/

# Test from another host on the network
# Navigate to https://kopia.jgitta.com in browser

# Check certificate (should show self-signed for internal TLS)
openssl s_client -connect kopia.jgitta.com:443 </dev/null 2>/dev/null | openssl x509 -text -noout

Network Access

From Internal Network (192.168.88.0/24)

https://kopia.jgitta.com          → Caddy (HTTPS)
↓
http://127.0.0.1:51515           → Kopia Web UI

DNS Resolution

kopia.jgitta.com  → 192.168.88.27 (MikroTik configured)
                  ↓
              Caddy port 443

Security Considerations

TLS Certificates

  • Internal Setup: Using tls internal (self-signed, no validation needed)
  • For Public Access: Implement Let's Encrypt with DNS01 challenge
  • ACME CA: Already configured for Let's Encrypt in docker-compose.yml

Access Control

  • Limited to internal network (192.168.88.0/24) via MikroTik firewall
  • No exposure to external internet (unless router configured otherwise)
  • Basic authentication can be added to Caddyfile if needed

Headers & Security

  • X-Frame-Options prevents clickjacking
  • X-Content-Type-Options prevents MIME sniffing
  • Strict-Transport-Security enforces HTTPS
  • Cache-Control manages client caching

Adding Basic Authentication (Optional)

To protect Kopia Web UI with username/password:

kopia.jgitta.com {
    # Generate hash: caddy hash-password
    basicauth / {
        admin JDJhJDEwJFlOQ3I4...  # Replace with generated hash
    }
    
    reverse_proxy 127.0.0.1:51515 {
        # ... rest of config
    }
}

Then login with:

  • Username: admin
  • Password: [what you hashed]

Monitoring & Maintenance

Check Service Status

sudo docker-compose -f /srv/docker/caddy/docker-compose.yml ps

View Logs

# Real-time logs
sudo docker-compose -f /srv/docker/caddy/docker-compose.yml logs -f

# Last 50 lines
sudo docker-compose -f /srv/docker/caddy/docker-compose.yml logs --tail=50

Reload Configuration (Zero Downtime)

# If you modify the Caddyfile:
sudo docker-compose -f /srv/docker/caddy/docker-compose.yml restart

Verify Certificate

ls -la /var/lib/docker/volumes/caddy_data/_data/caddy/certificates/

Troubleshooting

Caddy won't start

# Check syntax
sudo docker run --rm -v /srv/docker/caddy/Caddyfile:/etc/caddy/Caddyfile caddy validate

# View detailed logs
sudo docker-compose logs caddy

Cannot connect to kopia.jgitta.com

  1. Verify DNS: nslookup kopia.jgitta.com (should return 192.168.88.27)
  2. Check Caddy is running: sudo docker-compose ps
  3. Test connectivity: curl -v https://kopia.jgitta.com/ -k
  4. Check firewall on MikroTik allows port 443

Certificate errors

  • If using self-signed (internal TLS), browser will warn — this is expected
  • Add exception in browser, or use curl -k to ignore certificate warnings

Kopia backend unreachable

  • Verify Kopia container is running on siklos: docker ps | grep kopia
  • Test local port: curl http://localhost:51515 (from siklos)
  • Check port forwarding in docker-compose.yml

Integration with Existing Services

Other Reverse Proxies

If you have existing Caddy or Nginx:

  1. Add kopia.jgitta.com block to existing configuration
  2. Or use this as a separate Caddy instance on different port
  3. Configure MikroTik to route traffic appropriately

Gitea Integration

Once deployed:

  • Add to INFRASTRUCTURE-COMPLETE.md under "Web Access" section
  • Document kopia.jgitta.com URL as HTTPS endpoint
  • Update Gitea repository with Caddy configuration


Status: Ready for deployment
Last Updated: April 27, 2026
Next Step: Deploy Caddy configuration on siklos and test HTTPS access