---
title: "Deploy Nhost | (Just Updated) Firebase Alternative, Auth + GraphQL + Storage, Secrets Generated"
description: "Auth, GraphQL API and file storage in one stack, secrets generated"
category: "Other"
url: https://railway.com/deploy/nhost-or-just-updated-firebase-alternati
---

# Deploy Nhost | (Just Updated) Firebase Alternative, Auth + GraphQL + Storage, Secrets Generated

Auth, GraphQL API and file storage in one stack, secrets generated

**[Deploy Nhost | (Just Updated) Firebase Alternative, Auth + GraphQL + Storage, Secrets Generated on Railway](https://railway.com/template/nhost-or-just-updated-firebase-alternati)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/nhost-or-just-updated-firebase-alternati/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Other

## Template content

### storage

- **Image:** nhost/storage:0.7.2@sha256:8692cf7eba6b775681863796bfb53160d41167818bbfebe8392dea4ce264eb27
- **Start command:** `/nix/store/99kk118sis0wavsvvgidfh536pslm524-hasura-storage-0.7.2/bin/hasura-storage serve`

### graphql

- **Image:** nhost/graphql-engine:v2.46.0-ce@sha256:bfc3e5fd51e87f99dc0894976f16c14165d9c0fbd1fe503a3ebfbaf02600fed0
- **Start command:** `/bin/sh -c 'export HASURA_GRAPHQL_ENABLE_CONSOLE=true HASURA_GRAPHQL_DEV_MODE=false HASURA_GRAPHQL_SERVER_HOST="*" HASURA_GRAPHQL_SERVER_PORT=8080 HASURA_GRAPHQL_ENABLE_TELEMETRY=false HASURA_GRAPHQL_UNAUTHORIZED_ROLE=public HASURA_GRAPHQL_CORS_DOMAIN="*"; exec graphql-engine serve'`

### gateway

- **Image:** caddy@sha256:d8542f48d34a9cf4e4c11a478865229840e87e4c96ea3f439101f31a5d35f75f
- **Start command:** `/bin/sh -c 'printf ":%s {\n\thandle /railway_health {\n\t\trespond \"ok\" 200\n\t}\n\thandle_path /auth/v1/* {\n\t\treverse_proxy %s:4000\n\t}\n\thandle /storage/* {\n\t\turi strip_prefix /storage\n\t\treverse_proxy %s:8000\n\t}\n\thandle {\n\t\treverse_proxy %s:8080\n\t}\n}\n" "$PORT" "$AUTH_HOST" "$STORAGE_HOST" "$GRAPHQL_HOST" > /etc/caddy/Caddyfile && exec caddy run --config /etc/caddy/Caddyfile --adapter caddyfile'`
- **Health check:** /railway_health
- **Public domain:** Yes

### auth

- **Image:** nhost/auth:0.40.2@sha256:8674c405184e0b14f5cb80912b1275ac51fb0325035862dacfe943ad77de95b3

### objects

- **Image:** ghcr.io/bon5co/buzz-railway-minio:latest@sha256:6842303eaf3e2c6413d84c2f67b9dd51ab2992214ecc72230dde4c3050145f00

### postgres

- **Image:** postgres:18.6@sha256:74935e72241653ca55e0414067e6d8763aceb8a810eb51b452253ec3dcfc4336
- **Start command:** `/bin/sh -c 'printf "CREATE SCHEMA IF NOT EXISTS auth;\nCREATE SCHEMA IF NOT EXISTS storage;\nCREATE EXTENSION IF NOT EXISTS pgcrypto;\nCREATE EXTENSION IF NOT EXISTS citext;\n" > /docker-entrypoint-initdb.d/00-nhost.sql; exec docker-entrypoint.sh postgres'`

## Documentation

# Deploy and Host Nhost (Auth, GraphQL, Storage) on Railway

Nhost is an open-source Firebase alternative: Postgres with an instant GraphQL API (Hasura), email/password and OAuth authentication, and file storage on S3-compatible object storage. This template deploys the whole stack behind one public gateway, with every secret generated for you.

## About Hosting Nhost

The template starts six services: `gateway` (public HTTPS entry point), `graphql` (Hasura engine), `auth` (Nhost Auth), `storage` (Nhost Storage), `postgres` (private, volume at `/var/lib/postgresql`) and `objects` (MinIO, private, volume at `/data`). Only the gateway has a public domain. It routes `/auth/v1/*` to Auth, `/storage/*` to Storage and everything else to the GraphQL engine. The admin secret, JWT signing key, database password and object-store keys are generated per deploy, so nothing has to be filled in before you click Deploy. Auth and Storage create their own tables on first boot.

Machine-readable contract:

```
public_url:     https://${RAILWAY_PUBLIC_DOMAIN of service gateway}
graphql:        POST /v1/graphql   (anonymous role is rejected; send a user JWT or the admin secret)
console:        /console           (enter the admin secret)
auth:           /auth/v1/signup/email-password, /auth/v1/signin/email-password
storage:        POST /storage/v1/files   (multipart field file[])
health:         GET /railway_health  (200 when the gateway is up)
internal_urls:  graphql.railway.internal:8080, auth.railway.internal:4000, storage.railway.internal:8000, objects.railway.internal:9000
credentials:    HASURA_GRAPHQL_ADMIN_SECRET (service graphql), JWT_KEY (service graphql),
                POSTGRES_PASSWORD (service postgres), MINIO_ROOT_USER / MINIO_ROOT_PASSWORD (service objects)
```

Working check, run it after the deploy turns green:

```
curl -s -X POST https:///auth/v1/signup/email-password \
  -H 'content-type: application/json' \
  -d '{"email":"agent@example.com","password":"Passw0rd!xyz1"}'
# {"session":{"accessToken":"...","user":{...}}}

curl -s -X POST https:///storage/v1/files \
  -H "x-hasura-admin-secret: $HASURA_GRAPHQL_ADMIN_SECRET" \
  -F 'file[]=@hello.txt'
# {"processedFiles":[{"id":"...","isUploaded":true,...}]}
```

Email verification is switched off so a signup works immediately; configure SMTP on the `auth` service and set `AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED=true` for production. Permissions for the `user` role are not preset: define them in the console before exposing tables to end users.

## Why Deploy Nhost on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Nhost on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

- Auth, GraphQL API and file storage behind one domain
- All secrets generated automatically
- Postgres and object storage kept on persistent volumes
- Images pinned by digest, so redeploys do not change versions

## Common Use Cases

- Backend for web and mobile apps without writing a server
- Authenticated GraphQL data API for AI agents
- User uploads and media storage with signed access
- Self-hosted replacement for Firebase or Supabase

## Dependencies for Nhost Hosting

### Deployment Dependencies

- [Nhost on GitHub](https://github.com/nhost/nhost)
- [Nhost documentation](https://docs.nhost.io/)
- [Nhost Auth image](https://hub.docker.com/r/nhost/auth)
- [Nhost Storage image](https://hub.docker.com/r/nhost/storage)
- [Hasura GraphQL Engine image (Nhost build)](https://hub.docker.com/r/nhost/graphql-engine)
- [PostgreSQL](https://www.postgresql.org/) and [MinIO](https://min.io/)

### Implementation Details

The `gateway` is Caddy with a generated Caddyfile. The MinIO service is named `objects` because MinIO reserves the bucket name `minio`, and the bucket takes the service name. Auth and Storage images are distroless and configured only through environment variables. Rotate the admin secret by editing `HASURA_GRAPHQL_ADMIN_SECRET` on `graphql` (and the copies referenced by `auth` and `storage` follow it).


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/nhost-or-just-updated-firebase-alternati
