The canonical repo is now nostr://npub1krldcq2laqxeslseue8uyk24vg6mhmv0ra6ldc52hyfwdx5azd8se5j65x/relay.ngit.dev/podsteadr, with Gitea kept as a mirror. The archy-integration skill maps each file here that Archipelago's manifests depend on to the archy files that must follow it, plus the release, regenerate/check and node-test steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.7 KiB
name, description
| name | description |
|---|---|
| archy-integration | Use when changing podsteadr or podsteadr-player in a way Archipelago (the archy repo) depends on — Dockerfile, env vars/config, ports, routes, health check, data paths, container names, blossom/mediamtx config or image versions, the player's nginx/FIPS gateway — or when releasing a new podsteadr version to Archipelago nodes. Lists which archy files follow which files here, how to regenerate and check them, and how to push both sides. |
podsteadr ↔ archy integration
podsteadr ships on Archipelago as a four-container app packaged in the archy repo. Archy holds no podsteadr source: it runs images built from this repo and from podsteadr-player, described by manifests. When something here changes that the manifests describe, archy has to change too, or nodes run the new image with stale settings.
Repos and remotes
| Repo | Local | Source of truth (origin) |
Mirror |
|---|---|---|---|
| podsteadr | ~/podsteadr |
nostr://npub1krldcq2laqxeslseue8uyk24vg6mhmv0ra6ldc52hyfwdx5azd8se5j65x/relay.ngit.dev/podsteadr |
gitea |
| podsteadr-player | ~/podsteadr-player |
nostr://npub1krldcq2laqxeslseue8uyk24vg6mhmv0ra6ldc52hyfwdx5azd8se5j65x/relay.ngit.dev/podsteadr-player |
gitea |
| archy | ~/archy |
Gitea origin for branches/PRs (see below) |
ngit |
- ngit is the source of truth for both app repos. Push every branch to
origin(ngit) first, then togiteaso the mirror stays current:git push origin <branch> && git push gitea <branch>. - The ngit account on this machine (
npub1krld…j65x) owns the two app repos but is not a maintainer of archy's ngit repo, so archy branches go to Gitea (git push origin <branch>) and PRs are opened through the Gitea API (token is in the remote URL). Pushing archy to ngit is rejected until that npub is added as a maintainer. - Follow archy's own
CLAUDE.mdwhen editing it: work on a branch, stage by path (nevergit add -A—~/archyoften has other people's uncommitted work), commit and push each unit of work, no node hostnames or IPs in archy.
What in archy follows what here
Until archy PR #163 (branch feat/podsteadr-app) is merged, the four-container
package — the player manifest, the stack registration in core, the build
scripts — exists only on that branch, so base archy work on it rather than on
main.
Archy paths are relative to ~/archy. "Manifest" means apps/<app>/manifest.yml.
podsteadr (this repo)
| Change here | Update in archy |
|---|---|
Dockerfile |
apps/podsteadr/Dockerfile is a vendored copy: keep its header comment, replace everything from # ---- frontend ---- down with this repo's file. Check with diff <(sed -n '/^# ---- frontend/,$p' ~/archy/apps/podsteadr/Dockerfile) <(sed -n '/^# ---- frontend/,$p' Dockerfile). |
New/renamed env var in server/src/config.ts |
apps/podsteadr/manifest.yml environment (fixed values) or derived_env (values built from the node's address, e.g. PUBLIC_URL). Keep docker-compose.yml here in step too. |
| Default ports, or a new listening port | Manifest ports (every port needs auth:; auth: none needs an auth_rationale), interfaces if it's a UI/API, apps/PORTS.md, add auth: none ports to the allowlist in the unauthenticated-endpoint test in core/container/src/manifest.rs, then regenerate (the FIPS firewall list in core/archipelago/src/fips/app_ports.rs comes from the manifests). |
MESH_BLOSSOM_PORT / blossom's public port |
Must equal blossom's host port (8098) in apps/podsteadr-blossom/manifest.yml and its interfaces.main.port. |
Health route (/api/health) |
Manifest health_check.path. |
Data layout under DATA_DIR (/data) or RECORDINGS_DIR (/recordings), or the runtime user (node, uid 1000) |
Manifest volumes, data_uid, and the "Data" section of apps/podsteadr/README.md. Never change a path in a way that strands existing data: archy's rule is that migrations never destroy data. |
Where the vendored nostr-provider.js lives in the image (/app/public/nostr-provider.js) |
Manifest hooks.post_install copy_from_host.dest. |
blossom/config.yml |
The config embedded under files: in apps/podsteadr-blossom/manifest.yml. It's a copy, not identical: keep archy's paths and comments. |
mediamtx/mediamtx.yml (including the auth webhook URL http://podsteadr-app:8095/...) |
The config embedded under files: in apps/podsteadr-mediamtx/manifest.yml. |
blossom or mediamtx image version in docker-compose.yml |
container.image in the matching archy manifest. |
Service DNS names the app uses (mediamtx, blossom, podsteadr-app), container names, or adding/removing a container |
Network aliases in the manifests, and the stack registration in core: core/archipelago/src/app_ops.rs (stack_member_app_ids, owning_package), api/rpc/package/stacks.rs, install.rs, runtime.rs (orchestrator_uninstall_app_ids), config.rs (all_container_names), dependencies.rs (startup_order), crash_recovery.rs (auto-start list and the podsteadr StackRecoverySpec aliases), container/docker_packages.rs (excluded_services). Grep core/ for podsteadr to find them all. |
| User-facing description, features, screenshots | Manifest description and apps/podsteadr/README.md. |
podsteadr-player (~/podsteadr-player)
| Change there | Update in archy |
|---|---|
Listening port (8097) in nginx.conf / Dockerfile |
apps/podsteadr-player/manifest.yml ports, interfaces, health_check.endpoint, apps/PORTS.md, the ("podsteadr-player", 8097) entry in the unauthenticated-endpoint test in core/container/src/manifest.rs, then regenerate. |
Ports or hosts the /fips/ gateway relays (nginx.conf, njs/fips.js, src/lib/net.ts) |
The player manifest's auth_rationale describes them, and every relayed port must be opened over FIPS by some manifest's interfaces (8095 and 8098 today). |
Files nginx writes (pid, temp paths in /tmp) |
The root filesystem is read-only; only the /tmp tmpfs in the manifest is writable. |
/healthz |
Player manifest health_check.path. |
| Base image or anything needing more capabilities or egress | Player manifest security/network. It uses network: pasta because the gateway needs IPv6 egress to the mesh; bridge networks can't reach FIPS addresses. |
Shipping a new version to nodes
Manifests pin images with pull_policy: if-not-present, so a node that already
has a tag will never pick up a rebuilt image under the same tag. Every release
needs a new tag.
- Merge the change in this repo (and/or the player) and push to
originandgitea. - In archy, on a branch: bump
versionand thecontainer.imagetag inapps/podsteadr/manifest.ymland/orapps/podsteadr-player/manifest.yml, plusVERSIONinapps/podsteadr/build-from-prototype.sh. - Build and publish the images from
~/archy:./apps/podsteadr/push-to-registry.sh <version>(registrysource.archipelago-foundation.org/lfg2025; needspodman login). To test on a node without publishing, runbuild-from-prototype.sh ~/podsteadr ~/podsteadr-playeron that node instead. - Regenerate and check (below), commit by path, push, open or update the archy PR.
podsteadr is not in archy's per-app OTA update mapping (scripts/image-versions.sh,
core/archipelago/src/container/image_versions.rs, scripts/generate-app-catalog.sh),
so new versions reach nodes with an Archipelago release, not through the App
Store "Update" button.
Regenerate and check (run in ~/archy)
python3 scripts/generate-app-catalog.py # catalogs, app_ports.rs, app-session config
python3 scripts/generate-app-catalog.py # second run must report total_updated=0
python3 scripts/check-app-catalog-drift.py
python3 scripts/check-app-build-contexts.py .
for a in podsteadr podsteadr-blossom podsteadr-mediamtx podsteadr-player; do
./scripts/validate-app-manifest.sh apps/$a/manifest.yml
done
cd core && cargo test -p archipelago-container manifest
If you touched core: cargo test -p archipelago (from core/). It needs a recent
stable toolchain; if the system rustc fails on atomic_try_update, put the
rustup stable toolchain first on PATH. If you touched neode-ui/:
cd neode-ui && npx vitest run src/views/apps src/views/appSession.
Testing on a node
Before an archy release: build both images on a test node with
build-from-prototype.sh (it works around rootless podman seeing /var/tmp
read-only), deploy the archy branch, install podsteadr from the App Store, and
run tests/lifecycle/run-gate.sh on the node (install, stop/start/restart,
reinstall, reboot and archipelago-restart survival, uninstall with all four
containers removed). Installing, stopping and uninstalling need a dashboard
login, so the node's owner clicks those.