@astrojs/node standalone output as Railway; no Docker authoring required, Fly generates a Dockerfile with fly launch.fly ext create upstash-redis), auto-injects REDIS_URL into the app.auto_stop_machines = "stop" in fly.toml).flyctl installed — brew install flyctl on macOS, or curl -L https://fly.io/install.sh | sh.fly auth login
cd neuromast
fly launch --no-deploy
Wizard prompts: pick a region close to your Mac, skip the Postgres and "add a database" questions (we'll add Redis separately), and accept the generated Dockerfile. Fly writes a fly.toml with your app name.
ADAPTER=node as a build-time argEdit the generated Dockerfile — add ENV ADAPTER=node before the npm run build line so Astro picks the Node adapter instead of Cloudflare:
ENV ADAPTER=node
RUN npm run build
fly ext create upstash-redis
Pick a region matching your app's. Fly creates the database and adds REDIS_URL as a secret on your app. Neuromast's storage factory auto-detects it.
fly secrets set POLL_TOKEN="$(openssl rand -hex 32)"
fly secrets set SHARED_SECRET="$(openssl rand -hex 32)" # optional
fly secrets set HOOK_SCHEME_GITHUB=github HOOK_SECRET_GITHUB=<your-webhook-secret>
fly deploy
Builds the Docker image, pushes to Fly's registry, runs a health check, switches traffic. First deploy takes ~2 minutes; subsequent ones are faster.
export AXOL_CLOUD_URL=https://<your-app>.fly.dev
export POLL_TOKEN='the-bearer-you-set'
export SHARED_SECRET='the-shared-key-you-set'
curl -X POST "$AXOL_CLOUD_URL/app/api/hooks/smoke?key=$SHARED_SECRET" \
-H 'content-type: application/json' \
-d '{"title":"hello","body":"from fly"}'
AXOL_CLOUD_URL="$AXOL_CLOUD_URL" \
AXOL_POLL_TOKEN="$POLL_TOKEN" \
./lateral-line/install.sh
fly deploy
For continuous deployment, Fly has an official GitHub Action (superfly/flyctl-actions). Add a FLY_API_TOKEN repo secret and a workflow that runs flyctl deploy --remote-only.
fly secrets set NAME=newvalue overwrites and triggers an automatic restart. Machines pick up the change within seconds.
Hobby: ~$5/month credit, covers a single small machine + Upstash Redis idle. Auto-stop reduces idle bill to near-zero; cold start adds ~2 s to the first request.
The Dockerfile ran npm ci with NODE_ENV=production, which skipped devDeps. Move @astrojs/node to dependencies (already done in neuromast's package.json — check your fork).
fly secrets list should show a REDIS_URL managed by upstash-redis. If missing, re-run fly ext create upstash-redis.
401 on every request
fly secrets list to confirm POLL_TOKEN is set. Secrets are per-app — adding them to the wrong app is a common first-time mistake.
Set auto_stop_machines = "off" in fly.toml to keep machines warm. Trade-off: higher idle bill. Alternatively, lower min_machines_running.