refactor(caddy): modularise deployment init
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)
This commit is contained in:
4 files changed
+182
-83
No files matched your search
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# AWS CLI Installation for Debian/Ubuntu
|
||||||
|
# Installs the AWS CLI v2 via the official installer bundle when it is not
|
||||||
|
# already available on the system. Required by install-caddy.sh for
|
||||||
|
# downloading the Caddy binary from S3-compatible storage.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
if command -v aws >/dev/null 2>&1; then
|
||||||
|
echo "==> aws-cli already installed at '$(command -v aws)'. Nothing to do."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> aws-cli not found, installing via official bundle..."
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "${TMP_DIR}"' EXIT
|
||||||
|
|
||||||
|
curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "${TMP_DIR}/awscliv2.zip"
|
||||||
|
unzip -q "${TMP_DIR}/awscliv2.zip" -d "${TMP_DIR}"
|
||||||
|
"${TMP_DIR}/aws/install"
|
||||||
|
|
||||||
|
echo "========================================================="
|
||||||
|
echo " aws-cli installed successfully: $(command -v aws)"
|
||||||
|
echo "========================================================="
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Base Dependencies Installation for Debian/Ubuntu
|
||||||
|
# Installs the packages required by the other server initialisation scripts.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 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 "==> Updating package index..."
|
||||||
|
apt-get update -qq
|
||||||
|
|
||||||
|
echo "==> Installing base dependencies (acl, libcap2-bin, rsync, curl, unzip)..."
|
||||||
|
apt-get install -y acl libcap2-bin rsync curl unzip
|
||||||
|
|
||||||
|
echo "========================================================="
|
||||||
|
echo " Base dependencies installed successfully!"
|
||||||
|
echo "========================================================="
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# Caddy & Bot Deployment Environment Initialisation Script for Debian
|
# Caddy Installation for Debian/Ubuntu
|
||||||
# Supports automatic binary download from S3-compatible storage.
|
# 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
|
set -euo pipefail
|
||||||
|
|
||||||
# S3 and Binary Environment Variables (with fallback defaults)
|
# S3 and binary environment variables (with fallback defaults)
|
||||||
S3_ENDPOINT="${S3_ENDPOINT:-}"
|
S3_ENDPOINT="${S3_ENDPOINT:-}"
|
||||||
S3_BUCKET="${S3_BUCKET:-}"
|
S3_BUCKET="${S3_BUCKET:-}"
|
||||||
S3_REGION="${S3_REGION:-us-east-1}"
|
S3_REGION="${S3_REGION:-us-east-1}"
|
||||||
@@ -16,7 +20,6 @@ BIN_URI="${BIN_URI:-caddy-custom-linux-amd64}"
|
|||||||
|
|
||||||
BIN_SOURCE="./${BIN_URI}"
|
BIN_SOURCE="./${BIN_URI}"
|
||||||
BIN_DEST="/usr/local/bin/caddy"
|
BIN_DEST="/usr/local/bin/caddy"
|
||||||
WWW_ROOT="/var/www"
|
|
||||||
CADDY_CONF_DIR="/etc/caddy"
|
CADDY_CONF_DIR="/etc/caddy"
|
||||||
CADDY_DATA_DIR="/var/lib/caddy"
|
CADDY_DATA_DIR="/var/lib/caddy"
|
||||||
|
|
||||||
@@ -26,21 +29,7 @@ if [ "$(id -u)" -ne 0 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "==> [1/8] Installing base dependencies..."
|
echo "==> [1/5] Resolving Caddy binary..."
|
||||||
apt-get update -qq
|
|
||||||
apt-get install -y acl libcap2-bin rsync curl unzip
|
|
||||||
|
|
||||||
echo "==> [2/8] Ensuring aws-cli is installed..."
|
|
||||||
if ! command -v aws >/dev/null 2>&1; then
|
|
||||||
echo "aws-cli not found, installing via official bundle..."
|
|
||||||
TMP_DIR=$(mktemp -d)
|
|
||||||
curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "${TMP_DIR}/awscliv2.zip"
|
|
||||||
unzip -q "${TMP_DIR}/awscliv2.zip" -d "${TMP_DIR}"
|
|
||||||
"${TMP_DIR}/aws/install"
|
|
||||||
rm -rf "${TMP_DIR}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "==> [3/8] Resolving Caddy binary..."
|
|
||||||
if [ ! -f "${BIN_SOURCE}" ]; then
|
if [ ! -f "${BIN_SOURCE}" ]; then
|
||||||
if [ -n "${S3_BUCKET}" ]; then
|
if [ -n "${S3_BUCKET}" ]; then
|
||||||
echo "Local binary '${BIN_SOURCE}' not found. Downloading from S3 bucket '${S3_BUCKET}'..."
|
echo "Local binary '${BIN_SOURCE}' not found. Downloading from S3 bucket '${S3_BUCKET}'..."
|
||||||
@@ -65,7 +54,7 @@ else
|
|||||||
echo "Found local binary at '${BIN_SOURCE}', skipping S3 download."
|
echo "Found local binary at '${BIN_SOURCE}', skipping S3 download."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "==> [4/8] Creating system users and groups..."
|
echo "==> [2/5] Creating caddy system user and group..."
|
||||||
# Create caddy system user and group (no login shell, dedicated home)
|
# Create caddy system user and group (no login shell, dedicated home)
|
||||||
if ! getent group caddy >/dev/null 2>&1; then
|
if ! getent group caddy >/dev/null 2>&1; then
|
||||||
groupadd --system caddy
|
groupadd --system caddy
|
||||||
@@ -81,72 +70,20 @@ if ! id -u caddy >/dev/null 2>&1; then
|
|||||||
caddy
|
caddy
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create deployment user 'bot'
|
echo "==> [3/5] Installing Caddy binary and granting capabilities..."
|
||||||
if ! id -u bot >/dev/null 2>&1; then
|
|
||||||
useradd -m -s /bin/bash bot
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Configure SSH directory for bot
|
|
||||||
install -d -m 700 -o bot -g bot /home/bot/.ssh
|
|
||||||
touch /home/bot/.ssh/authorized_keys
|
|
||||||
chown bot:bot /home/bot/.ssh/authorized_keys
|
|
||||||
chmod 600 /home/bot/.ssh/authorized_keys
|
|
||||||
|
|
||||||
echo "==> [5/8] Installing Caddy binary and granting capabilities..."
|
|
||||||
install -m 750 -o root -g caddy "${BIN_SOURCE}" "${BIN_DEST}"
|
install -m 750 -o root -g caddy "${BIN_SOURCE}" "${BIN_DEST}"
|
||||||
|
|
||||||
# Grant capability to bind to privileged ports (<1024) without running as root
|
# Grant capability to bind to privileged ports (<1024) without running as root
|
||||||
setcap 'cap_net_bind_service=+ep' "${BIN_DEST}"
|
setcap 'cap_net_bind_service=+ep' "${BIN_DEST}"
|
||||||
|
|
||||||
echo "==> [6/8] Setting up web root directory permissions (${WWW_ROOT})..."
|
echo "==> [4/5] Preparing config directory (${CADDY_CONF_DIR})..."
|
||||||
mkdir -p "${WWW_ROOT}"
|
|
||||||
|
|
||||||
# Set base ownership: bot (deployment) and caddy (web server group)
|
|
||||||
chown -R bot:caddy "${WWW_ROOT}"
|
|
||||||
|
|
||||||
# Directory base permissions (SGID ensures newly created items inherit group 'caddy')
|
|
||||||
find "${WWW_ROOT}" -type d -exec chmod 2755 {} +
|
|
||||||
find "${WWW_ROOT}" -type f -exec chmod 644 {} +
|
|
||||||
|
|
||||||
# Apply POSIX ACLs: bot has rwx, caddy has read/execute, with default inheritance
|
|
||||||
setfacl -R -m u:bot:rwx,u:caddy:rX "${WWW_ROOT}"
|
|
||||||
setfacl -R -d -m u:bot:rwx,u:caddy:rX "${WWW_ROOT}"
|
|
||||||
|
|
||||||
echo "==> [7/8] Creating Caddy configuration and sample site..."
|
|
||||||
mkdir -p "${CADDY_CONF_DIR}"
|
mkdir -p "${CADDY_CONF_DIR}"
|
||||||
chown root:caddy "${CADDY_CONF_DIR}"
|
chown root:caddy "${CADDY_CONF_DIR}"
|
||||||
chmod 755 "${CADDY_CONF_DIR}"
|
chmod 755 "${CADDY_CONF_DIR}"
|
||||||
|
|
||||||
if [ ! -f "${CADDY_CONF_DIR}/Caddyfile" ]; then
|
echo "==> [5/5] Registering systemd service..."
|
||||||
cat <<'EOF' > "${CADDY_CONF_DIR}/Caddyfile"
|
# The unit is only registered here; prepare-caddy-cicd.sh starts it once the
|
||||||
:80 {
|
# site Caddyfile and web root are in place.
|
||||||
root * /var/www
|
|
||||||
file_server
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
chown root:caddy "${CADDY_CONF_DIR}/Caddyfile"
|
|
||||||
chmod 644 "${CADDY_CONF_DIR}/Caddyfile"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "${WWW_ROOT}/index.html" ]; then
|
|
||||||
cat <<'EOF' > "${WWW_ROOT}/index.html"
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Caddy Ready</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Caddy server is running</h1>
|
|
||||||
<p>Static files root: <code>/var/www</code></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
EOF
|
|
||||||
chown bot:caddy "${WWW_ROOT}/index.html"
|
|
||||||
chmod 644 "${WWW_ROOT}/index.html"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "==> [8/8] Configuring systemd service and starting Caddy..."
|
|
||||||
cat <<'EOF' > /etc/systemd/system/caddy.service
|
cat <<'EOF' > /etc/systemd/system/caddy.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Caddy
|
Description=Caddy
|
||||||
@@ -173,12 +110,13 @@ WantedBy=multi-user.target
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now caddy
|
|
||||||
|
|
||||||
echo "========================================================="
|
echo "========================================================="
|
||||||
echo " Initialisation finished successfully!"
|
echo " Caddy installation finished successfully!"
|
||||||
echo " - Binary: ${BIN_DEST} (Capabilities: cap_net_bind_service)"
|
echo " - Binary: ${BIN_DEST} (Capabilities: cap_net_bind_service)"
|
||||||
echo " - Web Root: ${WWW_ROOT} (Managed by: bot, Read by: caddy)"
|
echo " - User/Group: caddy:caddy"
|
||||||
echo " - Config: ${CADDY_CONF_DIR}/Caddyfile"
|
echo " - Config dir: ${CADDY_CONF_DIR}"
|
||||||
echo " - Status: $(systemctl is-active caddy)"
|
echo " - Service registered but not yet started."
|
||||||
echo "========================================================="
|
echo " - Next: run prepare-caddy-cicd.sh to create the site config"
|
||||||
|
echo " and web root, then start Caddy."
|
||||||
|
echo "========================================================="
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Caddy CI/CD Serving Preparation for Debian/Ubuntu
|
||||||
|
# Prepares the server so a CI/CD pipeline can publish content that Caddy
|
||||||
|
# serves: creates the deployment user 'bot' with its SSH access, creates and
|
||||||
|
# hands over the web root to bot:caddy with ACLs that keep it readable by the
|
||||||
|
# Caddy server, writes the default site Caddyfile and sample page, then starts
|
||||||
|
# the Caddy service. The web root defaults to /var/www and can be overridden
|
||||||
|
# by exporting the WEB_ROOT environment variable before running.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Web root served by Caddy; override by exporting WEB_ROOT before running
|
||||||
|
WEB_ROOT="${WEB_ROOT:-/var/www}"
|
||||||
|
CADDY_CONF_DIR="/etc/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
|
||||||
|
|
||||||
|
if [ ! -f /etc/systemd/system/caddy.service ]; then
|
||||||
|
echo "Error: caddy.service not found. Run install-caddy.sh first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! getent group caddy >/dev/null 2>&1; then
|
||||||
|
echo "Error: group 'caddy' does not exist. Run install-caddy.sh first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> [1/5] Creating deployment user 'bot'..."
|
||||||
|
# Create deployment user 'bot'
|
||||||
|
if ! id -u bot >/dev/null 2>&1; then
|
||||||
|
useradd -m -s /bin/bash bot
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> [2/5] Configuring SSH directory for bot..."
|
||||||
|
# Configure SSH directory for bot
|
||||||
|
install -d -m 700 -o bot -g bot /home/bot/.ssh
|
||||||
|
touch /home/bot/.ssh/authorized_keys
|
||||||
|
chown bot:bot /home/bot/.ssh/authorized_keys
|
||||||
|
chmod 600 /home/bot/.ssh/authorized_keys
|
||||||
|
|
||||||
|
echo "==> [3/5] Creating web root and handing it to bot (${WEB_ROOT})..."
|
||||||
|
if [ ! -d "${WEB_ROOT}" ]; then
|
||||||
|
mkdir -p "${WEB_ROOT}"
|
||||||
|
|
||||||
|
cat <<EOF > "${WEB_ROOT}/index.html"
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Caddy Ready</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Caddy server is running</h1>
|
||||||
|
<p>Static files root: <code>${WEB_ROOT}</code></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
echo " '${WEB_ROOT}' already exists - leaving existing content untouched."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set base ownership: bot (deployment) and caddy (web server group)
|
||||||
|
chown -R bot:caddy "${WEB_ROOT}"
|
||||||
|
|
||||||
|
# Directory base permissions (SGID ensures newly created items inherit group 'caddy')
|
||||||
|
find "${WEB_ROOT}" -type d -exec chmod 2755 {} +
|
||||||
|
find "${WEB_ROOT}" -type f -exec chmod 644 {} +
|
||||||
|
|
||||||
|
# Apply POSIX ACLs: bot has rwx, caddy has read/execute, with default inheritance
|
||||||
|
setfacl -R -m u:bot:rwx,u:caddy:rX "${WEB_ROOT}"
|
||||||
|
setfacl -R -d -m u:bot:rwx,u:caddy:rX "${WEB_ROOT}"
|
||||||
|
|
||||||
|
echo "==> [4/5] Writing site Caddyfile (${CADDY_CONF_DIR}/Caddyfile)..."
|
||||||
|
mkdir -p "${CADDY_CONF_DIR}"
|
||||||
|
chown root:caddy "${CADDY_CONF_DIR}"
|
||||||
|
chmod 755 "${CADDY_CONF_DIR}"
|
||||||
|
|
||||||
|
if [ ! -f "${CADDY_CONF_DIR}/Caddyfile" ]; then
|
||||||
|
cat <<EOF > "${CADDY_CONF_DIR}/Caddyfile"
|
||||||
|
:80 {
|
||||||
|
root * ${WEB_ROOT}
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
chown root:caddy "${CADDY_CONF_DIR}/Caddyfile"
|
||||||
|
chmod 644 "${CADDY_CONF_DIR}/Caddyfile"
|
||||||
|
else
|
||||||
|
echo " '${CADDY_CONF_DIR}/Caddyfile' already exists - leaving it untouched."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> [5/5] Starting Caddy service..."
|
||||||
|
systemctl enable --now caddy
|
||||||
|
|
||||||
|
echo "========================================================="
|
||||||
|
echo " Caddy CI/CD preparation finished successfully!"
|
||||||
|
echo " - Deployment user: bot (SSH keys accepted in authorized_keys)"
|
||||||
|
echo " - Web Root: ${WEB_ROOT} (owned by bot:caddy, readable by caddy)"
|
||||||
|
echo " - Config: ${CADDY_CONF_DIR}/Caddyfile"
|
||||||
|
echo " - Status: $(systemctl is-active caddy)"
|
||||||
|
echo "========================================================="
|
||||||
Reference in new issue
Block a user