mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
Motivation: Release images should be built, checked, published, and consumed through the same Nostr-native OCI path operators will use, without relying on an unreviewed local release procedure. Approach: Add a checked-in container manifest, a Docker-to-OCI layout helper, automatic tag publication and pull verification, a safe exact-tag backfill workflow, and deployment CI that imports and runs the exact generated layout. Correctness: Release tags come only from reviewed OCI index annotations; ordinary publication preserves prior tags; historical backfills cannot move latest or prerelease channels; generated images and temporary resources use bounded, validated names and cleanup. Excluded scope: This change does not alter ngit-grasp runtime behavior, change package versions, create v3.0.2, publish a container, move a release tag, or run the heavyweight container build in the coding VM. Validation: git diff --check; shellcheck on all container scripts; actionlint on all affected workflows; ngit parsing of .ngit/containers.yaml; canonical source and v3.0.1 tag resolution. The PR pipeline performs the full OCI build, import, and deployment test. Assisted-by: Codex (GPT-5)
172 lines
6.2 KiB
Markdown
172 lines
6.2 KiB
Markdown
# Deploy on managed hosting
|
|
|
|
The supplied container can run on Railway, Render, and Fly.io when each service
|
|
has a custom domain, one persistent `/data` volume, and exactly one running
|
|
instance. These platforms terminate TLS and proxy WebSockets to ngit-grasp.
|
|
|
|
Managed hosting is best for a small or moderate relay whose operator accepts
|
|
brief upgrade downtime. For a large existing relay, use NixOS, systemd, or
|
|
Compose so startup migrations and storage snapshots remain under direct
|
|
operator control.
|
|
|
|
Read the [deployment contract](../reference/deployment-contract.md) first. In
|
|
particular, provider replicas do not make ngit-grasp highly available: their
|
|
local volumes do not replicate application state.
|
|
|
|
## Common requirements
|
|
|
|
For every provider:
|
|
|
|
- set `NGIT_DOMAIN` to the final custom hostname, not the provider hostname;
|
|
- mount durable storage at `/data` before the first successful start;
|
|
- keep the instance count at one and disable scale-to-zero;
|
|
- keep `NGIT_BASE_PATH=/` unless path routing has been designed explicitly;
|
|
- allow at least five minutes between `SIGTERM` and forced termination; and
|
|
- take an external backup of `/data`, including `.relay-owner.nsec`.
|
|
|
|
The image maps a platform-provided `PORT` to `0.0.0.0:${PORT}`. Do not set
|
|
`NGIT_BIND_ADDRESS` unless the provider template below does so explicitly.
|
|
|
|
## Railway
|
|
|
|
`railway.toml` selects the Dockerfile, uses `/` as the health check, disables
|
|
old/new deployment overlap, and gives shutdown five minutes. Railway storage is
|
|
configured separately from config-as-code. See Railway's
|
|
[config-as-code reference](https://docs.railway.com/config-as-code/reference)
|
|
and [volume guide](https://docs.railway.com/volumes) for the provider-side
|
|
details.
|
|
|
|
From the repository root with the Railway CLI installed:
|
|
|
|
```bash
|
|
railway login
|
|
railway init
|
|
railway add --service ngit-grasp
|
|
railway service ngit-grasp
|
|
railway variable set NGIT_DOMAIN=ngit.example.com NGIT_BASE_PATH=/
|
|
railway volume add --mount-path /data
|
|
railway up
|
|
railway domain ngit.example.com
|
|
```
|
|
|
|
Add the DNS records returned by `railway domain`, then inspect status and verify
|
|
the public relay:
|
|
|
|
```bash
|
|
railway domain status ngit.example.com
|
|
railway deployment list --json
|
|
scripts/verify-deployment.sh https://ngit.example.com
|
|
```
|
|
|
|
Do not add replicas or multi-region configuration. Railway mounts a new volume
|
|
as root; the image entrypoint prepares it and drops privileges before starting
|
|
ngit-grasp.
|
|
|
|
Railway volume backups are useful recovery points, but also export or snapshot
|
|
state outside the platform. During a large storage migration, increase the
|
|
health-check timeout or move the upgrade to a directly operated host.
|
|
|
|
## Render
|
|
|
|
`render.yaml` describes a paid `starter` web service with a 10 GB disk mounted
|
|
at `/data`, a root health check, a five-minute shutdown delay, and automatic
|
|
deploys disabled. Render prompts for `NGIT_DOMAIN` when the Blueprint is
|
|
created. The fields follow Render's
|
|
[Blueprint specification](https://render.com/docs/blueprint-spec); its
|
|
[persistent disk guide](https://render.com/docs/disks) describes the storage
|
|
and scaling constraints.
|
|
|
|
The published image is available to provider workflows that accept a public
|
|
Docker-compatible registry reference:
|
|
|
|
```text
|
|
ncontainer.io/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp:latest
|
|
```
|
|
|
|
Pin an explicit release version instead of `latest` for repeatable production
|
|
deployments. The supplied `render.yaml` remains source-backed because Render
|
|
Blueprints require a repository connected through one of Render's supported
|
|
Git providers. Use Render's **Public Git Repository** flow with the canonical
|
|
URL:
|
|
|
|
```text
|
|
https://gitnostr.com/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
|
|
```
|
|
|
|
Choose Docker and apply the values from `render.yaml` in the service form:
|
|
|
|
- environment variable `NGIT_DOMAIN=ngit.example.com`;
|
|
- persistent disk mounted at `/data`;
|
|
- health check path `/`;
|
|
- maximum shutdown delay 300 seconds; and
|
|
- one instance with automatic deploys disabled.
|
|
|
|
Add and verify the custom domain before publishing it in repository
|
|
announcements. Render services backed by a persistent disk cannot run multiple
|
|
instances and have brief downtime during deploys, which matches the relay's
|
|
single-writer requirement.
|
|
|
|
After a manual deploy, run:
|
|
|
|
```bash
|
|
scripts/verify-deployment.sh https://ngit.example.com
|
|
```
|
|
|
|
Use Render disk snapshots plus an independent backup. Only `/data` persists;
|
|
all other container filesystem changes are ephemeral.
|
|
|
|
## Fly.io
|
|
|
|
Fly volumes are local to one Machine and are not automatically replicated. The
|
|
template therefore disables autostop, uses an immediate replacement strategy,
|
|
and must be deployed with high-availability seeding disabled. See Fly's
|
|
[configuration reference](https://fly.io/docs/reference/configuration/) and
|
|
[volume overview](https://fly.io/docs/volumes/overview/) for the underlying
|
|
platform behavior.
|
|
|
|
Copy and edit the template:
|
|
|
|
```bash
|
|
cp fly.toml.example fly.toml
|
|
# Set a unique app name, primary region, and NGIT_DOMAIN in fly.toml.
|
|
fly config validate --strict --config fly.toml
|
|
```
|
|
|
|
Create the app and one volume in the same region, then deploy one Machine:
|
|
|
|
```bash
|
|
fly apps create replace-with-a-unique-ngit-grasp-name
|
|
fly volumes create ngit_grasp_data --region ord --size 10
|
|
fly deploy --ha=false
|
|
fly scale count 1
|
|
fly certs add ngit.example.com
|
|
```
|
|
|
|
Use the app name and region selected in `fly.toml`, add the DNS records shown by
|
|
`fly certs`, then verify:
|
|
|
|
```bash
|
|
fly checks list
|
|
fly scale show
|
|
scripts/verify-deployment.sh https://ngit.example.com
|
|
```
|
|
|
|
Never scale above one: Fly creates a separate empty volume for each additional
|
|
Machine and does not copy ngit-grasp state. A single Machine and volume can be
|
|
unavailable after host failure, so maintain an external backup rather than
|
|
relying only on Fly snapshots.
|
|
|
|
## Upgrades
|
|
|
|
Managed volume deployments cannot provide a safe zero-downtime writer handoff.
|
|
Expect brief downtime:
|
|
|
|
1. disable automatic deploys;
|
|
2. take a complete provider snapshot and an external backup;
|
|
3. deploy the pinned revision with one instance;
|
|
4. inspect startup and integrity logs; and
|
|
5. run the public verifier.
|
|
|
|
For a storage-changing release, restore both the prior executable and its
|
|
matching pre-upgrade `/data` snapshot when rolling back.
|