* init develop command
* develop: use service names, random ports, project-specific dir
- extract environment config types to controllers/environment_config.rs
- use slugified service names instead of IDs in compose
- generate deterministic external ports (10000-60000) to avoid conflicts
- save compose to ~/.railway/develop/<project_id>/
- always run detached
* develop: show service names and URLs in output
* develop: resolve variables and override Railway networking vars
- Fetch resolved variables via VariablesForServiceDeployment API
- Override RAILWAY_PRIVATE_DOMAIN with docker-compose service slug
- Override RAILWAY_PUBLIC_DOMAIN and RAILWAY_TCP_PROXY_DOMAIN with localhost
- Override RAILWAY_TCP_PROXY_PORT with mapped local port
- Replace *.railway.internal refs in values with service slugs
- Filter deprecated vars (RAILWAY_STATIC_URL, RAILWAY_SERVICE_*_URL)
- Add docker-compose networking for inter-container communication
- Escape $ as $$ in commands for docker-compose interpolation
* develop: add volume support and down subcommand
- Add volumes field to docker-compose output (persist through up/down)
- Add `develop down` subcommand to stop containers
- Use environment ID for compose dir and volume names
- Show volume mount paths in service summary
* run: use local services when develop is active
Add --no-local flag to skip. Extracts shared variable override logic
into controllers/local_override.rs for reuse between run and develop.
* develop down: add --clean flag to remove volumes and files
* restart services on failure
* develop: add local HTTPS with mkcert and pretty URLs
- auto-generate TLS certs via mkcert for {project}.railway.dev
- add Caddy reverse proxy for HTTPS termination
- set RAILWAY_PUBLIC_DOMAIN to https://{domain}:{port}
- auto-add /etc/hosts entry on develop up
- remove hosts entry on develop down --clean
- skip cert generation if already exists
* develop: use .localhost TLD instead of .railway.dev
.localhost resolves to 127.0.0.1 per RFC 6761, eliminating need for
/etc/hosts manipulation and sudo prompts
* process manager
* develop: support port 443 for prettier public URLs
- Try binding to port 443 at startup for cleaner URLs
- Port 443 mode: https://{service}.{project}.railway.localhost
- Fallback mode: https://{project}.railway.localhost:{port}
- Generate wildcard certs (*.project.railway.localhost) for port 443
- SNI-based routing in Caddy when using port 443
- Add http:// prefix to private domain display
* develop: add session lock to prevent concurrent code service runs
- Add DevelopSessionLock using fs2 file locking to prevent multiple
develop sessions running code services for the same environment
- Check existing https_mode before falling back from port 443
- Lock auto-releases on drop or process crash
* develop: refactor into testable module structure
- Extract shared types to controllers/config/ (EnvironmentConfig)
- Create controllers/develop/ with submodules:
- ports.rs: slugify, generate_port + tests
- variables.rs: override_railway_vars + tests
- session.rs: DevelopSessionLock + tests
- traits.rs: EnvironmentDataProvider, CommandRunner + mocks
- compose.rs: DockerCompose types, build_port_infos
- https_proxy.rs: HttpsConfig, certs, Caddyfile gen
- code_runner.rs: ProcessManager
- local_config.rs: LocalDevConfig
- Add async-trait dependency for trait abstractions
- Old controller files re-export for backward compat
* develop: remove unused traits and cleanup backward compat stubs
- Delete unused EnvironmentDataProvider and CommandRunner traits (371 lines)
- Add fetch_environment_config() function to controllers/config
- Update develop.rs to use centralized fetch function
- Delete empty stub files: process_manager.rs, develop_lock.rs,
local_https.rs, local_dev_config.rs
- Update local_override.rs to import directly from develop module
* develop: remove unused get_env_vars, cleanup dead_code attributes
- Remove unused get_env_vars method from ServiceInstance
- Remove unnecessary #![allow(dead_code)] from compose.rs and output.rs
- Add explanatory comment for dead_code allow in environment.rs
(needed for API deserialization struct fields)
* dev: rename develop to dev, add clean subcommand
- rename command from `develop` to `dev` (with `develop` alias)
- extract `--clean` flag from `down` into separate `clean` subcommand
- update output: remove "Using port 443" msg, add checkmark to "Started X image services"
* dev: store data in ~/.railway/develop/{projectId} instead of environmentId
* remove unnecessary comments
* dev: add unit tests for compose, https_proxy, local_config
Tests for port building, caddyfile generation, cert existence, and config operations.
* dev: fix cross-platform compatibility for Linux/Windows
- Add extra_hosts to Caddy service for host.docker.internal on Linux
- Use shell execution (sh -c / cmd /C) for proper command parsing
- Replace path unwraps with to_string_lossy()
* dev: check docker compose availability before running
* fix: handle Windows error kind for file lock conflicts
* dev configure: add service menu and --remove <name> support
* dev: clarify comments in up_command
* fix: use fs2 lock_contended_error for cross-platform lock check
* fix: use privateNetworkEndpoint for private domain resolution
Previously used slugified service name which may not match the actual
private network endpoint configured in the environment.
* refactor: extract build_service_endpoints helper for privateNetworkEndpoint
DRYs up duplicate logic between dev.rs and local_override.rs.
Fixes run command using environment_id instead of project_id for
is_local_develop_active check.
* dev: improve empty state messages
Distinguish "no services at all" from "no code services" so users
get actionable guidance (railway add vs railway develop configure)
* fix: only show networking for code services when port configured
* fix: skip canonicalize on windows to avoid UNC path prefix
canonicalize() returns \\?\C:\... paths on Windows which cmd.exe rejects
* dev: improve empty state messages with color
* dev: show command as first log line for code services
* dev: add port selection to configure and detect port conflicts
- prompt for port during service configuration (default: inferred from Railway)
- skip port prompt if service has no networking config
- detect and warn about port conflicts during configure
- force reconfigure conflicting ports during `railway dev up`
- only set PORT env var for services with networking configured
* dev: allow configuring multiple services on first-time setup
Use multi-select prompt instead of single-select, with summary at end
* dev: show OS-specific Docker install URL
* dev: format Docker not found message
* remove test dir
* remove test and to gitignore
* dev: fix cross-service public domain replacement
When service A references service B's RAILWAY_PUBLIC_DOMAIN via variable
interpolation, the production domain wasn't being replaced with the local
equivalent. Now builds a mapping of production -> local public domains
and replaces them in all variable values.
* dev: show next steps when only image services running
* dev: extract constants and refactor up_command
- Add port range constants (PORT_RANGE_MIN, PORT_RANGE_SIZE, RANDOM_PORT_MIN, RANDOM_PORT_MAX)
- Add resolve_path() for cross-platform path canonicalization
- Move generate_random_port() to ports.rs
- Extract helper functions from up_command:
- print_image_service_summary()
- print_code_service_summary()
- build_public_domain_mapping()
- build_image_service_compose()
- setup_caddy_proxy()
|
||
|---|---|---|
| .cargo | ||
| .github | ||
| bin | ||
| npm-install | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| Dockerfile | ||
| flake.lock | ||
| flake.nix | ||
| install.sh | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| README.md | ||
| release.toml | ||
| shell.nix | ||
| v2.sh | ||
Railway CLI
This is the command line interface for Railway. Use it to connect your code to Railway's infrastructure without needing to worry about environment variables or configuration.
The Railway command line interface (CLI) connects your code to your Railway project from the command line.
The Railway CLI allows you to
- Create new Railway projects from the terminal
- Link to an existing Railway project
- Pull down environment variables for your project locally to run
- Create services and databases right from the comfort of your fingertips
Installation
Cargo
cargo install railwayapp --locked
Homebrew
brew install railway
NPM
npm install -g @railway/cli
Bash
# Install
bash <(curl -fsSL cli.new)
# Uninstall
bash <(curl -fsSL cli.new) -r
Scoop
scoop install railway
Arch Linux AUR
Install using Paru
paru -S railwayapp-cli
Install using Yay
yay -S railwayapp-cli
Docker
Before using the CLI in a non-interactive environment, ensure you have created an access token (only project-tokens are supported as of now) and set it as the RAILWAY_TOKEN environment variable. CI environments are automatically detected by the presence of CI=true variable. In these environments, only build logs will be streamed, and the CLI will exit with an appropriate code indicating success or failure.
Install from the command line
docker pull ghcr.io/railwayapp/cli:latest
Use in GitHub Actions
deploy-job:
runs-on: ubuntu-latest
container: ghcr.io/railwayapp/cli:latest
env:
SVC_ID: my-service
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
steps:
- uses: actions/checkout@v3
- run: railway up --service=${{ env.SVC_ID }}
Use in GitLab CICD
deploy-job:
image: ghcr.io/railwayapp/cli:latest
variables:
SVC_ID: my-service
script:
- railway up --service=$SVC_ID
Tip
GitLab can access a protected (secret) variable directly, all you need to do is to add it in CI/CD settings.
From source
See CONTRIBUTING.md for information on setting up this repo locally.
Documentation
Feedback
We would love to hear your feedback or suggestions. The best way to reach us is on Discord.
We also welcome pull requests into this repo. See CONTRIBUTING.md for information on setting up this repo locally.