diff --git a/configs/caddy/Caddyfile b/configs/caddy/Caddyfile index 58fb8a5..bacff1e 100644 --- a/configs/caddy/Caddyfile +++ b/configs/caddy/Caddyfile @@ -1,7 +1,7 @@ # Internal only (not in the browser URL): # 9010 merchant API | 9011 exchange API | 9012 bank API # 9013 bank landing | 9014 exchange landing | 9015 merchant landing -# 9020 castopod | 9021 bonfire | 9022 prime | 9023 bt | 9024 forgejo | 9025 paivana | 9026 lemmy | 9200 forgejo-ssh +# 9020 castopod | 9021 bonfire | 9022 prime | 9023 bt | 9024 forgejo | 9025 paivana | 9026 lemmy | 9027 decidim | 9200 forgejo-ssh # 9090 tops ng1 | 9091 tops ng2 | 9092 tops ng3 { @@ -39,28 +39,28 @@ taler.hacktivism.ch { # surface + aptdeploy HTML (taler.hacktivism.ch only) handle /taler-monitoring-surface_err { - redir * /taler-monitoring-surface_err/ 302 + redir /taler-monitoring-surface_err/ 302 } handle /taler-monitoring-surface_err* { root * /var/www/monitoring-sites/taler.hacktivism.ch file_server } handle /taler-monitoring-surface { - redir * /taler-monitoring-surface/ 302 + redir /taler-monitoring-surface/ 302 } handle /taler-monitoring-surface* { root * /var/www/monitoring-sites/taler.hacktivism.ch file_server } handle /taler-monitoring-aptdeploy_err { - redir * /taler-monitoring-aptdeploy_err/ 302 + redir /taler-monitoring-aptdeploy_err/ 302 } handle /taler-monitoring-aptdeploy_err* { root * /var/www/monitoring-sites/taler.hacktivism.ch file_server } handle /taler-monitoring-aptdeploy { - redir * /taler-monitoring-aptdeploy/ 302 + redir /taler-monitoring-aptdeploy/ 302 } handle /taler-monitoring-aptdeploy* { root * /var/www/monitoring-sites/taler.hacktivism.ch @@ -68,14 +68,14 @@ taler.hacktivism.ch { } handle /taler-monitoring-mattermost_err { - redir * /taler-monitoring-mattermost_err/ 302 + redir /taler-monitoring-mattermost_err/ 302 } handle /taler-monitoring-mattermost_err* { root * /var/www/monitoring-sites/taler.hacktivism.ch file_server } handle /taler-monitoring-mattermost { - redir * /taler-monitoring-mattermost/ 302 + redir /taler-monitoring-mattermost/ 302 } handle /taler-monitoring-mattermost* { root * /var/www/monitoring-sites/taler.hacktivism.ch @@ -83,14 +83,14 @@ taler.hacktivism.ch { } handle /taler-monitoring-mail_err { - redir * /taler-monitoring-mail_err/ 302 + redir /taler-monitoring-mail_err/ 302 } handle /taler-monitoring-mail_err* { root * /var/www/monitoring-sites/taler.hacktivism.ch file_server } handle /taler-monitoring-mail { - redir * /taler-monitoring-mail/ 302 + redir /taler-monitoring-mail/ 302 } handle /taler-monitoring-mail* { root * /var/www/monitoring-sites/taler.hacktivism.ch @@ -99,14 +99,14 @@ taler.hacktivism.ch { # taler-monitoring console HTML (host static — not in app containers) handle /monitoring_err { - redir * /monitoring_err/ 302 + redir /monitoring_err/ 302 } handle /monitoring_err* { root * /var/www/monitoring-sites/taler.hacktivism.ch file_server } handle /monitoring { - redir * /monitoring/ 302 + redir /monitoring/ 302 } handle /monitoring* { root * /var/www/monitoring-sites/taler.hacktivism.ch @@ -143,14 +143,14 @@ exchange.hacktivism.ch { # taler-monitoring console HTML (host static — not in app containers) handle /monitoring_err { - redir * /monitoring_err/ 302 + redir /monitoring_err/ 302 } handle /monitoring_err* { root * /var/www/monitoring-sites/exchange.hacktivism.ch file_server } handle /monitoring { - redir * /monitoring/ 302 + redir /monitoring/ 302 } handle /monitoring* { root * /var/www/monitoring-sites/exchange.hacktivism.ch @@ -177,14 +177,14 @@ bank.hacktivism.ch { # taler-monitoring console HTML (host static — not in app containers) handle /monitoring_err { - redir * /monitoring_err/ 302 + redir /monitoring_err/ 302 } handle /monitoring_err* { root * /var/www/monitoring-sites/bank.hacktivism.ch file_server } handle /monitoring { - redir * /monitoring/ 302 + redir /monitoring/ 302 } handle /monitoring* { root * /var/www/monitoring-sites/bank.hacktivism.ch @@ -315,7 +315,24 @@ lemmy.hacktivism.ch { } } -http://taler.hacktivism.ch, http://exchange.hacktivism.ch, http://bank.hacktivism.ch, http://castopod.hacktivism.ch, http://bonfire.hacktivism.ch, http://prime.hacktivism.ch, http://bt.hacktivism.ch, http://git.hacktivism.ch, http://paivana.hacktivism.ch, http://tops.ng1.hacktivism.ch, http://tops.ng2.hacktivism.ch, http://tops.ng3.hacktivism.ch, http://lemmy.hacktivism.ch { +# 9027 decidim (rails) +decidim.hacktivism.ch { + header Alt-Svc "clear" + reverse_proxy 127.0.0.1:9027 { + header_up Host {host} + header_up X-Forwarded-For {remote_host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Proto {scheme} + header_up X-Forwarded-Port 443 + flush_interval -1 + transport http { + read_timeout 3600s + write_timeout 3600s + } + } +} + +http://taler.hacktivism.ch, http://exchange.hacktivism.ch, http://bank.hacktivism.ch, http://castopod.hacktivism.ch, http://bonfire.hacktivism.ch, http://prime.hacktivism.ch, http://bt.hacktivism.ch, http://git.hacktivism.ch, http://paivana.hacktivism.ch, http://tops.ng1.hacktivism.ch, http://tops.ng2.hacktivism.ch, http://tops.ng3.hacktivism.ch, http://lemmy.hacktivism.ch, http://decidim.hacktivism.ch { handle /.well-known/acme-challenge/* { root * /var/www/acme file_server diff --git a/host/overview/LIVE.md b/host/overview/LIVE.md index 46ee303..11120be 100644 --- a/host/overview/LIVE.md +++ b/host/overview/LIVE.md @@ -36,6 +36,7 @@ ss -lntp | grep -E '90[0-9]{2}|9200|8080|9080|1789' | `koopa-forgejo` (+ postgres) | `forgejo:11-rootless` | **9024**, **9200** | `git.hacktivism.ch` | | **`koopa-paivana`** (+ upstream) | `localhost/koopa-paivana:latest` | **9025** | `paivana.hacktivism.ch` | | `koopa-lemmy-proxy` (+ lemmy, ui, pictrs, db) | `lemmy:0.19.20` | **9026** | `lemmy.hacktivism.ch` | +| `koopa-decidim` (+ postgres, redis, sidekiq) | `decidim/decidim:0.30.8` | **9027** | `decidim.hacktivism.ch` | | **`koopa-tor-relay`** | `localhost/koopa-tor-relay:latest` | **8080**, **9051** (host net) | Tor OR (non-exit) | | **`koopa-nym`** | `localhost/koopa-nym:latest` | **9080**, **1789**, **1790** (+ opt. WG) | Nym mixnet node (nym.com) | | `koopa-tops-ng1` | `nginx` | **9090** | `tops.ng1.hacktivism.ch` | @@ -61,6 +62,7 @@ Managed from **`/home/hernani/ansible-taler-exchange/`** (see `configs/taler-exc | `git.hacktivism.ch` | 9024 (HTTP); git-SSH **9200** host-direct | | `paivana.hacktivism.ch` | 9025 (paivana-httpd GOA paywall) | | `lemmy.hacktivism.ch` | 9026 | +| `decidim.hacktivism.ch` | 9027 | | `tops.ng1.hacktivism.ch` | 9090 | | `tops.ng2.hacktivism.ch` | 9091 | | `tops.ng3.hacktivism.ch` | 9092 | @@ -74,6 +76,7 @@ Config: `/etc/caddy/Caddyfile` (mirror `configs/caddy/Caddyfile`). | `~/ansible-taler-exchange/` | Ansible + scripts for exchange-ansible container | | `~/koopa-castopod/` | Castopod compose | | `~/koopa-lemmy/` | Lemmy compose | +| `~/koopa-decidim/` | Decidim compose | | `~/koopa-bonfire/` | Bonfire compose + gitbot | | `~/koopa-prime/` | Jellyfin + qBittorrent | | `~/koopa-forgejo/` | Forgejo rootless | @@ -90,6 +93,8 @@ Config: `/etc/caddy/Caddyfile` (mirror `configs/caddy/Caddyfile`). | Taler merchant/bank | root `start_base_services_*` → service user → `/usr/local/bin/start_*.sh` | | Exchange (GOA) | `~/ansible-taler-exchange/run-container-koopa.sh` then `deploy-hacktivism-goa.sh` | | User apps | `cd ~/koopa-* && podman-compose up -d` | +| Lemmy | user units `container-koopa-lemmy-db` + `container-koopa-lemmy` (linger) | +| Decidim | user units `container-koopa-decidim-db` + `container-koopa-decidim` (linger) | | tops (ng1–ng3) | user unit `container-koopa-tops.service` (linger) | ## Config mirrors in this repo (`configs/`) @@ -111,3 +116,4 @@ Config: `/etc/caddy/Caddyfile` (mirror `configs/caddy/Caddyfile`). | Forgejo | `2026/2026-07-10--forgejo-rootless.md` | | Bonfire public feeds | `configs/bonfire/public-feeds.md` | | Castopod content | `2026/2026-07-09--castopod-content.md` | +| Decidim | `2026/2026-08-17--decidim.md` · `configs/decidim/` | diff --git a/host/overview/services.md b/host/overview/services.md index 0c9daf2..6c72548 100644 --- a/host/overview/services.md +++ b/host/overview/services.md @@ -37,6 +37,7 @@ flowchart TB Forgejo["koopa-forgejo ROOTLESS\n:9024 HTTP / :9200 SSH"] Paivana["koopa-paivana\n:9025"] Lemmy["koopa-lemmy-proxy\n:9026"] + Decidim["koopa-decidim\n:9027"] end Tor["tor ORPort :8080"] @@ -63,6 +64,7 @@ flowchart TB CaddyHTTPS -->|git.hacktivism.ch| Forgejo CaddyHTTPS -->|paivana.hacktivism.ch| Paivana CaddyHTTPS -->|lemmy.hacktivism.ch| Lemmy + CaddyHTTPS -->|decidim.hacktivism.ch| Decidim ``` ## Port table @@ -84,6 +86,7 @@ flowchart TB | **9024** | podman | **forgejo** HTTP → `git.hacktivism.ch` | | **9025** | podman | **paivana** → `paivana.hacktivism.ch` | | **9026** | podman | **lemmy** → `lemmy.hacktivism.ch` | +| **9027** | podman | **decidim** → `decidim.hacktivism.ch` | | **9200** | podman | **forgejo** git-SSH (host-direct) | | 9090–9092 | podman | **tops** `koopa-tops-ng1`…`ng3` | | 8080 | tor | ORPort | diff --git a/scripts/caddy/README.md b/scripts/caddy/README.md index 8b022fd..a9f5139 100644 --- a/scripts/caddy/README.md +++ b/scripts/caddy/README.md @@ -10,6 +10,17 @@ sudo caddy validate --config /etc/caddy/Caddyfile sudo systemctl reload caddy ``` +## dossiers.ngi* — basic_auth (htaccess-in-front) + +Caddy **ignores** Apache `.htaccess`. Use: + +```bash +sudo bash /home/hernani/koopa-admin-log/scripts/caddy/apply-dossiers-ngi-basicauth.sh +``` + +Password file (not git): `/home/hernani/koopa-secrets/dossiers-ngi-basicauth.txt` +Hosts: `dossiers.ngi` / `dossiers.2.ngi` / `dossiers.3.ngi`.hacktivism.ch + ## New HTTPS vhost Add a site block to the Caddyfile (live + mirror), then validate and reload. Include the host in the shared HTTP site list (ACME + redirect) at the bottom of the file. diff --git a/scripts/lemmy/install-systemd.sh b/scripts/lemmy/install-systemd.sh index 626dc3b..f064f9f 100755 --- a/scripts/lemmy/install-systemd.sh +++ b/scripts/lemmy/install-systemd.sh @@ -1,12 +1,21 @@ #!/usr/bin/env bash # Install Lemmy user systemd units on koopa (boot via linger). set -euo pipefail -ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +HERE="$(cd "$(dirname "$0")" && pwd)" +LIVE="${HOME}/koopa-lemmy" +if [ -f "${HERE}/../../configs/lemmy/container-koopa-lemmy.service" ]; then + UNIT_SRC="${HERE}/../../configs/lemmy" +elif [ -f "${LIVE}/container-koopa-lemmy.service" ]; then + UNIT_SRC="${LIVE}" +else + echo "ERROR: lemmy unit files not found" >&2 + exit 1 +fi UNIT_DIR="${HOME}/.config/systemd/user" mkdir -p "${UNIT_DIR}" -cp "${ROOT}/configs/lemmy/container-koopa-lemmy-db.service" "${UNIT_DIR}/" -cp "${ROOT}/configs/lemmy/container-koopa-lemmy.service" "${UNIT_DIR}/" +cp "${UNIT_SRC}/container-koopa-lemmy-db.service" "${UNIT_DIR}/" +cp "${UNIT_SRC}/container-koopa-lemmy.service" "${UNIT_DIR}/" systemctl --user daemon-reload systemctl --user enable \ @@ -25,4 +34,13 @@ systemctl --user --no-pager --lines=0 status \ container-koopa-lemmy-db.service \ container-koopa-lemmy.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://lemmy.hacktivism.ch/" diff --git a/scripts/login-health/README.md b/scripts/login-health/README.md index 04b1a6b..0003217 100644 --- a/scripts/login-health/README.md +++ b/scripts/login-health/README.md @@ -65,7 +65,9 @@ overall: OK ok=42 warn=0 fail=0 | Git SSH | TCP `:9200` | **Critical** (→ overall FAIL): merchant, exchange, bank, forgejo, edge/critical ports. -**Optional** (→ WARN): castopod, bonfire, lemmy, prime, bt, paivana, tops, tor, nym. +**Optional** (→ WARN): castopod, bonfire, lemmy, decidim, prime, bt, paivana, tops, tor, nym. + +Collect also checks **linger** and that Lemmy/Decidim user units are **enabled** (reboot survival). Read-only. No restarts, no secrets. diff --git a/scripts/login-health/koopa-login-health.sh b/scripts/login-health/koopa-login-health.sh index aa9c2db..309a782 100755 --- a/scripts/login-health/koopa-login-health.sh +++ b/scripts/login-health/koopa-login-health.sh @@ -151,6 +151,7 @@ EXPECT_CONTAINERS=( koopa-castopod koopa-bonfire koopa-lemmy-proxy + koopa-decidim koopa-prime-jellyfin koopa-prime-qbittorrent koopa-forgejo @@ -173,6 +174,7 @@ OPTIONAL_CONTAINERS=( koopa-castopod koopa-bonfire koopa-lemmy-proxy + koopa-decidim koopa-paivana ) @@ -185,6 +187,7 @@ PROBES=( "castopod|http://127.0.0.1:9020/|200,302,303,307,308" "bonfire|http://127.0.0.1:9021/|200,302,303,307,308" "lemmy|http://127.0.0.1:9026/|200,302,303,307,308" + "decidim|http://127.0.0.1:9027/|200,301,302,303,307,308" "prime|http://127.0.0.1:9022/|200,302,303,307,308" "bt|http://127.0.0.1:9023/|200,302,303,307,308,401" "paivana|http://127.0.0.1:9025/|200,302,303,307,308" @@ -193,7 +196,7 @@ PROBES=( "tops-ng3|http://127.0.0.1:9092/|200,302,303" ) -OPTIONAL_PROBES=(castopod bonfire lemmy prime bt paivana tops-ng1 tops-ng2 tops-ng3) +OPTIONAL_PROBES=(castopod bonfire lemmy decidim prime bt paivana tops-ng1 tops-ng2 tops-ng3) C_OK=; C_WARN=; C_FAIL=; C_DIM=; C_RST=; C_BOLD= # colors only when writing for a tty later; snapshots are plain + optional ANSI if COLLECT_COLOR=1 @@ -277,6 +280,34 @@ do_collect() { record WARN "systemctl not available" fi + # Reboot survival: linger + enabled user units (public stacks). + if command -v loginctl >/dev/null 2>&1; then + linger_st=$(loginctl show-user "$(id -un)" -p Linger --value 2>/dev/null || echo no) + if [ "${linger_st}" = "yes" ]; then + record OK "linger=yes ($(id -un))" + else + record FAIL "linger=${linger_st} (user units will not start after reboot without login)" + fi + else + record WARN "loginctl not available (cannot check linger)" + fi + if command -v systemctl >/dev/null 2>&1 && [ "$(id -u 2>/dev/null)" != "0" ]; then + local u en + for u in \ + container-koopa-lemmy-db.service \ + container-koopa-lemmy.service \ + container-koopa-decidim-db.service \ + container-koopa-decidim.service + do + en=$(systemctl --user is-enabled "${u}" 2>/dev/null || echo unknown) + if [ "${en}" = "enabled" ]; then + record OK "unit ${u} enabled" + else + record WARN "unit ${u} is ${en} (will not start on reboot)" + fi + done + fi + if command -v ss >/dev/null 2>&1; then listen_blob=$(ss -lnt 2>/dev/null | awk '{print $4}' || true) for port in 9000 9001 9010 9011 9012 9024 9200; do @@ -286,7 +317,7 @@ do_collect() { record FAIL "nothing listening on :${port}" fi done - for port in 9020 9021 9022 9023 9025 9026 9090 9091 9092 8080 9080; do + for port in 9020 9021 9022 9023 9025 9026 9027 9090 9091 9092 8080 9080; do if printf '%s\n' "${listen_blob}" | grep -qE "[:.]${port}\$"; then record OK "listen :${port} (optional)" else @@ -323,7 +354,7 @@ do_collect() { fi fi done - for dep in koopa-forgejo-db koopa-castopod-mariadb koopa-castopod-redis koopa-bonfire-db koopa-lemmy-db; do + for dep in koopa-forgejo-db koopa-castopod-mariadb koopa-castopod-redis koopa-bonfire-db koopa-lemmy-db koopa-decidim-db koopa-decidim-redis; do if printf '%s\n' "${running_names}" | grep -qxF "${dep}"; then record INFO "dep ${dep} running" else