A full sweep found three peers silent. WordPress had updated itself to 7.1.2 from WP-Cron, and the new CA bundle dropped Caddy's root: it now runs the 7.1.2 image with automatic updates off. Mbin's messenger worker had died when the shared Postgres restarted under it: it now consumes again whenever it stops. Friendica sat in a quarantine left by the old breaker. The threads scenario checks that PrivaPub never sends carol's reply to Mastodon, since a relay Mastodon has just left (the relay scenario's) may still pass it on. With these, every scenario passes but the crawler's, which needs it switched on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
112 lines
5.6 KiB
Bash
112 lines
5.6 KiB
Bash
# Mbin 1.10.1: the threadiverse in Symfony (magazines, threads, comments, microblog posts, votes up and down), from its
|
|
# own image: FrankenPHP serving plain HTTP behind Caddy, and a messenger worker for its queues, on the shared Postgres
|
|
# (database mbin) and Redis (db 12), with a RabbitMQ of its own (its transports carry AMQP options). Symfony's HTTP
|
|
# client trusts the system bundle, so the pasture's is mounted over it. Its admin is mbuser, made by its console; its
|
|
# API takes an OAuth2 token, which mbin_settle gets through the authorization-code flow as mbuser (a client-credentials
|
|
# client acts as a bot, which may not vote).
|
|
MBIN_IMAGE=${MBIN_IMAGE:-ghcr.io/mbinorg/mbin:v1.10.1}
|
|
MBIN_RABBITMQ_IMAGE=${MBIN_RABBITMQ_IMAGE:-docker.io/library/rabbitmq:4-alpine}
|
|
MBIN_PASSWORD=Mbin-Pasture-Pass-1
|
|
. "$here/peers/shared.sh"
|
|
|
|
mbin_env() {
|
|
local dir="$here/.state/mbin"
|
|
[ -s "$dir/secret" ] || head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$dir/secret"
|
|
[ -s "$dir/mercure" ] || head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$dir/mercure"
|
|
[ -s "$dir/oauth-key" ] || head -c 16 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$dir/oauth-key"
|
|
cat <<ENV
|
|
APP_ENV=prod
|
|
APP_SECRET=$(cat "$dir/secret")
|
|
MBIN_USER=root
|
|
SERVER_NAME=:80
|
|
KBIN_DOMAIN=mbin.test
|
|
KBIN_TITLE=Pasture Mbin
|
|
KBIN_DEFAULT_LANG=en
|
|
KBIN_FEDERATION_ENABLED=true
|
|
KBIN_CONTACT_EMAIL=contact@mbin.test
|
|
KBIN_SENDER_EMAIL=noreply@mbin.test
|
|
KBIN_JS_ENABLED=true
|
|
KBIN_REGISTRATIONS_ENABLED=true
|
|
KBIN_API_ITEMS_PER_PAGE=25
|
|
KBIN_STORAGE_URL=https://mbin.test/media
|
|
KBIN_CAPTCHA_ENABLED=false
|
|
KBIN_ADMIN_ONLY_OAUTH_CLIENTS=false
|
|
MBIN_DOWNVOTES_MODE=enabled
|
|
MBIN_NEW_USERS_NEED_APPROVAL=false
|
|
MBIN_USE_FEDERATION_ALLOW_LIST=false
|
|
DATABASE_URL=postgresql://pasture:pasture@postgres:5432/mbin?serverVersion=17&charset=utf8
|
|
REDIS_DNS=redis://redis:6379/12
|
|
MESSENGER_TRANSPORT_DSN=amqp://guest:guest@pasture-mbin-rabbitmq:5672/%2f/messages
|
|
MAILER_DSN=null://null
|
|
MERCURE_URL=http://localhost/.well-known/mercure
|
|
MERCURE_PUBLIC_URL=https://mbin.test/.well-known/mercure
|
|
MERCURE_JWT_SECRET=$(cat "$dir/mercure")
|
|
MERCURE_PUBLISHER_JWT_KEY=$(cat "$dir/mercure")
|
|
MERCURE_SUBSCRIBER_JWT_KEY=$(cat "$dir/mercure")
|
|
CORS_ALLOW_ORIGIN=^https?://mbin\.test$
|
|
LOCK_DSN=flock
|
|
TRUSTED_PROXIES=$subnet
|
|
OAUTH_PRIVATE_KEY=/oauth2/private.pem
|
|
OAUTH_PUBLIC_KEY=/oauth2/public.pem
|
|
OAUTH_PASSPHRASE=$MBIN_PASSWORD
|
|
OAUTH_ENCRYPTION_KEY=$(cat "$dir/oauth-key")
|
|
ENV
|
|
}
|
|
|
|
mbin_up() {
|
|
shared_postgres_up
|
|
shared_redis_up
|
|
pg_db mbin
|
|
mkdir -p "$here/.state/mbin/oauth2"
|
|
if [ ! -s "$here/.state/mbin/oauth2/public.pem" ]; then
|
|
openssl genrsa -aes256 -passout "pass:$MBIN_PASSWORD" -out "$here/.state/mbin/oauth2/private.pem" 4096 2>/dev/null
|
|
openssl rsa -in "$here/.state/mbin/oauth2/private.pem" -passin "pass:$MBIN_PASSWORD" -pubout -out "$here/.state/mbin/oauth2/public.pem" 2>/dev/null
|
|
chmod 644 "$here/.state/mbin/oauth2/"*.pem
|
|
fi
|
|
mbin_env > "$here/.state/mbin/env"
|
|
# its API's own limits (two threads every six minutes) would throttle a scripted run: the same file, every limit raised
|
|
podman run --rm --entrypoint cat "$MBIN_IMAGE" config/packages/rate_limiter.yaml \
|
|
| sed -E 's/^( +limit:) [0-9]+$/\1 100000/' > "$here/.state/mbin/rate_limiter.yaml"
|
|
# (as its own user on a volume it owns: started as root, it writes an .erlang.cookie it then cannot read)
|
|
podman volume exists pasture-mbin-rabbitmq || podman volume create --label pasture=1 pasture-mbin-rabbitmq >/dev/null
|
|
podman run -d --replace --name pasture-mbin-rabbitmq --network $net --label pasture=1 --user rabbitmq -v pasture-mbin-rabbitmq:/var/lib/rabbitmq:U \
|
|
"$MBIN_RABBITMQ_IMAGE" >/dev/null
|
|
for _ in $(seq 1 60); do podman exec pasture-mbin-rabbitmq rabbitmq-diagnostics -q ping >/dev/null 2>&1 && break; sleep 2; done
|
|
podman volume exists pasture-mbin-media || podman volume create --label pasture=1 pasture-mbin-media >/dev/null
|
|
local common=(--network $net --label pasture=1 --env-file "$here/.state/mbin/env" -v pasture-mbin-media:/app/public/media
|
|
-v "$here/.state/mbin/oauth2:/oauth2:z,ro" -v "$ca/bundle.pem:/etc/ssl/certs/ca-certificates.crt:z,ro"
|
|
-v "$here/.state/mbin/rate_limiter.yaml:/app/config/packages/rate_limiter.yaml:z,ro")
|
|
podman run -d --replace --name pasture-mbin "${common[@]}" "$MBIN_IMAGE" >/dev/null
|
|
# the web container runs the migrations as it starts; the worker waits for them
|
|
for _ in $(seq 1 120); do
|
|
podman logs pasture-mbin 2>&1 | grep -q "PHP app ready" && break
|
|
sleep 2
|
|
done
|
|
mbin_worker
|
|
for _ in $(seq 1 60); do
|
|
site mbin.test -s -o /dev/null -w '%{http_code}' https://mbin.test:6443/api/instance 2>/dev/null | grep -q 200 && break
|
|
sleep 2
|
|
done
|
|
mbin_settle
|
|
echo "mbin: https://mbin.test:6443"
|
|
}
|
|
|
|
mbin_console() { podman exec pasture-mbin php bin/console "$@"; }
|
|
|
|
# mbuser (admin, verified), the instance's keys, and mbuser's OAuth token from the authorization-code flow
|
|
mbin_settle() {
|
|
mbin_console mbin:ap:keys:update >/dev/null 2>&1 || true
|
|
mbin_console mbin:user:create mbuser mbuser@mbin.test "$MBIN_PASSWORD" >/dev/null 2>&1 || true
|
|
mbin_console mbin:user:admin mbuser >/dev/null 2>&1 || true
|
|
mbin_console mbin:user:verify mbuser >/dev/null 2>&1 || true
|
|
python3 "$here/peers/mbin_token.py" "$MBIN_PASSWORD" "$here/.state/mbin/client.json" > "$here/.state/mbin.token" 2>"$here/.state/mbin/token.log" || true
|
|
}
|
|
|
|
# mbin_worker: the messenger worker, consuming again whenever it stops (an hour's time limit, or a lost database: a
|
|
# Postgres restarted once left Mbin sending nothing for a day)
|
|
mbin_worker() {
|
|
podman run -d --replace --name pasture-mbin-worker "${common[@]}" "$MBIN_IMAGE" sh -c 'while :; do
|
|
php bin/console messenger:consume scheduler_default old async outbox deliver inbox resolve receive failed --time-limit=3600; sleep 5
|
|
done' >/dev/null
|
|
}
|