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
This commit is contained in:
@@ -0,0 +1,360 @@
|
||||
# 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
|
||||
|
||||
```caddy
|
||||
# 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
|
||||
|
||||
```yaml
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```caddy
|
||||
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
|
||||
```bash
|
||||
sudo docker-compose -f /srv/docker/caddy/docker-compose.yml ps
|
||||
```
|
||||
|
||||
### View Logs
|
||||
```bash
|
||||
# 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)
|
||||
```bash
|
||||
# If you modify the Caddyfile:
|
||||
sudo docker-compose -f /srv/docker/caddy/docker-compose.yml restart
|
||||
```
|
||||
|
||||
### Verify Certificate
|
||||
```bash
|
||||
ls -la /var/lib/docker/volumes/caddy_data/_data/caddy/certificates/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Caddy won't start
|
||||
```bash
|
||||
# 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
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- Kopia Backup Setup: `kopia-nextcloud-backblaze-setup.md`
|
||||
- Infrastructure Complete: `INFRASTRUCTURE-COMPLETE.md`
|
||||
- Caddy Documentation: https://caddyserver.com/docs/caddyfile
|
||||
- Docker Compose: https://docs.docker.com/compose/
|
||||
|
||||
---
|
||||
|
||||
**Status**: Ready for deployment
|
||||
**Last Updated**: April 27, 2026
|
||||
**Next Step**: Deploy Caddy configuration on siklos and test HTTPS access
|
||||
Reference in New Issue
Block a user