admin-log: add conflict-free clementine/vs-only paths onto main

This commit is contained in:
Hernâni Marques 2026-09-07 17:17:10 +02:00
parent a2300b617b
commit ba863f8a93
No known key found for this signature in database
8 changed files with 380 additions and 0 deletions

View file

@ -0,0 +1,137 @@
#!/usr/bin/env bash
# Apply HTTP basic_auth (Caddy equivalent of "htaccess in front")
# to dossiers.ngi / dossiers.2.ngi / dossiers.3.ngi.hacktivism.ch
#
# Caddy file_server does NOT honor Apache .htaccess — this edits the Caddyfile.
#
# On koopa (password for sudo):
# sudo -n true 2>/dev/null || sudo -v
# sudo bash /home/hernani/koopa-admin-log/scripts/caddy/apply-dossiers-ngi-basicauth.sh
#
# Idempotent. Password file is NOT in git:
# /home/hernani/koopa-secrets/dossiers-ngi-basicauth.txt
set -euo pipefail
if [[ "$(id -u)" -ne 0 ]]; then
echo "ERROR: run as root: sudo bash $0" >&2
exit 1
fi
CADDY=/etc/caddy/Caddyfile
USER_NAME="${DOSSIERS_AUTH_USER:-hernani}"
SECRETS_DIR=/home/hernani/koopa-secrets
PASS_FILE="${SECRETS_DIR}/dossiers-ngi-basicauth.txt"
SITES=(
dossiers.ngi.hacktivism.ch
dossiers.2.ngi.hacktivism.ch
dossiers.3.ngi.hacktivism.ch
)
if [[ ! -f "$CADDY" ]]; then
echo "ERROR: missing $CADDY" >&2
exit 1
fi
command -v caddy >/dev/null || { echo "ERROR: caddy not in PATH" >&2; exit 1; }
mkdir -p "$SECRETS_DIR"
chown hernani:hernani "$SECRETS_DIR"
chmod 700 "$SECRETS_DIR"
if [[ -f "$PASS_FILE" ]]; then
# shellcheck disable=SC1090
# file format: USER=... PASS=... HASH=...
# PASS may contain spaces; read with grep
USER_NAME="$(awk -F= '/^USER=/{print substr($0,6); exit}' "$PASS_FILE")"
PASS="$(awk -F= '/^PASS=/{print substr($0,6); exit}' "$PASS_FILE")"
HASH="$(awk -F= '/^HASH=/{print substr($0,6); exit}' "$PASS_FILE")"
if [[ -z "$USER_NAME" || -z "$HASH" ]]; then
echo "ERROR: $PASS_FILE incomplete — move it aside and re-run" >&2
exit 1
fi
echo "OK: reusing credentials in $PASS_FILE"
else
PASS="$(openssl rand -base64 18 | tr -d '/+=' | head -c 20)"
HASH="$(caddy hash-password --plaintext "$PASS")"
umask 077
cat >"$PASS_FILE" <<EOF
USER=${USER_NAME}
PASS=${PASS}
HASH=${HASH}
EOF
chown hernani:hernani "$PASS_FILE"
chmod 600 "$PASS_FILE"
echo "OK: wrote new password to $PASS_FILE (not git)"
fi
# Caddyfile treats $ as env — double it for a literal bcrypt hash
HASH_CADDY="${HASH//\$/\$\$}"
ts=$(date +%Y%m%d-%H%M%S)
cp -a "$CADDY" "${CADDY}.bak-dossiers-auth-${ts}"
echo "backup ${CADDY}.bak-dossiers-auth-${ts}"
python3 - "$CADDY" "$USER_NAME" "$HASH_CADDY" "${SITES[@]}" <<'PY'
import sys
from pathlib import Path
path = Path(sys.argv[1])
user = sys.argv[2]
hash_caddy = sys.argv[3]
sites = sys.argv[4:]
text = path.read_text()
orig = text
def inject_block(src: str, site: str) -> str:
marker = f"{site} {{"
i = src.find(marker)
if i < 0:
raise SystemExit(f"ERROR: site block not found: {site}")
# already has basic_auth in this block?
j = src.find("\n}", i)
if j < 0:
raise SystemExit(f"ERROR: unclosed block: {site}")
block = src[i:j]
if "basic_auth" in block or "basicauth" in block:
print(f"OK: {site} already has basic_auth")
return src
needle = ' header Alt-Svc "clear"\n'
k = block.find(needle)
auth = (
needle
+ " basic_auth {\n"
+ f" {user} {hash_caddy}\n"
+ " }\n"
)
if k >= 0:
new_block = block.replace(needle, auth, 1)
else:
# insert after opening brace
nl = block.find("\n")
new_block = block[: nl + 1] + auth + block[nl + 1 :]
print(f"OK: injected basic_auth in {site}")
return src[:i] + new_block + src[j:]
for s in sites:
text = inject_block(text, s)
if text == orig:
print("no Caddyfile change")
else:
path.write_text(text)
print(f"wrote {path}")
PY
echo "== validate =="
caddy validate --config "$CADDY"
echo "== reload =="
if systemctl is-active --quiet caddy; then
systemctl reload caddy
else
echo "WARN: caddy unit not active — start it yourself" >&2
fi
echo
echo "Done. Browser: https://dossiers.ngi.hacktivism.ch/ (and .2. / .3.)"
echo "User/pass: $PASS_FILE"
echo "Reload later: sudo caddy validate --config $CADDY && sudo systemctl reload caddy"

View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Apply hacktivism colors + header CSS on the live organization.
set -euo pipefail
cd "${HOME}/koopa-decidim"
set -a
# shellcheck disable=SC1091
source .env
# shellcheck disable=SC1091
source users.env
set +a
podman exec \
-e DECIDIM_HOST="${DECIDIM_HOST:-decidim.hacktivism.ch}" \
-e DECIDIM_SYSTEM_EMAIL \
-e DECIDIM_SYSTEM_PASSWORD \
-e DECIDIM_ADMIN_EMAIL \
-e DECIDIM_ADMIN_PASSWORD \
-e DECIDIM_ADMIN_NAME \
-e DECIDIM_APPLICATION_NAME \
-e DECIDIM_DEFAULT_LOCALE \
-e DECIDIM_AVAILABLE_LOCALES \
koopa-decidim bundle exec rails runner /code/lib/koopa_bootstrap.rb
echo "branding applied. public: https://decidim.hacktivism.ch/"

View file

@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Install Decidim user systemd units on koopa (boot via linger).
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
LIVE="${HOME}/koopa-decidim"
# admin-log tree (scripts/decidim → ../..) or live ~/koopa-decidim/bin
if [ -f "${HERE}/../../configs/decidim/container-koopa-decidim.service" ]; then
UNIT_SRC="${HERE}/../../configs/decidim"
elif [ -f "${LIVE}/container-koopa-decidim.service" ]; then
UNIT_SRC="${LIVE}"
else
echo "ERROR: decidim unit files not found" >&2
exit 1
fi
UNIT_DIR="${HOME}/.config/systemd/user"
mkdir -p "${UNIT_DIR}"
cp "${UNIT_SRC}/container-koopa-decidim-db.service" "${UNIT_DIR}/"
cp "${UNIT_SRC}/container-koopa-decidim.service" "${UNIT_DIR}/"
systemctl --user daemon-reload
systemctl --user enable \
container-koopa-decidim-db.service \
container-koopa-decidim.service
if ! podman ps --format '{{.Names}}' | grep -qx koopa-decidim; then
(cd "${HOME}/koopa-decidim" && set -a && source .env && set +a && podman-compose up -d)
fi
systemctl --user start \
container-koopa-decidim-db.service \
container-koopa-decidim.service
systemctl --user --no-pager --lines=0 status \
container-koopa-decidim-db.service \
container-koopa-decidim.service || true
if command -v loginctl >/dev/null 2>&1; then
if [ "$(loginctl show-user "$(id -un)" -p Linger --value 2>/dev/null || echo no)" != "yes" ]; then
echo "NOTE: enable linger so units start after reboot without login:"
echo " sudo loginctl enable-linger $(id -un)"
else
echo "linger already enabled for $(id -un)"
fi
fi
echo "OK. Public: https://decidim.hacktivism.ch/"

39
scripts/decidim/seed-example.sh Executable file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Publish public example process/meeting + optional isoc user from users.env.
set -euo pipefail
cd "${HOME}/koopa-decidim"
set -a
# shellcheck disable=SC1091
source .env
# shellcheck disable=SC1091
source users.env
set +a
src=""
if [ -f "${HOME}/src/koopa/koopa-admin-log/configs/decidim/seed_example.rb" ]; then
src="${HOME}/src/koopa/koopa-admin-log/configs/decidim/seed_example.rb"
elif [ -f ./seed_example.rb ]; then
src="./seed_example.rb"
else
echo "ERROR: seed_example.rb not found" >&2
exit 1
fi
podman cp "${src}" koopa-decidim:/code/lib/koopa_seed_example.rb
avatar_host="${DECIDIM_ISOC_AVATAR:-${HOME}/koopa-decidim/assets/img/isoc-gold.png}"
avatar_ctr=""
if [ -f "${avatar_host}" ]; then
avatar_ctr="/tmp/isoc-gold.png"
podman cp "${avatar_host}" "koopa-decidim:${avatar_ctr}"
fi
podman exec \
-e DECIDIM_HOST="${DECIDIM_HOST:-decidim.hacktivism.ch}" \
-e DECIDIM_ADMIN_EMAIL \
-e DECIDIM_ISOC_EMAIL \
-e DECIDIM_ISOC_PASSWORD \
-e DECIDIM_ISOC_NAME \
-e DECIDIM_ISOC_NICKNAME \
-e DECIDIM_ISOC_AVATAR="${avatar_ctr}" \
koopa-decidim bundle exec rails runner /code/lib/koopa_seed_example.rb
echo "seed done. public: https://decidim.hacktivism.ch/processes/example"

21
scripts/decidim/up.sh Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euo pipefail
DIR="${HOME}/koopa-decidim"
cd "${DIR}"
set -a
# shellcheck disable=SC1091
source .env
set +a
podman-compose up -d
echo "== wait for :9027 =="
ok=0
for i in $(seq 1 80); do
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 "http://127.0.0.1:9027/" || true)
echo "try $i: $code"
case "$code" in
2*|3*) ok=1; break ;;
esac
sleep 5
done
[[ "$ok" -eq 1 ]] || { echo "ERROR: no answer on 9027"; podman-compose ps; exit 1; }
echo "local ok. public: https://decidim.hacktivism.ch/"