feat(deploy): manifest-driven config, teardown + db-perms, hardening
deploy.sh:
- never rsync into /; stage to /tmp on the remote and install at final
paths via sudo bash heredoc, closing the parent-dir attribute leak
that broke three hosts in the earlier rsync incident
- shell-quote heredoc args via ${var@Q}
- drop -A -X on the remaining (web) rsyncs
- generic worker.secrets loop reads (env-var → pass path) from manifest;
GITEA_TOKEN now flows through automatically
- in-memory bash substitution for templates (secrets never on argv)
- simplify semanage port labelling: --add 2>/dev/null || --modify (the
old grep pre-check matched only the first listed port)
- restorecon back to short flags (Fedora policycoreutils has no long
forms; --recursive errored at deploy time)
- quieter health probe loop: curl diagnostics only on final failure
manifest as source of truth:
- api.config.bind drives BIND_ADDR, firewalld port, semanage label,
health-probe URL
- web.config.{server_name,root,api_upstream} drives nginx render,
rsync targets, restorecon scope
- nginx config renamed to site.conf.tmpl; firewalld svc to
moments-api.xml.tmpl; both rendered at deploy time
- topology flip: api → nikola, worker → frootmig (anjie freed)
new scripts:
- script/teardown.sh: idempotent component teardown, never rsyncs,
shared-state cleanup gated on absence of remaining env files,
--remove-docroot guard against shallow / system paths
- script/db-perms.sh: rewritten — fixes grep/append role mismatch that
appended duplicates on re-run, adds postgres reload, hits primary +
standby in a single invocation
readme: genericized; deployment topology no longer carries real host
or site names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
63
script/db-perms.sh
Executable file
63
script/db-perms.sh
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Idempotently add cert_cn → role mappings to pg_ident.conf.d on the moments
|
||||
# postgres primary and standby, then reload postgres so the changes take
|
||||
# effect. Re-running is a no-op (no duplicate lines, no spurious reload).
|
||||
#
|
||||
# Run from a workstation with ssh access to both pg hosts. This script ssh's
|
||||
# out; do NOT run it on magrathea/frankie directly.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
api_host=nikola.kosherinata.internal
|
||||
worker_host=frootmig.kosherinata.internal
|
||||
|
||||
pg_hosts=(
|
||||
magrathea.kosherinata.internal
|
||||
frankie.kosherinata.internal
|
||||
)
|
||||
|
||||
# Each (cert_cn host, role) pair becomes one cert_cn line in
|
||||
# pg_ident.conf.d/<cert_cn host>.conf on every pg host listed above.
|
||||
mapping_pairs=(
|
||||
"$api_host" moments_ro
|
||||
"$worker_host" moments_rw
|
||||
)
|
||||
|
||||
ident_dir=/var/lib/pgsql/18/data/pg_ident.conf.d
|
||||
|
||||
for pg_host in "${pg_hosts[@]}"; do
|
||||
printf '==> %s\n' "$pg_host"
|
||||
ssh -o BatchMode=yes "$pg_host" "sudo bash -s -- ${ident_dir@Q} ${mapping_pairs[@]@Q}" <<'REMOTE_EOF'
|
||||
set -euo pipefail
|
||||
ident_dir="$1"; shift
|
||||
|
||||
changed=0
|
||||
while [[ $# -gt 0 ]]; do
|
||||
cert_cn_host="$1"
|
||||
role="$2"
|
||||
shift 2
|
||||
|
||||
line="cert_cn ${cert_cn_host} ${role}"
|
||||
file="${ident_dir}/${cert_cn_host}.conf"
|
||||
|
||||
# The heredoc runs as root via sudo bash, so [[ -f ]] and grep are fine
|
||||
# without dropping privs. tee --append runs as postgres so a newly-created
|
||||
# file lands with the conventional postgres:postgres ownership.
|
||||
if [[ -f "$file" ]] && grep --fixed-strings --line-regexp --quiet -- "$line" "$file"; then
|
||||
printf ' present: %s\n' "$line"
|
||||
else
|
||||
printf '%s\n' "$line" | sudo -u postgres tee --append "$file" >/dev/null
|
||||
printf ' added: %s\n' "$line"
|
||||
changed=1
|
||||
fi
|
||||
done
|
||||
|
||||
if (( changed )); then
|
||||
systemctl reload postgresql-18
|
||||
echo " reloaded postgresql-18"
|
||||
else
|
||||
echo " no changes; reload skipped"
|
||||
fi
|
||||
REMOTE_EOF
|
||||
done
|
||||
Reference in New Issue
Block a user