asxpio now probes public hosts tied to each datacenter once a minute and stores 5-minute rows (bingo_monitor_* tables, granted to the read-only bingo role). Show them: /:locale/status lists every monitored site with its current state and a 24-hour bar, /status.json has the same data, and monitored datacenter pages get a small block. A site is down only when nothing answered for two buckets. Everything reads as unknown when the worker is stale or fewer than half of the control hosts in Russia answer, since probes run from Finland and filtering can look like an outage. The page says plainly that this is not an incident record. Refresh test/schema.sql for asxpio's migration 017. Assisted-by: Claude:opus-5-5
4.1 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 the
datacenterbingo-photos bucket (asxpio's admin uploads them there).
- 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:GetObjectondatacenterbingo-photos. Both are provisioned by thestoragerepo (init/), from the sameBINGO_*secrets set on both repos.
Research
Before adding or changing datacenters, incidents or photos, follow
OSINT.md. It covers sources, verification, photo rules (no people, and
renderings only for unbuilt sites) and credit format.
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.- Feeds:
/:locale/feed.xml(RSS 2.0) and/:locale/feed.json(JSON Feed 1.1), the latest 50 incidents, newest first. Item IDs aretag:<host>,2026:incident-<id>, so they stay stable when an incident is edited. Pages advertise both via<link rel="alternate">and in the footer. /data.json: every datacenter with names in all locales, specs, pages, photo credit and incidents with sources. Licensed CC BY 4.0, with the attribution inside the file. Feeds and dataset sendAccess-Control-Allow-Origin: *.- Reachability:
/:locale/statusand/status.json(Bingo::Status), plus a block on monitored datacenter pages. They read thebingo_monitor_*tables that asxpio'sbin/monitorwrites (TCP probes from Finland, 5-minute buckets, control hosts in Russia). States: up, degraded, down (nothing answered for two buckets), unknown (worker stale, or under half the controls answering). Not incidents: never cross out a cell from this alone. 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) |