admin-log: add conflict-free clementine/vs-only paths onto main
This commit is contained in:
parent
a2300b617b
commit
ba863f8a93
8 changed files with 380 additions and 0 deletions
43
2026/2026-08-17--decidim.md
Normal file
43
2026/2026-08-17--decidim.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Decidim — decidim.hacktivism.ch (2026-08-17)
|
||||||
|
|
||||||
|
Site: **https://decidim.hacktivism.ch/**
|
||||||
|
Port **9027** → Caddy. Stack: `koopa-decidim` + `koopa-decidim-sidekiq` + `koopa-decidim-db` + `koopa-decidim-redis`. Image `decidim/decidim:0.30.8`.
|
||||||
|
|
||||||
|
Live: `~/koopa-decidim/` (compose mirror `configs/decidim/`). Secrets only on host (`.env`, `users.env`).
|
||||||
|
|
||||||
|
Instance name **hacktivism**. Theme: exchange-dark (gold `#e8a838`, bg `#1a1410`) via `theme/hacktivism.css`. Analog: `configs/lemmy/`.
|
||||||
|
|
||||||
|
Admin users are on the host (`~/koopa-decidim/users.env`), not in this repo.
|
||||||
|
|
||||||
|
Caddy: `sudo /home/hernani/koopa-caddy/apply.sh`
|
||||||
|
Boot: `scripts/decidim/install-systemd.sh` (linger already yes on koopa).
|
||||||
|
|
||||||
|
## Cookie / privacy
|
||||||
|
|
||||||
|
Stock Decidim still emits `#dc-dialog-wrapper` (Accept all / essential / Settings). This instance has no third-party trackers; privacy is default.
|
||||||
|
|
||||||
|
- CSS: `#dc-dialog-wrapper, .cookies__container { display: none !important; }`
|
||||||
|
- JS: `/hacktivism-consent.js` sets `decidim-consent={"essential":true}` if missing
|
||||||
|
- Live 2026-08-17: HTML 200, CSS/JS 200, hide rules in public `/hacktivism.css`
|
||||||
|
|
||||||
|
## Reboot (checked 2026-08-17)
|
||||||
|
|
||||||
|
| Item | Value |
|
||||||
|
|------|--------|
|
||||||
|
| linger `hernani` | yes |
|
||||||
|
| `container-koopa-decidim-db` | enabled + active |
|
||||||
|
| `container-koopa-decidim` | enabled + active |
|
||||||
|
| `container-koopa-lemmy-db` / `container-koopa-lemmy` | enabled + active |
|
||||||
|
| listen | `:9027` `:9026` |
|
||||||
|
|
||||||
|
login-health: probes + containers + linger + these units enabled. Loopback HTTP on :9027 is **301** (app wants HTTPS; TLS is Caddy). Probe allows 301. After reboot: login-health only unless asked.
|
||||||
|
|
||||||
|
## Public example + isoc
|
||||||
|
|
||||||
|
- Process **example** (published, not private): `https://decidim.hacktivism.ch/processes/example`
|
||||||
|
— title **Öffentliche digitale Allmende** (public-by-default reading).
|
||||||
|
- Published meeting **Offene Runde: Lesen ohne Konto** + one public proposal + background page.
|
||||||
|
- Homepage block `highlighted_processes` published.
|
||||||
|
- Participant `isoc` on the host (`users.env`); password not in this repo.
|
||||||
|
- Avatar: gold ISOC globe (same crop as Bonfire `@isoc`); host file `~/koopa-decidim/assets/img/isoc-gold.png`, not in this repo.
|
||||||
|
- Seed: `scripts/decidim/seed-example.sh` / `configs/decidim/seed_example.rb`.
|
||||||
16
2026/2026-09-05--hernani-ollama-user+power.md
Normal file
16
2026/2026-09-05--hernani-ollama-user+power.md
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# koopa: hernani user Ollama + power sampling (2026-09-05)
|
||||||
|
|
||||||
|
Freigabe: operator — install Ollama under hernani (no root package); loopback only; laptop tunnels.
|
||||||
|
|
||||||
|
## Ollama
|
||||||
|
|
||||||
|
- Binary: `~hernani/.local/bin/ollama` (v0.33.3 from GitHub `ollama-linux-amd64.tar.zst`)
|
||||||
|
- Unit: `~/.config/systemd/user/ollama.service` · `OLLAMA_HOST=127.0.0.1:11434` · enabled
|
||||||
|
- Access: SSH as **hernani** from clementine/magikoopa → LocalForward (helper `koopa-ollama-tunnel` → laptop `:11438`)
|
||||||
|
- Models: small + exotic pulls (see pull log `/tmp/ollama-koopa-pull-20260905.log`) — prefer ≤3B
|
||||||
|
|
||||||
|
## Power / energy
|
||||||
|
|
||||||
|
- Deployed `host-power.py` to `~hernani/.local/bin/host-power`
|
||||||
|
- Laptop: `remote-power koopa` / `koopa-power` → JSON watts; combo derives Wh
|
||||||
|
- RAPL `energy_uj` root-only → quality **estimated** until Freigabe for `enable-host-power-access.sh --apply`
|
||||||
55
2026/2026-09-07--git-meta-origin-forgejo.md
Normal file
55
2026/2026-09-07--git-meta-origin-forgejo.md
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# `$HOME/git/` meta-repo origin on git.hacktivism.ch (2026-09-07)
|
||||||
|
|
||||||
|
## Remote
|
||||||
|
|
||||||
|
| Item | Value |
|
||||||
|
|------|--------|
|
||||||
|
| Host | **Forgejo rootless** `https://git.hacktivism.ch/` |
|
||||||
|
| Repo | **hernani/git** (meta-repo: non-secret globals only) |
|
||||||
|
| Visibility | **private** (`DEFAULT_PRIVATE` template is public — create with `private:true`) |
|
||||||
|
| Default branch | `main` |
|
||||||
|
| SSH clone (FQDN form) | `git@git.hacktivism.ch:hernani/git.git` |
|
||||||
|
| SSH URL (API form) | `ssh://git@git.hacktivism.ch:9200/hernani/git.git` |
|
||||||
|
| Local tree | `$HOME/git/` (`PATH[git-root]`) |
|
||||||
|
|
||||||
|
Unauth HTTPS browse of a private repo → **404** (expected).
|
||||||
|
|
||||||
|
## Local setup (done 2026-09-07 ~14:21)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "$HOME/git"
|
||||||
|
git remote add origin git@git.hacktivism.ch:hernani/git.git
|
||||||
|
git push -u origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
SSH Host `git.hacktivism.ch`: `HostName 127.0.0.1`, `Port 9200`, `User git`, `ProxyJump hernani@koopa`, `IdentityFile ~/.ssh/id_ed25519`.
|
||||||
|
|
||||||
|
## Create via One-Shot-Token (on koopa)
|
||||||
|
|
||||||
|
Do **not** use xAI / host-expert-ssh mutate for this. SSH as `hernani` → local HTTP **9024**.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# unique token name (default gitea-admin may already exist)
|
||||||
|
podman exec koopa-forgejo gitea admin user generate-access-token \
|
||||||
|
--username hernani \
|
||||||
|
--token-name "oneshot-git-meta-$(date +%s)" \
|
||||||
|
--scopes write:repository,write:admin \
|
||||||
|
--raw
|
||||||
|
# → TOKEN (never log / never commit)
|
||||||
|
|
||||||
|
curl -sS -X POST \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"name":"git","private":true,"auto_init":false,"default_branch":"main"}' \
|
||||||
|
http://127.0.0.1:9024/api/v1/admin/users/hernani/repos
|
||||||
|
# expect HTTP 201, full_name=hernani/git
|
||||||
|
```
|
||||||
|
|
||||||
|
Token delete via API often **403** with those scopes — purge leftover `oneshot-*` in Forgejo UI if needed.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- This admin-log’s own origin: `2026-07-10--admin-log-origin-forgejo.md` (public)
|
||||||
|
- Forgejo install: `2026-07-10--forgejo-rootless.md`
|
||||||
|
- Host skill quirk: private repos need explicit `private:true`
|
||||||
|
- Meta Must: no secrets / no child worktrees in this Forgejo repo
|
||||||
137
scripts/caddy/apply-dossiers-ngi-basicauth.sh
Executable file
137
scripts/caddy/apply-dossiers-ngi-basicauth.sh
Executable 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"
|
||||||
22
scripts/decidim/apply-branding.sh
Executable file
22
scripts/decidim/apply-branding.sh
Executable 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/"
|
||||||
47
scripts/decidim/install-systemd.sh
Executable file
47
scripts/decidim/install-systemd.sh
Executable 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
39
scripts/decidim/seed-example.sh
Executable 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
21
scripts/decidim/up.sh
Executable 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/"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue