Docker Deployment

One-click deployment with Docker Compose.

Overview

Deploy Drip server with Docker Compose for easy management and automatic TLS via Caddy. This is the recommended approach for containerized deployments.

Prerequisites

  • Docker and Docker Compose installed
  • Domain with DNS pointing to your server
  • Cloudflare account (for DNS challenge)

Step 1: Create Project Directory

bash
mkdir drip && cd drip

Step 2: Create Configuration Files

docker-compose.yml

yaml
services:
  caddy:
    image: slothcroissant/caddy-cloudflaredns:latest
    container_name: drip-caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
    environment:
      DOMAIN: ${DOMAIN}
      ACME_EMAIL: ${ACME_EMAIL:-}
      CF_API_TOKEN: ${CF_API_TOKEN}
    extra_hosts:
      - "host.docker.internal:host-gateway"
    mem_limit: 256m
    mem_reservation: 64m

  drip-server:
    image: driptunnel/drip-server:${VERSION:-latest}
    container_name: drip-server
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./config.yaml:/app/config.yaml:ro
    environment:
      GOMEMLIMIT: 256MiB
    mem_limit: 512m
    mem_reservation: 128m

volumes:
  caddy-data:

Caddyfile

caddyfile
{
    email {$ACME_EMAIL}
}

{$DOMAIN}, *.{$DOMAIN} {
    tls {
        dns cloudflare {$CF_API_TOKEN}
        protocols tls1.3 tls1.3
    }
    reverse_proxy host.docker.internal:8443 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
        flush_interval -1
    }
}

config.yaml

yaml
# Drip Server Configuration (Caddy reverse proxy mode)
# Use with: docker-compose.yml
#
# Architecture:
#   Client --[HTTPS/WSS]--> Caddy:443 --[HTTP/WS]--> drip-server:8443
#   Client --[TCP tunnel]--> drip-server:20000-20100 (direct, no proxy)

# Server port - Caddy will proxy to this port (internal only)
port: 8443

# Domain for client connections (required)
domain: tunnel.example.com

# Domain for tunnel URLs (optional, defaults to domain)
# tunnel_domain: example.com

# Authentication token (required for production)
# Generate with: openssl rand -hex 32
token: YOUR_SECRET_TOKEN

# TLS disabled - Caddy handles TLS termination
tls_enabled: false

# Public port for URLs - set to 443 since Caddy serves on 443
public_port: 443

# TCP tunnel port range (exposed directly to clients, not through Caddy)
tcp_port_min: 20000
tcp_port_max: 20100

# Monitoring - Use separate token
# Generate with: openssl rand -hex 32
metrics_token: YOUR_METRICS_TOKEN

# Optional settings
# debug: false              # Enable debug logging
# pprof_port: 6060          # Enable pprof profiling
# transports:               # Allowed transports (default: tcp,wss)
#   - tcp
#   - wss
# tunnel_types:             # Allowed tunnel types (default: http,https,tcp)
#   - http
#   - https
#   - tcp

.env (Secure Environment File)

bash
# Domain configuration
DOMAIN=tunnel.example.com
ACME_EMAIL=your-email@example.com

# Cloudflare API token for DNS challenge
# Get from: Cloudflare Dashboard → My Profile → API Tokens
CF_API_TOKEN=your-cloudflare-api-token

# Drip server version (use specific version in production)
VERSION=latest

Step 3: Get Cloudflare API Token

  1. Go to Cloudflare Dashboard → My Profile → API Tokens
  2. Create Token → Edit zone DNS template
  3. Set permissions: Zone - DNS - Edit
  4. Include specific zone: your domain
  5. Copy the token to .env file

Step 4: Start Services

bash
docker-compose up -d

Management Commands

bash
# View logs
docker-compose logs -f

# View Caddy logs only
docker-compose logs -f caddy

# View Drip server logs only
docker-compose logs -f drip-server

# Restart services
docker-compose restart

# Stop services
docker-compose down

# Update to latest version
docker-compose pull && docker-compose up -d

Verify Setup

bash
# Check container status
docker-compose ps

# Test health endpoint
curl https://tunnel.example.com/health

# Check server stats (if metrics_token configured)
curl -H "Authorization: Bearer YOUR_METRICS_TOKEN" \
  https://tunnel.example.com/stats

Firewall Configuration

Make sure to open the required ports:

bash
# HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# TCP tunnel port range
sudo ufw allow 20000:20100/tcp

# Verify rules
sudo ufw status

Security Checklist

Before going to production:

  • [ ] Generated secure random token (32+ chars) with openssl rand -hex 32
  • [ ] Replaced placeholder token in config.yaml
  • [ ] Set file permissions to 600 for config.yaml and .env
  • [ ] Using specific image version (not latest)
  • [ ] Configured separate metrics_token
  • [ ] Firewall configured to only allow necessary ports
  • [ ] DNS records pointing to server IP
  • [ ] Tested health endpoint returns 200

Troubleshooting

Certificate Issues

bash
# Check Caddy logs for certificate errors
docker-compose logs caddy | grep -i cert

# Verify DNS is pointing to your server
dig tunnel.example.com

# Check Cloudflare API token permissions
docker-compose logs caddy | grep -i cloudflare

Connection Issues

bash
# Check if containers are running
docker-compose ps

# Check drip-server logs
docker-compose logs drip-server

# Test internal connectivity
docker-compose exec caddy wget -qO- http://host.docker.internal:8443/health

Authentication Errors

bash
# Verify token in config
docker-compose exec drip-server cat /app/config.yaml | grep token

# Check for whitespace issues in token