Nhost
Backend platform with Postgres, a GraphQL API, authentication and file storage.
- Replaces
-
Paid backend-as-a-service services, such as Firebase.
All open-source alternatives to Firebase
- Difficulty
-
Difficulty: Hard
10 services (2 database or broker: minio, postgres), 10 volume mounts, 13 env values to set, host access: docker_socket. Heuristic score 10 of 11: hard. A source checkout is needed, so the rating is at least medium.
- Stack
TypeScript (language), PostgreSQL (database)
- Deployment
docker_compose
- Requirements
Not stated.
- License
-
MIT(OSI-approved open source) - Business model
-
Unknown
The README at the pinned commit does not state a business model, so it stays unknown.
Source: github.com/nhost/nhost/blob/e584591/README.md, read on .
- Repository
GitHub stats
- Stars
- 9,364
- Forks
- 636
- Open issues and pull requests
- 155
- Last push
- 2026-10-22
- Latest release
- @nhost/[email protected]
- Released
- 2026-10-20
From the GitHub API on . These numbers are a snapshot, not live. GitHub detected the license as MIT.
Compose file
services:
auth:
image: nhost/auth:0.40.2
depends_on:
graphql:
condition: service_healthy
postgres:
condition: service_healthy
environment:
AUTH_ACCESS_CONTROL_ALLOWED_EMAIL_DOMAINS: ""
AUTH_ACCESS_CONTROL_ALLOWED_EMAILS: ""
AUTH_ACCESS_CONTROL_ALLOWED_REDIRECT_URLS: ""
AUTH_ACCESS_CONTROL_BLOCKED_EMAIL_DOMAINS: ""
AUTH_ACCESS_CONTROL_BLOCKED_EMAILS: ""
AUTH_ACCESS_TOKEN_EXPIRES_IN: "900"
AUTH_ANONYMOUS_USERS_ENABLED: "false"
AUTH_API_PREFIX: /v1
AUTH_CLIENT_URL: http://localhost:3000
AUTH_CONCEAL_ERRORS: "false"
AUTH_DISABLE_NEW_USERS: "false"
AUTH_DISABLE_SIGNUP: "false"
AUTH_EMAIL_PASSWORDLESS_ENABLED: "false"
AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED: "${AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED}"
AUTH_GRAVATAR_DEFAULT: blank
AUTH_GRAVATAR_ENABLED: "true"
AUTH_GRAVATAR_RATING: g
AUTH_HOST: 0.0.0.0
AUTH_JWT_CUSTOM_CLAIMS: '{}'
AUTH_LOCALE_ALLOWED_LOCALES: en
AUTH_LOCALE_DEFAULT: en
AUTH_MFA_ENABLED: "false"
AUTH_MFA_TOTP_ISSUER: ""
AUTH_OTP_EMAIL_ENABLED: "false"
AUTH_PASSWORD_HIBP_ENABLED: "false"
AUTH_PASSWORD_MIN_LENGTH: "9"
AUTH_PORT: "4000"
AUTH_RATE_LIMIT_BRUTE_FORCE_BURST: "10"
AUTH_RATE_LIMIT_BRUTE_FORCE_INTERVAL: 5m
AUTH_RATE_LIMIT_EMAIL_BURST: "10"
AUTH_RATE_LIMIT_EMAIL_INTERVAL: 1h
AUTH_RATE_LIMIT_EMAIL_IS_GLOBAL: "true"
AUTH_RATE_LIMIT_ENABLE: "true"
AUTH_RATE_LIMIT_GLOBAL_BURST: "100"
AUTH_RATE_LIMIT_GLOBAL_INTERVAL: 1m
AUTH_RATE_LIMIT_SIGNUPS_BURST: "10"
AUTH_RATE_LIMIT_SIGNUPS_INTERVAL: 5m
AUTH_RATE_LIMIT_SMS_BURST: "10"
AUTH_RATE_LIMIT_SMS_INTERVAL: 1h
AUTH_REFRESH_TOKEN_EXPIRES_IN: "2592000"
AUTH_REQUIRE_ELEVATED_CLAIM: disabled
AUTH_SERVER_URL: http://${AUTH_URL}/v1
AUTH_SMTP_AUTH_METHOD: LOGIN
AUTH_SMTP_HOST: mailhog
AUTH_SMTP_PASS: password
AUTH_SMTP_PORT: "1025"
AUTH_SMTP_SECURE: "false"
AUTH_SMTP_SENDER: [email protected]
AUTH_SMTP_USER: user
AUTH_TURNSTILE_SECRET: ""
AUTH_USER_DEFAULT_ALLOWED_ROLES: user,me
AUTH_USER_DEFAULT_ROLE: user
HASURA_GRAPHQL_ADMIN_SECRET: ${GRAPHQL_ADMIN_SECRET}
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
HASURA_GRAPHQL_GRAPHQL_URL: http://graphql:8080/v1/graphql
HASURA_GRAPHQL_JWT_SECRET: ${JWT_SECRET}
POSTGRES_MIGRATIONS_CONNECTION: postgres://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
healthcheck:
test:
- CMD
- wget
- --spider
- -S
- http://localhost:4000/healthz
timeout: 60s
interval: 5s
start_period: 60s
labels:
traefik.enable: "true"
traefik.http.routers.auth.entrypoints: web
traefik.http.routers.auth.rule: Host(`${AUTH_URL}`)
traefik.http.routers.auth.service: auth
traefik.http.routers.auth.tls: "false"
traefik.http.services.auth.loadbalancer.server.port: "4000"
restart: always
volumes:
- type: bind
source: nhost/emails
target: /app/email-templates
read_only: false
console:
image: nhost/graphql-engine:v2.46.0-ce.cli-migrations-v3
depends_on:
graphql:
condition: service_healthy
entrypoint:
- hasura-cli
command:
- console
- --no-browser
- --endpoint=http://graphql:8080
- --address=0.0.0.0
- --console-port=9695
- --api-port=80
- --api-host=http://${GRAPHQL_URL}
- --console-hge-endpoint=http://${GRAPHQL_URL}
environment:
GRAPHITE_WEBHOOK_SECRET: ""
HASURA_GRAPHQL_ADMIN_INTERNAL_ERRORS: "true"
HASURA_GRAPHQL_ADMIN_SECRET: ${GRAPHQL_ADMIN_SECRET}
HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets
HASURA_GRAPHQL_CORS_DOMAIN: '*'
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
HASURA_GRAPHQL_DEV_MODE: "true"
HASURA_GRAPHQL_DISABLE_CORS: "false"
HASURA_GRAPHQL_ENABLE_ALLOWLIST: "false"
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS: "false"
HASURA_GRAPHQL_ENABLE_TELEMETRY: "false"
HASURA_GRAPHQL_ENABLED_APIS: metadata,graphql,pgdump,config
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup,http-log,webhook-log,websocket-log
HASURA_GRAPHQL_EVENTS_HTTP_POOL_SIZE: "100"
HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS: "true"
HASURA_GRAPHQL_JWT_SECRET: ${JWT_SECRET}
HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_BATCH_SIZE: "100"
HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL: "1000"
HASURA_GRAPHQL_LOG_LEVEL: warn
HASURA_GRAPHQL_PG_CONNECTIONS: "50"
HASURA_GRAPHQL_PG_TIMEOUT: "180"
HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES: "false"
HASURA_GRAPHQL_TX_ISOLATION: read-committed
HASURA_GRAPHQL_UNAUTHORIZED_ROLE: public
HASURA_GRAPHQL_USE_PREPARED_STATEMENTS: "true"
HASURA_GRAPHQL_WS_READ_COOKIE: "false"
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:0.0.0.0
- ${STORAGE_URL}:host-gateway
healthcheck:
test:
- CMD-SHELL
- timeout 1s bash -c ':> /dev/tcp/127.0.0.1/9695' || exit 1
timeout: 60s
interval: 5s
start_period: 60s
labels:
traefik.enable: "true"
traefik.http.routers.console.entrypoints: web
traefik.http.routers.console.rule: Host(`${GRAPHQL_URL}`)
traefik.http.routers.console.service: console
traefik.http.routers.console.tls: "false"
traefik.http.routers.migrate.entrypoints: web
traefik.http.routers.migrate.rule: Host(`${GRAPHQL_URL}`) && PathPrefix(`/apis/`)
traefik.http.routers.migrate.service: migrate
traefik.http.routers.migrate.tls: "false"
traefik.http.services.console.loadbalancer.server.port: "9695"
traefik.http.services.migrate.loadbalancer.server.port: "80"
restart: always
volumes:
- type: bind
source: nhost
target: /app
read_only: false
working_dir: /app
dashboard:
image: nhost/dashboard:2.34.0
environment:
NEXT_PUBLIC_ENV: dev
NEXT_PUBLIC_NHOST_ADMIN_SECRET: ${GRAPHQL_ADMIN_SECRET}
NEXT_PUBLIC_NHOST_AUTH_URL: http://${AUTH_URL}/v1
NEXT_PUBLIC_NHOST_FUNCTIONS_URL: http://${FUNCTIONS_URL}/v1
NEXT_PUBLIC_NHOST_GRAPHQL_URL: http://${GRAPHQL_URL}/v1/graphql
NEXT_PUBLIC_NHOST_HASURA_API_URL: http://${GRAPHQL_URL}
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL: http://${GRAPHQL_URL}/console
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL: http://${GRAPHQL_URL}
NEXT_PUBLIC_NHOST_PLATFORM: "false"
NEXT_PUBLIC_NHOST_STORAGE_URL: http://${STORAGE_URL}/v1
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
labels:
traefik.enable: "true"
traefik.http.routers.dashboard.entrypoints: web
traefik.http.routers.dashboard.rule: Host(`${DASHBOARD_URL}`)
traefik.http.routers.dashboard.service: dashboard
traefik.http.routers.dashboard.tls: "false"
traefik.http.services.dashboard.loadbalancer.server.port: "3000"
restart: ""
working_dir: ""
functions:
image: nhost/functions:22-1.4.0
environment:
GRAPHITE_WEBHOOK_SECRET: ""
HASURA_GRAPHQL_ADMIN_SECRET: ${GRAPHQL_ADMIN_SECRET}
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
HASURA_GRAPHQL_GRAPHQL_URL: http://graphql:8080/v1/graphql
HASURA_GRAPHQL_JWT_SECRET: ${JWT_SECRET}
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
healthcheck:
test:
- CMD
- wget
- --spider
- -S
- http://localhost:3000/healthz
timeout: 600s
interval: 5s
start_period: 600s
labels:
traefik.enable: "true"
traefik.http.middlewares.replace-functions.replacepathregex.regex: /v1(/|$$)(.*)
traefik.http.middlewares.replace-functions.replacepathregex.replacement: /$$2
traefik.http.routers.functions.entrypoints: web
traefik.http.routers.functions.middlewares: replace-functions
traefik.http.routers.functions.rule: Host(`${FUNCTIONS_URL}`) && PathPrefix(`/v1`)
traefik.http.routers.functions.service: functions
traefik.http.routers.functions.tls: "false"
traefik.http.services.functions.loadbalancer.server.port: "3000"
restart: always
volumes:
- type: bind
source: .
target: /opt/project
read_only: false
- type: volume
source: root_node_modules
target: /opt/project/node_modules
read_only: false
- type: volume
source: functions_node_modules
target: /opt/project/functions/node_modules
read_only: false
graphql:
image: nhost/graphql-engine:v2.46.0-ce
depends_on:
postgres:
condition: service_healthy
environment:
GRAPHITE_WEBHOOK_SECRET: ""
HASURA_GRAPHQL_ADMIN_INTERNAL_ERRORS: "true"
HASURA_GRAPHQL_ADMIN_SECRET: ${GRAPHQL_ADMIN_SECRET}
HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets
HASURA_GRAPHQL_CORS_DOMAIN: '*'
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
HASURA_GRAPHQL_DEV_MODE: "true"
HASURA_GRAPHQL_DISABLE_CORS: "false"
HASURA_GRAPHQL_ENABLE_ALLOWLIST: "false"
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS: "false"
HASURA_GRAPHQL_ENABLE_TELEMETRY: "false"
HASURA_GRAPHQL_ENABLED_APIS: metadata,graphql,pgdump,config
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup,http-log,webhook-log,websocket-log
HASURA_GRAPHQL_EVENTS_HTTP_POOL_SIZE: "100"
HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS: "true"
HASURA_GRAPHQL_JWT_SECRET: ${JWT_SECRET}
HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_BATCH_SIZE: "100"
HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL: "1000"
HASURA_GRAPHQL_LOG_LEVEL: warn
HASURA_GRAPHQL_PG_CONNECTIONS: "50"
HASURA_GRAPHQL_PG_TIMEOUT: "180"
HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES: "false"
HASURA_GRAPHQL_TX_ISOLATION: read-committed
HASURA_GRAPHQL_UNAUTHORIZED_ROLE: public
HASURA_GRAPHQL_USE_PREPARED_STATEMENTS: "true"
HASURA_GRAPHQL_WS_READ_COOKIE: "false"
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
healthcheck:
test:
- CMD-SHELL
- curl http://localhost:8080/healthz > /dev/null 2>&1
timeout: 60s
interval: 5s
start_period: 60s
labels:
traefik.enable: "true"
traefik.http.middlewares.replace-graphql.replacepathregex.regex: /v1(/|$$)(.*)
traefik.http.middlewares.replace-graphql.replacepathregex.replacement: /v1/graphql$$2
traefik.http.routers.hasura.entrypoints: web
traefik.http.routers.hasura.rule: Host(`${GRAPHQL_URL}`) && ( PathPrefix(`/v1`) || PathPrefix(`/v2`) || PathPrefix(`/api/`) || PathPrefix(`/console/assets`) )
traefik.http.routers.hasura.service: hasura
traefik.http.routers.hasura.tls: "false"
traefik.http.services.graphql.loadbalancer.server.port: "8080"
traefik.http.services.hasura.loadbalancer.server.port: "8080"
restart: always
mailhog:
image: jcalonso/mailhog:v1.0.1
environment:
SMTP_HOST: mailhog
SMTP_PASS: password
SMTP_PORT: "1025"
SMTP_SECURE: "false"
SMTP_SENDER: [email protected]
SMTP_USER: user
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
labels:
traefik.enable: "true"
traefik.http.routers.mailhog.entrypoints: web
traefik.http.routers.mailhog.rule: Host(`${MAILHOG_URL}`)
traefik.http.routers.mailhog.service: mailhog
traefik.http.routers.mailhog.tls: "false"
traefik.http.services.mailhog.loadbalancer.server.port: "8025"
restart: always
volumes:
- type: volume
source: mailhog
target: /maildir
minio:
image: minio/minio:RELEASE.2025-02-28T09-55-16Z
entrypoint:
- /bin/sh
command:
- -c
- mkdir -p /data/nhost && /usr/bin/minio server --address :9000 /data
environment:
MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_KEY}
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
restart: always
volumes:
- type: volume
source: minio
target: /data
postgres:
image: postgres:16
environment:
POSTGRES_DB: postgres
POSTGRES_DEV_INSECURE: "true"
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_USER: postgres
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
healthcheck:
test:
- CMD-SHELL
- pg_isready -U postgres
- -d
- postgres
- -q
timeout: 60s
interval: 5s
start_period: 60s
ports:
- mode: ingress
target: 5432
published: "5432"
protocol: tcp
restart: always
volumes:
- type: volume
source: pgdata
target: /var/lib/postgresql/data/
read_only: false
- type: bind
source: ./initdb.d
target: /docker-entrypoint-initdb.d
read_only: true
storage:
image: nhost/storage:0.7.2
depends_on:
graphql:
condition: service_healthy
minio:
condition: service_started
postgres:
condition: service_healthy
command:
- serve
environment:
BIND: :5000
HASURA_ENDPOINT: http://graphql:8080/v1
HASURA_GRAPHQL_ADMIN_SECRET: ${GRAPHQL_ADMIN_SECRET}
HASURA_METADATA: "1"
POSTGRES_MIGRATIONS: "1"
POSTGRES_MIGRATIONS_SOURCE: postgres://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres?sslmode=disable
PUBLIC_URL: http://${STORAGE_URL}
S3_ACCESS_KEY: ${STORAGE_ACCESS_KEY}
S3_BUCKET: nhost
S3_ENDPOINT: http://minio:9000
S3_REGION: ""
S3_ROOT_FOLDER: ""
S3_SECRET_KEY: ${STORAGE_SECRET_KEY}
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
labels:
traefik.enable: "true"
traefik.http.routers.storage.entrypoints: web
traefik.http.routers.storage.rule: Host(`${STORAGE_URL}`) && PathPrefix(`/v1`)
traefik.http.routers.storage.service: storage
traefik.http.routers.storage.tls: "false"
traefik.http.services.storage.loadbalancer.server.port: "5000"
restart: always
traefik:
image: traefik:v3.1
command:
- --api.insecure=true
- --providers.docker=true
- --providers.file.directory=/opt/traefik
- --providers.file.watch=true
- --providers.docker.exposedbydefault=false
- --providers.docker.constraints=Label(`com.docker.compose.project`,`docker-compose`)
- --entrypoints.web.address=:80
extra_hosts:
- host.docker.internal:host-gateway
- ${AUTH_URL}:host-gateway
- ${DB_URL}:host-gateway
- ${FUNCTIONS_URL}:host-gateway
- ${GRAPHQL_URL}:host-gateway
- ${STORAGE_URL}:host-gateway
ports:
- mode: ingress
target: 80
published: "80"
protocol: tcp
restart: always
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
read_only: true
volumes:
functions_node_modules: {}
root_node_modules: {}
pgdata: {}
mailhog: {}
minio: {}
From the app's own repository: github.com/nhost/nhost/blob/e584591/examples/docker-compose/docker-compose.yaml.
Compose file from nhost/nhost, used inside a checkout of that repository (documented setup B).
Install
- Docker with the Compose plugin and git (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
A host with Docker, the Docker Compose plugin and git. This entry needs a checkout of the project repository.
- Get the source at commit e584591 (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
git init nhost cd nhost git remote add origin https://github.com/nhost/nhost.git git sparse-checkout init --cone git sparse-checkout set examples/docker-compose git fetch --depth 1 --filter=blob:none origin e5845916dcec56e1dc22b19be45ef01e954416e2 git checkout FETCH_HEAD - Go to the folder the docs use (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
cd examples/docker-compose - The compose file in the checkout: examples/docker-compose/docker-compose.yaml (shown here for reading) (github.com/nhost/nhost/blob/e584591/examples/docker-compose/docker-compose.yaml)
Use the compose file shown above.
- Copy .env.example to .env (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
cp .env.example .env - What the compose file check ran with (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
The compose file check ran in a checkout of nhost/nhost at e5845916dcec56e1dc22b19be45ef01e954416e2 (a sparse checkout: the top-level files and the folder examples/docker-compose), in the folder examples/docker-compose, after .env.example was copied to .env. The example guide tells the reader to clone the repository, go into examples/docker-compose, copy .env.example to .env and run docker compose up -d.
- Start it (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
docker compose up -d - Open the app (github.com/nhost/nhost/blob/e584591/examples/docker-compose/README.md)
Open http://local.dashboard.local.nhost.run. The docs name this address. The compose file publishes host port 80 for the traefik service.
Compose file check: config_ok on 2026-10-22.
Gotchas and maintenance
Gotchas
- The compose file has placeholder values. Placeholder values: AUTH_SMTP_PASS is "password" (auth), SMTP_PASS is "password" (mailhog). (github.com/nhost/nhost/blob/e584591/examples/docker-compose/docker-compose.yaml, checked 2026-10-22)
- The compose file publishes host ports. Host ports: 5432 (postgres), 80 (traefik). A port without a host address listens on all host network interfaces. (github.com/nhost/nhost/blob/e584591/examples/docker-compose/docker-compose.yaml, checked 2026-10-22)
- The compose file mounts host folders. Host paths mounted into containers: nhost/emails at /app/email-templates (auth), nhost at /app (console), . at /opt/project (functions), ./initdb.d at /docker-entrypoint-initdb.d (postgres). (github.com/nhost/nhost/blob/e584591/examples/docker-compose/docker-compose.yaml, checked 2026-10-22)
- Some services get elevated host access. traefik mounts the Docker socket, which gives it control of Docker on the host. (github.com/nhost/nhost/blob/e584591/examples/docker-compose/docker-compose.yaml, checked 2026-10-22)
Signals
- Open issues and pull requests: 155
- Last push: 2026-10-22 (0 days before this page was built)
- Latest release: @nhost/[email protected] on 2026-10-20 (2 days before this page was built)