Demo images / Build & push demo images (push) Failing after 2m22s
Replaces the registry host across 86 files: 309 references, covering all 40 app manifests, the orchestrator and container crates, the release and catalog scripts, both demo-images workflows, the ISO builder, demo-deploy, and the frontend marketplace data. Verified the domain actually serves the registry before rewriting anything, rather than assuming the web host implies the registry: - TLS verifies clean, HTTP/2 on the web root - an anonymous token grants a manifest fetch (HTTP 200) with no credentials - skopeo inspect --no-creds resolves an image and lists its tags That last check is the one that matters: an outside developer with no account can now pull, which was the functional blocker for publishing at all. Plain-HTTP references become HTTPS in the same pass, so OTA downloads stop crossing the network in the clear. Deliberately NOT rewritten: - The public FIPS anchor on port 8444. It is a functional network endpoint every node dials to bootstrap the mesh — closer to Bitcoin Core's hardcoded seeds than to leaked infrastructure. The domain does resolve to the same host, so it could become a hostname, but that adds a DNS dependency to the path used precisely when things are broken. Worth a deliberate decision, not a side effect of this change. - The companion APK on port 2100. The domain returns 404 for that path, so rewriting it would swap a working URL for a broken one. The Releases page does serve (200), which is where the plan already wants those binaries. - releases/app-catalog.json, releases/manifest.json and release-manifest.json. These carry `signature` and `signed_by`; editing their contents invalidates the signature and the fleet refuses artifacts that fail verification. They were rewritten in a first pass and reverted — they must be regenerated and re-signed through the signing ceremony instead, which needs the mnemonic. So the catalog still advertises the old host until that ceremony runs. Nodes resolve images through the signed catalog, not the on-disk manifests, so this commit alone does not change what a node pulls. Verified: archipelago-container 75/75; every manifest still parses with a top-level app block; no signed artifact modified. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
110 lines
5.7 KiB
Markdown
110 lines
5.7 KiB
Markdown
# Archipelago Public Demo — build info & status
|
|
|
|
**Status:** implemented & deployable (2026-07-14)
|
|
**Branch:** `main` — the demo machinery was merged from the old `demo-build`
|
|
branch and now lives on main, pushed to
|
|
`gitea-vps2` = `https://source.archipelago-foundation.org/lfg2025/archy.git`.
|
|
|
|
A public, click-to-play demo of the Archipelago UI, 100% mock-data driven,
|
|
multi-visitor, deployed via Portainer. See also `docs/archive/demo-deployment-design.md`
|
|
(original design) and `demo-deploy/` (thin prebuilt-image stack).
|
|
|
|
---
|
|
|
|
## Deploy (Portainer)
|
|
|
|
Build-from-repo (works today, no registry needed):
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| Repository URL | `https://source.archipelago-foundation.org/lfg2025/archy.git` |
|
|
| Reference | `refs/heads/main` |
|
|
| Compose path | `docker-compose.demo.yml` |
|
|
| Auth | user `lfg2025`, password = Gitea token |
|
|
| UI port | **2100** · Login password: **`entertoexit`** |
|
|
|
|
Redeploy after each push. `docker-compose.demo.yml` builds two images
|
|
(`neode-ui/Dockerfile.backend` = mock server, `neode-ui/Dockerfile.web` = nginx+UI).
|
|
The thin `demo-deploy/docker-compose.yml` pulls prebuilt `:demo` images instead
|
|
(needs the CI image pipeline / registry wired — `.github/workflows/demo-images.yml`).
|
|
|
|
### Flags / env
|
|
- Backend: `DEMO=1` (compose sets it) → multi-session sandbox, no real runtime.
|
|
- Web build: `VITE_DEMO=1` (Dockerfile.web ARG, default 1) → inlined demo UI behaviour.
|
|
- Optional: `ANTHROPIC_API_KEY` (NOT needed — AIUI chat is canned in demo),
|
|
`DEMO_SESSION_TTL_MS` (45m), `DEMO_MAX_SESSIONS` (500), `DEMO_FILE_QUOTA_BYTES` (50MB).
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
Everything is gated behind `DEMO` (off = classic single-user dev mock, unchanged).
|
|
|
|
- **`neode-ui/mock-backend.js`** — the entire fake backend (Node/Express, ~95+ RPCs).
|
|
- **Per-session isolation:** `AsyncLocalStorage` + Proxy. Globals (`mockData`,
|
|
`walletState`, `userState`, `mockState`, `bitcoinRelayMockState`) are Proxies
|
|
that resolve to the current request's store, keyed by a `demo_sid` cookie.
|
|
Deep-cloned from `SEED_*` on first hit; idle-reaped; per-session WS fan-out.
|
|
- **Files:** per-session in-memory store + curated disk files (see below).
|
|
- Forces simulation mode in DEMO (`docker=null`).
|
|
- **`neode-ui/src/composables/useDemoIntro.ts`** — the frontend demo switch
|
|
(`IS_DEMO`), per-day intro gate, `DEMO_PASSWORD`, app demoability + launch URLs.
|
|
- **`neode-ui/docker/nginx-demo.conf`** — routes `/rpc`, `/ws`, `/app/*`,
|
|
`/electrs-status`, `/proxy/`, `/lnd-connect-info`, the IndeeHub/Mempool
|
|
reverse-proxies, and the SPA.
|
|
- **`docker/{bitcoin-ui,electrs-ui,lnd-ui,fedimint-ui}/`** — the REAL registry app
|
|
UIs, served statically under `/app/<id>/` with mocked data endpoints.
|
|
- **`demo/aiui/`** — prebuilt AIUI dist (chat is canned; `?mockArchy&seed`).
|
|
- **`demo/files/`** — curated cloud files drop-in (see below).
|
|
|
|
## Demo features (all implemented)
|
|
Per-session sandbox · per-session file upload (Range streaming) · testnet/signet
|
|
flavor · per-day intro replay · `entertoexit` login (prefilled + hint) · version
|
|
`<real>-demo` · onboarding wizard skipped (intro kept) · "No demo" install gating ·
|
|
real app UIs (Bitcoin Core vs Knots by subversion, ElectrumX, LND, Fedimint;
|
|
Mempool/IndeeHub iframed) · 12 federation nodes / 5 peers · FIPS active · interactive
|
|
buy flow (testnet addresses, bolt11, 2s QR) · real testnet tx links (mempool.space) ·
|
|
networking profits 5,231,978 sats + labelled wallet txs · VPN · Nostr relays ·
|
|
node-visibility toggle · dummy Cashu mints + Fedimint federations · AIUI canned
|
|
reply + `?mockArchy` mock data + `?seed` pre-loaded "Content Showcase" chat.
|
|
|
|
---
|
|
|
|
## Curated cloud files (`demo/files/`)
|
|
Drop real files into `demo/files/<Folder>/<file>` and commit — they become the
|
|
cloud content for every visitor (read-only; git access = the "private login").
|
|
Loader **merges per top-level folder**: adding `Music/` swaps only Music and keeps
|
|
the sample Documents/Photos/Videos. Empty → built-in seeds. Text inlined; binaries
|
|
streamed from disk with HTTP Range (seek). Backend reads `/demo/files` —
|
|
**Dockerfile.backend COPYs it; `.dockerignore` must allow it.**
|
|
|
|
---
|
|
|
|
## Gotchas (READ before editing)
|
|
- **Sibling dirs need both the Dockerfile COPY and a `.dockerignore` allow.**
|
|
`docker/bitcoin-ui`, `docker/electrs-ui`, `docker/lnd-ui`, `docker/fedimint-ui`,
|
|
`demo/files` are outside `neode-ui/`; they're copied into the backend image and
|
|
un-ignored in `.dockerignore` (`* ` + `!docker/` + `docker/*` + `!docker/<ui>/`).
|
|
Forgetting either → Portainer build "not found" or runtime 500/404.
|
|
- **Real app UIs assume root-serving** — served via `express.static('/app/<id>')`
|
|
+ `/app/<id>/assets/*` → `/assets/*` redirect + per-path data endpoints
|
|
(`bitcoin-status`, `rpc/v1`, `bitcoin-rpc/`, `/proxy/lnd/*`, `/electrs-status`).
|
|
- **Uploaded-via-UI files are ephemeral** (per-session, lost on redeploy/reap).
|
|
Only `demo/files/` persists.
|
|
- **Mempool iframe is best-effort** (third-party CSP/websockets). **IndeeHub** is
|
|
reverse-proxied with header-strip + `sub_filter` asset rewrite; if still black,
|
|
it's indee's own `X-Frame-Options` (fix on that server).
|
|
- **AIUI `?seed` bootstrap hardcodes the current AIUI bundle hash**
|
|
(`/aiui/assets/seedPrompts-CLWaUv28.js`) — re-paste if AIUI is rebuilt. Tiny
|
|
first-load IndexedDB race (one refresh shows the chat).
|
|
- **Running mock-backend.js locally in the sandbox is flaky:** start backgrounded,
|
|
`sleep 5+`, then curl; NEVER `pkill -f mock-backend` (it matches & kills the
|
|
shell) — use `pkill -x node`.
|
|
- **Delete-405** seen pre-redeploy was nginx/stale; backend DELETE returns 200.
|
|
|
|
---
|
|
|
|
## Commit trail (demo-build, newest last)
|
|
`2715f2d8` sandbox → … → `7efebb4a` media merge + AIUI seed. ~14 commits, all
|
|
`feat(demo)/fix(demo)`.
|