feat(files): gate files. browse behind FILES_BROWSE (on|off)
Per-host toggle for the read-only, no-auth browse of the shared upload dir,
so it can stay on for the LAN-party host (oxps) and be off on the
internet-facing one (cochi). Defaults to `on` — existing hosts unchanged.
Neither layer has conditionals, so each gets the value substituted in:
- caddy: docker-compose mounts 62-files.${FILES_BROWSE:-on}.caddy at the
fixed conf.d target (62-files.caddy -> 62-files.on.caddy, plus a
comments-only 62-files.off.caddy stub — caddy needs a parseable file
there). Same trick as FILES_MOUNT_MODE.
- nginx: render-nginx.sh splices nginx/files-browse.server.tmpl into
${FILES_BROWSE_SERVER} and adds/omits the name in the port-80 redirect.
This is the gate that matters; caddy is bound to 127.0.0.1.
Applying a change needs render-nginx.sh --install plus a caddy
--force-recreate (single-file bind mount pins the inode). With `off`,
drop `files` from LE_SUBDOMAINS on that host. upload. is unaffected.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
92c6f5fc8f
commit
8507ffd020
9 files changed
+122
-33
No files matched your search
+28
-2
@@ -17,6 +17,11 @@
|
||||
# APP_DIR host path to this repo (cert files live under APP_DIR/certs)
|
||||
# — defaults to the repo root (this checkout)
|
||||
# SITE_NAME installed filename (default ulicraft.conf)
|
||||
# FILES_BROWSE on|off (default on) — emit the files.${BASE_DOMAIN}
|
||||
# read-only browse vhost. `off` omits the server block AND
|
||||
# the name from the port-80 redirect, so the host serves
|
||||
# nothing for it (no cert needed either). Same var gates the
|
||||
# caddy side in docker-compose.yml.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.." # repo root
|
||||
@@ -40,7 +45,28 @@ SITE_NAME="${SITE_NAME:-ulicraft.conf}"
|
||||
export BASE_DOMAIN APP_DIR
|
||||
export CADDY_HTTP_PORT="${CADDY_HTTP_PORT:-80}"
|
||||
|
||||
rendered="$(envsubst '$BASE_DOMAIN $APP_DIR $CADDY_HTTP_PORT' < "$TEMPLATE")"
|
||||
# files.${BASE_DOMAIN} — the no-auth read-only browse. Per-host toggle: on for
|
||||
# the LAN-party box, off where the share must not be publicly listable. nginx
|
||||
# has no conditionals, so the vhost is a separate template spliced in here (or
|
||||
# replaced by a comment). Keep in sync with the caddy mount in docker-compose.yml,
|
||||
# which reads the same var.
|
||||
: "${FILES_BROWSE:=on}"
|
||||
FILES_BROWSE_TEMPLATE="${FILES_BROWSE_TEMPLATE:-nginx/files-browse.server.tmpl}"
|
||||
case "$FILES_BROWSE" in
|
||||
on)
|
||||
[ -f "$FILES_BROWSE_TEMPLATE" ] || die "template not found: $FILES_BROWSE_TEMPLATE"
|
||||
FILES_BROWSE_NAME=" files.${BASE_DOMAIN}"
|
||||
FILES_BROWSE_SERVER="$(envsubst '$BASE_DOMAIN $APP_DIR' < "$FILES_BROWSE_TEMPLATE")"
|
||||
;;
|
||||
off)
|
||||
FILES_BROWSE_NAME=""
|
||||
FILES_BROWSE_SERVER="# files.${BASE_DOMAIN} disabled on this host (FILES_BROWSE=off in .env)."
|
||||
;;
|
||||
*) die "FILES_BROWSE must be 'on' or 'off' (got '$FILES_BROWSE')" ;;
|
||||
esac
|
||||
export FILES_BROWSE_NAME FILES_BROWSE_SERVER
|
||||
|
||||
rendered="$(envsubst '$BASE_DOMAIN $APP_DIR $CADDY_HTTP_PORT $FILES_BROWSE_NAME $FILES_BROWSE_SERVER' < "$TEMPLATE")"
|
||||
|
||||
if [ "${1:-}" != "--install" ]; then
|
||||
printf '%s\n' "$rendered"
|
||||
@@ -52,7 +78,7 @@ command -v nginx >/dev/null 2>&1 || die "nginx not found on PATH"
|
||||
avail="/etc/nginx/sites-available/$SITE_NAME"
|
||||
enabled="/etc/nginx/sites-enabled/$SITE_NAME"
|
||||
|
||||
log "installing $TEMPLATE -> $avail (APP_DIR=$APP_DIR, CADDY_HTTP_PORT=$CADDY_HTTP_PORT)"
|
||||
log "installing $TEMPLATE -> $avail (APP_DIR=$APP_DIR, CADDY_HTTP_PORT=$CADDY_HTTP_PORT, FILES_BROWSE=$FILES_BROWSE)"
|
||||
printf '%s\n' "$rendered" | sudo tee "$avail" >/dev/null
|
||||
sudo ln -sf "$avail" "$enabled"
|
||||
sudo nginx -t
|
||||
|
||||
Reference in new issue
Block a user