189 lines
5.9 KiB
Bash
Executable File
189 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# --- CONFIGURATION ---
|
|
SECRETS_FILES=(
|
|
"/mnt/secrets/caddy.env"
|
|
"/mnt/secrets/redis.env"
|
|
)
|
|
CADDY_BIN="/usr/bin/caddy"
|
|
SYSTEMD_OVERRIDE_DIR="/etc/systemd/system/caddy.service.d"
|
|
GO_VERSION="1.25.5"
|
|
|
|
# List of modules we REQUIRE (must match the build section below)
|
|
REQUIRED_MODULES=(
|
|
"github.com/caddy-dns/cloudflare"
|
|
"github.com/corazawaf/coraza-caddy/v2"
|
|
"github.com/pberkel/caddy-storage-redis"
|
|
)
|
|
|
|
# --- 1. PRE-FLIGHT CHECKS ---
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root"
|
|
exit 1
|
|
fi
|
|
|
|
echo "--- STARTING SETUP ---"
|
|
|
|
# --- 2. INTELLIGENT MODULE CHECK ---
|
|
NEEDS_BUILD=false
|
|
|
|
if ! command -v caddy &> /dev/null; then
|
|
echo "⚠️ Caddy not found. Build required."
|
|
NEEDS_BUILD=true
|
|
else
|
|
# Get list of compiled modules in the current binary
|
|
CURRENT_MODULES=$(caddy list-modules --packages)
|
|
|
|
echo "Checking existing Caddy modules..."
|
|
for mod in "${REQUIRED_MODULES[@]}"; do
|
|
if [[ "$CURRENT_MODULES" != *"$mod"* ]]; then
|
|
echo "⚠️ Missing module: $mod"
|
|
NEEDS_BUILD=true
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ "$NEEDS_BUILD" = false ]; then
|
|
echo "✅ Existing Caddy binary has all required modules. Skipping build."
|
|
else
|
|
echo "🛠️ Build required. Initializing build environment..."
|
|
|
|
# --- 3. INSTALL GO (Only if Build Needed) ---
|
|
echo "Installing system dependencies..."
|
|
apt update && apt install -y debian-keyring debian-archive-keyring apt-transport-https curl git tar gcc
|
|
|
|
if command -v go &>/dev/null && [[ "$(go version)" == *"go$GO_VERSION"* ]]; then
|
|
echo "✅ Go $GO_VERSION is already installed."
|
|
else
|
|
echo "⬇️ Installing Go $GO_VERSION..."
|
|
rm -rf /usr/local/go
|
|
rm -f /usr/bin/go
|
|
|
|
curl -OL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"
|
|
tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz"
|
|
rm "go${GO_VERSION}.linux-amd64.tar.gz"
|
|
ln -sf /usr/local/go/bin/go /usr/bin/go
|
|
fi
|
|
|
|
# --- 4. PREPARE XCADDY ---
|
|
if ! command -v xcaddy &>/dev/null; then
|
|
echo "Installing xcaddy..."
|
|
/usr/local/go/bin/go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
|
|
fi
|
|
|
|
# Locate xcaddy
|
|
export PATH=$PATH:/root/go/bin
|
|
XCADDY_EXEC=$(which xcaddy 2>/dev/null || echo "$(go env GOPATH)/bin/xcaddy")
|
|
|
|
# --- 5. BUILD BINARY ---
|
|
echo "🧱 Building Caddy with custom modules..."
|
|
"$XCADDY_EXEC" build \
|
|
--with github.com/caddy-dns/cloudflare \
|
|
--with github.com/corazawaf/coraza-caddy/v2 \
|
|
--with github.com/gamalan/caddy-tlsredis \
|
|
--output ./caddy-custom
|
|
|
|
if [ ! -f "./caddy-custom" ]; then
|
|
echo "CRITICAL ERROR: Build failed."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Replacing standard Caddy binary..."
|
|
# Ensure standard caddy deps are present
|
|
if ! dpkg -s caddy &> /dev/null; then
|
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
|
|
apt update && apt install -y caddy
|
|
fi
|
|
|
|
systemctl stop caddy
|
|
mv ./caddy-custom "$CADDY_BIN"
|
|
chmod +x "$CADDY_BIN"
|
|
fi
|
|
|
|
# --- 6. CONFIGURE SYSTEMD SECRETS ---
|
|
echo "Configuring Systemd Secrets..."
|
|
|
|
mkdir -p "$SYSTEMD_OVERRIDE_DIR"
|
|
echo "[Service]" > "$SYSTEMD_OVERRIDE_DIR/override.conf"
|
|
|
|
for SECRETS_FILE in "${SECRETS_FILES[@]}"; do
|
|
if [ ! -f "$SECRETS_FILE" ]; then
|
|
echo "⚠️ WARNING: Secrets file not found: $SECRETS_FILE"
|
|
continue
|
|
fi
|
|
|
|
echo "Reading secrets from $SECRETS_FILE..."
|
|
while IFS= read -r line || [ -n "$line" ]; do
|
|
# Skip comments/empty lines
|
|
[[ "$line" =~ ^#.*$ ]] && continue
|
|
[[ -z "${line// }" ]] && continue
|
|
|
|
# Clean 'export' and whitespace
|
|
clean_line="${line//export /}"
|
|
clean_line=$(echo "$clean_line" | xargs)
|
|
|
|
# Inject
|
|
echo "Environment=\"$clean_line\"" >> "$SYSTEMD_OVERRIDE_DIR/override.conf"
|
|
echo " + Injected: ${clean_line%%=*}"
|
|
done < "$SECRETS_FILE"
|
|
done
|
|
|
|
# --- 6.5 SETUP WAF (CORAZA & OWASP CRS) ---
|
|
echo "Setting up WAF Rules (OWASP CRS)..."
|
|
WAF_DEST="/etc/caddy/coraza"
|
|
mkdir -p "$WAF_DEST"
|
|
|
|
# 1. Download OWASP Core Rule Set (v4.0.0)
|
|
# We only download if the rules directory is missing
|
|
if [ ! -d "$WAF_DEST/rules" ]; then
|
|
echo "Downloading OWASP CRS v4..."
|
|
curl -SL https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.0.0.tar.gz -o /tmp/crs.tar.gz
|
|
tar -xzf /tmp/crs.tar.gz -C /tmp
|
|
|
|
# Move rules to destination
|
|
mv /tmp/coreruleset-4.0.0/rules "$WAF_DEST/"
|
|
# We rename the example setup to the standard name
|
|
mv /tmp/coreruleset-4.0.0/crs-setup.conf.example "$WAF_DEST/crs-setup.conf"
|
|
|
|
rm -rf /tmp/crs.tar.gz /tmp/coreruleset-4.0.0
|
|
else
|
|
echo "✅ OWASP Rules already present."
|
|
fi
|
|
|
|
# 2. Deploy YOUR Custom WAF Configs
|
|
# This copies your 'waf' folder contents into /etc/caddy/coraza/
|
|
if [ -d "./waf" ]; then
|
|
echo "Copying custom WAF configurations..."
|
|
cp -r ./waf/* "$WAF_DEST/"
|
|
|
|
# Fix permissions
|
|
chown -R caddy:caddy "$WAF_DEST"
|
|
# Ensure logs directory exists
|
|
mkdir -p /var/log/caddy
|
|
chown -R caddy:caddy /var/log/caddy
|
|
else
|
|
echo "WARNING: ./waf folder not found in repo. Skipping custom configs."
|
|
fi
|
|
|
|
if [ -f "./Caddyfile" ]; then
|
|
echo "Updating /etc/caddy/Caddyfile..."
|
|
cp "./Caddyfile" /etc/caddy/Caddyfile
|
|
fi
|
|
|
|
# --- 7. FINISH ---
|
|
echo "Reloading..."
|
|
systemctl daemon-reload
|
|
systemctl enable caddy
|
|
# Only restart if we actually changed something or if service is dead
|
|
if [ "$NEEDS_BUILD" = true ] || ! systemctl is-active --quiet caddy; then
|
|
systemctl restart caddy
|
|
else
|
|
# If we didn't rebuild, just reload config to be safe/fast
|
|
systemctl reload caddy
|
|
fi
|
|
|
|
echo "Done! Status:"
|
|
systemctl status caddy --no-pager
|