ops: paivana and caddy config refresh

This commit is contained in:
Hernâni Marques 2026-09-09 00:52:54 +02:00
parent d8dbc6242b
commit 56f814a6de
No known key found for this signature in database
74 changed files with 4517 additions and 79 deletions

View file

@ -14,7 +14,8 @@ Directories are named to match **live podman container names** where possible.
| `caddy/` `firewalld/` `systemd/` | host services | |
| `tor/` | **`koopa-tor-relay`** (podman host net) | `localhost/koopa-tor-relay:latest` (**non-root** uid 1000) |
| `nym/` | **`koopa-nym`** (nym.com nym-node) | `localhost/koopa-nym:latest` (**non-root** uid 1000) |
| `paivana/` | **`koopa-paivana`** (+ upstream) | `localhost/koopa-paivana:latest` (**non-root**); upstream unprivileged nginx |
| `paivana/` | **`koopa-paivana`** + paywalls + upstream | `localhost/koopa-paivana:latest` (**non-root**); public **9025/90289030** |
| `notes/` | **`koopa-silverbullet`** (SilverBullet) | `localhost/koopa-silverbullet:cachyos` (backend **127.0.0.1:19128**; paywall **9028**) |
| `forgejo/` | **`koopa-forgejo`** | rootless image + `user: 1000` + `userns keep-id` |
| `prime/` | jellyfin / qbittorrent | linuxserver **PUID/PGID=1000** |

36
configs/bbb/Containerfile Normal file
View file

@ -0,0 +1,36 @@
# koopa-bbb-front — BigBlueButton front (Ubuntu)
# Exception to CachyOS policy: BBB packages and install scripts target Ubuntu.
# Build: bash ~/koopa-admin-log/scripts/bbb/build.sh → localhost/koopa-bbb-front:ubuntu
#
# Placeholder reverse-proxy target (nginx) until Greenlight and/or BBB core
# (bbb-install on Ubuntu) is chosen. Not production BBB media.
ARG UBUNTU_IMAGE=docker.io/library/ubuntu:24.04
FROM ${UBUNTU_IMAGE}
ENV DEBIAN_FRONTEND=noninteractive \
TZ=Europe/Zurich
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates curl nginx tini \
&& rm -rf /var/lib/apt/lists/*
RUN printf '%s\n' \
'server {' \
' listen 80 default_server;' \
' root /var/www/html;' \
' index index.html;' \
' location = /health { access_log off; default_type text/plain; return 200 "ok\n"; }' \
' location / { try_files $uri $uri/ =404; }' \
'}' > /etc/nginx/sites-available/default \
&& printf '%s\n' \
'<!doctype html><meta charset=utf-8><title>bbb.hacktivism.ch</title>' \
'<p>BBB front stub (Ubuntu 24.04). Full BigBlueButton / Greenlight is a separate Ubuntu install step.</p>' \
> /var/www/html/index.html
COPY entrypoint.sh /docker-entrypoint.sh
RUN chmod 755 /docker-entrypoint.sh
EXPOSE 80
ENTRYPOINT ["/usr/bin/tini", "--", "/docker-entrypoint.sh"]

38
configs/bbb/README.md Normal file
View file

@ -0,0 +1,38 @@
# BBB (BigBlueButton) — Ubuntu container (koopa)
CachyOS exception: BBB packages and `bbb-install` target **Ubuntu**. Front stub image is Ubuntu 24.04.
| Item | Value |
|------|--------|
| Stack | BigBlueButton (front stub → core later) |
| Image | `localhost/koopa-bbb-front:ubuntu` (`FROM docker.io/library/ubuntu:24.04`) |
| Live dir | `/home/hernani/koopa-bbb/` |
| Container | `koopa-bbb-front` |
| Host port | **9032** |
| Public site | `bbb.hacktivism.ch` |
## Phases
1. **Front stub (this tree)** — nginx placeholder on `:9032` so Caddy + DNS can land.
2. **Greenlight (optional)** — Rails UI talking to a real BBB API; still Ubuntu-based images.
3. **BBB core** — FreeSWITCH / mediasoup / akka-apps. Prefer official Ubuntu install (`bbb-install.sh`) on a dedicated Ubuntu host/VM, or a known multi-container BBB compose. Not CachyOS.
Media UDP/TCP and TURN are documented when core is chosen — not in this stub.
## Build + up (koopa)
```bash
bash /path/to/koopa-admin-log/scripts/bbb/build.sh
mkdir -p ~/koopa-bbb && cp -a /path/to/koopa-admin-log/configs/bbb/{compose.yml,Containerfile,entrypoint.sh} ~/koopa-bbb/
cd ~/koopa-bbb && HOST_PORT=9032 podman-compose up -d
```
## Caddy
```bash
sudo bash /path/to/koopa-admin-log/scripts/caddy/caddy-apply.sh \
--snippet /path/to/koopa-admin-log/configs/caddy/bbb.hacktivism.ch.caddy \
--site bbb.hacktivism.ch --port 9032 --label bbb
```
DNS + VeciGate for the hostname after apply Freigabe.

31
configs/bbb/compose.yml Normal file
View file

@ -0,0 +1,31 @@
# koopa-bbb — BigBlueButton front on Ubuntu (exception to CachyOS)
# Live: /home/hernani/koopa-bbb/
# Build: bash ~/koopa-admin-log/scripts/bbb/build.sh → localhost/koopa-bbb-front:ubuntu
#
# HOST_PORT: 9032 → Caddy bbb.hacktivism.ch
# Core BBB / Greenlight: separate follow-up (Ubuntu), not this stub.
services:
bbb-front:
image: localhost/koopa-bbb-front:ubuntu
build:
context: .
dockerfile: Containerfile
container_name: koopa-bbb-front
restart: unless-stopped
environment:
- TZ=Europe/Zurich
ports:
- "${HOST_PORT:-9032}:80"
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
labels:
org.hacktivism.service: bbb
org.hacktivism.host_port: "${HOST_PORT:-9032}"
org.hacktivism.site: bbb.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.port_status: allocated-9032
org.hacktivism.image_base: ubuntu

3
configs/bbb/entrypoint.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
set -euo pipefail
exec nginx -g 'daemon off;'

View file

@ -0,0 +1,27 @@
# koopa BBB Ubuntu VM — lean defaults (host ~15 Gi / 4 cores)
# Override before sourcing: RAM_MIB=4096 VCPUS=2 …
VM_NAME=koopa-bbb
# Official prod=16G; local-dev floor=8G. Koopa lean default=6G + guest swap.
RAM_MIB=6144
VCPUS=2
DISK_GB=50
# Ubuntu 22.04 LTS (bbb-install 3.0). 24.04 only if docs for your branch say so.
OS_VARIANT=ubuntu22.04
CLOUD_IMAGE_URL=https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img
HOSTNAME=bbb.hacktivism.ch
# Bridged LAN (preferred for media DNAT). Set BRIDGE= after host-prep creates br0.
BRIDGE=
# Fallback: libvirt default NAT (media harder; ok for first boot/ssh)
NETWORK_SOURCE=default
# Guest swap (MiB) — important when RAM_MIB < 8192
SWAP_MIB=4096
# SSH pubkey injected via cloud-init (path on koopa host)
SSH_PUBKEY_FILE=/home/hernani/.ssh/id_ed25519.pub
# Disk pool
POOL_DIR=/var/lib/libvirt/images
# bbb-install branch + Greenlight
BBB_INSTALL_BRANCH=v3.0.x-release
BBB_INSTALL_EXTRA=-g
# After VM has IP: Caddy may stay on :9032 stub until cutover, or point at VM:80
CADDY_BACKEND_HINT=VM_HTTP_80_OR_DNAT

View file

@ -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 | 9027 decidim | 9200 forgejo-ssh
# 9020 castopod | 9021 bonfire | 9022 prime | 9023 bt | 9024 forgejo | 9025 paivana | 9026 lemmy | 9027 decidim | 9029 galene | 9030 cryptpad | 9031 meet | 9032 bbb | 9028 silverbullet | 9200 forgejo-ssh
# 9090 tops ng1 | 9091 tops ng2 | 9092 tops ng3
{
@ -332,7 +332,101 @@ decidim.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, http://decidim.hacktivism.ch {
# 9028 silverbullet / SilverBullet — allocated 2026-09-08
# Merge into /etc/caddy/Caddyfile (sudo).
# Also add http://silverbullet.hacktivism.ch to the shared ACME/redirect list.
silverbullet.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9028 {
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
}
}
}
# 9029 galene — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site galene.hacktivism.ch --port 9029 --label galene
galene.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9029 {
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
}
}
}
# 9030 cryptpad — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site cryptpad.hacktivism.ch --port 9030 --label cryptpad
# CryptPad also needs sandbox subdomain (cryptpad-ui / sandbox) — wire after first boot.
cryptpad.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9030 {
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
}
}
}
# 9031 meet (Jitsi) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site meet.hacktivism.ch --port 9031 --label meet
# WebRTC media (UDP/JVB) is separate from this HTTPS vhost — VeciGate/firewall later.
meet.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9031 {
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
}
}
}
# 9032 bbb (BigBlueButton) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site bbb.hacktivism.ch --port 9032 --label bbb
# Stack image base: Ubuntu (not CachyOS). Media/UDP ports TBD with install.
bbb.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9032 {
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, http://galene.hacktivism.ch, http://cryptpad.hacktivism.ch, http://meet.hacktivism.ch, http://bbb.hacktivism.ch {
handle /.well-known/acme-challenge/* {
root * /var/www/acme
file_server

View file

@ -0,0 +1,343 @@
# 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 | 9027 decidim | 9200 forgejo-ssh
# 9090 tops ng1 | 9091 tops ng2 | 9092 tops ng3
{
email info+koopa@hacktivism.ch
http_port 9000
https_port 9001
auto_https disable_redirects
# Caddy listens on 9001 behind VeciGate/https-proxy :443.
# Default HTTP/3 would send Alt-Svc: h3=":9001" — break public HTTPS on :443.
servers {
protocols h1 h2
}
}
(proxy_public) {
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Port 443
header_down Location "^https?://[^/]+:90[0-9]{2}(.*)$" "https://{host}$1"
}
taler.hacktivism.ch {
tls /etc/caddy/certs/taler.hacktivism.ch/fullchain.pem /etc/caddy/certs/taler.hacktivism.ch/privkey.pem
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9015 {
import proxy_public
}
}
# surface + aptdeploy HTML (taler.hacktivism.ch only)
handle /taler-monitoring-surface_err {
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
}
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
}
handle /taler-monitoring-aptdeploy_err* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-aptdeploy {
redir /taler-monitoring-aptdeploy/ 302
}
handle /taler-monitoring-aptdeploy* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-mattermost_err {
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
}
handle /taler-monitoring-mattermost* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-mail_err {
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
}
handle /taler-monitoring-mail* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
# SPA: /webui → /webui/
redir /webui /webui/ 302
# Merchant API + WebUI (nginx :9010 → unix socket)
reverse_proxy https://127.0.0.1:9010 {
transport http {
tls_insecure_skip_verify
}
import proxy_public
}
}
exchange.hacktivism.ch {
tls /etc/caddy/certs/exchange.hacktivism.ch/fullchain.pem /etc/caddy/certs/exchange.hacktivism.ch/privkey.pem
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9014 {
import proxy_public
}
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/exchange.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/exchange.hacktivism.ch
file_server
}
reverse_proxy 127.0.0.1:9011 {
import proxy_public
}
}
bank.hacktivism.ch {
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/bank.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/bank.hacktivism.ch
file_server
}
# Static terms/privacy on landing nginx :9013
handle /terms* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
handle /privacy* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
reverse_proxy 127.0.0.1:9012 {
import proxy_public
}
}
castopod.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9020 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
}
}
bonfire.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9021 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
prime.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9022 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
bt.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9023 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
}
}
# 9024 forgejo HTTP (SSH :9200 host-direct, not via Caddy)
git.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9024 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
flush_interval -1
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
# Taler Operations design previews (static nginx)
tops.ng1.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9090 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
tops.ng2.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9091 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
tops.ng3.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9092 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 9025 paivana-httpd (GOA paywall)
paivana.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9025 {
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
}
}
# 9026 lemmy (+ ui/pictrs via internal nginx)
lemmy.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9026 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
flush_interval -1
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
# 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
}
handle {
redir https://{host}{uri} permanent
}
}

View file

@ -0,0 +1,399 @@
# 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 | 9027 decidim | 9029 galene | 9030 cryptpad | 9031 meet | 9200 forgejo-ssh
# 9090 tops ng1 | 9091 tops ng2 | 9092 tops ng3
{
email info+koopa@hacktivism.ch
http_port 9000
https_port 9001
auto_https disable_redirects
# Caddy listens on 9001 behind VeciGate/https-proxy :443.
# Default HTTP/3 would send Alt-Svc: h3=":9001" — break public HTTPS on :443.
servers {
protocols h1 h2
}
}
(proxy_public) {
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Port 443
header_down Location "^https?://[^/]+:90[0-9]{2}(.*)$" "https://{host}$1"
}
taler.hacktivism.ch {
tls /etc/caddy/certs/taler.hacktivism.ch/fullchain.pem /etc/caddy/certs/taler.hacktivism.ch/privkey.pem
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9015 {
import proxy_public
}
}
# surface + aptdeploy HTML (taler.hacktivism.ch only)
handle /taler-monitoring-surface_err {
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
}
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
}
handle /taler-monitoring-aptdeploy_err* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-aptdeploy {
redir /taler-monitoring-aptdeploy/ 302
}
handle /taler-monitoring-aptdeploy* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-mattermost_err {
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
}
handle /taler-monitoring-mattermost* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-mail_err {
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
}
handle /taler-monitoring-mail* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
# SPA: /webui → /webui/
redir /webui /webui/ 302
# Merchant API + WebUI (nginx :9010 → unix socket)
reverse_proxy https://127.0.0.1:9010 {
transport http {
tls_insecure_skip_verify
}
import proxy_public
}
}
exchange.hacktivism.ch {
tls /etc/caddy/certs/exchange.hacktivism.ch/fullchain.pem /etc/caddy/certs/exchange.hacktivism.ch/privkey.pem
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9014 {
import proxy_public
}
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/exchange.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/exchange.hacktivism.ch
file_server
}
reverse_proxy 127.0.0.1:9011 {
import proxy_public
}
}
bank.hacktivism.ch {
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/bank.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/bank.hacktivism.ch
file_server
}
# Static terms/privacy on landing nginx :9013
handle /terms* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
handle /privacy* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
reverse_proxy 127.0.0.1:9012 {
import proxy_public
}
}
castopod.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9020 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
}
}
bonfire.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9021 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
prime.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9022 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
bt.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9023 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
}
}
# 9024 forgejo HTTP (SSH :9200 host-direct, not via Caddy)
git.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9024 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
flush_interval -1
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
# Taler Operations design previews (static nginx)
tops.ng1.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9090 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
tops.ng2.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9091 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
tops.ng3.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9092 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 9025 paivana-httpd (GOA paywall)
paivana.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9025 {
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
}
}
# 9026 lemmy (+ ui/pictrs via internal nginx)
lemmy.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9026 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
flush_interval -1
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
# 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
}
}
}
# 9029 galene — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site galene.hacktivism.ch --port 9029 --label galene
galene.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9029 {
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
}
}
}
# 9030 cryptpad — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site cryptpad.hacktivism.ch --port 9030 --label cryptpad
# CryptPad also needs sandbox subdomain (cryptpad-ui / sandbox) — wire after first boot.
cryptpad.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9030 {
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
}
}
}
# 9031 meet (Jitsi) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site meet.hacktivism.ch --port 9031 --label meet
# WebRTC media (UDP/JVB) is separate from this HTTPS vhost — VeciGate/firewall later.
meet.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9031 {
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, http://galene.hacktivism.ch, http://cryptpad.hacktivism.ch, http://meet.hacktivism.ch {
handle /.well-known/acme-challenge/* {
root * /var/www/acme
file_server
}
handle {
redir https://{host}{uri} permanent
}
}

View file

@ -0,0 +1,418 @@
# 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 | 9027 decidim | 9029 galene | 9030 cryptpad | 9031 meet | 9032 bbb | 9200 forgejo-ssh
# 9090 tops ng1 | 9091 tops ng2 | 9092 tops ng3
{
email info+koopa@hacktivism.ch
http_port 9000
https_port 9001
auto_https disable_redirects
# Caddy listens on 9001 behind VeciGate/https-proxy :443.
# Default HTTP/3 would send Alt-Svc: h3=":9001" — break public HTTPS on :443.
servers {
protocols h1 h2
}
}
(proxy_public) {
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Port 443
header_down Location "^https?://[^/]+:90[0-9]{2}(.*)$" "https://{host}$1"
}
taler.hacktivism.ch {
tls /etc/caddy/certs/taler.hacktivism.ch/fullchain.pem /etc/caddy/certs/taler.hacktivism.ch/privkey.pem
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9015 {
import proxy_public
}
}
# surface + aptdeploy HTML (taler.hacktivism.ch only)
handle /taler-monitoring-surface_err {
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
}
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
}
handle /taler-monitoring-aptdeploy_err* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-aptdeploy {
redir /taler-monitoring-aptdeploy/ 302
}
handle /taler-monitoring-aptdeploy* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-mattermost_err {
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
}
handle /taler-monitoring-mattermost* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /taler-monitoring-mail_err {
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
}
handle /taler-monitoring-mail* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/taler.hacktivism.ch
file_server
}
# SPA: /webui → /webui/
redir /webui /webui/ 302
# Merchant API + WebUI (nginx :9010 → unix socket)
reverse_proxy https://127.0.0.1:9010 {
transport http {
tls_insecure_skip_verify
}
import proxy_public
}
}
exchange.hacktivism.ch {
tls /etc/caddy/certs/exchange.hacktivism.ch/fullchain.pem /etc/caddy/certs/exchange.hacktivism.ch/privkey.pem
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9014 {
import proxy_public
}
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/exchange.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/exchange.hacktivism.ch
file_server
}
reverse_proxy 127.0.0.1:9011 {
import proxy_public
}
}
bank.hacktivism.ch {
header Alt-Svc "clear"
# Public landing first
redir / /intro/ 302
handle /intro* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
# taler-monitoring console HTML (host static — not in app containers)
handle /monitoring_err {
redir /monitoring_err/ 302
}
handle /monitoring_err* {
root * /var/www/monitoring-sites/bank.hacktivism.ch
file_server
}
handle /monitoring {
redir /monitoring/ 302
}
handle /monitoring* {
root * /var/www/monitoring-sites/bank.hacktivism.ch
file_server
}
# Static terms/privacy on landing nginx :9013
handle /terms* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
handle /privacy* {
reverse_proxy 127.0.0.1:9013 {
import proxy_public
}
}
reverse_proxy 127.0.0.1:9012 {
import proxy_public
}
}
castopod.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9020 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
}
}
bonfire.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9021 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
prime.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9022 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
flush_interval -1
}
}
bt.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9023 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
}
}
# 9024 forgejo HTTP (SSH :9200 host-direct, not via Caddy)
git.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9024 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
flush_interval -1
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
# Taler Operations design previews (static nginx)
tops.ng1.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9090 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
tops.ng2.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9091 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
tops.ng3.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9092 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 9025 paivana-httpd (GOA paywall)
paivana.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9025 {
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
}
}
# 9026 lemmy (+ ui/pictrs via internal nginx)
lemmy.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9026 {
header_up Host {host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
flush_interval -1
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
# 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
}
}
}
# 9029 galene — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site galene.hacktivism.ch --port 9029 --label galene
galene.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9029 {
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
}
}
}
# 9030 cryptpad — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site cryptpad.hacktivism.ch --port 9030 --label cryptpad
# CryptPad also needs sandbox subdomain (cryptpad-ui / sandbox) — wire after first boot.
cryptpad.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9030 {
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
}
}
}
# 9031 meet (Jitsi) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site meet.hacktivism.ch --port 9031 --label meet
# WebRTC media (UDP/JVB) is separate from this HTTPS vhost — VeciGate/firewall later.
meet.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9031 {
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
}
}
}
# 9032 bbb (BigBlueButton) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site bbb.hacktivism.ch --port 9032 --label bbb
# Stack image base: Ubuntu (not CachyOS). Media/UDP ports TBD with install.
bbb.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9032 {
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, http://galene.hacktivism.ch, http://cryptpad.hacktivism.ch, http://meet.hacktivism.ch, http://bbb.hacktivism.ch {
handle /.well-known/acme-challenge/* {
root * /var/www/acme
file_server
}
handle {
redir https://{host}{uri} permanent
}
}

View file

@ -4,6 +4,7 @@
|------|------|
| **`Caddyfile`** | Multi-vhost config mirror (`/etc/caddy/Caddyfile` on host) |
| `git.hacktivism.ch.caddy` | Site-block snippet for Forgejo |
| `silverbullet.hacktivism.ch.caddy` | Site-block snippet for SilverBullet |
| `Caddyfile.taler-host` | **Legacy** Taler-only sketch — do not deploy |
Also: `host/caddy/Caddyfile` (same as `Caddyfile` here).

View file

@ -0,0 +1,18 @@
# 9032 bbb (BigBlueButton) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site bbb.hacktivism.ch --port 9032 --label bbb
# Stack image base: Ubuntu (not CachyOS). Media/UDP ports TBD with install.
bbb.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9032 {
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
}
}
}

View file

@ -0,0 +1,18 @@
# 9030 cryptpad — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site cryptpad.hacktivism.ch --port 9030 --label cryptpad
# Backend is koopa-cryptpad-edge (HTTP+WS). Sandbox subdomain (cryptpad-ui) — wire after first boot.
cryptpad.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9030 {
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
}
}
}

View file

@ -0,0 +1,17 @@
# 9029 galene — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site galene.hacktivism.ch --port 9029 --label galene
galene.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9029 {
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
}
}
}

View file

@ -0,0 +1,18 @@
# 9031 meet (Jitsi) — allocated 2026-09-08
# Merge: scripts/caddy/caddy-apply.sh --site meet.hacktivism.ch --port 9031 --label meet
# WebRTC media (UDP/JVB) is separate from this HTTPS vhost — VeciGate/firewall later.
meet.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9031 {
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
}
}
}

View file

@ -0,0 +1,18 @@
# 9028 silverbullet / SilverBullet — allocated 2026-09-08
# Merge into /etc/caddy/Caddyfile (sudo).
# Also add http://silverbullet.hacktivism.ch to the shared ACME/redirect list.
silverbullet.hacktivism.ch {
header Alt-Svc "clear"
reverse_proxy 127.0.0.1:9028 {
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
}
}
}

View file

@ -0,0 +1,47 @@
# koopa-cryptpad — CryptPad on CachyOS base + Node from pacman
# Build on koopa (x86_64):
# bash ~/koopa-admin-log/scripts/cryptpad/build.sh
# → localhost/koopa-cryptpad:cachyos
#
# App tree from upstream release tarball (not the official Debian-ish image).
ARG CACHYOS_IMAGE=docker.io/cachyos/cachyos:latest
FROM ${CACHYOS_IMAGE}
ARG CRYPTPAD_VERSION=2025.9.0
ARG CRYPTPAD_URL=https://github.com/cryptpad/cryptpad/archive/refs/tags/${CRYPTPAD_VERSION}.tar.gz
ENV TZ=Europe/Zurich \
PATH=/usr/local/bin:$PATH \
CRYPTPAD_HOME=/cryptpad
RUN pacman -Syu --noconfirm --needed \
bash curl ca-certificates catatonit tar git \
nodejs npm \
&& pacman -Scc --noconfirm \
&& rm -rf /var/cache/pacman/pkg/* /tmp/*
# npm may block git deps (EALLOWGIT); rewrite git+ssh → https and allow git installs.
RUN curl -fsSL "$CRYPTPAD_URL" -o /tmp/cryptpad.tgz \
&& mkdir -p /cryptpad \
&& tar -xzf /tmp/cryptpad.tgz -C /cryptpad --strip-components=1 \
&& rm -f /tmp/cryptpad.tgz \
&& cd /cryptpad \
&& git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" \
&& git config --global url."https://github.com/".insteadOf "git@github.com:" \
&& git config --global url."https://".insteadOf "git://" \
&& printf 'allow-git=all\nallow-remote=all\n' > /root/.npmrc \
&& (npm ci --omit=dev --allow-git=all --allow-remote=all \
|| npm install --omit=dev --allow-git=all --allow-remote=all) \
&& (npm run install:components || true) \
&& rm -rf /root/.npm /tmp/* /var/cache/pacman/pkg/*
COPY entrypoint.sh /docker-entrypoint.sh
RUN mkdir -p /cryptpad/config /cryptpad/data /cryptpad/datastore /cryptpad/block /cryptpad/blob \
/cryptpad/blobstage /cryptpad/data/logs
COPY config.example.js /cryptpad/config/config.js
RUN chmod 755 /docker-entrypoint.sh
EXPOSE 3000
WORKDIR /cryptpad
ENTRYPOINT ["/usr/bin/catatonit", "--", "/docker-entrypoint.sh"]

View file

@ -0,0 +1,32 @@
# CryptPad — on CachyOS (koopa)
| Item | Value |
|------|--------|
| Stack | [CryptPad](https://cryptpad.org/) |
| Image | `localhost/koopa-cryptpad:cachyos` |
| Live dir | `/home/hernani/koopa-cryptpad/` |
| Host port | **9030** = Paivana paywall; nginx edge backend **127.0.0.1:19130** → app |
| App ports (internal) | **3000** HTTP, **3003** websocket |
| Public site | `cryptpad.hacktivism.ch` |
`websocketPort` must differ from `httpPort` (upstream default 3003). Compose runs `koopa-cryptpad-edge` (nginx) so Caddy still only targets **9030**.
Upstream wants a separate **safe/sandbox** origin for some builds — add a second vhost after first boot if the admin UI requires it.
## Build + up
```bash
bash /path/to/koopa-admin-log/scripts/cryptpad/build.sh
mkdir -p ~/koopa-cryptpad
cp -a /path/to/koopa-admin-log/configs/cryptpad/{compose.yml,config.example.js} ~/koopa-cryptpad/
cp ~/koopa-cryptpad/config.example.js ~/koopa-cryptpad/config.js
# edit httpUnsafeOrigin / httpSafeOrigin in config.js
cd ~/koopa-cryptpad && podman-compose up -d
```
## Caddy
```bash
sudo bash /path/to/koopa-admin-log/scripts/caddy/caddy-apply.sh \
--snippet …/configs/caddy/cryptpad.hacktivism.ch.caddy \
--site cryptpad.hacktivism.ch --port 9030 --label cryptpad
```

View file

@ -0,0 +1,53 @@
# koopa-cryptpad — CryptPad on CachyOS + nginx edge (HTTP+WS on :9030)
# Live: /home/hernani/koopa-cryptpad/
# Build: bash ~/koopa-admin-log/scripts/cryptpad/build.sh → localhost/koopa-cryptpad:cachyos
#
# Public :9030 = koopa-paivana-cryptpad (shared paivana image).
# Edge backend loopback only — Paivana DEST → 127.0.0.1:19130
# App listens 3000 (http) + 3003 (websocket) inside the net.
services:
cryptpad:
image: localhost/koopa-cryptpad:cachyos
build:
context: .
dockerfile: Containerfile
args:
CRYPTPAD_VERSION: "${CRYPTPAD_VERSION:-2025.9.0}"
container_name: koopa-cryptpad
restart: unless-stopped
environment:
- TZ=Europe/Zurich
volumes:
- ./data:/cryptpad/data
- ./datastore:/cryptpad/datastore
- ./block:/cryptpad/block
- ./blob:/cryptpad/blob
- ./config.js:/cryptpad/config/config.js:ro
expose:
- "3000"
- "3003"
labels:
org.hacktivism.service: cryptpad
org.hacktivism.host_port: "9030"
org.hacktivism.backend_port: "${BACKEND_PORT:-19130}"
org.hacktivism.site: cryptpad.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.port_status: backend-19130-paywall-9030
org.hacktivism.image_base: cachyos
edge:
image: docker.io/library/nginx:alpine
container_name: koopa-cryptpad-edge
restart: unless-stopped
depends_on:
- cryptpad
volumes:
- ./edge.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "127.0.0.1:${BACKEND_PORT:-19130}:80"
labels:
org.hacktivism.service: cryptpad-edge
org.hacktivism.host_port: "9030"
org.hacktivism.backend_port: "${BACKEND_PORT:-19130}"
org.hacktivism.site: cryptpad.hacktivism.ch
org.hacktivism.managed_by: koopa-admin

View file

@ -0,0 +1,13 @@
/* CryptPad config http on 3000, websockets on 3003 (must differ).
* Live: mount ./config.js over /cryptpad/config/config.js
* Edge nginx in compose merges both onto host :9030 (Caddy unchanged).
*/
module.exports = {
httpUnsafeOrigin: 'https://cryptpad.hacktivism.ch',
httpSafeOrigin: 'https://cryptpad.hacktivism.ch',
httpAddress: '0.0.0.0',
httpPort: 3000,
websocketPort: 3003,
logToStdout: true,
maxWorkers: 2,
};

View file

@ -0,0 +1,37 @@
# Front for koopa-cryptpad: HTTP :3000 + /cryptpad_websocket → :3003
upstream cryptpad_http {
server cryptpad:3000;
}
upstream cryptpad_ws {
server cryptpad:3003;
}
server {
listen 80 default_server;
server_name _;
client_max_body_size 150m;
location /cryptpad_websocket {
proxy_pass http://cryptpad_ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
proxy_pass http://cryptpad_http;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}

5
configs/cryptpad/entrypoint.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
set -euo pipefail
cd /cryptpad
# Expect config.js already present (compose mounts or image default).
exec node server.js "$@"

View file

@ -0,0 +1,41 @@
# koopa-galene — Galene SFU on CachyOS base
# Build on koopa (x86_64):
# bash ~/koopa-admin-log/scripts/galene/build.sh
# → localhost/koopa-galene:cachyos
#
# Upstream no longer ships release tarballs; build from git tag/branch.
ARG CACHYOS_IMAGE=docker.io/cachyos/cachyos:latest
FROM ${CACHYOS_IMAGE}
ARG GALENE_REF=galene-0.96.3
ARG GALENE_REPO=https://github.com/jech/galene.git
ENV TZ=Europe/Zurich \
PATH=/usr/local/bin:$PATH \
GALENE_DATA=/data \
GOPATH=/tmp/go \
GOTOOLCHAIN=auto
RUN pacman -Syu --noconfirm --needed \
bash curl ca-certificates catatonit tar git go \
&& pacman -Scc --noconfirm \
&& rm -rf /var/cache/pacman/pkg/* /tmp/*
RUN set -eux \
&& git clone --depth 1 --branch "$GALENE_REF" "$GALENE_REPO" /src/galene \
&& cd /src/galene \
&& CGO_ENABLED=0 go build -ldflags='-s -w' -o /usr/local/bin/galene . \
&& test -x /usr/local/bin/galene \
&& mkdir -p /opt/galene \
&& cp -a /src/galene/static /opt/galene/static \
&& rm -rf /src/galene /tmp/go /root/go /var/cache/pacman/pkg/*
COPY entrypoint.sh /docker-entrypoint.sh
RUN chmod 755 /docker-entrypoint.sh \
&& mkdir -p /data/groups /data/recordings /data/data \
&& ln -sfn /opt/galene/static /data/static
EXPOSE 8443
WORKDIR /data
ENTRYPOINT ["/usr/bin/catatonit", "--", "/docker-entrypoint.sh"]

36
configs/galene/README.md Normal file
View file

@ -0,0 +1,36 @@
# Galene — SFU on CachyOS (koopa)
| Item | Value |
|------|--------|
| Stack | [Galene](https://galene.org/) |
| Image | `localhost/koopa-galene:cachyos` (`FROM docker.io/cachyos/cachyos`) |
| Build | Go from git tag `GALENE_REF` (default `galene-0.96.3`; no release tarballs) |
| Live dir | `/home/hernani/koopa-galene/` |
| Container | `koopa-galene` |
| Host port | **9029** = Paivana paywall; Galene HTTP backend **127.0.0.1:19129** (`-insecure`) |
| Public site | `galene.hacktivism.ch` |
## Build + up (koopa)
```bash
bash /path/to/koopa-admin-log/scripts/galene/build.sh
mkdir -p ~/koopa-galene && cp -a /path/to/koopa-admin-log/configs/galene/compose.yml ~/koopa-galene/
cd ~/koopa-galene && podman-compose up -d
```
## Caddy
```bash
sudo bash /path/to/koopa-admin-log/scripts/caddy/caddy-apply.sh \
--snippet /path/to/koopa-admin-log/configs/caddy/galene.hacktivism.ch.caddy \
--site galene.hacktivism.ch --port 9029 --label galene
```
DNS + VeciGate for the hostname; WebRTC UDP ports documented when first room is live.
## Notes
- Volume `./data` must not hide UI assets; entrypoint passes `-static /opt/galene/static`.
- Example group: copy `groups/hacktivism.json.example``~/koopa-galene/data/groups/hacktivism.json` (change op password).
- WebRTC UDP: compose publishes **1000010099/udp**; set the same range in VeciGate DNAT → koopa. Entrypoint uses `-udp-range` (`GALENE_UDP_RANGE`).
- Built-in TURN (`-turn auto`) logs `no public addresses` until the host has a reachable public/mapped address; fix UDP/NAT first, then re-check logs.

View file

@ -0,0 +1,30 @@
# koopa-galene — Galene on CachyOS
# Live: /home/hernani/koopa-galene/
# Build: bash ~/koopa-admin-log/scripts/galene/build.sh → localhost/koopa-galene:cachyos
#
# Public :9029 = koopa-paivana-galene (shared paivana image).
# Backend loopback only — Paivana DEST → 127.0.0.1:19129 (HTTP -insecure).
# WebRTC UDP: still published (see README / ports.md)
services:
galene:
image: localhost/koopa-galene:cachyos
container_name: koopa-galene
restart: unless-stopped
environment:
- TZ=Europe/Zurich
- GALENE_UDP_RANGE=${GALENE_UDP_RANGE:-10000-10099}
volumes:
- ./data:/data
- ./entrypoint.sh:/docker-entrypoint.sh:ro
ports:
- "127.0.0.1:${BACKEND_PORT:-19129}:8443"
- "${GALENE_UDP_LO:-10000}-${GALENE_UDP_HI:-10099}:${GALENE_UDP_LO:-10000}-${GALENE_UDP_HI:-10099}/udp"
labels:
org.hacktivism.service: galene
org.hacktivism.host_port: "9029"
org.hacktivism.backend_port: "${BACKEND_PORT:-19129}"
org.hacktivism.site: galene.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.port_status: backend-19129-paywall-9029
org.hacktivism.image_base: cachyos

21
configs/galene/entrypoint.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/bash
set -euo pipefail
# Galene listens HTTPS by default; behind Caddy we serve plain HTTP on :8443
# with -insecure (TLS terminated at Caddy).
# Static assets stay in the image (/opt/galene/static); the ./data volume must
# not shadow them — pass -static explicitly.
DATA="${GALENE_DATA:-/data}"
STATIC="${GALENE_STATIC:-/opt/galene/static}"
# Host/UDP map: VeciGate WAN → koopa 10000-10099/udp (see configs/ports.md).
UDP_RANGE="${GALENE_UDP_RANGE:-10000-10099}"
mkdir -p "$DATA/groups" "$DATA/recordings" "$DATA/data"
cd "$DATA"
exec /usr/local/bin/galene \
-http "0.0.0.0:8443" \
-insecure \
-static "$STATIC" \
-udp-range "$UDP_RANGE" \
-data "$DATA/data" \
-groups "$DATA/groups" \
-recordings "$DATA/recordings" \
"$@"

View file

@ -0,0 +1,7 @@
{
"displayName": "hacktivism",
"public": true,
"op": [{"username": "op", "password": "changeme"}],
"presenter": [{}],
"other": []
}

View file

@ -0,0 +1,55 @@
# koopa-meet-web — Jitsi Meet web assets on CachyOS
# Build: bash ~/koopa-admin-log/scripts/meet/build.sh → localhost/koopa-meet-web:cachyos
#
# Full Meet needs prosody + jicofo + jvb (see compose.yml). This image serves
# the static web UI via nginx from Arch/CachyOS packages + upstream meet tarball.
# Signaling/media containers are separate services in the same compose.
ARG CACHYOS_IMAGE=docker.io/cachyos/cachyos:latest
FROM ${CACHYOS_IMAGE}
ARG JITSI_MEET_VERSION=stable
ARG JITSI_MEET_URL=https://download.jitsi.org/jitsi-meet/src/jitsi-meet-1.0.0.tar.bz2
ENV TZ=Europe/Zurich
RUN pacman -Syu --noconfirm --needed \
bash curl ca-certificates catatonit tar nginx \
&& pacman -Scc --noconfirm \
&& rm -rf /var/cache/pacman/pkg/* /tmp/*
# CachyOS/Arch nginx.conf embeds a default server and does NOT include http.d/.
# Replace it with a minimal conf that serves the branded landing.
RUN mkdir -p /usr/share/jitsi-meet /etc/nginx/http.d \
&& printf '%s\n' \
'worker_processes 1;' \
'events { worker_connections 1024; }' \
'http {' \
' include mime.types;' \
' default_type application/octet-stream;' \
' sendfile on;' \
' keepalive_timeout 65;' \
' server {' \
' listen 80 default_server;' \
' server_name _;' \
' root /usr/share/jitsi-meet;' \
' index index.html;' \
' location / { try_files $uri $uri/ /index.html; }' \
' }' \
'}' > /etc/nginx/nginx.conf \
&& printf '%s\n' \
'<!doctype html><html lang=en><meta charset=utf-8>' \
'<meta name=viewport content="width=device-width,initial-scale=1">' \
'<title>meet.hacktivism.ch</title>' \
'<style>body{font-family:system-ui,sans-serif;max-width:40rem;margin:3rem auto;padding:0 1rem;line-height:1.5}' \
'code{background:#f2f2f2;padding:.1rem .35rem;border-radius:4px}</style>' \
'<h1>meet.hacktivism.ch</h1>' \
'<p>Jitsi Meet <strong>web</strong> (CachyOS). Signaling/media (prosody / jicofo / jvb) is Phase&nbsp;2 — see compose + README.</p>' \
'<p>HTTP OK on host port <code>9031</code>. Full rooms need UDP/JVB after Phase&nbsp;2.</p>' \
> /usr/share/jitsi-meet/index.html
COPY entrypoint.sh /docker-entrypoint.sh
RUN chmod 755 /docker-entrypoint.sh
EXPOSE 80
ENTRYPOINT ["/usr/bin/catatonit", "--", "/docker-entrypoint.sh"]

23
configs/meet/README.md Normal file
View file

@ -0,0 +1,23 @@
# Meet (Jitsi) — CachyOS web stub (koopa)
| Item | Value |
|------|--------|
| Public site | `meet.hacktivism.ch` |
| Public port | **9031** (`koopa-paivana-meet`) |
| Backend | `127.0.0.1:19131` (`koopa-meet-web`) |
| Image (web) | `localhost/koopa-meet-web:cachyos` |
| Live dir | `/home/hernani/koopa-meet/` |
Phase 1 = Caddy vhost + branded nginx landing on CachyOS (`koopa-meet-web`) behind Paivana (GOA:42).
Phase 2 = prosody + jicofo + jvb — scaffold in `compose.phase2.yml` (`profiles: [phase2]`); images under `configs/meet/phase2/` still TODO. Not `docker-jitsi-meet` Debian by default.
UDP/JVB and TURN need VeciGate once rooms work (range TBD in `ports.md`).
## Caddy
Caddy stays on `127.0.0.1:9031` (paywall). App bind is loopback `19131` only.
```bash
sudo bash /path/to/koopa-admin-log/scripts/caddy/caddy-apply.sh \
--snippet …/configs/caddy/meet.hacktivism.ch.caddy \
--site meet.hacktivism.ch --port 9031 --label meet
```

View file

@ -0,0 +1,49 @@
# Phase-2 stubs — NOT started by default.
# Usage (after images exist):
# cd ~/koopa-meet && podman-compose -f compose.yml -f compose.phase2.yml up -d
#
# Do not pull official docker-jitsi-meet Debian images as the default base.
# Build CachyOS (or pinned binary) images under configs/meet/phase2/ when ready.
services:
prosody:
profiles: ["phase2"]
image: localhost/koopa-meet-prosody:cachyos
container_name: koopa-meet-prosody
restart: unless-stopped
environment:
- TZ=Europe/Zurich
# ports / volumes: fill when Containerfile exists
labels:
org.hacktivism.service: meet-prosody
org.hacktivism.site: meet.hacktivism.ch
org.hacktivism.phase: "2"
jicofo:
profiles: ["phase2"]
image: localhost/koopa-meet-jicofo:cachyos
container_name: koopa-meet-jicofo
restart: unless-stopped
environment:
- TZ=Europe/Zurich
depends_on:
- prosody
labels:
org.hacktivism.service: meet-jicofo
org.hacktivism.site: meet.hacktivism.ch
org.hacktivism.phase: "2"
jvb:
profiles: ["phase2"]
image: localhost/koopa-meet-jvb:cachyos
container_name: koopa-meet-jvb
restart: unless-stopped
environment:
- TZ=Europe/Zurich
# UDP host publish TBD in ports.md when allocated
depends_on:
- prosody
labels:
org.hacktivism.service: meet-jvb
org.hacktivism.site: meet.hacktivism.ch
org.hacktivism.phase: "2"

26
configs/meet/compose.yml Normal file
View file

@ -0,0 +1,26 @@
# koopa-meet — Jitsi Meet (CachyOS web stub + follow-up signaling/media)
# Live: /home/hernani/koopa-meet/
# Public :9031 = koopa-paivana-meet (shared paivana image).
# Backend loopback only — Paivana DEST → 127.0.0.1:19131
#
# Next: add prosody / jicofo / jvb services (CachyOS images or pinned binaries).
# Official docker-jitsi-meet is Debian-based — do not pull those as default here.
services:
meet-web:
image: localhost/koopa-meet-web:cachyos
build:
context: .
dockerfile: Containerfile
container_name: koopa-meet-web
restart: unless-stopped
environment:
- TZ=Europe/Zurich
ports:
- "127.0.0.1:${BACKEND_PORT:-19131}:80"
labels:
org.hacktivism.service: meet
org.hacktivism.backend_port: "${BACKEND_PORT:-19131}"
org.hacktivism.site: meet.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.port_status: backend-19131-paywall-9031
org.hacktivism.image_base: cachyos

3
configs/meet/entrypoint.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
set -euo pipefail
exec nginx -g 'daemon off;'

View file

@ -0,0 +1,5 @@
# Live on koopa: ~/koopa-silverbullet/.env (not git)
# Allocate HOST_PORT only after live `ss` + Freigabe + ports.md update.
HOST_PORT=9028
# Optional SilverBullet app auth (prefer Caddy basicauth):
# SB_USER=hernani:changeme

View file

@ -0,0 +1,44 @@
# koopa-silverbullet — SilverBullet on CachyOS base + server binary
# Build on koopa (x86_64):
# bash ~/koopa-admin-log/scripts/notes/build.sh
# → localhost/koopa-silverbullet:cachyos
#
# Base: docker.io/cachyos/cachyos (Arch-derived). App binary from upstream
# silverbullet-server-linux-x86_64 release (not the Alpine ghcr image).
ARG CACHYOS_IMAGE=docker.io/cachyos/cachyos:latest
FROM ${CACHYOS_IMAGE}
ARG SB_VERSION=2.10.0
ARG SB_ZIP_URL=https://github.com/silverbulletmd/silverbullet/releases/download/${SB_VERSION}/silverbullet-server-linux-x86_64.zip
ENV SB_HOSTNAME=0.0.0.0 \
SB_FOLDER=/space \
SB_PORT=3000 \
SB_NAME=SilverBullet \
TZ=Europe/Zurich \
PATH=/usr/local/bin:$PATH
# catatonit = Arch/CachyOS container init (tini not in repos)
RUN pacman -Syu --noconfirm --needed \
bash curl git openssh catatonit unzip \
&& pacman -Scc --noconfirm \
&& rm -rf /var/cache/pacman/pkg/* /tmp/*
# Fetch + install server binary (build-time; no Deno in image)
RUN curl -fsSL "$SB_ZIP_URL" -o /tmp/sb.zip \
&& unzip -o /tmp/sb.zip -d /tmp \
&& install -m 755 /tmp/silverbullet /silverbullet \
&& /silverbullet --version || true \
&& rm -rf /tmp/sb.zip /tmp/silverbullet
COPY entrypoint.sh /docker-entrypoint.sh
RUN chmod 755 /docker-entrypoint.sh \
&& mkdir -p /space
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS "http://127.0.0.1:${SB_PORT}/.instance" || exit 1
WORKDIR /space
ENTRYPOINT ["/usr/bin/catatonit", "--", "/docker-entrypoint.sh"]

65
configs/notes/README.md Normal file
View file

@ -0,0 +1,65 @@
# SilverBullet — SilverBullet on CachyOS (koopa)
Cross-host markdown notes (magikoopa + clementine). Stack name **SilverBullet** (parked web UI). Product **FreeNotes** = separate native enc notes (not this stack).
| Item | Value |
|------|--------|
| Stack | [SilverBullet](https://silverbullet.md/) server binary |
| Image | `localhost/koopa-silverbullet:cachyos` (`FROM docker.io/cachyos/cachyos`) |
| Live dir | `/home/hernani/koopa-silverbullet/` |
| Container | `koopa-silverbullet` |
| Host port | **9028** = Paivana paywall; app backend **127.0.0.1:19128** |
| Public site | `silverbullet.hacktivism.ch` |
| Auth | Paivana (GOA:42); no Caddy basic_auth |
| Forgejo space backup | private `hernani/freenotes` (historical name; SB space only) |
## Cutover freenotes → silverbullet (koopa)
Live still may be `~/koopa-freenotes` / CT `koopa-freenotes`. Scripts default dry-run; `--apply` needs Freigabe.
```bash
bash /path/to/koopa-admin-log/scripts/notes/status.sh
bash /path/to/koopa-admin-log/scripts/notes/cutover-to-silverbullet.sh
# Freigabe:
bash /path/to/koopa-admin-log/scripts/notes/cutover-to-silverbullet.sh --apply
```
See `scripts/notes/README.md` for seed + Caddy order. DNS: `silverbullet.hacktivism.ch`.
## Build + recreate (koopa)
```bash
# clone koopa-admin-log from Forgejo when needed (no permanent ~/ clone)
bash /path/to/koopa-admin-log/scripts/notes/build.sh
cd ~/koopa-silverbullet
podman-compose down
podman-compose up -d
bash /path/to/koopa-admin-log/scripts/notes/up.sh
```
## Caddy apply (sudo on koopa)
```bash
sudo bash /path/to/koopa-admin-log/scripts/caddy/merge-notes-site.sh
# seed from secrets-enc SoT so apply does not rotate PASS
sudo NOTES_AUTH_SEED=/tmp/silverbullet-basicauth-seed.txt \
bash /path/to/koopa-admin-log/scripts/caddy/apply-notes-basicauth.sh
```
Runtime: `/etc/caddy/secrets/silverbullet-basicauth.txt` (root-only). Never recreate `~/koopa-secrets`.
## Space SoT (Forgejo)
Private `hernani/freenotes` — live tree `~/koopa-silverbullet/space/` (git). On-koopa push uses oneshot HTTP token (no hernani SSH key in `~/.ssh`); laptop push via `git@git.hacktivism.ch:hernani/freenotes.git` (ProxyJump).
## Client apps (hosts)
Notes-like **system apps** (standalone Brave/Chrome `--app=` window + own profile): `configs/notes/client-apps/`.
- magikoopa: `~/Applications/SilverBullet.app``bash client-apps/install-magikoopa.sh`
- clementine (on-box): `silverbullet.desktop``bash client-apps/install-clementine.sh`
- optional: browser **Install app** (PWA) for Dock identity
## Plugs (SB)
`space/_plug/`: `treeview.plug.js`, `silversearch.plug.js` — see `PLUGS.md`.

View file

@ -0,0 +1,23 @@
# SilverBullet — system Notes apps (hosts)
Goal: **like Apple Notes** — a real system app window on each laptop, not a browser bookmark and not SilverBullet plugs.
| Host | App | Behavior |
|------|-----|----------|
| magikoopa | `SilverBullet.app``~/Applications/` | Brave/Chrome **`--app=`** + own profile (`SilverBullet-BraveProfile`) — no tab bar |
| clementine | `silverbullet.desktop` | same `--app=` via Brave/Chromium + `~/.local/share/SilverBullet-browser` |
| both (optional) | Browser **Install app** / PWA | even closer to native Dock/menu identity |
**Not this:** `space/_plug/` (TreeView/SilverSearch) — those are in-editor extensions.
Install:
```bash
# magikoopa
bash configs/notes/client-apps/install-magikoopa.sh
# clementine (on-box)
bash configs/notes/client-apps/install-clementine.sh
```
First launch: log in once (Caddy basicauth); credentials stay in the app profile.

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key><string>SilverBullet</string>
<key>CFBundleDisplayName</key><string>SilverBullet</string>
<key>CFBundleIdentifier</key><string>ch.hacktivism.silverbullet</string>
<key>CFBundleVersion</key><string>1</string>
<key>CFBundleShortVersionString</key><string>1.0</string>
<key>CFBundleExecutable</key><string>SilverBullet</string>
<key>CFBundlePackageType</key><string>APPL</string>
<key>LSMinimumSystemVersion</key><string>12.0</string>
<key>CFBundleIconFile</key><string>AppIcon</string>
</dict>
</plist>

View file

@ -0,0 +1,31 @@
#!/bin/bash
# SilverBullet — Notes-like system app (standalone window, not a browser tab)
URL="https://silverbullet.hacktivism.ch/"
USER_DATA="${HOME}/Library/Application Support/SilverBullet-BraveProfile"
mkdir -p "$USER_DATA"
BRAVE="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
# Dedicated Chromium profile so this feels like its own app (Dock, cookies, no tab chrome)
if [[ -x "$BRAVE" ]]; then
exec "$BRAVE" \
--user-data-dir="$USER_DATA" \
--class=SilverBullet \
--app="$URL" \
--name=SilverBullet
elif [[ -x "$CHROME" ]]; then
exec "$CHROME" \
--user-data-dir="$USER_DATA" \
--class=SilverBullet \
--app="$URL" \
--name=SilverBullet
else
# last resort: Safari has no --app; open dedicated window via osascript
exec osascript <<'OSA'
tell application "Safari"
activate
make new document with properties {URL:"https://silverbullet.hacktivism.ch/"}
end tell
OSA
fi

View file

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Install SilverBullet XFCE launcher on clementine (on-box). No Freigabe (user home).
set -euo pipefail
SRC="$(cd "$(dirname "$0")" && pwd)/silverbullet.desktop"
APPDIR="${HOME}/.local/share/applications"
DESK="${HOME}/Desktop"
mkdir -p "$APPDIR" "$DESK"
install -m 0644 "$SRC" "$APPDIR/silverbullet.desktop"
install -m 0644 "$SRC" "$DESK/silverbullet.desktop"
# refresh menu cache if available
command -v update-desktop-database >/dev/null && update-desktop-database "$APPDIR" || true
echo "STATUS=ok DESKTOP=$APPDIR/silverbullet.desktop SHORTCUT=$DESK/silverbullet.desktop"
echo "TIP=open https://silverbullet.hacktivism.ch then browser Install app for PWA"

View file

@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Install SilverBullet.app into ~/Applications (magikoopa). No Freigabe (user home).
set -euo pipefail
SRC="$(cd "$(dirname "$0")" && pwd)/SilverBullet.app"
DEST="${HOME}/Applications/SilverBullet.app"
URL="${HOME}/Desktop/SilverBullet.url"
mkdir -p "${HOME}/Applications" "${HOME}/Desktop"
if [[ -d "$SRC" ]]; then
rm -rf "$DEST"
cp -R "$SRC" "$DEST"
else
# bootstrap minimal app if scaffold app tree missing
mkdir -p "$DEST/Contents/MacOS" "$DEST/Contents/Resources"
cat >"$DEST/Contents/Info.plist" <<'PLIST'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key><string>SilverBullet</string>
<key>CFBundleDisplayName</key><string>SilverBullet</string>
<key>CFBundleIdentifier</key><string>ch.hacktivism.silverbullet</string>
<key>CFBundleVersion</key><string>1</string>
<key>CFBundleShortVersionString</key><string>1.0</string>
<key>CFBundleExecutable</key><string>SilverBullet</string>
<key>CFBundlePackageType</key><string>APPL</string>
<key>LSMinimumSystemVersion</key><string>12.0</string>
</dict>
</plist>
PLIST
printf '%s\n' '#!/bin/bash' 'open "https://silverbullet.hacktivism.ch/"' >"$DEST/Contents/MacOS/SilverBullet"
chmod +x "$DEST/Contents/MacOS/SilverBullet"
fi
printf '%s\n' '[InternetShortcut]' 'URL=https://silverbullet.hacktivism.ch/' >"$URL"
echo "STATUS=ok APP=$DEST URL=$URL"

View file

@ -0,0 +1,12 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=SilverBullet
Comment=Notes-like SilverBullet on koopa standalone window
TryExec=brave-browser
Exec=sh -c 'B=""; for c in brave-browser brave chromium chromium-browser google-chrome; do command -v "$c" >/dev/null && B="$c" && break; done; if [ -n "$B" ]; then exec "$B" --user-data-dir="$HOME/.local/share/SilverBullet-browser" --class=SilverBullet --app=https://silverbullet.hacktivism.ch/; else exec xdg-open https://silverbullet.hacktivism.ch/; fi'
Terminal=false
Categories=Office;Network;
Keywords=notes;todo;silverbullet;
StartupWMClass=SilverBullet
StartupNotify=true

38
configs/notes/compose.yml Normal file
View file

@ -0,0 +1,38 @@
# koopa-silverbullet — SilverBullet on CachyOS base (parked; FreeNotes = native enc)
# Live: /home/hernani/koopa-silverbullet/
# Build: bash ~/koopa-admin-log/scripts/notes/build.sh → localhost/koopa-silverbullet:cachyos
#
# Public :9028 = koopa-paivana-silverbullet (shared paivana image).
# Backend loopback only — Paivana DEST → 127.0.0.1:19128
services:
notes:
image: localhost/koopa-silverbullet:cachyos
build:
context: .
dockerfile: Containerfile
args:
SB_VERSION: "${SB_VERSION:-2.10.0}"
container_name: koopa-silverbullet
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Zurich
- SB_INDEX_PAGE=index
- SB_NAME=SilverBullet
- SB_SHELL_BACKEND=off
# Optional app-layer auth (prefer Caddy basicauth; leave empty in .env to skip):
# - SB_USER=${SB_USER}
volumes:
- ./space:/space
ports:
- "127.0.0.1:${BACKEND_PORT:-19128}:3000"
labels:
org.hacktivism.service: silverbullet
org.hacktivism.host_port: "9028"
org.hacktivism.backend_port: "${BACKEND_PORT:-19128}"
org.hacktivism.site: silverbullet.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.port_status: backend-19128-paywall-9028
org.hacktivism.image_base: cachyos

View file

@ -0,0 +1,28 @@
# container-koopa-silverbullet.service
# Install on koopa as hernani (after compose create):
# mkdir -p ~/.config/systemd/user
# cp configs/notes/container-koopa-silverbullet.service ~/.config/systemd/user/
# systemctl --user daemon-reload
# systemctl --user enable --now container-koopa-silverbullet.service
# Requires: loginctl enable-linger hernani (root, once)
#
# Container must already exist (podman-compose up -d once).
[Unit]
Description=Podman container-koopa-silverbullet.service (SilverBullet)
Documentation=https://silverbullet.md/
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/user/1000/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
TimeoutStopSec=90
ExecStart=/usr/bin/podman start koopa-silverbullet
ExecStop=/usr/bin/podman stop -t 20 koopa-silverbullet
ExecStopPost=/usr/bin/podman stop -t 20 koopa-silverbullet
Type=forking
[Install]
WantedBy=default.target

36
configs/notes/entrypoint.sh Executable file
View file

@ -0,0 +1,36 @@
#!/bin/bash
# SilverBullet entrypoint (CachyOS/Arch user tools).
# Adapted from upstream docker-entrypoint.sh (busybox → shadow useradd).
set -euo pipefail
if [[ -f /space/CONTAINER_BOOT.md ]]; then
echo "Executing CONTAINER_BOOT.md script"
bash /space/CONTAINER_BOOT.md &
fi
SB_FOLDER="${SB_FOLDER:-/space}"
if [[ -z "${PUID:-}" && "$(id -u)" == "0" ]]; then
PUID=$(stat -c "%u" "$SB_FOLDER")
echo "Will run SilverBullet with UID $PUID (from owner of $SB_FOLDER)"
fi
if [[ -z "${PGID:-}" ]]; then
PGID=$(stat -c "%g" "$SB_FOLDER")
fi
if [[ "${PUID:-0}" == "0" || "$(id -u)" != "0" ]]; then
exec /silverbullet "$@"
fi
echo "Creating silverbullet user UID=$PUID GID=$PGID"
getent group silverbullet >/dev/null 2>&1 || groupadd -g "$PGID" silverbullet || groupadd -o -g "$PGID" silverbullet
getent passwd silverbullet >/dev/null 2>&1 || useradd -M -N -g silverbullet -u "$PUID" -d "$SB_FOLDER" -s /bin/bash silverbullet \
|| useradd -o -M -N -g silverbullet -u "$PUID" -d "$SB_FOLDER" -s /bin/bash silverbullet
echo "Running SilverBullet as PUID=$PUID PGID=$PGID"
# quote-safe: pass args via "$@" under su -c is awkward; use runuser when present
if command -v runuser >/dev/null 2>&1; then
exec runuser -u silverbullet -- /silverbullet "$@"
fi
args=$(printf '%q ' "$@")
exec su silverbullet -s /bin/bash -c "/silverbullet $args"

View file

@ -0,0 +1,12 @@
# Plugs (apps)
Third-party SilverBullet plugs in (loaded automatically).
| Plug | Role |
|------|------|
| treeview.plug.js | Folder sidebar (Apple Notes-like) |
| silversearch.plug.js | Full-text search |
Install/update: drop into , reload SilverBullet.
Builtin SB plugs stay in the image; only extras live here.

View file

@ -0,0 +1,31 @@
# TODO
Canonical ADHD todo (SilverBullet space SoT; FreeNotes = separate native enc).
## Now (max 3) — active quest board
- [x] magikoopa SilverBullet.app (`~/Applications`) + Desktop SilverBullet.url
- [ ] Install silverbullet.desktop on clementine (on-box: client-apps/install-clementine.sh)
- [ ] One-shot migrate: Apple Notes export + Dokumente/TODO.md → here (or FreeNotes later)
- [ ] Human sudo: confirm `sudo ls -la /etc/caddy/secrets/silverbullet-basicauth.txt`
- [ ] Live cutover Freigabe: dir/container → koopa-silverbullet; Caddy → silverbullet.hacktivism.ch; DNS
## Next
- [x] Private Forgejo backup remote for space/ (hernani/freenotes — historical name)
- [x] Seed notes space on koopa
- [x] Caddy merge + basicauth scripts (live cutover pending Freigabe)
- [ ] DNS / public hostname silverbullet.hacktivism.ch (human)
- [x] Update productivity-adhd-notes 02 / 02b → single SoT pointing here
- [x] Wire magikoopa SSH push to hernani/freenotes (ProxyJump) — clone ~/git/freenotes
## Someday / amnesty
- [ ] PWA install both laptops (browser Install app)
- [ ] Second-layer SB_USER if basicauth alone is not enough
- [ ] TreeView / SilverSearch UX polish after first week
## Stats (gamification — agent updates)
- Session streak: 1
- Quests finished today: 6
- XP today: 60
- Last win: rename stack freenotes → silverbullet
- Boss: silverbullet cutover
- Boss HP: 70%

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,13 @@
# Inbox
Apple **Quick Note** analogue. Dump here first; triage into [[TODO]] (Now / Next / Waiting / Someday) or a dedicated page.
Rules:
- Empty capture OK — fill the next `- [ ]` line and save.
- Do not create a new folder just to capture.
- After triage, clear or check off lines so Inbox stays short.
## Capture
- [ ]

View file

@ -0,0 +1,46 @@
---
# SilverBullet index page (SB_INDEX_PAGE=index)
# Apple-Notes-like home: pins + capture path + search
---
# Notes
Cross-host notes (magikoopa + clementine) via koopa SilverBullet.
Mental model = Apple Notes: **folders/pages · list · editor**, pin primary TODO, Quick Note → triage.
| Page | Apple analogue | Role |
|------|----------------|------|
| [[TODO]] | Pinned primary note | ADHD SoT: Now≤3 / Next / Waiting / Someday / Stats |
| [[inbox]] | Quick Note | Capture before triage |
## Pins
- [[TODO]]
- [[inbox]]
## How to use (Apple habits → here)
1. **Capture** into [[inbox]] (or SB quick-note if enabled) — do not invent folders first.
2. **Triage** into [[TODO]] sections (Now max 3). Same rules as former Apple Notes guide.
3. **Find** with Page Picker / search (**Cmd/Ctrl-K**).
4. **New page** when a topic is not a todo (meetings, dumps) — link from TODO by title, do not dump transcripts into TODO.
5. Optional later: TreeView plug (folder sidebar), Space Lua query page = “smart folder” for `#tag` open tasks.
## Shortcuts (target)
| Action | Typical SB |
|--------|------------|
| Open page / filter | Cmd/Ctrl-K (Page Picker) |
| Quick note | Ctrl-q (if client supports) → prefer landing in [[inbox]] |
| Search body | built-in search / SilverSearch plug |
## Hygiene (from Apple Notes ADHD pack)
- One primary [[TODO]] — no competing systems.
- Capture first; tags (`#taler` …) optional and light.
- On “Im back”: re-read **Now** only.
- No passwords/tokens in notes.
## Apps
- [[PLUGS]] — TreeView + SilverSearch

View file

@ -2,27 +2,32 @@
GNU Taler **paivana-httpd** reverse-proxy paywall (DD 95 / DD 76 style), GOA payments.
One process = one `BASE_URL` + one `DESTINATION_BASE_URL` + one `MERCHANT_BACKEND_URL`.
Shared **image / secrets / entrypoint / conf template**; per-service env sets
`PAIVANA_BASE_URL` + `PAIVANA_DESTINATION_BASE_URL`. Portal on **9025**; app
paywalls on **90289031** (Caddy unchanged). App backends listen loopback only
(`19128` SilverBullet, `19129` Galene HTTP, `19130` CryptPad edge, `19131` Meet).
| Item | Value |
|------|--------|
| Live | `/home/hernani/koopa-paivana/` |
| Containers | `koopa-paivana`, `koopa-paivana-upstream` |
| Containers | `koopa-paivana`, `koopa-paivana-{silverbullet,galene,cryptpad,meet}`, `koopa-paivana-upstream` |
| Image | `localhost/koopa-paivana:latest` (built from `Containerfile`); process **uid 1000** `paivana-httpd` |
| Upstream | `nginxinc/nginx-unprivileged` on **:8080** (not root nginx:80) |
| Host port | **9025** → Caddy `paivana.hacktivism.ch` |
| Currency | **GOA** |
| Upstream | portal: `nginxinc/nginx-unprivileged` on **:8080**; apps via host `172.17.0.1:1912819131` |
| Host ports | **9025** portal; **9028/9029/9030/9031** app paywalls → Caddy |
| Currency | **GOA** (goa-shop); other units need other merchant backends / later instances |
| Merchant | `https://taler.hacktivism.ch/instances/goa-shop/` |
| Template | `paivana` (`template_type: paivana`, amount **`GOA:4200`**, `website_regex: .*`) |
| Access | **`-g`** site-wide: pay once → example upstream free to browse |
| Upstream | example site in `upstream/` (compose service) |
| Template | `paivana` (`template_type: paivana`, amount **`GOA:42`**, `website_regex: .*`) |
| Access | **`-g`** site-wide: pay once → that hostname free to browse |
## Layout
| Path | Role |
|------|------|
| `Containerfile` | Multi-stage: build paivana-httpd from `git.taler.net/paivana` + Taler libs |
| `compose.yml` | `koopa-paivana` + nginx upstream |
| `conf/paivana.conf.template` | Config; secrets substituted at start |
| `entrypoint.sh` | Inject secrets → run `paivana-httpd -g -f` |
| `compose.yml` | portal + 4 app paywalls + nginx upstream (YAML anchor `x-paivana-common`) |
| `conf/paivana.conf.template` | Shared conf; `@BASE_URL@` / `@DESTINATION_BASE_URL@` / secrets at start |
| `entrypoint.sh` | Env + secrets → run `paivana-httpd -g -f` |
| `secrets/` | **not in git** — live only |
| `upstream/` | Protected demo content |
| `container-koopa-paivana.service` | systemd --user oneshot compose up |
@ -90,9 +95,10 @@ extra_hosts:
| Check | Expect |
|-------|--------|
| `curl -si http://127.0.0.1:9025/` | **302**`/.well-known/paivana/templates/paivana#…` |
| `https://paivana.hacktivism.ch/` | **402** paywall HTML + `paivana: taler://pay-template/…` |
| `curl -si http://127.0.0.1:902{8,9,0}/` | **302** same template path (per-host BASE_URL) |
| `https://{paivana,silverbullet,galene,cryptpad,meet}.hacktivism.ch/` | unpaid → **302** `…/templates/paivana#…` (or paywall HTML) |
| monitoring `urls` | `www.paivana` OK |
| e2e (GOA, lokal) | `e2e.paivana` Template-Pay **GOA:4200** (wenn `E2E_PAIVANA=1`) |
| e2e (GOA, lokal) | `e2e.paivana` Template-Pay **GOA:42** (wenn `E2E_PAIVANA=1`) |
---
@ -137,22 +143,27 @@ Flags `-g` (site-wide payment) and `-f` (X-Forwarded-For).
## Merchant template
Create (or replace via PATCH / DELETE+POST — see live merchant API):
```bash
curl -X POST 'https://taler.hacktivism.ch/instances/goa-shop/private/templates' \
-H "Authorization: Bearer secret-token:…" \
-H 'Content-Type: application/json' \
-d '{
"template_id": "paivana",
"template_description": "Paivana paywall (GOA)",
"template_description": "Paivana paywall portal (GOA)",
"template_contract": {
"template_type": "paivana",
"summary": "Access to paivana.hacktivism.ch",
"summary": "Access to paivana.hacktivism.ch portal",
"website_regex": ".*",
"choices": [{ "amount": "GOA:4200", "description": "Unlock example site (then free to browse)" }]
"choices": [{ "amount": "GOA:42", "description": "Unlock portal (cryptpad / galene / silverbullet links)" }]
}
}'
```
goa-shop is GOA-only. TESTPAYSAN / FLOODS / talersticker CHF / stage-CHF need
other `MERCHANT_BACKEND_URL` values (separate Paivana process or later phase).
## Docs
- https://docs.taler.net/taler-paivana-manual.html

View file

@ -1,29 +1,45 @@
# koopa-paivana — host :9025 → Caddy paivana.hacktivism.ch
# koopa-paivana — shared image/secrets/entrypoint for portal + app paywalls
# Live: /home/hernani/koopa-paivana/
#
# Public Caddy targets (unchanged):
# 9025 → portal (paivana.hacktivism.ch)
# 9028 → paywall silverbullet
# 9029 → paywall galene
# 9030 → paywall cryptpad
# 9031 → paywall meet (Jitsi web)
# App backends (loopback only; see app compose):
# 127.0.0.1:19128 / 19129 / 19130 / 19131
x-paivana-common: &paivana-common
image: localhost/koopa-paivana:latest
restart: unless-stopped
user: "1000:1000"
userns_mode: keep-id
extra_hosts:
- "taler.hacktivism.ch:172.17.0.1"
- "bank.hacktivism.ch:172.17.0.1"
- "exchange.hacktivism.ch:172.17.0.1"
volumes:
- ./conf/paivana.conf.template:/etc/paivana/paivana.conf.template:ro
- ./entrypoint.sh:/usr/local/bin/paivana-entrypoint:ro
- ./secrets/merchant-access-token:/run/secrets/merchant-access-token:ro
- ./secrets/paivana-secret:/run/secrets/paivana-secret:ro
labels:
org.hacktivism.managed_by: koopa-admin
org.hacktivism.currency: GOA
services:
paivana:
<<: *paivana-common
build:
context: .
dockerfile: Containerfile
image: localhost/koopa-paivana:latest
container_name: koopa-paivana
restart: unless-stopped
# Image already USER paivana-httpd; pin numeric + keep-id for host secrets/volumes.
user: "1000:1000"
userns_mode: keep-id
ports:
- "9025:9967"
extra_hosts:
# pasta publishes merchant on host :9010. Prefer fixed IPv4 — host-gateway
# alone still loses to public AAAA and times out from the container.
- "taler.hacktivism.ch:172.17.0.1"
- "bank.hacktivism.ch:172.17.0.1"
- "exchange.hacktivism.ch:172.17.0.1"
volumes:
- ./conf/paivana.conf.template:/etc/paivana/paivana.conf.template:ro
- ./entrypoint.sh:/usr/local/bin/paivana-entrypoint:ro
- ./secrets/merchant-access-token:/run/secrets/merchant-access-token:ro
- ./secrets/paivana-secret:/run/secrets/paivana-secret:ro
environment:
PAIVANA_BASE_URL: https://paivana.hacktivism.ch/
PAIVANA_DESTINATION_BASE_URL: http://upstream:8080/
depends_on:
- upstream
labels:
@ -33,8 +49,68 @@ services:
org.hacktivism.managed_by: koopa-admin
org.hacktivism.currency: GOA
# App paywalls: same image/secrets; BASE/DEST via env. Caddy still hits 90289031.
paivana-silverbullet:
<<: *paivana-common
container_name: koopa-paivana-silverbullet
ports:
- "9028:9967"
environment:
PAIVANA_BASE_URL: https://silverbullet.hacktivism.ch/
PAIVANA_DESTINATION_BASE_URL: http://172.17.0.1:19128/
labels:
org.hacktivism.service: paivana-silverbullet
org.hacktivism.host_port: "9028"
org.hacktivism.site: silverbullet.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.currency: GOA
paivana-galene:
<<: *paivana-common
container_name: koopa-paivana-galene
ports:
- "9029:9967"
environment:
PAIVANA_BASE_URL: https://galene.hacktivism.ch/
PAIVANA_DESTINATION_BASE_URL: http://172.17.0.1:19129/
labels:
org.hacktivism.service: paivana-galene
org.hacktivism.host_port: "9029"
org.hacktivism.site: galene.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.currency: GOA
paivana-cryptpad:
<<: *paivana-common
container_name: koopa-paivana-cryptpad
ports:
- "9030:9967"
environment:
PAIVANA_BASE_URL: https://cryptpad.hacktivism.ch/
PAIVANA_DESTINATION_BASE_URL: http://172.17.0.1:19130/
labels:
org.hacktivism.service: paivana-cryptpad
org.hacktivism.host_port: "9030"
org.hacktivism.site: cryptpad.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.currency: GOA
paivana-meet:
<<: *paivana-common
container_name: koopa-paivana-meet
ports:
- "9031:9967"
environment:
PAIVANA_BASE_URL: https://meet.hacktivism.ch/
PAIVANA_DESTINATION_BASE_URL: http://172.17.0.1:19131/
labels:
org.hacktivism.service: paivana-meet
org.hacktivism.host_port: "9031"
org.hacktivism.site: meet.hacktivism.ch
org.hacktivism.managed_by: koopa-admin
org.hacktivism.currency: GOA
upstream:
# Non-root nginx (listens on 8080). See DESTINATION_BASE_URL in conf template.
image: docker.io/nginxinc/nginx-unprivileged:1.27-alpine
container_name: koopa-paivana-upstream
restart: unless-stopped

View file

@ -1,14 +1,14 @@
# paivana.hacktivism.ch — paywall reverse proxy
# Secrets injected by entrypoint from /run/secrets/
# Shared paivana-httpd conf — BASE/DEST injected by entrypoint (env).
# Secrets injected from /run/secrets/
[paivana]
SERVE = tcp
PORT = 9967
BIND_TO = 0.0.0.0
BASE_URL = https://paivana.hacktivism.ch/
BASE_URL = @BASE_URL@
DESTINATION_BASE_URL = http://upstream:8080/
DESTINATION_BASE_URL = @DESTINATION_BASE_URL@
MERCHANT_BACKEND_URL = https://taler.hacktivism.ch/instances/goa-shop/
MERCHANT_ACCESS_TOKEN = @MERCHANT_ACCESS_TOKEN@

View file

@ -5,6 +5,10 @@ SECRET_FILE="${PAIVANA_SECRET_FILE:-/run/secrets/paivana-secret}"
TEMPLATE="${PAIVANA_CONF_TEMPLATE:-/etc/paivana/paivana.conf.template}"
OUT="${PAIVANA_CONF:-/tmp/paivana.conf}"
# Per-instance (portal + app paywalls share this entrypoint/image).
BASE_URL="${PAIVANA_BASE_URL:-https://paivana.hacktivism.ch/}"
DEST_URL="${PAIVANA_DESTINATION_BASE_URL:-http://upstream:8080/}"
if [ ! -r "$TOKEN_FILE" ]; then
echo "missing merchant token: $TOKEN_FILE" >&2
exit 1
@ -17,10 +21,12 @@ fi
TOKEN=$(tr -d '\n\r' < "$TOKEN_FILE")
SECRET=$(tr -d '\n\r' < "$SECRET_FILE")
awk -v t="$TOKEN" -v s="$SECRET" '
awk -v t="$TOKEN" -v s="$SECRET" -v b="$BASE_URL" -v d="$DEST_URL" '
{
gsub(/@MERCHANT_ACCESS_TOKEN@/, t)
gsub(/@PAIVANA_SECRET@/, s)
gsub(/@BASE_URL@/, b)
gsub(/@DESTINATION_BASE_URL@/, d)
print
}
' "$TEMPLATE" > "$OUT"

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Example site — free after GOA:4200</title>
<title>hacktivism tools — unlocked</title>
<style>
:root { color-scheme: light dark; }
body {
@ -26,29 +26,41 @@
.price { font-variant-numeric: tabular-nums; }
code { background: color-mix(in srgb, CanvasText 12%, transparent); padding: 0.1em 0.35em; border-radius: 3px; }
.card {
margin-top: 1.5rem;
margin-top: 1.25rem;
padding: 1rem 1.1rem;
border: 1px solid color-mix(in srgb, CanvasText 18%, transparent);
border-radius: 10px;
}
ul { padding-left: 1.2rem; }
a { color: inherit; }
.sites a {
display: block;
margin: 0.45rem 0;
font-weight: 600;
}
</style>
</head>
<body>
<span class="badge">unlocked</span>
<h1>Example site</h1>
<h1>hacktivism tools</h1>
<p>
You paid <strong class="price">GOA:4200</strong> once via GNU Taler / Paivana.
This whole example site is now free for you to browse (site-wide access cookie).
You paid once via GNU Taler / Paivana
(<strong class="price">GOA:42</strong> on this merchant).
Site-wide access cookie is set for <code>paivana.hacktivism.ch</code>.
</p>
<div class="card sites">
<p><strong>Sites</strong></p>
<a href="https://cryptpad.hacktivism.ch/">cryptpad.hacktivism.ch</a>
<a href="https://galene.hacktivism.ch/">galene.hacktivism.ch</a>
<a href="https://silverbullet.hacktivism.ch/">silverbullet.hacktivism.ch</a>
</div>
<div class="card">
<p><strong>What this demonstrates</strong></p>
<p><strong>Notes</strong></p>
<ul>
<li>Paywall: <code>paivana-httpd</code> in front of a normal upstream HTTP site</li>
<li>Currency: exploration money <code>GOA</code> on exchange.hacktivism.ch</li>
<li>After payment: no further charge for pages behind this proxy</li>
<li>One Paivana process = one <code>DESTINATION_BASE_URL</code> → this portal is the gated upstream.</li>
<li>Merchant: <code>goa-shop</code> · template <code>paivana</code>.</li>
<li>Host: <code>https://paivana.hacktivism.ch/</code></li>
</ul>
<p style="margin-bottom:0">Host: <code>https://paivana.hacktivism.ch/</code></p>
</div>
</body>
</html>

View file

@ -16,16 +16,27 @@
| 9022 | podman `koopa-prime` (Jellyfin) → Caddy `prime.hacktivism.ch` |
| 9023 | podman qBittorrent → Caddy `bt.hacktivism.ch` |
| **9024** | podman **`koopa-forgejo`** (HTTP) → Caddy **`git.hacktivism.ch`** |
| **9025** | podman **`koopa-paivana`** (paivana-httpd) → Caddy **`paivana.hacktivism.ch`** |
| **9025** | podman **`koopa-paivana`** (portal paywall) → Caddy **`paivana.hacktivism.ch`** |
| **9026** | podman **`koopa-lemmy-proxy`** → Caddy **`lemmy.hacktivism.ch`** |
| **9027** | podman **`koopa-decidim`** → Caddy **`decidim.hacktivism.ch`** |
| **9028** | podman **`koopa-paivana-silverbullet`** → Caddy **`silverbullet.hacktivism.ch`** (app backend `127.0.0.1:19128`) |
| **9029** | podman **`koopa-paivana-galene`** → Caddy **`galene.hacktivism.ch`** (app backend `127.0.0.1:19129`; UDP 1000010099 still Galene) |
| **9030** | podman **`koopa-paivana-cryptpad`** → Caddy **`cryptpad.hacktivism.ch`** (edge backend `127.0.0.1:19130`) |
| **9031** | podman **`koopa-paivana-meet`** → Caddy **`meet.hacktivism.ch`** (app backend `127.0.0.1:19131`) |
| **9032** | podman **`koopa-bbb-front`** (Ubuntu) → Caddy **`bbb.hacktivism.ch`** |
| **9200** | podman **Forgejo git-SSH** (host-direct; not Caddy) |
| 90909092 | podman `koopa-tops-ng1``ng3` → Caddy `tops.ng{1,2,3}.hacktivism.ch` |
| 8080 | Tor ORPort |
VeciGate: WAN **80→9000**, WAN **443→9001**.
Public apps: Caddy vhosts on **9001** → 127.0.0.1:{90109015, 90209027, 90909092}.
Git SSH needs separate NAT/firewall **9200/tcp** if exposed to WAN.
Public apps: Caddy vhosts on **9001** → 127.0.0.1:{90109015, 90209032, 90909092}.
Git SSH needs separate NAT/firewall **9200/tcp** if exposed to WAN.
Meet/Galene/BBB media UDP is separate from these HTTP ports.
| UDP range | Role |
|-----------|------|
| **1000010099/udp** | **Galene** WebRTC (host publish + planned VeciGate DNAT → koopa) |
| (TBD) | Meet JVB / BBB media — allocate when Phase2 / full BBB leaves park |
| **1789** | podman **`koopa-nym`** mixnet (nym.com nym-node) |
| **1790** | podman **`koopa-nym`** verloc |