From 5a2a9e1c746aa7fd523cdf8f2fc77325937926db Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Apr 2026 16:42:30 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20infra:=20edge-control=20install.sh=20ove?= =?UTF-8?q?rwrites=20/etc/caddy/Caddyfile=20with=20no=20carve-out=20for=20?= =?UTF-8?q?apex/static=20sites=20=E2=80=94=20landing=20page=20lost=20on=20?= =?UTF-8?q?install=20(#788)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- tools/edge-control/README.md | 24 +++++++++++++++++++ tools/edge-control/install.sh | 43 +++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/tools/edge-control/README.md b/tools/edge-control/README.md index c49e78a..019b385 100644 --- a/tools/edge-control/README.md +++ b/tools/edge-control/README.md @@ -83,9 +83,12 @@ curl -sL https://raw.githubusercontent.com/disinto-admin/disinto/fix/issue-621/t - Permissions: `root:disinto-register 0750` 3. **Installs Caddy**: + - Backs up any pre-existing `/etc/caddy/Caddyfile` to `/etc/caddy/Caddyfile.pre-disinto` - Download Caddy with Gandi DNS plugin - Enable admin API on `127.0.0.1:2019` - Configure wildcard cert for `*.disinto.ai` via DNS-01 + - Creates `/etc/caddy/extra.d/` for operator-owned site blocks + - Emitted Caddyfile ends with `import /etc/caddy/extra.d/*.caddy` 4. **Sets up SSH**: - Creates `disinto-register` authorized_keys with forced command @@ -95,6 +98,27 @@ curl -sL https://raw.githubusercontent.com/disinto-admin/disinto/fix/issue-621/t - `/opt/disinto-edge/register.sh` — forced command handler - `/opt/disinto-edge/lib/*.sh` — helper libraries +## Operator-Owned Site Blocks + +Edge-control owns the top-level `/etc/caddy/Caddyfile` and dynamic `.` routes injected via the Caddy admin API. Operators own everything under `/etc/caddy/extra.d/`. + +To serve non-tunnel content (apex domain, www redirect, static sites), drop `.caddy` files into `/etc/caddy/extra.d/`: + +```bash +# Example: /etc/caddy/extra.d/landing.caddy +disinto.ai { + root * /home/debian/disinto-site + file_server +} + +# Example: /etc/caddy/extra.d/www-redirect.caddy +www.disinto.ai { + redir https://disinto.ai{uri} permanent +} +``` + +These files survive across `install.sh` re-runs. The `--extra-caddyfile ` flag overrides the default import glob (`/etc/caddy/extra.d/*.caddy`) if needed. + ## Usage ### Register a Tunnel (from dev box) diff --git a/tools/edge-control/install.sh b/tools/edge-control/install.sh index fcd33b9..9571311 100755 --- a/tools/edge-control/install.sh +++ b/tools/edge-control/install.sh @@ -43,18 +43,21 @@ INSTALL_DIR="/opt/disinto-edge" REGISTRY_DIR="/var/lib/disinto" CADDY_VERSION="2.8.4" DOMAIN_SUFFIX="disinto.ai" +EXTRA_CADDYFILE="/etc/caddy/extra.d/*.caddy" usage() { cat < Gandi API token for wildcard cert (required) - --install-dir Install directory (default: /opt/disinto-edge) - --registry-dir Registry directory (default: /var/lib/disinto) - --caddy-version Caddy version to install (default: ${CADDY_VERSION}) - --domain-suffix Domain suffix for tunnels (default: disinto.ai) - -h, --help Show this help + --gandi-token Gandi API token for wildcard cert (required) + --install-dir Install directory (default: /opt/disinto-edge) + --registry-dir Registry directory (default: /var/lib/disinto) + --caddy-version Caddy version to install (default: ${CADDY_VERSION}) + --domain-suffix Domain suffix for tunnels (default: disinto.ai) + --extra-caddyfile Import path for operator-owned Caddy config + (default: /etc/caddy/extra.d/*.caddy) + -h, --help Show this help Example: $0 --gandi-token YOUR_GANDI_API_TOKEN @@ -84,6 +87,10 @@ while [[ $# -gt 0 ]]; do DOMAIN_SUFFIX="$2" shift 2 ;; + --extra-caddyfile) + EXTRA_CADDYFILE="$2" + shift 2 + ;; -h|--help) usage ;; @@ -229,7 +236,25 @@ chmod 600 "$GANDI_ENV" # discovers the server name dynamically via _discover_server_name() so we # don't need to name the server here. CADDYFILE="/etc/caddy/Caddyfile" -cat > "$CADDYFILE" <<'CADDYEOF' + +# Back up existing Caddyfile before overwriting +if [ -f "$CADDYFILE" ] && [ ! -f "${CADDYFILE}.pre-disinto" ]; then + cp "$CADDYFILE" "${CADDYFILE}.pre-disinto" + log_info "Backed up existing Caddyfile to ${CADDYFILE}.pre-disinto" +fi + +# Create extra.d directory for operator-owned site blocks +EXTRA_DIR="/etc/caddy/extra.d" +mkdir -p "$EXTRA_DIR" +chmod 0755 "$EXTRA_DIR" +if getent group caddy >/dev/null 2>&1; then + chown root:caddy "$EXTRA_DIR" +else + log_warn "Group 'caddy' does not exist; extra.d owned by root:root" +fi +log_info "Created ${EXTRA_DIR} for operator-owned Caddy config" + +cat > "$CADDYFILE" < "$CADDYFILE" <<'CADDYEOF' dns gandi {env.GANDI_API_KEY} } } + +# Operator-owned site blocks (apex, www, static content, etc.) +import ${EXTRA_CADDYFILE} CADDYEOF # Start Caddy @@ -362,6 +390,7 @@ echo "Configuration:" echo " Install directory: ${INSTALL_DIR}" echo " Registry: ${REGISTRY_FILE}" echo " Caddy admin API: http://127.0.0.1:2019" +echo " Operator site blocks: ${EXTRA_DIR}/ (import ${EXTRA_CADDYFILE})" echo "" echo "Users:" echo " disinto-register - SSH forced command (runs ${INSTALL_DIR}/register.sh)"