Split the monolithic init-caddy.sh into four ordered, idempotent setup scripts for the Caddy deployment environment: - install-base-deps: install required apt packages - install-aws-cli: bootstrap AWS CLI v2 - install-caddy: fetch binary, create caddy:caddy, register systemd unit - prepare-caddy-cicd: create bot deploy user + SSH, hand over web root with ACLs, write site Caddyfile and start the service - Make the web root overridable via WEB_ROOT (default /var/www)
123 lines
4.0 KiB
Bash
123 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Caddy Installation for Debian/Ubuntu
|
|
# Downloads the Caddy binary (from a local file or S3-compatible storage),
|
|
# creates the caddy:caddy system user and group, installs the binary with
|
|
# cap_net_bind_service, prepares the config directory and registers the
|
|
# systemd unit. The service itself is started by prepare-caddy-cicd.sh once
|
|
# the site Caddyfile and web root exist.
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# S3 and binary environment variables (with fallback defaults)
|
|
S3_ENDPOINT="${S3_ENDPOINT:-}"
|
|
S3_BUCKET="${S3_BUCKET:-}"
|
|
S3_REGION="${S3_REGION:-us-east-1}"
|
|
S3_ACCESS_KEY="${S3_ACCESS_KEY:-}"
|
|
S3_SECRET_KEY="${S3_SECRET_KEY:-}"
|
|
BIN_URI="${BIN_URI:-caddy-custom-linux-amd64}"
|
|
|
|
BIN_SOURCE="./${BIN_URI}"
|
|
BIN_DEST="/usr/local/bin/caddy"
|
|
CADDY_CONF_DIR="/etc/caddy"
|
|
CADDY_DATA_DIR="/var/lib/caddy"
|
|
|
|
# Ensure script is executed with root privileges
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "Error: This script must be run as root." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> [1/5] Resolving Caddy binary..."
|
|
if [ ! -f "${BIN_SOURCE}" ]; then
|
|
if [ -n "${S3_BUCKET}" ]; then
|
|
echo "Local binary '${BIN_SOURCE}' not found. Downloading from S3 bucket '${S3_BUCKET}'..."
|
|
|
|
# Export AWS credentials for the current execution
|
|
export AWS_ACCESS_KEY_ID="${S3_ACCESS_KEY}"
|
|
export AWS_SECRET_ACCESS_KEY="${S3_SECRET_KEY}"
|
|
export AWS_DEFAULT_REGION="${S3_REGION}"
|
|
|
|
AWS_CMD_ARGS=()
|
|
if [ -n "${S3_ENDPOINT}" ]; then
|
|
AWS_CMD_ARGS+=(--endpoint-url "${S3_ENDPOINT}")
|
|
fi
|
|
|
|
aws s3 cp "s3://${S3_BUCKET}/${BIN_URI}" "${BIN_SOURCE}" "${AWS_CMD_ARGS[@]}"
|
|
echo "Successfully downloaded '${BIN_URI}' from S3."
|
|
else
|
|
echo "Error: Local binary '${BIN_SOURCE}' not found, and S3_BUCKET is empty. Cannot continue." >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Found local binary at '${BIN_SOURCE}', skipping S3 download."
|
|
fi
|
|
|
|
echo "==> [2/5] Creating caddy system user and group..."
|
|
# Create caddy system user and group (no login shell, dedicated home)
|
|
if ! getent group caddy >/dev/null 2>&1; then
|
|
groupadd --system caddy
|
|
fi
|
|
|
|
if ! id -u caddy >/dev/null 2>&1; then
|
|
useradd --system \
|
|
--gid caddy \
|
|
--create-home \
|
|
--home-dir "${CADDY_DATA_DIR}" \
|
|
--shell /usr/sbin/nologin \
|
|
--comment "Caddy web server" \
|
|
caddy
|
|
fi
|
|
|
|
echo "==> [3/5] Installing Caddy binary and granting capabilities..."
|
|
install -m 750 -o root -g caddy "${BIN_SOURCE}" "${BIN_DEST}"
|
|
|
|
# Grant capability to bind to privileged ports (<1024) without running as root
|
|
setcap 'cap_net_bind_service=+ep' "${BIN_DEST}"
|
|
|
|
echo "==> [4/5] Preparing config directory (${CADDY_CONF_DIR})..."
|
|
mkdir -p "${CADDY_CONF_DIR}"
|
|
chown root:caddy "${CADDY_CONF_DIR}"
|
|
chmod 755 "${CADDY_CONF_DIR}"
|
|
|
|
echo "==> [5/5] Registering systemd service..."
|
|
# The unit is only registered here; prepare-caddy-cicd.sh starts it once the
|
|
# site Caddyfile and web root are in place.
|
|
cat <<'EOF' > /etc/systemd/system/caddy.service
|
|
[Unit]
|
|
Description=Caddy
|
|
Documentation=https://caddyserver.com/docs/
|
|
After=network.target network-online.target
|
|
Requires=network-online.target
|
|
|
|
[Service]
|
|
Type=notify
|
|
User=caddy
|
|
Group=caddy
|
|
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile
|
|
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
|
|
TimeoutStopSec=5s
|
|
LimitNOFILE=1048576
|
|
LimitNPROC=512
|
|
PrivateTmp=true
|
|
ProtectSystem=full
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
systemctl daemon-reload
|
|
|
|
echo "========================================================="
|
|
echo " Caddy installation finished successfully!"
|
|
echo " - Binary: ${BIN_DEST} (Capabilities: cap_net_bind_service)"
|
|
echo " - User/Group: caddy:caddy"
|
|
echo " - Config dir: ${CADDY_CONF_DIR}"
|
|
echo " - Service registered but not yet started."
|
|
echo " - Next: run prepare-caddy-cicd.sh to create the site config"
|
|
echo " and web root, then start Caddy."
|
|
echo "========================================================="
|