The bingo card ran inside the asxpio container, dispatched by Host. Give the public site its own repo, image and deploy so it can be released and mirrored independently of asxp.io. Editing stays in the asxp.io admin, which keeps owning the schema and the photo pipeline; this app only reads the shared bingo tables and the bingo/ photos, through a read-only DB role and MinIO user. Tests load a snapshot of the asxpio-built schema (test/schema.sql). Assisted-by: Claude:opus-5
2.9 KiB
datacenterbingo
Public site for datacenterbingo.xyz: a 5×5 bingo card of Russia's largest
datacenters, crossed out on publicly sourced incidents. Ruby/Sinatra,
read-only. Primary repo git.czsk.it/asxpi/datacenterbingo (Forgejo, CI and
deploy); github.com/asxpi/datacenterbingo is a push mirror.
Shared with asxpio
Content is edited in the asxp.io admin (/admin/bingo, repo asxpio:
lib/bingo.rb, lib/bingo_admin.rb). Both apps use the same Postgres tables
(bingo_datacenters, bingo_incidents) and the photos under bingo/ in
asxpio's MinIO bucket.
- asxpio owns the schema. Migrations live there. After it adds a
bingo migration, refresh
test/schema.sql(instructions in its header) and update the models here. lib/bingo.rbhere is the read side of asxpio's: models,Board,PROVIDERS, theTUI strings, and photo/IndexNow key reading. The admin side (writes, photo upload and resizing, IndexNow pings, ranking, seeding,guess_provider) stays in asxpio. Keep shared parts in step:PROVIDERS,Board, and model methods.- Prod uses a read-only DB role
bingo(SELECT on the two tables) and a MinIO user limited tos3:GetObjectonasxpio-invoices/bingo/*. Both are provisioned by thestoragerepo (init/), from the sameBINGO_*secrets set on both repos.
Layout
app.rb:BingoWeb. Routes:/(redirect by Accept-Language),/ru|en|uk(card;?view=all,?p[]=provider),/:locale/dc/:slug,/sitemap.xml,/robots.txt,/p/:file(photo proxy, immutable),/<indexnow-key>.txt, icons,/healthz.config.ru:www.→BINGO_HOST301.views/:layout.erb(CSS and SEO head),index.erb(card, provider filter, dialogs),dc.erb, partials.assets/: icons.- Card rules: always 5×5. The bare locale URL is the operational card
(indexed).
?view=alland provider-filtered URLs are noindex, with canonical pointing to the bare page.
Dev and tests
nix develop, then bin/test. That provisions an ephemeral Postgres and
loads test/schema.sql. Run cp .env.example .env for a local server
(rackup), pointing it at a DB that has the bingo tables.
Deploy
On push to main, .forgejo/workflows/deploy.yaml tests, builds with kaniko
to $FJ_REGISTRY/$FJ_USER/datacenterbingo, then over SSH writes
/opt/datacenterbingo/{docker-compose.yml,.env} and runs
docker compose up -d. The container is on the traefik and storage
networks, and the Traefik router datacenterbingo takes BINGO_HOST and
www..
Secrets:
| Secret | Purpose |
|---|---|
FJ_REGISTRY, FJ_USER, FJ_TOKEN |
kaniko clone + push (write:package, read:repository); Forgejo reserves the FORGEJO_ prefix |
DEPLOY_IP, DEPLOY_USER, DEPLOY_SSH_KEY |
SSH to prod |
BINGO_DB_PASSWORD |
read-only Postgres role bingo |
BINGO_S3_ACCESS_KEY, BINGO_S3_SECRET_KEY |
read-only MinIO user |
INDEXNOW |
same key as asxpio's INDEXNOW (served here, pinged from there) |