jinn-node-railway-deploy
Deploy a jinn-node worker to Railway using the standalone jinn-node runtime contract.
Use this skill only after local setup is complete and .operate/ exists with a working service.
When to use
Use this skill when the user asks to:
- deploy a worker to Railway,
- migrate a locally configured operator node to Railway,
- run canary worker validation with a canary
X402_GATEWAY_URL.
Do not use this skill for local-only setup (yarn setup, local worker loops).
Workflow
Run the deploy script from jinn-node/:
cd jinn-node
bash scripts/deploy-railway.sh --project <name> [--service <name>]
Both --project and --service are "upsert" — links to existing if found, creates if not.
Options
| Flag |
Description |
--project <name> |
Railway project name or ID (required unless already linked) |
--service <name> |
Service name (default: jinn-worker) |
--skip-import |
Skip .operate/.gemini SSH import (for re-deploys) |
--dry-run |
Preview commands without executing |
--help |
Show usage |
Examples
# First-time deploy
bash scripts/deploy-railway.sh --project jinn-worker
# Deploy with custom service name
bash scripts/deploy-railway.sh --project jinn-shared --service canary-worker
# Re-deploy (credentials already on volume)
bash scripts/deploy-railway.sh --project jinn-worker --skip-import
# Preview
bash scripts/deploy-railway.sh --project jinn-worker --dry-run
What the script does
- Validates preconditions (
.operate/, .env, Railway CLI >= 4.16.0, auth)
- Links or creates Railway project + service
- Creates persistent volume at
/home/jinn
- Reads
.env and pushes all non-empty variables to Railway (batched, --skip-deploys)
- First-time only: deploys idle container (
tail -f /dev/null), imports .operate/ (on-chain keys, wallets) and .gemini/ (LLM OAuth tokens) via SSH, then restores real start command
- Deploys the worker
- Verifies deployment and shows recent logs
Canary validation
For canary rollout:
- Set
X402_GATEWAY_URL to canary gateway and WORKSTREAM_FILTER to canary workstream in .env
- Deploy with the script
- Validate tool/business success
- Promote: update
.env with prod gateway URL, re-deploy with --skip-import
Credential bridge
Workers do not carry third-party API keys (Twitter, Umami, Supabase, etc.). Instead:
- On-chain identity (
.operate/): Contains private keys, wallets, and service configs. Imported to volume at /home/jinn/.operate. Used for ERC-8128 signed HTTP requests to the Control API.
- LLM auth (
.gemini/): Contains Gemini CLI OAuth tokens. Imported to /home/jinn/.gemini. Alternatively, set GEMINI_API_KEY in .env.
- Third-party credentials: Served at runtime by the credential bridge at
X402_GATEWAY_URL. The worker probes the bridge at startup and on each job claim to discover which credential providers are available. No API keys in .env.
- Configuration:
jinn.yaml (auto-generated on volume) contains service URLs, chain config, worker tuning, and feature flags. Secrets (RPC_URL, OPERATE_PASSWORD, GEMINI_API_KEY, GITHUB_TOKEN) stay in .env.
This means .env should contain only secrets and git identity — not infrastructure URLs or worker configuration.
Runtime contract reminders
- Railway deployment is
.operate-first (/home/jinn/.operate).
JINN_SERVICE_MECH_ADDRESS and JINN_SERVICE_SAFE_ADDRESS are fallback overrides, not primary operator flow.
- Use
railway.toml in the repo root.
- Healthcheck port: Railway auto-sets
PORT. The worker reads HEALTHCHECK_PORT > PORT > 8080. Do not set PORT manually.
- Do NOT use
railway logs -f — in CLI 4.16+, -f is --filter, not "follow". Use railway logs --lines N.
Failure handling
If deployment fails:
List deployments and identify the failed one:
railway deployment list
Capture deployment-specific logs:
railway logs --lines 300 <failed-deployment-id>
Confirm volume exists and is attached:
railway volume list
Confirm /home/jinn/.operate and /home/jinn/.gemini are present:
railway ssh -- 'ls -la /home/jinn/.operate /home/jinn/.gemini'
Verify OPERATE_PASSWORD matches local keystore.
Verify endpoint URLs and gateway mode (canary vs prod).
References
references/variables.md — full variable contract
references/volume-import.md — manual SSH import steps (if script import fails)
1---2name: jinn-node-railway-deploy3description: Deploy a jinn-node worker to Railway with volume mount, credential import, and health verification. Use when user says "deploy to Railway", "railway setup", "deploy worker", "run on Railway", or "move to cloud". Requires local setup complete first.4---56# jinn-node-railway-deploy78Deploy a `jinn-node` worker to Railway using the standalone `jinn-node` runtime contract.910Use this skill only **after local setup is complete** and `.operate/` exists with a working service.1112## When to use1314Use this skill when the user asks to:15- deploy a worker to Railway,16- migrate a locally configured operator node to Railway,17- run canary worker validation with a canary `X402_GATEWAY_URL`.1819Do not use this skill for local-only setup (`yarn setup`, local worker loops).2021## Workflow2223Run the deploy script from `jinn-node/`:2425```bash26cd jinn-node27bash scripts/deploy-railway.sh --project <name> [--service <name>]28```2930Both `--project` and `--service` are "upsert" — links to existing if found, creates if not.3132### Options3334| Flag | Description |35|------|-------------|36| `--project <name>` | Railway project name or ID (required unless already linked) |37| `--service <name>` | Service name (default: `jinn-worker`) |38| `--skip-import` | Skip `.operate/.gemini` SSH import (for re-deploys) |39| `--dry-run` | Preview commands without executing |40| `--help` | Show usage |4142### Examples4344```bash45# First-time deploy46bash scripts/deploy-railway.sh --project jinn-worker4748# Deploy with custom service name49bash scripts/deploy-railway.sh --project jinn-shared --service canary-worker5051# Re-deploy (credentials already on volume)52bash scripts/deploy-railway.sh --project jinn-worker --skip-import5354# Preview55bash scripts/deploy-railway.sh --project jinn-worker --dry-run56```5758### What the script does59601. Validates preconditions (`.operate/`, `.env`, Railway CLI >= 4.16.0, auth)612. Links or creates Railway project + service623. Creates persistent volume at `/home/jinn`634. Reads `.env` and pushes all non-empty variables to Railway (batched, `--skip-deploys`)645. First-time only: deploys idle container (`tail -f /dev/null`), imports `.operate/` (on-chain keys, wallets) and `.gemini/` (LLM OAuth tokens) via SSH, then restores real start command656. Deploys the worker667. Verifies deployment and shows recent logs6768### Canary validation6970For canary rollout:711. Set `X402_GATEWAY_URL` to canary gateway and `WORKSTREAM_FILTER` to canary workstream in `.env`722. Deploy with the script733. Validate tool/business success744. Promote: update `.env` with prod gateway URL, re-deploy with `--skip-import`7576## Credential bridge7778Workers do **not** carry third-party API keys (Twitter, Umami, Supabase, etc.). Instead:7980- **On-chain identity** (`.operate/`): Contains private keys, wallets, and service configs. Imported to volume at `/home/jinn/.operate`. Used for ERC-8128 signed HTTP requests to the Control API.81- **LLM auth** (`.gemini/`): Contains Gemini CLI OAuth tokens. Imported to `/home/jinn/.gemini`. Alternatively, set `GEMINI_API_KEY` in `.env`.82- **Third-party credentials**: Served at runtime by the credential bridge at `X402_GATEWAY_URL`. The worker probes the bridge at startup and on each job claim to discover which credential providers are available. No API keys in `.env`.83- **Configuration**: `jinn.yaml` (auto-generated on volume) contains service URLs, chain config, worker tuning, and feature flags. Secrets (RPC_URL, OPERATE_PASSWORD, GEMINI_API_KEY, GITHUB_TOKEN) stay in `.env`.8485This means `.env` should contain only secrets and git identity — not infrastructure URLs or worker configuration.8687## Runtime contract reminders8889- Railway deployment is `.operate`-first (`/home/jinn/.operate`).90- `JINN_SERVICE_MECH_ADDRESS` and `JINN_SERVICE_SAFE_ADDRESS` are fallback overrides, not primary operator flow.91- Use `railway.toml` in the repo root.92- **Healthcheck port:** Railway auto-sets `PORT`. The worker reads `HEALTHCHECK_PORT` > `PORT` > `8080`. Do not set `PORT` manually.93- **Do NOT use `railway logs -f`** — in CLI 4.16+, `-f` is `--filter`, not "follow". Use `railway logs --lines N`.9495## Failure handling9697If deployment fails:98991. List deployments and identify the failed one:100 ```bash101 railway deployment list102 ```1031042. Capture deployment-specific logs:105 ```bash106 railway logs --lines 300 <failed-deployment-id>107 ```1081093. Confirm volume exists and is attached:110 ```bash111 railway volume list112 ```1131144. Confirm `/home/jinn/.operate` and `/home/jinn/.gemini` are present:115 ```bash116 railway ssh -- 'ls -la /home/jinn/.operate /home/jinn/.gemini'117 ```1181195. Verify `OPERATE_PASSWORD` matches local keystore.1201216. Verify endpoint URLs and gateway mode (canary vs prod).122123## References124125- `references/variables.md` — full variable contract126- `references/volume-import.md` — manual SSH import steps (if script import fails)