@tachyon-gg/railway-deploy 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +323 -137
- package/dist/index.js +4330 -2127
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://bun.sh/)
|
|
8
8
|
[](https://biomejs.dev/)
|
|
9
9
|
|
|
10
|
-
Declarative infrastructure management for [Railway](https://railway.com). Define your Railway project's services, variables, domains, volumes, and buckets in YAML, and `railway-deploy` will diff against the live state and apply changes -- like Terraform, but purpose-built for Railway.
|
|
10
|
+
Declarative infrastructure management for [Railway](https://railway.com). Define your Railway project's services, variables, domains, volumes, and buckets in YAML, and `railway-deploy` will diff against the live state and apply changes atomically -- like Terraform, but purpose-built for Railway.
|
|
11
11
|
|
|
12
12
|
## Quick start
|
|
13
13
|
|
|
@@ -16,21 +16,24 @@ Declarative infrastructure management for [Railway](https://railway.com). Define
|
|
|
16
16
|
npx @tachyon-gg/railway-deploy --help
|
|
17
17
|
|
|
18
18
|
# Validate a config file
|
|
19
|
-
npx @tachyon-gg/railway-deploy --validate
|
|
19
|
+
npx @tachyon-gg/railway-deploy --validate project.yaml
|
|
20
20
|
|
|
21
21
|
# Dry-run (show what would change)
|
|
22
|
-
npx @tachyon-gg/railway-deploy
|
|
22
|
+
npx @tachyon-gg/railway-deploy project.yaml -e production
|
|
23
23
|
|
|
24
24
|
# Apply changes
|
|
25
|
-
npx @tachyon-gg/railway-deploy --apply
|
|
25
|
+
npx @tachyon-gg/railway-deploy --apply -e production project.yaml
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## CLI flags
|
|
29
29
|
|
|
30
30
|
| Flag | Description |
|
|
31
31
|
|------|-------------|
|
|
32
|
+
| `-e, --environment <name>` | Target environment (required except for `--validate`) |
|
|
32
33
|
| `--apply` | Execute changes (default: dry-run) |
|
|
34
|
+
| `--stage` | Stage changes in Railway without committing (preview in dashboard) |
|
|
33
35
|
| `-y, --yes` | Skip confirmation for destructive ops |
|
|
36
|
+
| `--allow-data-loss` | Allow operations that can cause data loss (e.g., volume deletion) |
|
|
34
37
|
| `--env-file <path>` | Load `.env` file for `${VAR}` resolution |
|
|
35
38
|
| `-v, --verbose` | Show detailed diffs (old -> new values) |
|
|
36
39
|
| `--no-color` | Disable ANSI color output |
|
|
@@ -46,108 +49,244 @@ npx @tachyon-gg/railway-deploy --apply environments/production.yaml
|
|
|
46
49
|
|
|
47
50
|
## Config reference
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
Project configs are YAML files describing the desired state of a Railway project across one or more environments. Add schema support to your editor:
|
|
50
53
|
|
|
51
54
|
```yaml
|
|
52
|
-
# yaml-language-server: $schema=./schemas/
|
|
55
|
+
# yaml-language-server: $schema=./schemas/project.schema.json
|
|
53
56
|
```
|
|
54
57
|
|
|
55
|
-
### Top-level
|
|
58
|
+
### Top-level structure
|
|
56
59
|
|
|
57
60
|
```yaml
|
|
58
|
-
project: My Project
|
|
59
|
-
|
|
61
|
+
project: My Project # Railway project name (must match exactly)
|
|
62
|
+
environments: # Environments to manage
|
|
63
|
+
- staging
|
|
64
|
+
- production
|
|
65
|
+
|
|
66
|
+
shared_variables: { ... } # Variables shared across all services
|
|
67
|
+
services: { ... } # Service definitions
|
|
68
|
+
volumes: { ... } # Persistent volume definitions
|
|
69
|
+
buckets: { ... } # S3-compatible bucket definitions
|
|
70
|
+
```
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
APP_ENV: production
|
|
63
|
-
API_PORT: "8080"
|
|
72
|
+
### Shared variables
|
|
64
73
|
|
|
65
|
-
services
|
|
66
|
-
web: { ... }
|
|
67
|
-
worker: { ... }
|
|
74
|
+
Shared variables are available to all services in an environment. Use the string shorthand for values that are the same everywhere, or the object form for per-environment overrides:
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
```yaml
|
|
77
|
+
shared_variables:
|
|
78
|
+
# String shorthand — same value in all environments
|
|
79
|
+
ADMIN_PORT: "8081"
|
|
80
|
+
PUBLIC_PORT: "8080"
|
|
81
|
+
|
|
82
|
+
# Object form — default value with per-environment overrides
|
|
83
|
+
JWT_SECRET:
|
|
84
|
+
value: ${JWT_SECRET_DEFAULT}
|
|
85
|
+
environments:
|
|
86
|
+
staging:
|
|
87
|
+
value: ${JWT_SECRET_STAGING}
|
|
88
|
+
production:
|
|
89
|
+
value: ${JWT_SECRET_PROD}
|
|
72
90
|
```
|
|
73
91
|
|
|
74
|
-
|
|
92
|
+
Supports `${ENV_VAR}` syntax (resolved from your local environment or `--env-file`) and `${{shared.OTHER_VAR}}` self-references.
|
|
75
93
|
|
|
76
|
-
|
|
94
|
+
> **Note:** Shared variables cannot contain `${{service.VAR}}` cross-service references. Railway resolves shared variables without a service context.
|
|
95
|
+
|
|
96
|
+
### Volumes
|
|
97
|
+
|
|
98
|
+
Volumes are declared at the top level with optional per-environment overrides. Services reference them by name.
|
|
77
99
|
|
|
78
100
|
```yaml
|
|
101
|
+
volumes:
|
|
102
|
+
pg-data:
|
|
103
|
+
size_mb: 50000
|
|
104
|
+
region: us-east4
|
|
105
|
+
environments:
|
|
106
|
+
production:
|
|
107
|
+
size_mb: 100000
|
|
108
|
+
|
|
109
|
+
redis-data: {} # Minimal declaration — Railway defaults
|
|
110
|
+
|
|
79
111
|
services:
|
|
80
|
-
|
|
81
|
-
redis:
|
|
112
|
+
postgres:
|
|
82
113
|
source:
|
|
83
|
-
image:
|
|
84
|
-
|
|
85
|
-
|
|
114
|
+
image: postgres:17
|
|
115
|
+
volume: # Reference a declared volume
|
|
116
|
+
name: pg-data
|
|
117
|
+
mount: /var/lib/postgresql/data
|
|
118
|
+
```
|
|
86
119
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
120
|
+
Every volume referenced by a service must be declared in the `volumes` block.
|
|
121
|
+
|
|
122
|
+
### Buckets
|
|
123
|
+
|
|
124
|
+
S3-compatible Railway buckets. The key is the bucket name.
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
buckets:
|
|
128
|
+
media-uploads:
|
|
129
|
+
region: iad
|
|
130
|
+
environments:
|
|
131
|
+
eu-production:
|
|
132
|
+
region: fra
|
|
133
|
+
|
|
134
|
+
logs: {} # Minimal — uses default region
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Services
|
|
138
|
+
|
|
139
|
+
Each service defines defaults that apply to all environments. Per-environment overrides go under `environments.<name>`:
|
|
92
140
|
|
|
93
|
-
|
|
141
|
+
```yaml
|
|
142
|
+
services:
|
|
94
143
|
web:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
144
|
+
source:
|
|
145
|
+
repo: myorg/web-app
|
|
146
|
+
start_command: npm start
|
|
98
147
|
variables:
|
|
99
|
-
|
|
148
|
+
PORT: "3000"
|
|
149
|
+
environments:
|
|
150
|
+
staging:
|
|
151
|
+
source:
|
|
152
|
+
repo: myorg/web-app
|
|
153
|
+
branch: develop
|
|
154
|
+
production:
|
|
155
|
+
source:
|
|
156
|
+
repo: myorg/web-app
|
|
157
|
+
branch: main
|
|
158
|
+
wait_for_ci: true
|
|
159
|
+
|
|
160
|
+
# Service without environments block — exists in all environments
|
|
161
|
+
redis:
|
|
162
|
+
source:
|
|
163
|
+
image: redis:7
|
|
164
|
+
|
|
165
|
+
# Service scoped to specific environments
|
|
166
|
+
debug-tools:
|
|
167
|
+
source:
|
|
168
|
+
image: debug:latest
|
|
169
|
+
environments:
|
|
170
|
+
staging: {} # Only in staging
|
|
100
171
|
```
|
|
101
172
|
|
|
102
|
-
|
|
173
|
+
#### Service scope rules
|
|
174
|
+
|
|
175
|
+
- Service **has** `environments` block -> only exists in environments listed there
|
|
176
|
+
- Service **has no** `environments` block -> exists in ALL declared environments
|
|
177
|
+
|
|
178
|
+
#### Merge rules
|
|
179
|
+
|
|
180
|
+
When a service has per-environment overrides:
|
|
181
|
+
|
|
182
|
+
| Field type | Merge behavior |
|
|
183
|
+
|------------|---------------|
|
|
184
|
+
| `params`, `variables` | Shallow merge (override keys replace defaults) |
|
|
185
|
+
| `domains`, `source`, `volume`, `regions`, `healthcheck`, `build` | Replace entirely |
|
|
186
|
+
| Scalar fields (`start_command`, etc.) | Override replaces |
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### Service fields reference
|
|
103
191
|
|
|
104
|
-
Every
|
|
192
|
+
Every field below can be used on service defaults, per-environment overrides, and templates.
|
|
105
193
|
|
|
106
194
|
#### Source
|
|
107
195
|
|
|
196
|
+
Source is a discriminated union — use **either** `repo` or `image`, not both.
|
|
197
|
+
|
|
108
198
|
```yaml
|
|
199
|
+
# Repo source — deploy from a GitHub repository
|
|
109
200
|
source:
|
|
110
|
-
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
check_suites: true # Wait for GitHub Actions to pass before deploying
|
|
201
|
+
repo: myorg/my-repo
|
|
202
|
+
branch: main # Branch to deploy from
|
|
203
|
+
root_directory: /packages/api # Root directory (monorepo support)
|
|
204
|
+
wait_for_ci: true # Wait for GitHub Actions to pass before deploying
|
|
205
|
+
```
|
|
116
206
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
207
|
+
```yaml
|
|
208
|
+
# Image source — deploy from a container image
|
|
209
|
+
source:
|
|
210
|
+
image: nginx:latest # Docker image (Docker Hub, GHCR, etc.)
|
|
211
|
+
registry_credentials: # For private container registries
|
|
212
|
+
username: ${REGISTRY_USER}
|
|
213
|
+
password: ${REGISTRY_PASS}
|
|
214
|
+
auto_updates: # Auto-update schedule for image-based services
|
|
215
|
+
monday:
|
|
216
|
+
start_hour: 0
|
|
217
|
+
end_hour: 6
|
|
218
|
+
friday:
|
|
219
|
+
start_hour: 0
|
|
220
|
+
end_hour: 6
|
|
120
221
|
```
|
|
121
222
|
|
|
122
223
|
#### Build
|
|
123
224
|
|
|
225
|
+
Build is a discriminated union — fields depend on the `builder` value.
|
|
226
|
+
|
|
124
227
|
```yaml
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
watch_patterns:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
228
|
+
# Railpack (default)
|
|
229
|
+
build:
|
|
230
|
+
builder: railpack
|
|
231
|
+
command: npm run build # Custom build command
|
|
232
|
+
watch_patterns: # File patterns that trigger deploys
|
|
233
|
+
- /packages/api/src/**
|
|
234
|
+
metal: true # Enable Metal build environment (faster builds)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
# Nixpacks
|
|
239
|
+
build:
|
|
240
|
+
builder: nixpacks
|
|
241
|
+
command: npm run build
|
|
242
|
+
watch_patterns:
|
|
243
|
+
- /packages/api/src/**
|
|
244
|
+
metal: true
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```yaml
|
|
248
|
+
# Dockerfile
|
|
249
|
+
build:
|
|
250
|
+
builder: dockerfile
|
|
251
|
+
dockerfile_path: Dockerfile.prod # Path to Dockerfile
|
|
252
|
+
watch_patterns:
|
|
253
|
+
- /packages/api/src/**
|
|
254
|
+
metal: true
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
`railway_config_file` is a separate service-level field (not part of `build`):
|
|
258
|
+
|
|
259
|
+
```yaml
|
|
260
|
+
railway_config_file: railway.toml # Path to railway.json/toml in the repository
|
|
133
261
|
```
|
|
134
262
|
|
|
135
263
|
#### Deploy
|
|
136
264
|
|
|
137
265
|
```yaml
|
|
138
|
-
start_command: npm start
|
|
139
|
-
|
|
266
|
+
start_command: npm start # Custom start command
|
|
267
|
+
|
|
268
|
+
pre_deploy_command: # Run before deployment (e.g., migrations)
|
|
140
269
|
- npm run migrate
|
|
141
270
|
- npm run seed
|
|
142
|
-
|
|
143
|
-
|
|
271
|
+
|
|
272
|
+
cron_schedule: "*/5 * * * *" # Cron schedule (5-field format)
|
|
273
|
+
# Note: cron forces restart_policy to NEVER
|
|
274
|
+
# and disables serverless
|
|
275
|
+
|
|
276
|
+
healthcheck: # HTTP healthcheck
|
|
144
277
|
path: /health
|
|
145
|
-
timeout: 300
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
278
|
+
timeout: 300 # Timeout in seconds (default: 300)
|
|
279
|
+
|
|
280
|
+
# Restart policy — string shorthand or object with max_retries
|
|
281
|
+
restart_policy: always # always, never, or on_failure
|
|
282
|
+
|
|
283
|
+
restart_policy: # Object form for on_failure with retries
|
|
284
|
+
type: on_failure
|
|
285
|
+
max_retries: 5
|
|
286
|
+
|
|
287
|
+
serverless: true # Enable serverless sleeping (scale to zero when idle)
|
|
288
|
+
draining_seconds: 30 # Graceful shutdown timeout (SIGTERM to SIGKILL)
|
|
289
|
+
overlap_seconds: 10 # Blue-green deploy overlap duration
|
|
151
290
|
```
|
|
152
291
|
|
|
153
292
|
#### Networking
|
|
@@ -155,31 +294,35 @@ overlap_seconds: 10 # Blue-green deploy overlap duration
|
|
|
155
294
|
```yaml
|
|
156
295
|
# Custom domains
|
|
157
296
|
domains:
|
|
158
|
-
- app.example.com
|
|
159
|
-
- domain: api.example.com
|
|
297
|
+
- app.example.com # Simple domain
|
|
298
|
+
- domain: api.example.com # Domain with target port
|
|
160
299
|
target_port: 8080
|
|
161
300
|
|
|
162
|
-
# Railway-provided domain
|
|
163
|
-
railway_domain:
|
|
164
|
-
railway_domain: # ...with a specific target port
|
|
301
|
+
# Railway-provided domain (*.up.railway.app)
|
|
302
|
+
railway_domain:
|
|
165
303
|
target_port: 3000
|
|
166
304
|
|
|
167
|
-
# TCP
|
|
168
|
-
|
|
305
|
+
# TCP proxy (for non-HTTP services like databases)
|
|
306
|
+
tcp_proxy: 5432
|
|
307
|
+
|
|
308
|
+
# Private networking
|
|
309
|
+
private_hostname: postgres # Internal DNS hostname for service-to-service communication
|
|
169
310
|
|
|
170
311
|
# Outbound networking
|
|
171
|
-
ipv6_egress: true
|
|
172
|
-
static_outbound_ips: true
|
|
312
|
+
ipv6_egress: true # Enable IPv6 outbound traffic
|
|
313
|
+
static_outbound_ips: true # Assign permanent outbound IP addresses
|
|
173
314
|
```
|
|
174
315
|
|
|
175
316
|
#### Scaling
|
|
176
317
|
|
|
177
318
|
```yaml
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
319
|
+
regions: us-east4 # Single region (1 replica)
|
|
320
|
+
# or
|
|
321
|
+
regions: # Multi-region with replica counts
|
|
322
|
+
us-east4: 3
|
|
323
|
+
us-west1: 1
|
|
181
324
|
|
|
182
|
-
limits:
|
|
325
|
+
limits: # Resource limits per replica
|
|
183
326
|
memory_gb: 8
|
|
184
327
|
vcpus: 4
|
|
185
328
|
```
|
|
@@ -187,9 +330,9 @@ limits: # Resource limits per replica
|
|
|
187
330
|
#### Storage
|
|
188
331
|
|
|
189
332
|
```yaml
|
|
190
|
-
volume:
|
|
191
|
-
|
|
192
|
-
|
|
333
|
+
volume: # Reference a top-level volume
|
|
334
|
+
name: pg-data # Must match a key in the volumes block
|
|
335
|
+
mount: /var/lib/postgresql/data # Absolute mount path
|
|
193
336
|
```
|
|
194
337
|
|
|
195
338
|
#### Variables
|
|
@@ -212,25 +355,17 @@ variables:
|
|
|
212
355
|
| `%{service_name}` | At config load time | Built-in: the service's config key |
|
|
213
356
|
| `null` | N/A | Marks a variable for deletion |
|
|
214
357
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
`%{param}` is expanded first, so it can be used inside `${{}}` Railway references. This is useful for templates that need to reference their own or other services' variables:
|
|
358
|
+
`%{param}` is expanded first, so it can be used inside `${{}}` Railway references:
|
|
218
359
|
|
|
219
360
|
```yaml
|
|
220
361
|
variables:
|
|
221
|
-
# Reference own service's variable (resolves %{service_name} at config time,
|
|
222
|
-
# Railway resolves the ${{}} reference at runtime)
|
|
223
362
|
DATABASE_URL: ${{%{service_name}.DATABASE_URL}}
|
|
224
|
-
|
|
225
|
-
# Reference another service by param
|
|
226
363
|
REDIS_URL: ${{%{cache_service}.REDIS_URL}}
|
|
227
364
|
```
|
|
228
365
|
|
|
229
366
|
### Service templates
|
|
230
367
|
|
|
231
|
-
Templates extract reusable service definitions with parameterized values.
|
|
232
|
-
|
|
233
|
-
The built-in `%{service_name}` param is always available and resolves to the service's key in the config (e.g., `web`, `api`). It cannot be overridden.
|
|
368
|
+
Templates extract reusable service definitions with parameterized values. The built-in `%{service_name}` param resolves to the service's key in the config.
|
|
234
369
|
|
|
235
370
|
```yaml
|
|
236
371
|
# services/web.yaml
|
|
@@ -255,105 +390,156 @@ healthcheck:
|
|
|
255
390
|
path: /health
|
|
256
391
|
timeout: 300
|
|
257
392
|
|
|
258
|
-
|
|
259
|
-
region: us-east-1
|
|
260
|
-
num_replicas: 1
|
|
393
|
+
regions: us-east4
|
|
261
394
|
```
|
|
262
395
|
|
|
263
|
-
Referenced from
|
|
396
|
+
Referenced from a project config:
|
|
264
397
|
|
|
265
398
|
```yaml
|
|
266
399
|
services:
|
|
267
400
|
web:
|
|
268
|
-
template:
|
|
401
|
+
template: services/web.yaml
|
|
269
402
|
params:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
403
|
+
replicas: "1"
|
|
404
|
+
environments:
|
|
405
|
+
staging:
|
|
406
|
+
params:
|
|
407
|
+
tag: alpha
|
|
408
|
+
production:
|
|
409
|
+
params:
|
|
410
|
+
tag: v2.0.0
|
|
411
|
+
replicas: "3"
|
|
412
|
+
variables:
|
|
413
|
+
EXTRA: added-by-env
|
|
414
|
+
APP_VERSION: null # Deletes the template-defined variable
|
|
415
|
+
domains:
|
|
416
|
+
- production.example.com # Overrides template domains
|
|
277
417
|
```
|
|
278
418
|
|
|
279
|
-
Template override precedence: environment config values override template values for `source`, `domains`, and `variables`.
|
|
280
|
-
|
|
281
419
|
### Complete example
|
|
282
420
|
|
|
283
421
|
```yaml
|
|
284
|
-
# yaml-language-server: $schema=./schemas/
|
|
422
|
+
# yaml-language-server: $schema=./schemas/project.schema.json
|
|
285
423
|
project: My SaaS App
|
|
286
|
-
|
|
424
|
+
environments:
|
|
425
|
+
- staging
|
|
426
|
+
- production
|
|
287
427
|
|
|
288
428
|
shared_variables:
|
|
289
|
-
|
|
290
|
-
SENTRY_DSN:
|
|
429
|
+
APP_PORT: "3000"
|
|
430
|
+
SENTRY_DSN:
|
|
431
|
+
value: ${SENTRY_DSN_DEFAULT}
|
|
432
|
+
environments:
|
|
433
|
+
production:
|
|
434
|
+
value: ${SENTRY_DSN_PROD}
|
|
435
|
+
|
|
436
|
+
volumes:
|
|
437
|
+
pg-data:
|
|
438
|
+
size_mb: 50000
|
|
439
|
+
environments:
|
|
440
|
+
production:
|
|
441
|
+
size_mb: 200000
|
|
442
|
+
redis-data: {}
|
|
443
|
+
|
|
444
|
+
buckets:
|
|
445
|
+
uploads:
|
|
446
|
+
region: iad
|
|
291
447
|
|
|
292
448
|
services:
|
|
293
449
|
web:
|
|
294
450
|
source:
|
|
295
451
|
repo: myorg/web-app
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
452
|
+
root_directory: /packages/web
|
|
453
|
+
build:
|
|
454
|
+
builder: nixpacks
|
|
455
|
+
command: npm run build
|
|
456
|
+
metal: true
|
|
300
457
|
start_command: npm start
|
|
301
|
-
root_directory: /packages/web
|
|
302
458
|
pre_deploy_command: npm run migrate
|
|
303
459
|
healthcheck:
|
|
304
460
|
path: /health
|
|
305
461
|
timeout: 60
|
|
306
|
-
restart_policy:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
railway_domain: true
|
|
313
|
-
region:
|
|
314
|
-
region: us-east-1
|
|
315
|
-
num_replicas: 2
|
|
316
|
-
limits:
|
|
317
|
-
memory_gb: 4
|
|
318
|
-
vcpus: 2
|
|
462
|
+
restart_policy:
|
|
463
|
+
type: on_failure
|
|
464
|
+
max_retries: 5
|
|
465
|
+
serverless: true
|
|
466
|
+
railway_domain:
|
|
467
|
+
target_port: 3000
|
|
319
468
|
variables:
|
|
320
469
|
PORT: "3000"
|
|
321
470
|
DATABASE_URL: ${{Postgres.DATABASE_URL}}
|
|
471
|
+
environments:
|
|
472
|
+
staging:
|
|
473
|
+
source:
|
|
474
|
+
repo: myorg/web-app
|
|
475
|
+
branch: develop
|
|
476
|
+
domains:
|
|
477
|
+
- staging.example.com
|
|
478
|
+
production:
|
|
479
|
+
source:
|
|
480
|
+
repo: myorg/web-app
|
|
481
|
+
branch: main
|
|
482
|
+
wait_for_ci: true
|
|
483
|
+
domains:
|
|
484
|
+
- app.example.com
|
|
485
|
+
- domain: api.example.com
|
|
486
|
+
target_port: 8080
|
|
487
|
+
regions:
|
|
488
|
+
us-east4: 2
|
|
489
|
+
limits:
|
|
490
|
+
memory_gb: 4
|
|
491
|
+
vcpus: 2
|
|
322
492
|
|
|
323
493
|
postgres:
|
|
324
494
|
source:
|
|
325
|
-
image: postgres:
|
|
495
|
+
image: postgres:17
|
|
496
|
+
private_hostname: postgres
|
|
326
497
|
volume:
|
|
327
|
-
mount: /var/lib/postgresql/data
|
|
328
498
|
name: pg-data
|
|
329
|
-
|
|
499
|
+
mount: /var/lib/postgresql/data
|
|
500
|
+
tcp_proxy: 5432
|
|
330
501
|
variables:
|
|
331
502
|
POSTGRES_DB: myapp
|
|
332
503
|
|
|
333
504
|
redis:
|
|
334
505
|
source:
|
|
335
506
|
image: redis:7-alpine
|
|
507
|
+
private_hostname: redis
|
|
336
508
|
volume:
|
|
337
|
-
mount: /data
|
|
338
509
|
name: redis-data
|
|
339
|
-
|
|
510
|
+
mount: /data
|
|
511
|
+
tcp_proxy: 6379
|
|
340
512
|
|
|
341
513
|
worker:
|
|
342
|
-
template:
|
|
514
|
+
template: services/worker.yaml
|
|
343
515
|
params:
|
|
344
516
|
queue: default
|
|
345
|
-
|
|
517
|
+
serverless: false
|
|
346
518
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
519
|
+
cron:
|
|
520
|
+
source:
|
|
521
|
+
repo: myorg/web-app
|
|
522
|
+
root_directory: /packages/cron
|
|
523
|
+
cron_schedule: "0 0 * * *"
|
|
524
|
+
start_command: node scripts/cleanup.js
|
|
350
525
|
```
|
|
351
526
|
|
|
527
|
+
## Known limitations
|
|
528
|
+
|
|
529
|
+
- **Region management.** Setting `regions` deploys to those regions. Railway always maintains at least one region — the last region cannot be removed. Changing regions is supported (old regions are removed and new ones added). Multi-region is supported via a map of region to replica count.
|
|
530
|
+
- **Service groups** are read-only. Railway's public API does not expose group creation -- groups can only be managed via the Railway dashboard. Existing groups are respected when reading config.
|
|
531
|
+
- **Custom domains** may require DNS verification to take effect.
|
|
532
|
+
- **Registry credentials** are write-only. Railway never returns credentials in config responses, so removal of registry credentials from your config is not detectable -- we simply stop sending them.
|
|
533
|
+
- **Static outbound IPs** are managed via a separate API call (not atomic with the config patch). If the patch succeeds but the egress call fails, IPs may not be configured.
|
|
534
|
+
- **Volume size/region** can only be set or increased, not cleared or reduced. Railway does not support shrinking volumes.
|
|
535
|
+
- **Volume mount removal** is supported via the `volumeDelete` mutation and requires the `--allow-data-loss` flag, since it permanently deletes the volume and its data.
|
|
536
|
+
- **Bucket deletion** is not supported by Railway's API. Buckets that are removed from config will be left in place with a warning.
|
|
537
|
+
|
|
352
538
|
## JSON schemas
|
|
353
539
|
|
|
354
540
|
Editor support (autocompletion, validation) is available via JSON schemas:
|
|
355
541
|
|
|
356
|
-
- `schemas/
|
|
542
|
+
- `schemas/project.schema.json` -- project config files
|
|
357
543
|
- `schemas/service-template.schema.json` -- service template files
|
|
358
544
|
|
|
359
545
|
## Development
|