diff --git a/deployments/copyparty/deploy.sh b/deployments/copyparty/deploy.sh index f6372c1..4dc9a25 100644 --- a/deployments/copyparty/deploy.sh +++ b/deployments/copyparty/deploy.sh @@ -237,11 +237,32 @@ if [[ ! -f "$CONF" ]]; then log "Generating $CONF (admin account)..." install -m 0640 "$SCRIPT_DIR/copyparty.conf.example" "$CONF" sed -i "s|__ADMIN_PW__|${ADMIN_PW}|" "$CONF" - if [[ -n "$FTP_NAT" ]]; then - sed -i -E "s|^[[:space:]]*#[[:space:]]*ftp-nat:.*| ftp-nat: ${FTP_NAT}|" "$CONF" - fi else - log "$CONF exists; leaving it alone." + log "$CONF exists; keeping it." +fi + +# FTP_NAT has exactly one route to the running service: this conf file. Nothing +# in docker-compose.yml interpolates it and the copyparty service is given no +# environment, so .env's copy is a record, not the live setting. The summary at +# the end tells operators to fix passive FTPS by re-running with FTP_NAT=... -- +# so that has to apply to an EXISTING conf too, not only a freshly created one. +# Must stay above the chown further down, since `sed -i` rewrites as root. +CONF_CHANGED=0 +if [[ -n "$FTP_NAT" ]]; then + # `|| true` is load-bearing: on a still-commented conf the grep matches + # nothing, and under `set -o pipefail` that would abort this assignment. + cur_nat="$(grep -E '^[[:space:]]*ftp-nat:' "$CONF" | head -n1 | sed -E 's/^[[:space:]]*ftp-nat:[[:space:]]*//; s/[[:space:]]*#.*$//; s/[[:space:]]*$//' || true)" + if [[ "$cur_nat" == "$FTP_NAT" ]]; then + : # already applied + elif grep -qE '^[[:space:]]*#?[[:space:]]*ftp-nat:' "$CONF"; then + log "Setting 'ftp-nat: ${FTP_NAT}' in $CONF (was: ${cur_nat:-unset})." + # `#?` so an already-set value is corrected, not just the commented + # template line. + sed -i -E "s|^[[:space:]]*#?[[:space:]]*ftp-nat:.*| ftp-nat: ${FTP_NAT}|" "$CONF" + CONF_CHANGED=1 + else + warn "No ftp-nat line in $CONF to set. Add ' ftp-nat: ${FTP_NAT}' under [global] by hand." + fi fi # Read back the admin password for the summary (works on first run + re-runs). # Strip the leading 'admin:', any trailing inline #comment, and surrounding space. @@ -296,6 +317,16 @@ else log ".env exists; leaving it alone." fi +# .env's FTP_NAT is a record rather than the live setting, but let it disagree +# with the conf and the next reader cannot tell which one is deployed. +if [[ -n "$FTP_NAT" ]]; then + cur_env_nat=$(sed -n 's/^FTP_NAT=//p' "$ENV_FILE" | tail -n1) + if [[ "$cur_env_nat" != "$FTP_NAT" ]]; then + set_env FTP_NAT "$FTP_NAT" + log "Recorded FTP_NAT=${FTP_NAT} in $ENV_FILE." + fi +fi + # Validate required values landed. missing=() for var in COPYPARTY_DOMAIN ACME_EMAIL; do @@ -328,6 +359,14 @@ docker compose pull log "Starting stack..." docker compose up -d --remove-orphans +# compose does not recreate a service whose image and compose config are +# unchanged, so a conf edit on a re-run would sit on disk while the running +# process keeps the old ftp-nat. Restart it explicitly. +if [[ "$CONF_CHANGED" == "1" ]]; then + log "copyparty.conf changed; restarting copyparty to apply it..." + docker compose restart copyparty +fi + # ---------------------------------------------------------------------------- # Wait for health # ----------------------------------------------------------------------------