feat: inject .env into container; install subdomain for docker too

This commit is contained in:
root 2026-07-17 12:26:47 +00:00
parent 452ae5b898
commit d39974c0cc

View file

@ -195,31 +195,6 @@ runs:
write_fragment "$(printf '%s {\n\timport accesslog\n\troot * /srv/sites/%s\n\tfile_server\n\ttry_files {path} /index.html\n}\n' "$SITE_ADDR" "$DOMAIN")" write_fragment "$(printf '%s {\n\timport accesslog\n\troot * /srv/sites/%s\n\tfile_server\n\ttry_files {path} /index.html\n}\n' "$SITE_ADDR" "$DOMAIN")"
# ---- optional install-script subdomain: curl get.<domain> | sh ----
# Opt-in via .env INSTALL_SH=<file in build output> (e.g. install.sh).
# Serves that one file as text/plain at get.<domain> (self-managed
# fragment ${SLUG}-get.caddy, separate from the main one). Unset the var
# → the subdomain is removed on the next deploy. Dev must add the DNS
# A-record get.<domain> → our IP themselves.
GFRAG="/srv/platform/caddy/sites/${SLUG}-get.caddy"
if [ -n "${INSTALL_SH:-}" ]; then
GDOM="get.${DOMAIN}"
[ -f "/srv/sites/${DOMAIN}/${INSTALL_SH}" ] \
|| echo "::warning::${INSTALL_SH} not in build output — ${GDOM} will 404 until you add public/${INSTALL_SH}"
dig +short A "$GDOM" 2>/dev/null | grep -q "$OUR_IP" \
|| echo "::warning::no A record ${GDOM} → ${OUR_IP} yet — add it; TLS issues once it resolves"
GNEW=$(printf '%s {\n\troot * /srv/sites/%s\n\trewrite * /%s\n\theader Content-Type text/plain\n\tfile_server\n}\n' "$GDOM" "$DOMAIN" "$INSTALL_SH")
if [ ! -f "$GFRAG" ] || [ "$(cat "$GFRAG")" != "$GNEW" ]; then
printf '%s' "$GNEW" > "$GFRAG"
reload_caddy && echo " install subdomain → https://${GDOM} (serves /${INSTALL_SH})" \
|| { echo "::error::caddy reload failed for $GFRAG"; rm -f "$GFRAG"; reload_caddy || true; }
else
echo " install subdomain fragment unchanged"
fi
elif [ -f "$GFRAG" ]; then
rm -f "$GFRAG"; reload_caddy || true; echo " install subdomain removed (INSTALL_SH unset)"
fi
# Remove any prior container LAST — zero-downtime: a pre-existing # Remove any prior container LAST — zero-downtime: a pre-existing
# container kept serving the domain (via its old fragment) all through # container kept serving the domain (via its old fragment) all through
# the build above, until the file_server fragment took over just now. # the build above, until the file_server fragment took over just now.
@ -241,16 +216,26 @@ runs:
echo "::endgroup::" echo "::endgroup::"
echo "::group::run container" echo "::group::run container"
# runtime secrets: only keys listed in .env RUNTIME_KEYS, pulled from secrets_json # Everything in .env (except platform-control keys) is passed straight into
# the container as env vars — the dev keeps config in .env and just pushes,
# nothing to set up by hand. Forgejo Actions secrets via RUNTIME_KEYS still
# work and are layered on top (and override .env on name clash).
RTENV="/tmp/runtime.env"; : > "$RTENV" RTENV="/tmp/runtime.env"; : > "$RTENV"
CTRL=" DOMAIN DEPLOY BUILD_DIR APP_PORT WWW EXTRA_DOMAINS TWITTER TWITTER_URL X INSTALL_SH RUNTIME_KEYS ENABLED "
while IFS='=' read -r k v; do
[ -z "$k" ] && continue
case "$CTRL" in *" $k "*) continue ;; esac
printf '%s=%s\n' "$k" "$v" >> "$RTENV"
done < /tmp/envp
RK="${RUNTIME_KEYS:-}" RK="${RUNTIME_KEYS:-}"
OLDIFS=$IFS; IFS=', ' OLDIFS=$IFS; IFS=', '
for key in $RK; do for key in $RK; do
[ -z "$key" ] && continue [ -z "$key" ] && continue
val=$(printf '%s' "$SJSON" | jq -r --arg k "$key" '.[$k] // empty') val=$(printf '%s' "$SJSON" | jq -r --arg k "$key" '.[$k] // empty')
if [ -n "$val" ]; then printf '%s=%s\n' "$key" "$val" >> "$RTENV"; echo " + runtime env: $key"; fi if [ -n "$val" ]; then printf '%s=%s\n' "$key" "$val" >> "$RTENV"; echo " + secret from Forgejo: $key"; fi
done done
IFS=$OLDIFS IFS=$OLDIFS
echo " + $(grep -c . "$RTENV" || echo 0) env vars into container (from .env)"
set -- --name "$SLUG" --network sites --restart unless-stopped --env-file "$RTENV" \ set -- --name "$SLUG" --network sites --restart unless-stopped --env-file "$RTENV" \
--label "platform.project=${REPO}" --label "platform.slug=${SLUG}" --label "platform.domain=${DOMAIN}" --label "platform.project=${REPO}" --label "platform.slug=${SLUG}" --label "platform.domain=${DOMAIN}"
if [ "$DT" = "docker-db" ]; then if [ "$DT" = "docker-db" ]; then
@ -270,4 +255,34 @@ runs:
echo "::error::unknown DEPLOY=$DT (use static | docker | docker-db)"; exit 1 ;; echo "::error::unknown DEPLOY=$DT (use static | docker | docker-db)"; exit 1 ;;
esac esac
# ---- install subdomain (curl get.<domain> | sh) — static OR docker ----
# Opt in via .env INSTALL_SH=<file> (looked up in the repo at root or public/).
# The file is copied to a tiny dir and served as text/plain at get.<domain>,
# regardless of deploy type. Unset INSTALL_SH → the subdomain is removed.
# Dev adds the DNS A-record get.<domain> → our IP themselves.
GFRAG="/srv/platform/caddy/sites/${SLUG}-get.caddy"
GDIR="/srv/sites/.get-${SLUG}"
if [ -n "${INSTALL_SH:-}" ]; then
GDOM="get.${DOMAIN}"; GFILE=$(basename "$INSTALL_SH")
SRC=""
for cand in "/tmp/repo/${INSTALL_SH}" "/tmp/repo/public/${INSTALL_SH}"; do
[ -f "$cand" ] && { SRC="$cand"; break; }
done
rm -rf "$GDIR"; mkdir -p "$GDIR"
if [ -n "$SRC" ]; then cp "$SRC" "$GDIR/$GFILE"
else echo "::warning::${INSTALL_SH} not found in repo (root or public/) — ${GDOM} will 404"; fi
dig +short A "$GDOM" 2>/dev/null | grep -q "$OUR_IP" \
|| echo "::warning::no A record ${GDOM} → ${OUR_IP} yet — add it; TLS issues once it resolves"
GNEW=$(printf '%s {\n\troot * %s\n\trewrite * /%s\n\theader Content-Type text/plain\n\tfile_server\n}\n' "$GDOM" "$GDIR" "$GFILE")
if [ ! -f "$GFRAG" ] || [ "$(cat "$GFRAG")" != "$GNEW" ]; then
printf '%s' "$GNEW" > "$GFRAG"
reload_caddy && echo " install subdomain → https://${GDOM}" \
|| { echo "::error::caddy reload failed for $GFRAG"; rm -f "$GFRAG"; reload_caddy || true; }
else
echo " install subdomain fragment unchanged"
fi
elif [ -f "$GFRAG" ]; then
rm -f "$GFRAG"; rm -rf "$GDIR"; reload_caddy || true; echo " install subdomain removed (INSTALL_SH unset)"
fi
echo "✅ deployed https://${DOMAIN}${ALT:+ + https://$ALT}" echo "✅ deployed https://${DOMAIN}${ALT:+ + https://$ALT}"