ops: paivana and caddy config refresh
This commit is contained in:
parent
d8dbc6242b
commit
56f814a6de
74 changed files with 4517 additions and 79 deletions
40
scripts/notes/README.md
Normal file
40
scripts/notes/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# SilverBullet — scripts (koopa)
|
||||
|
||||
Product **FreeNotes** is separate (native enc). These scripts operate the parked **SilverBullet** web stack on port **9028**.
|
||||
|
||||
| Script | Role |
|
||||
|--------|------|
|
||||
| `status.sh` | Read-only dirs / containers / `:9028` |
|
||||
| `build.sh` | `podman build` → `localhost/koopa-silverbullet:cachyos` |
|
||||
| `up.sh` | `podman-compose up` in `~/koopa-silverbullet` + health |
|
||||
| `cutover-to-silverbullet.sh` | Live freenotes → silverbullet (default **dry-run**; `--apply` mutates) |
|
||||
| `prepare-basicauth-seed.sh` | SoT → `/tmp/silverbullet-basicauth-seed.txt` (no sudo) |
|
||||
|
||||
Caddy (sudo, separate): `scripts/caddy/merge-notes-site.sh`, `apply-notes-basicauth.sh`.
|
||||
|
||||
## Cutover order (needs Freigabe + DNS)
|
||||
|
||||
On koopa as `hernani` (admin-log clone from Forgejo when needed):
|
||||
|
||||
```bash
|
||||
bash …/scripts/notes/status.sh
|
||||
bash …/scripts/notes/cutover-to-silverbullet.sh # dry-run
|
||||
bash …/scripts/notes/cutover-to-silverbullet.sh --apply # Freigabe
|
||||
```
|
||||
|
||||
Then Caddy (root) + seed from laptop SoT:
|
||||
|
||||
```bash
|
||||
# laptop (unlocked secrets-enc):
|
||||
bash …/scripts/notes/prepare-basicauth-seed.sh
|
||||
scp /tmp/silverbullet-basicauth-seed.txt hernani@koopa:/tmp/
|
||||
|
||||
# koopa root:
|
||||
sudo bash …/scripts/caddy/merge-notes-site.sh
|
||||
sudo NOTES_AUTH_SEED=/tmp/silverbullet-basicauth-seed.txt \
|
||||
bash …/scripts/caddy/apply-notes-basicauth.sh
|
||||
```
|
||||
|
||||
DNS: `silverbullet.hacktivism.ch` → koopa (human). Public: `https://silverbullet.hacktivism.ch/`.
|
||||
|
||||
Keeps on cutover: `space/`, `.env`. Refreshes compose/Containerfile/entrypoint/unit from `configs/notes/`.
|
||||
23
scripts/notes/build.sh
Executable file
23
scripts/notes/build.sh
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
# Build SilverBullet image on CachyOS base (run on koopa).
|
||||
# bash ~/koopa-admin-log/scripts/notes/build.sh
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
CTX="${ROOT}/configs/notes"
|
||||
TAG="${IMAGE_TAG:-localhost/koopa-silverbullet:cachyos}"
|
||||
SB_VERSION="${SB_VERSION:-2.10.0}"
|
||||
|
||||
cd "$CTX"
|
||||
[[ -f Containerfile ]] || { echo "ERROR: missing $CTX/Containerfile" >&2; exit 1; }
|
||||
[[ -f entrypoint.sh ]] || { echo "ERROR: missing $CTX/entrypoint.sh" >&2; exit 1; }
|
||||
|
||||
echo "build $TAG (SB_VERSION=$SB_VERSION) ctx=$CTX"
|
||||
podman build \
|
||||
--build-arg "SB_VERSION=${SB_VERSION}" \
|
||||
-t "$TAG" \
|
||||
-f Containerfile \
|
||||
.
|
||||
|
||||
echo "OK: $TAG"
|
||||
podman image inspect "$TAG" --format '{{.Id}} {{.Size}} {{.Architecture}}' 2>/dev/null || true
|
||||
162
scripts/notes/cutover-to-silverbullet.sh
Executable file
162
scripts/notes/cutover-to-silverbullet.sh
Executable file
|
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/env bash
|
||||
# Cut over live stack freenotes → silverbullet on koopa (hernani).
|
||||
# Default: dry-run. Mutate only with --apply.
|
||||
#
|
||||
# bash /path/to/koopa-admin-log/scripts/notes/cutover-to-silverbullet.sh
|
||||
# bash /path/to/koopa-admin-log/scripts/notes/cutover-to-silverbullet.sh --apply
|
||||
#
|
||||
# Keeps: space/, .env. Refreshes: compose.yml, Containerfile, entrypoint.sh, systemd unit.
|
||||
# Image: retag localhost/koopa-freenotes:cachyos → localhost/koopa-silverbullet:cachyos (no rebuild).
|
||||
# Does NOT touch Caddy (sudo) — print next steps only.
|
||||
set -euo pipefail
|
||||
|
||||
APPLY=0
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
--apply) APPLY=1 ;;
|
||||
-h|--help)
|
||||
sed -n '2,12p' "$0"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown arg: $a (use --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
OLD_DIR="${HOME}/koopa-freenotes"
|
||||
NEW_DIR="${HOME}/koopa-silverbullet"
|
||||
OLD_CT=koopa-freenotes
|
||||
NEW_CT=koopa-silverbullet
|
||||
OLD_IMG=localhost/koopa-freenotes:cachyos
|
||||
NEW_IMG=localhost/koopa-silverbullet:cachyos
|
||||
PORT=9028
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
CFG="${ROOT}/configs/notes"
|
||||
|
||||
[[ -d "$CFG" ]] || { echo "ERROR: missing $CFG" >&2; exit 1; }
|
||||
[[ -f "$CFG/compose.yml" ]] || { echo "ERROR: missing $CFG/compose.yml" >&2; exit 1; }
|
||||
|
||||
mode=dry-run
|
||||
[[ "$APPLY" -eq 1 ]] && mode=apply
|
||||
echo "STATUS=start MODE=$mode HOST=$(hostname -s) OLD_DIR=$OLD_DIR NEW_DIR=$NEW_DIR"
|
||||
|
||||
have_old=0
|
||||
have_new=0
|
||||
[[ -d "$OLD_DIR" ]] && have_old=1
|
||||
[[ -d "$NEW_DIR" ]] && have_new=1
|
||||
echo "STATUS=dirs OLD=$have_old NEW=$have_new"
|
||||
|
||||
ct_old=$(podman ps -a --format '{{.Names}}' 2>/dev/null | grep -Fx "$OLD_CT" || true)
|
||||
ct_new=$(podman ps -a --format '{{.Names}}' 2>/dev/null | grep -Fx "$NEW_CT" || true)
|
||||
echo "STATUS=containers OLD=${ct_old:-none} NEW=${ct_new:-none}"
|
||||
|
||||
img_old=$(podman images -q "$OLD_IMG" 2>/dev/null || true)
|
||||
img_new=$(podman images -q "$NEW_IMG" 2>/dev/null || true)
|
||||
echo "STATUS=images OLD=${img_old:-none} NEW=${img_new:-none}"
|
||||
|
||||
dir_err=0
|
||||
if [[ "$have_old" -eq 0 && "$have_new" -eq 1 ]]; then
|
||||
echo "STATUS=already_cutover DIR=$NEW_DIR"
|
||||
elif [[ "$have_old" -eq 0 && "$have_new" -eq 0 ]]; then
|
||||
echo "STATUS=warn neither $OLD_DIR nor $NEW_DIR (ok for laptop dry-run; apply needs koopa)"
|
||||
dir_err=1
|
||||
elif [[ "$have_old" -eq 1 && "$have_new" -eq 1 ]]; then
|
||||
echo "STATUS=warn both dirs exist — resolve manually before --apply"
|
||||
dir_err=1
|
||||
fi
|
||||
|
||||
plan() { echo "PLAN: $*"; }
|
||||
|
||||
plan "stop+rm container $OLD_CT (if present)"
|
||||
plan "mv $OLD_DIR → $NEW_DIR (if old present)"
|
||||
plan "copy compose/Containerfile/entrypoint/unit from $CFG (keep space .env)"
|
||||
plan "podman tag $OLD_IMG $NEW_IMG (if new image missing)"
|
||||
plan "podman-compose up -d in $NEW_DIR"
|
||||
plan "health curl :$PORT"
|
||||
plan "optional: systemctl --user enable container-koopa-silverbullet.service"
|
||||
|
||||
if [[ "$APPLY" -ne 1 ]]; then
|
||||
echo "STATUS=dry-run NEXT=re-run on koopa with --apply (Freigabe)"
|
||||
echo "STATUS=caddy_next sudo bash $ROOT/scripts/caddy/merge-notes-site.sh"
|
||||
echo "STATUS=caddy_next sudo NOTES_AUTH_SEED=/tmp/silverbullet-basicauth-seed.txt bash $ROOT/scripts/caddy/apply-notes-basicauth.sh"
|
||||
echo "STATUS=dns_need silverbullet.hacktivism.ch → koopa"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$dir_err" -eq 1 ]]; then
|
||||
echo "ERROR: refuse --apply with ambiguous/missing live dirs" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$ct_old" ]]; then
|
||||
echo "STATUS=stop $OLD_CT"
|
||||
podman stop -t 20 "$OLD_CT" || true
|
||||
podman rm "$OLD_CT" || true
|
||||
fi
|
||||
|
||||
if [[ "$have_old" -eq 1 ]]; then
|
||||
echo "STATUS=mv $OLD_DIR → $NEW_DIR"
|
||||
mv "$OLD_DIR" "$NEW_DIR"
|
||||
fi
|
||||
|
||||
cd "$NEW_DIR"
|
||||
# Refresh stack files from admin-log; never overwrite space/ or .env
|
||||
cp -a "$CFG/compose.yml" "$NEW_DIR/compose.yml"
|
||||
cp -a "$CFG/Containerfile" "$NEW_DIR/Containerfile"
|
||||
cp -a "$CFG/entrypoint.sh" "$NEW_DIR/entrypoint.sh"
|
||||
chmod +x "$NEW_DIR/entrypoint.sh"
|
||||
cp -a "$CFG/container-koopa-silverbullet.service" "$NEW_DIR/container-koopa-silverbullet.service"
|
||||
cp -a "$CFG/.env.example" "$NEW_DIR/.env.example"
|
||||
# Drop obsolete unit name if present
|
||||
rm -f "$NEW_DIR/container-koopa-freenotes.service"
|
||||
echo "STATUS=refreshed_stack_files DIR=$NEW_DIR"
|
||||
|
||||
if [[ -z "$img_new" ]]; then
|
||||
if [[ -n "$img_old" ]]; then
|
||||
echo "STATUS=tag $OLD_IMG → $NEW_IMG"
|
||||
podman tag "$OLD_IMG" "$NEW_IMG"
|
||||
else
|
||||
echo "STATUS=build missing image via build.sh"
|
||||
bash "$ROOT/scripts/notes/build.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$ct_new" ]]; then
|
||||
echo "STATUS=rm stale $NEW_CT"
|
||||
podman stop -t 10 "$NEW_CT" || true
|
||||
podman rm "$NEW_CT" || true
|
||||
fi
|
||||
|
||||
echo "STATUS=compose_up"
|
||||
podman-compose up -d
|
||||
|
||||
ok=0
|
||||
for i in $(seq 1 40); do
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 "http://127.0.0.1:${PORT}/" || true)
|
||||
echo "STATUS=health try=$i code=$code"
|
||||
case "$code" in
|
||||
2*|3*) ok=1; break ;;
|
||||
esac
|
||||
sleep 3
|
||||
done
|
||||
[[ "$ok" -eq 1 ]] || { echo "ERROR: no answer on :${PORT}" >&2; podman-compose ps; exit 1; }
|
||||
|
||||
# User systemd unit (optional; ignore failures)
|
||||
UNIT_SRC="$NEW_DIR/container-koopa-silverbullet.service"
|
||||
UNIT_DST="${HOME}/.config/systemd/user/container-koopa-silverbullet.service"
|
||||
if [[ -f "$UNIT_SRC" ]] && command -v systemctl >/dev/null; then
|
||||
mkdir -p "${HOME}/.config/systemd/user"
|
||||
cp -a "$UNIT_SRC" "$UNIT_DST"
|
||||
systemctl --user daemon-reload || true
|
||||
systemctl --user disable --now container-koopa-freenotes.service 2>/dev/null || true
|
||||
systemctl --user enable --now container-koopa-silverbullet.service 2>/dev/null || true
|
||||
echo "STATUS=systemd_user unit=container-koopa-silverbullet.service"
|
||||
fi
|
||||
|
||||
echo "STATUS=ok CONTAINER=$NEW_CT DIR=$NEW_DIR PORT=$PORT"
|
||||
echo "STATUS=caddy_next sudo bash $ROOT/scripts/caddy/merge-notes-site.sh"
|
||||
echo "STATUS=caddy_next sudo NOTES_AUTH_SEED=/tmp/silverbullet-basicauth-seed.txt bash $ROOT/scripts/caddy/apply-notes-basicauth.sh"
|
||||
echo "STATUS=dns_need silverbullet.hacktivism.ch → koopa"
|
||||
25
scripts/notes/prepare-basicauth-seed.sh
Executable file
25
scripts/notes/prepare-basicauth-seed.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
# Copy silverbullet basicauth SoT → /tmp seed for apply-notes-basicauth.sh.
|
||||
# Run on magikoopa (or any host with unlocked koopa-admin-secrets-enc).
|
||||
# Does NOT touch /etc/caddy (no sudo). Does NOT print secret contents.
|
||||
#
|
||||
# bash scripts/notes/prepare-basicauth-seed.sh
|
||||
# # then on koopa (after scp seed or shared path):
|
||||
# sudo NOTES_AUTH_SEED=/tmp/silverbullet-basicauth-seed.txt \
|
||||
# bash …/scripts/caddy/apply-notes-basicauth.sh
|
||||
set -euo pipefail
|
||||
|
||||
OUT="${NOTES_AUTH_SEED_OUT:-/tmp/silverbullet-basicauth-seed.txt}"
|
||||
SOT_DEFAULT="${HOME}/git/koopa-admin-secrets-enc/koopa/home-hernani/caddy/silverbullet-basicauth.txt"
|
||||
SOT="${NOTES_AUTH_SOT:-$SOT_DEFAULT}"
|
||||
|
||||
[[ -f "$SOT" ]] || {
|
||||
echo "ERROR: missing SoT $SOT (unlock git-crypt / set NOTES_AUTH_SOT=)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
umask 077
|
||||
cp -a "$SOT" "$OUT"
|
||||
chmod 600 "$OUT"
|
||||
echo "STATUS=ok OUT=$OUT BYTES=$(wc -c <"$OUT" | tr -d ' ') NEXT=scp_or_use_NOTES_AUTH_SEED"
|
||||
echo "STATUS=hint scp $OUT hernani@koopa:/tmp/ && sudo NOTES_AUTH_SEED=$OUT bash …/apply-notes-basicauth.sh"
|
||||
39
scripts/notes/status.sh
Executable file
39
scripts/notes/status.sh
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
# Thin status for SilverBullet stack on koopa (hernani). Safe read-only.
|
||||
# bash scripts/notes/status.sh
|
||||
set -euo pipefail
|
||||
|
||||
OLD_DIR="${HOME}/koopa-freenotes"
|
||||
NEW_DIR="${HOME}/koopa-silverbullet"
|
||||
OLD_CT=koopa-freenotes
|
||||
NEW_CT=koopa-silverbullet
|
||||
OLD_IMG=localhost/koopa-freenotes:cachyos
|
||||
NEW_IMG=localhost/koopa-silverbullet:cachyos
|
||||
PORT=9028
|
||||
|
||||
echo "STATUS=host HOST=$(hostname -s)"
|
||||
echo "STATUS=dirs OLD=$([ -d "$OLD_DIR" ] && echo 1 || echo 0) NEW=$([ -d "$NEW_DIR" ] && echo 1 || echo 0)"
|
||||
|
||||
if command -v podman >/dev/null 2>&1; then
|
||||
ct_old=$(podman ps -a --format '{{.Names}} {{.Status}}' 2>/dev/null | grep -E "^${OLD_CT} " || true)
|
||||
ct_new=$(podman ps -a --format '{{.Names}} {{.Status}}' 2>/dev/null | grep -E "^${NEW_CT} " || true)
|
||||
echo "STATUS=ct_old ${ct_old:-none}"
|
||||
echo "STATUS=ct_new ${ct_new:-none}"
|
||||
img_old=$(podman images -q "$OLD_IMG" 2>/dev/null || true)
|
||||
img_new=$(podman images -q "$NEW_IMG" 2>/dev/null || true)
|
||||
echo "STATUS=img_old ${img_old:-none}"
|
||||
echo "STATUS=img_new ${img_new:-none}"
|
||||
else
|
||||
echo "STATUS=podman missing"
|
||||
fi
|
||||
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 "http://127.0.0.1:${PORT}/" 2>/dev/null || echo fail)
|
||||
echo "STATUS=local_http PORT=$PORT CODE=$code"
|
||||
|
||||
if [[ -d "$NEW_DIR" ]]; then
|
||||
echo "STATUS=cutover done DIR=$NEW_DIR"
|
||||
elif [[ -d "$OLD_DIR" ]]; then
|
||||
echo "STATUS=cutover pending DIR=$OLD_DIR NEXT=cutover-to-silverbullet.sh"
|
||||
else
|
||||
echo "STATUS=cutover unknown (no live dir)"
|
||||
fi
|
||||
23
scripts/notes/up.sh
Executable file
23
scripts/notes/up.sh
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
# Bring up koopa-silverbullet / SilverBullet.
|
||||
set -euo pipefail
|
||||
DIR="${HOME}/koopa-silverbullet"
|
||||
cd "${DIR}"
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
[[ -f .env ]] && source .env
|
||||
set +a
|
||||
PORT="${HOST_PORT:-9028}"
|
||||
podman-compose up -d
|
||||
echo "== wait for :${PORT} =="
|
||||
ok=0
|
||||
for i in $(seq 1 40); do
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 "http://127.0.0.1:${PORT}/" || true)
|
||||
echo "try $i: $code"
|
||||
case "$code" in
|
||||
2*|3*) ok=1; break ;;
|
||||
esac
|
||||
sleep 3
|
||||
done
|
||||
[[ "$ok" -eq 1 ]] || { echo "ERROR: no answer on ${PORT}"; podman-compose ps; exit 1; }
|
||||
echo "local ok. public (after Caddy+DNS): https://silverbullet.hacktivism.ch/"
|
||||
Loading…
Add table
Add a link
Reference in a new issue