Created
February 16, 2026 01:09
-
-
Save madeye/9a578ad8c9b8166f999719aa7784aa6f to your computer and use it in GitHub Desktop.
Auto setup script: Caddy + acme.sh TLS forward proxy with Basic Auth (Debian/Ubuntu)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Auto setup script: Caddy + acme.sh TLS forward proxy with authentication | |
| # Usage: sudo bash setup-caddy-proxy.sh | |
| # | |
| # Required environment variables: | |
| # DOMAIN - Your domain (e.g. proxy.example.com) | |
| # EMAIL - Email for acme.sh registration | |
| # PROXY_USER - Proxy basic auth username | |
| # PROXY_PASS - Proxy basic auth password | |
| # CF_Token - Cloudflare API token (or set vars for your DNS provider) | |
| # CF_Zone_ID - Cloudflare Zone ID (or set vars for your DNS provider) | |
| # | |
| # Optional: | |
| # DNS_PROVIDER - acme.sh DNS plugin name (default: dns_cf) | |
| # USE_NAIVE - Set to "yes" to use klzgrad/forwardproxy naive branch (default: yes) | |
| # | |
| set -euo pipefail | |
| # ── Colors ─────────────────────────────────────────────────────────────────── | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' | |
| info() { echo -e "${GREEN}[INFO]${NC} $*"; } | |
| warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } | |
| error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } | |
| # ── Pre-flight checks ─────────────────────────────────────────────────────── | |
| [[ $EUID -ne 0 ]] && error "This script must be run as root (or with sudo)." | |
| for var in DOMAIN EMAIL PROXY_USER PROXY_PASS CF_Token CF_Zone_ID; do | |
| [[ -z "${!var:-}" ]] && error "Environment variable $var is required but not set." | |
| done | |
| DNS_PROVIDER="${DNS_PROVIDER:-dns_cf}" | |
| USE_NAIVE="${USE_NAIVE:-yes}" | |
| info "Domain: $DOMAIN" | |
| info "Email: $EMAIL" | |
| info "Proxy user: $PROXY_USER" | |
| info "DNS provider: $DNS_PROVIDER" | |
| info "Naive branch: $USE_NAIVE" | |
| echo | |
| # ── Step 1: Install dependencies ──────────────────────────────────────────── | |
| info "Installing system dependencies..." | |
| apt update -qq | |
| apt install -y -qq curl git golang > /dev/null 2>&1 | |
| # ── Step 2: Install acme.sh ───────────────────────────────────────────────── | |
| if [[ ! -f "$HOME/.acme.sh/acme.sh" ]]; then | |
| info "Installing acme.sh..." | |
| curl -fsSL https://get.acme.sh | sh -s email="$EMAIL" | |
| else | |
| info "acme.sh already installed, skipping." | |
| fi | |
| # ── Step 3: Issue certificate ──────────────────────────────────────────────── | |
| info "Issuing TLS certificate for $DOMAIN via $DNS_PROVIDER..." | |
| export CF_Token CF_Zone_ID | |
| "$HOME/.acme.sh/acme.sh" --issue --dns "$DNS_PROVIDER" -d "$DOMAIN" --force || { | |
| warn "Certificate may already exist. Continuing..." | |
| } | |
| mkdir -p /etc/caddy/certs | |
| "$HOME/.acme.sh/acme.sh" --install-cert -d "$DOMAIN" \ | |
| --cert-file /etc/caddy/certs/cert.pem \ | |
| --key-file /etc/caddy/certs/key.pem \ | |
| --fullchain-file /etc/caddy/certs/fullchain.pem \ | |
| --reloadcmd "systemctl restart caddy || true" | |
| info "Certificate installed to /etc/caddy/certs/" | |
| # ── Step 4: Build Caddy with forwardproxy ──────────────────────────────────── | |
| info "Installing xcaddy..." | |
| GOBIN=/usr/local/bin go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest | |
| info "Building Caddy with forwardproxy plugin (this may take a few minutes)..." | |
| BUILD_DIR=$(mktemp -d) | |
| cd "$BUILD_DIR" | |
| if [[ "$USE_NAIVE" == "yes" ]]; then | |
| /usr/local/bin/xcaddy build \ | |
| --with github.com/caddyserver/forwardproxy=github.com/klzgrad/forwardproxy@naive | |
| else | |
| /usr/local/bin/xcaddy build \ | |
| --with github.com/caddyserver/forwardproxy | |
| fi | |
| mv caddy /usr/bin/caddy | |
| chmod +x /usr/bin/caddy | |
| cd / | |
| rm -rf "$BUILD_DIR" | |
| info "Caddy built and installed: $(/usr/bin/caddy version)" | |
| # ── Step 5: Create camouflage page ────────────────────────────────────────── | |
| mkdir -p /var/www/html | |
| cat > /var/www/html/index.html <<'HTMLEOF' | |
| <!DOCTYPE html> | |
| <html><head><meta charset="utf-8"><title>Welcome</title></head> | |
| <body><h1>It works!</h1><p>This is the default web page for this server.</p></body> | |
| </html> | |
| HTMLEOF | |
| # ── Step 6: Write Caddyfile ───────────────────────────────────────────────── | |
| info "Writing Caddyfile..." | |
| cat > /etc/caddy/Caddyfile <<EOF | |
| { | |
| order forward_proxy before file_server | |
| admin off | |
| } | |
| :443, ${DOMAIN} { | |
| tls /etc/caddy/certs/fullchain.pem /etc/caddy/certs/key.pem | |
| forward_proxy { | |
| basic_auth ${PROXY_USER} ${PROXY_PASS} | |
| hide_ip | |
| hide_via | |
| probe_resistance secret.localhost | |
| } | |
| file_server { | |
| root * /var/www/html | |
| } | |
| } | |
| EOF | |
| info "Caddyfile written to /etc/caddy/Caddyfile" | |
| # ── Step 7: Create systemd service ────────────────────────────────────────── | |
| info "Creating systemd service..." | |
| cat > /etc/systemd/system/caddy.service <<'EOF' | |
| [Unit] | |
| Description=Caddy | |
| After=network.target network-online.target | |
| Requires=network-online.target | |
| [Service] | |
| Type=notify | |
| User=root | |
| ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile | |
| ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile | |
| TimeoutStopSec=5s | |
| LimitNOFILE=1048576 | |
| LimitNPROC=512 | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| systemctl daemon-reload | |
| systemctl enable --now caddy | |
| info "Caddy service started." | |
| # ── Done ───────────────────────────────────────────────────────────────────── | |
| echo | |
| echo -e "${GREEN}══════════════════════════════════════════════════════════════${NC}" | |
| echo -e "${GREEN} Setup complete!${NC}" | |
| echo -e "${GREEN}══════════════════════════════════════════════════════════════${NC}" | |
| echo | |
| echo " Proxy URL: https://${PROXY_USER}:${PROXY_PASS}@${DOMAIN}:443" | |
| echo | |
| echo " Test with:" | |
| echo " curl -x https://${PROXY_USER}:${PROXY_PASS}@${DOMAIN}:443 https://httpbin.org/ip" | |
| echo | |
| echo " Logs:" | |
| echo " journalctl -u caddy -f" | |
| echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment