---
title: "Deploy Reloop | (Just Updated) Resend Alternative, Email API for Agents, No Setup"
description: "Reloop email API and dashboard, a Resend alternative with its own MTA"
category: "Other"
url: https://railway.com/deploy/reloop-or-just-updated-resend-alternativ
---

# Deploy Reloop | (Just Updated) Resend Alternative, Email API for Agents, No Setup

Reloop email API and dashboard, a Resend alternative with its own MTA

**[Deploy Reloop | (Just Updated) Resend Alternative, Email API for Agents, No Setup on Railway](https://railway.com/template/reloop-or-just-updated-resend-alternativ)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/reloop-or-just-updated-resend-alternativ/manifest.json

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

## Template content

### auth

- **Image:** reloopsh/be-auth@sha256:741ef934ec59aa173f8dcfa980c163c107e6e5693786777326eaf90e49cb47c5
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8000
(cd /app/packages/db && until /app/node_modules/.bin/drizzle-kit push --force; do echo migrate retry; sleep 3; done)
ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com}
export SETUP_MODE=true
(
  until wget -q -O /dev/null http://127.0.0.1:8000/api/auth/v1/ok; do sleep 2; done
  if wget -q -O /dev/null http://127.0.0.1:8000/api/auth/v1/setup/status; then
    i=0
    until wget -q -O /dev/null --header="Content-Type: application/json" --post-data="{\"adminKey\":\"$ADMIN_SETUP_KEY\",\"name\":\"Admin\",\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\",\"disableSignup\":true,\"organizationName\":\"Reloop\"}" http://127.0.0.1:8000/api/auth/v1/setup/complete; do i=$((i+1)); [ $i -gt 30 ] && break; sleep 3; done
    echo "reloop admin bootstrap done for $ADMIN_EMAIL"
  fi
) &
cd /app
exec bun run dist/index.js'`

### campaigns

- **Image:** reloopsh/be-campaigns@sha256:446287b0dc88f77ca5ac12199bda637e1e2216a38a47e281be161dba4fea3624
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8027
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### inbox

- **Image:** reloopsh/be-inbox@sha256:4d6fe16298fbec859c86cc6ac55f2804223e9d1c9ff52afc92c01845b99a5f74
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8028
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### upload

- **Image:** reloopsh/be-upload@sha256:22632cbbc686fa0c766a0ecd316b4bdeb3097fe5652d3b8e183133ff8055a299
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8018
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### proxy

- **Image:** caddy:2.10-alpine
- **Start command:** `/bin/sh -c 'cat > /tmp/Caddyfile <<EOT
{
  auto_https off
  admin off
  servers {
    trusted_proxies static private_ranges 100.64.0.0/10
  }
}
:${PORT:-8080} {
  encode zstd gzip
  handle /healthz {
    respond 200
  }
  handle /dashboard* {
    reverse_proxy dashboard.railway.internal:3000
  }
  handle /preferences* {
    reverse_proxy links.railway.internal:3005
  }
  handle /redirect* {
    reverse_proxy links.railway.internal:3005
  }
  handle /api/auth* {
    reverse_proxy auth.railway.internal:8000
  }
  handle /api/domain* {
    reverse_proxy domain.railway.internal:8011
  }
  handle /api/api-key* {
    reverse_proxy api-key.railway.internal:8012
  }
  handle /api/webhook* {
    reverse_proxy webhook.railway.internal:8013
  }
  handle /api/contacts* {
    reverse_proxy contacts.railway.internal:8014
  }
  handle /api/mail* {
    reverse_proxy mail.railway.internal:8015
  }
  handle /api/logs* {
    reverse_proxy logs.railway.internal:8016
  }
  handle /api/workflow* {
    reverse_proxy workflow.railway.internal:8017
  }
  handle /api/upload* {
    reverse_proxy upload.railway.internal:8018
  }
  handle /api/template* {
    reverse_proxy template.railway.internal:8019
  }
  handle /api/campaigns* {
    reverse_proxy campaigns.railway.internal:8027
  }
  handle /api/inbox* {
    reverse_proxy inbox.railway.internal:8028
  }
  handle /api/email* {
    reverse_proxy email.railway.internal:8022
  }
  @removed path /api/credits* /api/tool* /api/admin*
  handle @removed {
    respond 404
  }
  handle {
    redir /* /dashboard 302
  }
}
EOT
exec caddy run --config /tmp/Caddyfile --adapter caddyfile'`
- **Health check:** /healthz
- **Public domain:** Yes

### domain

- **Image:** reloopsh/be-domain@sha256:cb12e37221a697278822819fdf4fd0ada2bb2f13e2979be789c9c44ee09a3f56
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8011
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### smtp

- **Image:** reloopsh/be-smtp@sha256:689b49f762ee0d5f4c33bbfd073f7ebeb5cbae27194c36269883be7da415a86e
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export HOSTNAME="$PROXY_HOST"
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
mkdir -p /var/spool/kumomta/data /var/spool/kumomta/meta
chown -R kumod:kumod /var/spool/kumomta
exec /entrypoint.sh /opt/kumomta/sbin/kumod --policy /opt/kumomta/etc/policy/init.lua --user kumod'`

### contacts

- **Image:** reloopsh/be-contacts@sha256:43da0b373e2777fdc7af97d92fdb916320a27e2ffdea61df69bca477722b2dfa
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8014
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### redis

- **Image:** redis:7.4-alpine
- **Start command:** `/bin/sh -c 'chown -R redis:redis /data && exec docker-entrypoint.sh redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes --dir /data'`

### postgres

- **Image:** postgres:17.10-alpine
- **Start command:** `/bin/sh -c 'export POSTGRES_DB=reloop; exec docker-entrypoint.sh postgres'`

### nats

- **Image:** nats:2.10-alpine
- **Start command:** `/bin/sh -c 'mkdir -p /data && exec nats-server -js -sd /data -m 8222'`

### dashboard

- **Image:** reloopsh/fe-dashboard@sha256:dd2369d2f0d7fe836664ae49b2b4492f90ee654dd8af7c819e7ca07e469b58dc
- **Start command:** `/bin/sh -c 'export HOSTNAME=:: PORT=3000 SMTP_HOSTNAME="$PROXY_HOST"
cd /app && exec bun run server.js'`

### template

- **Image:** reloopsh/be-template@sha256:9734939a04b211aa99c96d89446cb5b28ba5e065a2b8388a88ae634c50f5f77d
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8019
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### links

- **Image:** reloopsh/fe-links@sha256:8a22fde21a656c25163e2b856a856053c5de91cbc4953cc23ed034c081eedfa5
- **Start command:** `/bin/sh -c 'export HOSTNAME=:: PORT=3005 INTERNAL_API_URL=http://contacts.railway.internal:8014/api/contacts INTERNAL_MAIL_API_URL=http://mail.railway.internal:8015/api/mail
cd /app && exec bun run server.js'`

### mail

- **Image:** reloopsh/be-mail@sha256:c4b2fe0de847a606f12fe0d50adadda9719135205cb227c6e12c6a6f0889aae8
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8015
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### api-key

- **Image:** reloopsh/be-api-key@sha256:535f9837d39acdd7e155a14752b1ab6e3cbef06331cf26634577ff82a0156572
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8012
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### email

- **Image:** reloopsh/be-email@sha256:4caf97f84d7faf7bf45f69e12b8226d724b0e58c0205cd82d1ef7031f4ea8b2d
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8022
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app/apps/backend/email && exec bun run start'`

### workflow

- **Image:** reloopsh/be-workflow@sha256:d7d75e9145891b7167b42b4fb1ec441c53361e825e5fdf0d72962ef95d3d5b56
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8017
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### webhook

- **Image:** reloopsh/be-webhook@sha256:644a6b79756f57c045c8572c42bee6dfb6b31663ee08d21f2565cead4dfc1ca9
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8013
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

### logs

- **Image:** reloopsh/be-logs@sha256:3c0be118c7df0ebd76e24ed65de014980f96a8c14c2783231a39b0c54c4065e0
- **Start command:** `/bin/sh -c 'export NODE_ENV=production RELOOP_VERSION=latest
export BASE_URL="https://$PROXY_HOST" TRACKING_BASE_URL="https://$PROXY_HOST" HOST_DOMAIN="$PROXY_HOST" TRACKING_DOMAIN="$PROXY_HOST"
export INBOUND_HOSTNAME="inbound.$PROXY_HOST" SMTP_HOSTNAME="$PROXY_HOST"
export AUTH_INTERNAL_BASE_URL=http://auth.railway.internal:8000
export PG_URL="postgresql://postgres:$POSTGRES_PASSWORD@postgres.railway.internal:5432/reloop"
export REDIS_URL="redis://:$REDIS_PASSWORD@redis.railway.internal:6379" NATS_URL=nats://nats.railway.internal:4222
export WORKBENCH_USER=admin APP_NAME=Reloop DISABLE_SIGNUP=true DISABLE_ORG_CREATION=false DKIM_SELECTOR=reloop DNS_RESOLVERS=8.8.8.8,8.8.4.4
export RELOOP_API_KEY= RELOOP_SENDER_DOMAIN= SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=false
export S3_ENDPOINT= S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET=reloop-uploads S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true
export KUMOMTA_HTTP_URL=http://smtp.railway.internal:8000 KUMOMTA_WEBHOOK_URL=http://domain.railway.internal:8011/api/domain KUMOMTA_CHECK_RECIPIENT_URL=http://domain.railway.internal:8011/api/domain
export KUMOMTA_RSPAMD_URL=http://spam.railway.internal:11333/checkv2 KUMOMTA_MIN_FREE_SPACE=5% KUMOMTA_MIN_FREE_INODES=0
export PORT=8016
until wget -q -O /dev/null http://auth.railway.internal:8000/api/auth/v1/ok; do sleep 2; done
cd /app && exec bun run dist/index.js'`

## Documentation

# Deploy and Host Reloop on Railway

**Built for an LLM agent to deploy and use.** There is no setup wizard and nothing to fill in: the admin account, its password, the internal secrets and every database password are generated at deploy time, the first-run setup is completed at boot, and the contract below lists every URL, variable name and one script that proves it works.

Reloop is an open-source email platform: a REST API and dashboard for transactional email, with domains, templates, contacts, campaigns, webhooks and logs, built on its own MTA (KumoMTA). It is a self-hosted alternative to Resend and SendGrid. This template runs the full stack.

## About Hosting Reloop

This template runs twenty services: a Caddy `proxy` that is the single public entry point, the `auth` service, the API services (`domain`, `api-key`, `webhook`, `contacts`, `mail`, `logs`, `workflow`, `upload`, `template`, `campaigns`, `inbox`, `email`), the `smtp` MTA, the `dashboard` and `links` frontends, and `postgres`, `redis` and `nats` as storage and messaging. Postgres, Redis, NATS and the MTA spool sit on volumes. All Reloop images are pinned by digest, so a redeploy never changes the version underneath you.

Everything is served from one domain, the `proxy` service: the dashboard at `/dashboard`, the APIs under `/api/SERVICE/v1`. The first sign-in is the admin user `ADMIN_EMAIL` (default `admin@example.com`) with `ADMIN_PASSWORD`, both on the `auth` service. Public sign-up is closed.

Limits to know before sending mail. Reloop sends from your own verified domain, so you add the domain, publish the DNS records it shows (SPF, DKIM, DMARC) and verify it before `POST /api/mail/v1/send` accepts a message. Railway allows outbound SMTP only on the Pro plan, and does not allow inbound port 25, so receiving mail at your own address is not possible on Railway. The API, dashboard, templates, contacts and API keys all work without that.

### Agent contract

- Public URL: `https://` plus the `RAILWAY_PUBLIC_DOMAIN` of the `proxy` service, used below as `RELOOP_URL`
- Private URL: `http://auth.railway.internal:8000` (auth); the API services listen on `8011` to `8028` on their own `SERVICE.railway.internal` name
- Credentials: `ADMIN_EMAIL` and `ADMIN_PASSWORD` on the `auth` service; API keys are minted through the API
- Auth: sign in once to get a session cookie, mint an API key, then send it as the header `x-api-key: KEY` on every API call. No key returns 401.
- Health: `GET /healthz` returns 200 with no credentials; `GET /api/auth/v1/ok` returns `{"ok":true}`

```bash
# run with RELOOP_URL, ADMIN_EMAIL and ADMIN_PASSWORD set
JAR=$(mktemp)
curl -s -o /dev/null -w 'health %{http_code}\n' "$RELOOP_URL/healthz"
curl -s -c "$JAR" -o /dev/null -w 'sign-in %{http_code}\n' -X POST "$RELOOP_URL/api/auth/v1/sign-in/email" \
  -H 'content-type: application/json' -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}"
KEY=$(curl -s -b "$JAR" -X POST "$RELOOP_URL/api/api-key/v1/" -H 'content-type: application/json' -d '{"name":"agent"}' | grep -o '"key":"[^"]*"' | head -1 | cut -d'"' -f4)
echo "key ${#KEY} chars"
curl -s -o /dev/null -w 'list-with-key %{http_code}\n' "$RELOOP_URL/api/api-key/v1/" -H "x-api-key: $KEY"
curl -s -o /dev/null -w 'list-no-key %{http_code}\n' "$RELOOP_URL/api/api-key/v1/"
```

A fresh deploy prints `health 200`, `sign-in 200`, a key length above zero, `list-with-key 200` and `list-no-key 401`. From there the same key drives the other services (`/api/domain/v1`, `/api/template/v1`, `/api/contacts/v1`, `/api/mail/v1`, and so on); the OpenAPI document of each is at its own `/openapi` path.

## Why Deploy Reloop 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 Reloop 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.

- **Agent-ready** - generated secrets, a bootstrapped admin, a contract block and one working script; no wizard before the first API call.
- **One public domain** - a single proxy fronts the dashboard and every API, with the services private behind it.
- **Redeploy-safe** - databases, the broker and the MTA spool sit on volumes; passwords and secrets are stable across redeploys.
- **Pinned images** - every Reloop image is pinned by digest.

## Common Use Cases

- **Transactional email for your own product** - send receipts, password resets and notifications through your own domain instead of a per-email hosted plan.
- **Email for AI agents** - give an agent an API key to manage domains, templates and contacts and to send mail.
- **Campaigns and contact lists** - run newsletters with templates, segments and webhooks on infrastructure you control.

## Dependencies for Reloop Hosting

- Postgres, Redis and NATS JetStream, all included in this template.
- A sending domain whose DNS you control, and the Railway Pro plan for outbound SMTP.

### Deployment Dependencies

- [reloop-labs/reloop](https://github.com/reloop-labs/reloop) - upstream project
- [KumoMTA](https://kumomta.com/) - the mail transfer agent Reloop sends through
- [Resend API reference](https://resend.com/docs/api-reference/introduction) - the API style Reloop follows


## 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/reloop-or-just-updated-resend-alternativ
