feat: add staging deployment bundles and tooling - #11
Conversation
Compose the Forge services into two version-pinned staging bundles for
the Calibnet box: `core` (sprue + signing-service + delegator +
postgres/minio/dynamodb) and `piri` (one storage node), wired over
public https://*.staging.fil.one URLs fronted by the host Caddy. No
indexer/IPNI/redis/Anvil/mailer; the host Lotus node is reached via
host-gateway.
Add `smelt staging keygen` to generate service identities, EVM wallets,
and UCAN proofs once — storing private keys in 1Password, committing the
proofs, and recording the public wallet addresses in wallets.env for
periodic top-ups. Contract addresses live once in smart-contracts.env;
the provision script renders configs (op inject + ${VAR}) and streams
them to the box with no local plaintext; the deploy script pulls pinned
images and verifies health. Includes a box bootstrap script and the
docs/STAGING_DEPLOY.md runbook.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
The box's root login shell is fish, which doesn't understand POSIX inline-assignment prefixes and word-splits unquoted values. Passing `VAR=val ... bash -s` as ssh command-line args therefore failed with "fish: Unknown command: signing-service". Stream the config as `export` statements (quoted with printf %q) into the script bash reads from stdin, so the login shell only ever sees a clean `bash -s` invocation. While here: - Pin the checkout to FORGE_REF (default main); the clone otherwise lands on the default branch, which lacked the staging files. - Default REPO_URL so it no longer has to be passed every run. - Print numbered [N/4] step progress as the remote script runs. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
There was a problem hiding this comment.
Pull request overview
Adds a complete “staging deployment” workflow to the repo: version-pinned Compose bundles for a real Calibnet staging box, plus scripts and a smelt staging keygen command to generate/stash secrets (1Password) and produce non-secret artifacts (wallet addresses + UCAN proofs) used by the deployment.
Changes:
- Introduces staging automation scripts for bootstrap/provision/deploy, and a runbook (
docs/STAGING_DEPLOY.md) describing the full manual procedure. - Adds
pkg/stagingkeygen tooling (wallet generation, UCAN proof generation, 1Password storage) and wires it intosmelt+Makefile. - Adds staging environment manifests/config (core + piri bundles, Caddy snippet, env files, proofs, DNS reference).
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/staging-provision.sh | Provisions rendered configs + key material from 1Password onto the staging host. |
| scripts/staging-deploy.sh | SSH-driven deploy of a chosen bundle using pinned Compose env files + health wait. |
| scripts/staging-bootstrap.sh | One-time host bootstrap: repo checkout, dirs, Caddy import wiring, basic verification. |
| pkg/staging/wallet.go | Generates random secp256k1 wallets + EVM address derivation for staging. |
| pkg/staging/wallet_test.go | Unit tests for wallet serialization/address formatting. |
| pkg/staging/proofs.go | Generates UCAN delegation proofs via ucantool. |
| pkg/staging/onepassword.go | Stores generated secrets into a single 1Password item via op CLI. |
| pkg/staging/keygen.go | Implements the staging “key ceremony”: keys, wallets, secrets, proofs, 1Password storage. |
| pkg/generate/keys.go | Exposes Ed25519 key generation for reuse by staging tooling. |
| Makefile | Adds staging targets and help text. |
| environments/staging/wallets.env | Commits public wallet addresses produced by keygen. |
| environments/staging/smart-contracts.env | Single source of truth for chain/RPC/contract addresses. |
| environments/staging/README.md | High-level staging environment overview and pointer to runbook. |
| environments/staging/proofs/piri-0-proof.txt | Committed piri delegation proof (base64+gzip container). |
| environments/staging/proofs/indexing-service-proof.txt | Committed indexing-service delegation proof (binary content). |
| environments/staging/proofs/egress-tracking-proof.txt | Committed egress-tracking delegation proof (binary content). |
| environments/staging/proofs/.gitkeep | Documents which proof files are expected to exist/commit. |
| environments/staging/piri/versions.env | Pins piri image reference (placeholder :main currently). |
| environments/staging/piri/entrypoint.sh | Staging-specific piri init/serve entrypoint with registrar-based registration. |
| environments/staging/piri/config/piri/piri-base-config.toml.tpl | Template for piri base config rendered from env at provision time. |
| environments/staging/piri/config/piri/piri-base-config.toml.example | Redacted example showing expected structure. |
| environments/staging/piri/config.env | Non-secret piri bundle config/env interpolation values. |
| environments/staging/piri/compose.yml | Piri bundle Compose manifest (ports, mounts, healthcheck, etc.). |
| environments/staging/dns/fil-one-staging.tf | Reference DNS Terraform resources (to be copied to infra repo). |
| environments/staging/core/versions.env | Pins core bundle images (placeholders :main currently). |
| environments/staging/core/secrets.env.tpl | 1Password-templated secrets env file template (not committed rendered output). |
| environments/staging/core/secrets.env.example | Redacted example of the secrets env file shape. |
| environments/staging/core/config/sprue/config.yaml.tpl | Sprue config template with 1Password-injected Postgres secret. |
| environments/staging/core/config/sprue/config.yaml.example | Redacted example of sprue config structure. |
| environments/staging/core/config/signer/signer.yaml | Non-secret signing-service config mounted from git tree. |
| environments/staging/core/config/delegator/delegator.yaml.tpl | Delegator config template (1Password transactor key + env-substituted chain info). |
| environments/staging/core/config/delegator/delegator.yaml.example | Redacted example of delegator config structure. |
| environments/staging/core/config.env | Non-secret core bundle config/env interpolation values. |
| environments/staging/core/compose.yml | Core bundle Compose manifest (sprue/signing-service/delegator + deps). |
| environments/staging/caddy/forge-staging.caddy | Caddy site blocks for staging service hostnames → loopback ports. |
| docs/STAGING_DEPLOY.md | End-to-end staging deployment runbook and operational notes. |
| cmd/smelt/cmd/staging.go | Adds smelt staging keygen Cobra command wiring and output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1 @@ | |||
| �X@��!�"Hs����˫om�M�Z��G�`����rz�n� Po��� 9w��)b�ahH4��qsucan/dlg@1.0.0-rc.1�caudx!did:web:delegator.staging.fil.oneccmdl/claim/cachecexp�cissxdid:web:indexer.staging.fil.onecpol�csubxdid:web:indexer.staging.fil.oneenoncePv�ߓ �mI�0��A | |||
There was a problem hiding this comment.
I followed the convention already used in this repo.
My preference is to change the extension to .bin, e.g. indexing-service-proof.bin.
@frrist what's your opinion on this?
There was a problem hiding this comment.
I don't have a strong preference for file suffix conventions. I'd prefere to avoid introducing unnescarry churn in this PR related to it, but will default to whatever @alanshaw thinks is best.
There was a problem hiding this comment.
Interestingly enough, some services have base64-encoded content in their proof files. Only indexing-service-proof.txt and egress-tracking-proof.txt are in binary format.
I'll ignore this for now; we have bigger fish to fry. 🤷🏻
Three failures surfaced when rendering and shipping the core bundle:
- op inject scans the whole template (comments included) for op:// and
{{ }} tokens, not just real references. Stray `op://` and `{{ }}` text
in template comments were resolved as references and aborted the render.
Reword the comments to avoid both.
- ship() built the remote write as bash syntax (`t=$(...)`, `{ ...; }`),
which the box's fish login shell rejects. Pipe the script to `bash -s`
instead (as staging-bootstrap.sh does), appending the secret payload
after the script so the install line's trailing `cat` consumes it.
- Provisioning opened a new SSH connection per file, and the box
rate-limits connection bursts — it refused partway through. Multiplex
every transfer onto one connection (ControlMaster/ControlPath).
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Assisted-by: Claude:claude-opus-4-8
storeInOnePassword used `op item create/edit` assignment statements of the form `label[password]=@<file>`, assuming op expands `@<file>` to the file's contents. It does not — that is a curl-ism — so op stored the literal temp path (e.g. "@/var/folders/.../delegator.pem") as every *-key value. Every PEM-loading service then crash-looped with "no PRIVATE KEY block found in PEM file", and op read faithfully shipped the path string to the box. Build a JSON item template instead, reading each field's value from its file, and pipe it to `op item create` over stdin. This stores the real key material and keeps secret values off the command line and out of shell history (op's docs recommend a template for sensitive values). The item is deleted first when present, matching keygen's documented full-overwrite semantics. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
The health gate only inspected the Health column, counting `starting` and `unhealthy`. A container with no healthcheck has an empty Health value, so a crash-looping one (State=restarting) was neither starting nor unhealthy — the loop saw zero "starting" and declared "all services healthy", letting a broken deploy report success. Inspect State + Health + ExitCode per container instead: fail on restarting/dead, exited non-zero, or unhealthy; keep waiting on created/starting; treat running (healthy or no healthcheck) and exited-0 one-shots (e.g. minio-init) as ready. Use a '|' delimiter so an empty Health field doesn't shift the parsed columns. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
Two corrections to the staging keygen 1Password storage: - Don't delete-then-create. A failed create left the item soft-deleted with nothing to replace it (which is how the staging item ended up archived). Edit in place when the item exists, create only when it's absent; keygen supplies the full field set, so an edit fully refreshes the values. - Give each custom field an explicit "id". The Secure Note template (op item template get) shows every field carries id/type/label/value, and op can reject a custom field that omits id. Set id = label so `op read op://vault/item/<label>` still resolves. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
b02e588 to
82127ce
Compare
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
staging-deploy.sh ran docker compose against whatever commit happened to be checked out on the box, so deploying a specific ref meant a manual ssh + git checkout first. Honour FORGE_REF (default main, matching staging-bootstrap) by syncing the box's checkout before deploying. Use git fetch + reset --hard rather than checkout + pull: it switches to a branch tip, tag, or commit sha uniformly with no detached-HEAD edge cases. Prefer origin/<ref> so a branch lands on the freshly-fetched remote tip, falling back to the bare ref for tags and shas. Abort first if the box has uncommitted changes to tracked files, so reset --hard never silently clobbers a hand-edit; untracked files (provisioned secrets, generated artifacts) are ignored. Update the runbook deploy and rollback steps accordingly. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Generalise the postgres-only reset into reset_bundle_data, which tears down every container in a bundle's Compose project and deletes its persistent data dirs (core: postgres/dynamodb/minio; piri: piri-0) before shipping fresh config and keys. Provisioning now resets the bundle to a clean slate so the next staging-deploy rebuilds everything. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
A crash-looping container oscillates running<->restarting faster than the poll interval, so a single 'compose ps' State snapshot could catch it mid-restart in a momentary 'running' state with empty Health and wrongly count it ready. Switch the gate to 'docker inspect' so it can read the non-racy RestartCount: a fresh 'up -d' starts every container at 0, so any nonzero count means it has already crashed and restarted. Also require two consecutive fully-ready polls (ready_streak) to guard the opposite race where a service comes up clean and crashes a second later. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
sprue does not consult the AWS SDK env vars for a custom S3 endpoint, so move the MinIO access/secret keys into storage.s3 of the rendered sprue-config.yaml and add use_path_style for MinIO. Drop the now-unused AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY from the container env and secrets templates. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
signing-service has no /.well-known/did.json route by design, so the verify loop always reported it as failed on a healthy deploy. It resolves its own DID from an in-memory document, and no peer resolves did:web:signing-service — piri uses the configured DID only as the signing-invocation audience, and the signed response is an EIP-712 signature verified on-chain, not a did:web-resolved UCAN receipt. Check only sprue and delegator; explain the omission inline. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
The piri image runs as USER nobody, but staging provisions the key files as 0440 root:root and creates the host data dir as root:root. As nobody, piri could neither read /keys/piri.pem (entrypoint died at DID extraction, the failure masked by set -e on the grep pipeline) nor write /data/piri. Set user: "0:0" on the piri-0 service, matching the local-dev stack — the compose generator already emits user: "0:0" for every piri node (pkg/generate/compose.go). The hand-written staging compose omitted it. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
The entrypoints captured the DID in a `PIRI_DID=$(piri identity parse | grep)` assignment. Under `set -e`, a parse failure (e.g. an unreadable key file) or a grep no-match aborts the script at the assignment, before the explicit error checks run — so the container crash-loops printing only "Extracting piri DID..." with no clue why. This is exactly what hid the recent staging key-permission failure. Run the parse on its own line, fail loudly with its stderr if it errors, and guard the grep with `|| true` so the no-did:key case reaches an informative check. Applied to both the staging and local-dev entrypoints (same defect). Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
Containers calling https://*.staging.fil.one resolved the box's own public IP and hairpin NAT back to the host timed out, hanging piri init's registrar request to the delegator (and any cross-bundle or upload->piri callback next). Map every *.staging.fil.one host that has a Caddy site to host-gateway via an x-staging-hosts extra_hosts anchor in both bundles, so calls reach the host's Caddy directly over the Docker bridge. TLS is intact: Caddy still terminates the real hostname's cert (SNI preserved) and reverse-proxies to the loopback port. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
…ic IP" This reverts commit 653c514.
Containers resolve https://*.staging.fil.one to the box's public IP and connect to it, but that traffic arrives over the Docker bridge while the stock UFW :443 rule is scoped to the public NIC. UFW's default deny-incoming then drops it -- the i/o timeout that hung piri init's registrar call to the delegator. staging-bootstrap now adds 'ufw allow from 172.16.0.0/12 to any port 443 proto tcp', mirroring the existing :1234 Lotus rule that already lets containers reach the host. Idempotent. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
piri init step [4/7] calls the delegator's request-approval, which 403s any DID not on its allow list. In local dev piri's entrypoint self-adds to the shared dynamodb-local; across the split staging bundles the piri bundle can't reach the core DynamoDB, so that step is dropped and nothing fills the gap. Add scripts/staging-allowlist-piri.sh to close it from the core side: it derives piri's DID from its provisioned key and runs the delegator's 'store allow-did' against the core DynamoDB. Idempotent. Wire it up as 'make staging-allowlist-piri', to be run after deploy-core and before deploy-piri, and document the ordering. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Point the piri bundle at a rolling per-PR tag so the modified piri node can be validated on staging before the PR lands on piri's main. Re-pushing the tag plus a redeploy picks up new builds without editing this file. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
`piri init` step [4/6] fails with InsufficientLockupFunds because lockup draws only on funds deposited into FilecoinPay, not on USDFC held in the payer wallet. The dev stack sidesteps this via its baked-in Anvil state; on Calibnet the deposit must be made out of band. Add scripts/staging-fund-payer.sh (+ `make staging-fund-payer`), which reads the payer key from 1Password and sends three cast transactions: approve, deposit, and setOperatorApproval for the warm-storage service. Amounts are baked in but env-overridable, defaulting well below the USDFC faucet's 10/day cap; the deposit is skipped when already funded. Document the step in the staging runbook (prereqs, both faucets, deploy sequence, and a new 5b explaining the wallet-vs-contract distinction). Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
Switch LOTUS_RPC_URL from http:// to ws://. Piri watches for tx confirmations via ChainNotify, a streaming subscription that only delivers events over a WebSocket; over plain HTTP the scheduler never fires and receipts sit pending forever. Use ws:// (not wss://) since the localhost Lotus node is plaintext with no TLS in front of it. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
FilOne Forge uses a different billing mechanism; the payment-plan check sprue inherited from Storacha is a left-over we don't need. Set allow_provision_without_payment_plan: true so staging can provision spaces without a customer payment plan, and document it in the runbook. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Replace dev-mode Vault with integrated Raft storage on the ZFS pool, add an unseal sidecar, and mint the unseal key + root token at runtime via make staging-vault-init (stored in 1Password). Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
## Summary
Fixed the DID document generation to correctly encode verification
method IDs and set the controller field.
## Key Changes
- **Fixed fragment encoding**: Changed `doc.Fragment("#key-0")` to
`doc.Fragment("key-0")` to prevent double-encoding of the `#` character.
The `Fragment()` method automatically prepends `#`, so passing `#key-0`
resulted in `#%23key-0` in the serialized output.
- **Set verification method controller**: Added `vm.Controller = doc.ID`
to properly associate the verification method with the DID document.
- **Added test coverage**: Created comprehensive test
(`TestDIDDocument`) that validates:
- DID document generation succeeds
- Document ID matches the service DID
- Verification method ID is correctly formatted as
`did:web:example.com#key-0`
- Verification method ID does not contain percent-encoded characters
- Verification method controller is set to the document ID
## Implementation Details
The fix ensures that DID documents conform to the W3C DID specification
by properly formatting the verification method ID and establishing the
correct controller relationship.
https://claude.ai/code/session_01YAjDX5F44mcX8ojb1ENjY
## References
- fil-forge/smelt#11
The hashicorp/vault image defaults to the vault user, so its entrypoint skips the /vault/file chown and Raft fails with permission denied on the root-owned bind mount. Start the container as root; the stock entrypoint chowns the data dir and su-exec's back down to the vault user. Also stream progress + dump logs on timeout in staging-vault-init.sh. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Running hilt-vault as root makes the entrypoint attempt setcap for the mlock capability, but setcap isn't in hashicorp/vault:2.0, so it aborts startup with exit 127 under the entrypoint's set -e. mlock is already disabled in vault.hcl, so set SKIP_SETCAP=true and drop the unused IPC_LOCK cap; the chown + step-down still run. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
This image's 'vault operator unseal -' does not read the key from stdin (it takes '-' literally), so pass the unseal key as an argument (it is already at rest in vault-secrets.env on the box). 'vault login -' does read the token from stdin, so the root token stays off argv. Ensure the KV v2 engine at secret/ on every run (only when absent) so a partially completed earlier run self-heals. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
vault login writes a token helper file whose behavior varies by environment and failed on the box even with a valid token. Read the root token from stdin into VAULT_TOKEN inside the container and use it directly for the KV v2 setup — no login, no token helper, still off argv. Surface a clear error if the token is ever rejected. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
The read-modify-write of the staging secrets item mirrored readOnePasswordFields, but not closely enough: `op item edit` rejects the payload with "sections[0].fields[N] has non-unique name" when two fields collide within the default section. Match the Go normalization exactly: drop fields with an empty label or empty value (e.g. the SECURE_NOTE notes field), and dedup by label (last wins) so no two fields share a name. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Chain the nine staging-* targets — provision both bundles, vault-init, deploy, register — into a single `make staging-reset` that wipes all staging data and redeploys from scratch, aborting on the first failure. Honors FORGE_REF for deploying a non-main branch. Keys and EVM wallets (only ever re-shipped from 1Password) and all on-chain state survive; the hilt-vault unseal key + root token rotate because the Vault store is wiped and re-initialized. Document it as a "One-shot reset" section and drop the now-fragile section numbers from the two adjacent headings the insertion shifted. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
pg_isready without -h checks the unix socket, which is up during the image's initdb bootstrap server (listen_addresses='') before TCP is listening. On a freshly-wiped data dir this marks postgres healthy too early, so postgres-init connects over TCP and psql exits 2, failing the deploy. Probe 127.0.0.1 so the check stays unready until the real server listens on TCP. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
Pipe the Hilt access-key response through jq to write a .env.staging file with all four AWS_ vars, so the S3 smoke test can source it instead of hand-copying the once-returned secret. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
Use curl --fail-with-body and capture the response before writing, so a non-2xx from hilt no longer clobbers .env.staging with empty AWS_ values. Also expand the requested S3 permission set to the subset hilt supports today (bucket + object + object-lock/retention/legal-hold). Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Assisted-by: Claude:claude-opus-4-8
| # Hosts expected to serve a did:web document. ingot is NOT here — it acts under | ||
| # a did:key and serves no did.json (checked separately via /health below). | ||
| HOSTS="sprue signing-service delegator piri-0 hilt" |
| # Secret handling matches the sibling staging scripts: values are read into | ||
| # memory, streamed over stdin, never written to local disk, never logged, and | ||
| # kept off argv (unseal key via `vault operator unseal -`, root token via | ||
| # `vault login -`). Do NOT enable `set -x`. |
|
Thanks @bajtos this is great work, and the runbook makes the whole flow easy to follow. Rather than line-level review, I have one structural ask and a proposal for where to take this next. The ask: I don't think this should land in smelt.Smelt's job is spinning up local Forge networks on a dev machine and providing an SDK for tests to drive them. This PR is a different concern — operating a remote environment (SSH provisioning, 1Password secrets, funded Calibnet wallets) — and it carries a hand-maintained parallel copy of the service wiring So: Would you be open to porting the branch to a new dedicated deployment repo instead? What I think this gets right — and why it strengthens the case for a separate repo. Design questions I think we still need to work throughNot blockers on this work, but things to settle in a short design doc before we automate:
Proposed next stepPort the branch to a new repo and keep iterating there, and let's write a short design doc covering the questions above before the CI/CD work starts. |
Allow browser clients on app.fil.one, staging.fil.one, and *.dev.fil.one to call the ingot S3 endpoint cross-origin. Assisted-by: Claude:claude-fable-5 Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
|
Heads-up from reviewing #19 (piri→upload blob-removal delegations): the staging deployment added here needs matching updates to pick up the piri/sprue blob-removal changes — and one of the steps is easy to get silently wrong. What needs to change1. The staging proof generator needs the same two commands. 2. The committed proof must be re-issued. 3. Bump the pinned images and redeploy both bundles. 4. The step that will silently not work: the provider must be deregistered and re-registered. The sequence that works: Also worth knowing: nothing forces this at registration time — sprue's Cleanest pathSince this PR hasn't merged yet, fold the Generated by Claude Code |
piri:main crash-loops with sqlite storage, so a fresh checkout no longer boots with the previous default manifest. Drop to a single node backed by postgres + s3. Also move piri-postgres to host port 15074 by default. Last but not least, update docs to list all services & their ports, including the recently added ones. ## References #11 --------- Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Co-authored-by: frrist <forrest@storacha.network> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
Closed in favour of fil-one/RFC#19, https://github.com/fil-forge/infra-central and https://github.com/fil-forge/infra-nodes |
Create an automated deployment process for updating the staging deployment running on a bare-metal box. The deployment is triggered manually from a dev machine.
Service endpoints:
Region:
eu-central-3Start reading here: docs/STAGING_DEPLOY.md
Notion page documenting the servers.com box we are deploying to:
https://app.notion.com/p/filecoin/Servers-com-Calibnet-Box-Runbook-36b7631f2825802b8e3ac9f25eadcc34
This pull request is not the final version, just the first step on the journey. A foundation we will iterate on in the upcoming weeks.
Depends on:
TODO: