Lock Down a Production Railway Project
Locking down a production project means reducing what an attacker can reach and what a leaked credential can do. On Railway that comes down to five controls: keep internal services off the public internet, turn on Under Attack Mode when traffic floods hit, scope every API token to the smallest surface that works, seal production secrets so they cannot be read back, and restrict who in your workspace can change production.
None of these require new infrastructure. They are settings on the project you already have. This guide walks through each one in the order you should apply them.
Remove public exposure from internal services
Every service with a public domain is attack surface. Databases, workers, queues, and internal APIs rarely need one.
Services in the same project and environment can reach each other over private networking without public exposure, over encrypted WireGuard tunnels that never leave Railway's network. Each one gets an internal DNS name:
<service-name>.railway.internalSo a service named api is reachable from its siblings at http://api.railway.internal:PORT, where PORT is the port your app listens on. Private networking is isolated per environment: services in production cannot reach services in staging, and services in other projects cannot reach yours at all.
To lock down an internal service:
- Open the service and go to Settings.
- Under Networking, delete any public domain the service does not need.
- Update callers to use the
<service-name>.railway.internalhostname instead of the public URL.
Use reference variables so the internal URL never gets hardcoded:
BACKEND_URL=http://${{api.RAILWAY_PRIVATE_DOMAIN}}:8080After this step, the only services with public domains should be the ones end users hit: typically a frontend and a public API.
Turn on Under Attack Mode during a DDoS
Railway's web application firewall (WAF) runs at the edge, in front of your service. Its main control is Under Attack Mode, an on-demand defense against DDoS attacks and bot floods.
While Under Attack Mode is on, every new visitor sees a browser check before any request reaches your service. Real browsers pass it once and continue normally. Non-browser traffic, including the bots and scripts driving the attack, is blocked at the edge. That's why it fits active incidents, not always-on protection.
Enable it from the dashboard:
- Open the service under attack and go to its Settings.
- In the Edge section, find Under Attack Mode.
- Pick a duration (1, 3, 12, or 24 hours, or until you turn it off), then click Activate.
It takes effect across Railway's global network within about 20 seconds. Or use the CLI:
railway waf under-attack enable --service web --duration 1h
railway waf under-attack status --service web
railway waf under-attack disable --service webTwo details matter for real deployments:
- Protecting a site and its API together. Clearance from the browser check is scoped to your whole domain. Enable Under Attack Mode on the site first, then on the API. Once a visitor passes the check on
example.com, requests toapi.example.comalso pass without a second check. This only works within one root domain;*.up.railway.appsubdomains are isolated from each other. - API-only domains. The check is only shown to browser navigations. A domain that serves only an API will have all of its traffic blocked while Under Attack Mode is on, so do not enable it on a standalone API that non-browser clients call directly.
Scope API tokens to the smallest surface
A leaked token is only as dangerous as its scope. Railway has three token types, and production automation should almost never use the broadest one.
| Token type | Scope | Use for |
|---|---|---|
| Account token | Everything you can access, across all workspaces | Personal scripts on your own machine only |
| Workspace token | One workspace | Team CI/CD, shared automation |
| Project token | One environment in one project | Deployments, service-specific automation |
For a production deploy pipeline, use a project token. It is scoped to a single environment within a single project, so a compromise of your CI system exposes one environment, not your whole account. Create it from the tokens page in your project settings, then authenticate with the Project-Access-Token header:
curl --request POST \
--url https://backboard.railway.com/graphql/v2 \
--header 'Project-Access-Token: <PROJECT_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{"query":"query { projectToken { projectId environmentId } }"}'Workspace tokens are created from the tokens page in your account settings by selecting a workspace. They can access all of that workspace's resources but nothing personal and nothing in other workspaces. The third option, an account token (created with "No workspace" selected), suits local, personal use only. Never put one in shared CI.
Store whichever token you use as a sealed variable or in your CI provider's secret store, never in the repository.
Seal production secrets
Sealed variables make a secret write-only. Railway still provides the value to builds and deployments, but it is never visible in the UI and cannot be retrieved through the API. If a dashboard session or an API token leaks, sealed values stay unreadable.
To seal an existing variable, open the 3-dot menu next to it in the service's Variables tab and choose Seal.
Sealing is permanent and has constraints to plan around:
- Sealed variables cannot be un-sealed. You can edit the value from the 3-dot menu, but you can never read the current value back.
- The values are not provided by
railway variablesorrailway runin the CLI. - They are not copied into PR environments, duplicated environments, or duplicated services, and they are not synced to external integrations.
That last point is a feature for production: a preview environment spun up from a pull request never receives your sealed production credentials. Give preview environments their own non-sealed test credentials for anything they need to boot.
When rotating, verify the new credential works before revoking the old one, because you cannot read a sealed value back. See rotate credentials without downtime for the full rotation flow.
Restrict who can change production
Infrastructure settings only help if account access is locked down too.
Enforce 2FA for the workspace. Workspace admins on the Pro plan and above can require every member to have two-factor authentication enabled before accessing the workspace. Toggle Require 2FA in your workspace's People settings. Members without 2FA are prompted to set it up before they can touch any workspace resource. See 2FA enforcement.
Use the least-privileged project role. Project members have three roles: Owner (full administration of the project), Editor (can deploy, change project settings, and add Editor or Viewer members, but cannot do destructive actions like deleting services or the project), and Viewer (read only, cannot deploy and cannot see environment variables). Default teammates to Viewer, move them to Editor when they need to deploy, and reserve Owner for the people who administer the project.
Gate deploys from unlinked GitHub users. If someone pushes to a connected branch without a linked Railway account, Railway does not deploy the push automatically. It creates a deployment approval on the service, and a project member must click Approve before the commit deploys.
Wait for CI before deploying. Enable Wait for CI so Railway waits for your GitHub workflows to pass before starting a deployment. A failing test suite then blocks the deploy instead of racing it.
Lockdown checklist
Run through this list on any project serving production traffic:
- Public domains removed from every service except user-facing ones
- Internal traffic moved to
<service-name>.railway.internalover private networking - Under Attack Mode tested once so you know the flow before an incident
- CI uses a project token, not an account token
- Production credentials sealed, with separate test credentials for preview environments
- 2FA enforcement on for the workspace
- Members hold the least-privileged role that lets them do their job
- Wait for CI enabled on the production service
For hardening beyond security, including health checks, restart policies, and observability, work through the production readiness checklist.