A self-hosted PHP dashboard to manage and rotate Railway environment variables. Works across global scope and per-service scope.
- Lists global and per-service Railway environment variables
- Rotates secrets on demand from the dashboard or on a schedule via
cron.php - Generates new values with configurable length and encoding (
hex,base64,alphanumeric) - Stores the previous value after each rotation, encrypted with AES-256-GCM
- Groups services into named sets for organised workflows
- Protects the dashboard with session-based auth and CSRF tokens
- Throttles login attempts with a separate SQLite rate-limit database
- PHP 8.2
- SQLite
- Nginx + PHP-FPM (Docker)
- Railway GraphQL API
| Variable | Required | Description |
|---|---|---|
RAILWAY_TOKEN |
yes | Railway API token with project write access |
RAILWAY_PROJECT_ID |
yes | Project ID (auto-injected by Railway, or set manually) |
RAILWAY_ENVIRONMENT_ID |
yes | Environment ID (auto-injected by Railway, or set manually) |
ADMIN_KEY |
yes | Password for the dashboard login |
SESSION_SECRET |
yes | Signs and encrypts the session cookie |
MASTER_KEY |
yes | Encrypts the secret history database at rest |
TRUSTED_PROXY_IPS |
no | Comma-separated proxy IPs to trust for X-Forwarded-For |
Note: When
RAILWAY_ENVIRONMENT_NAMEis set the session cookie usesSecure+SameSite=Strict. Without it the cookie usesSameSite=Lax(suitable for local development).
The app writes two SQLite files under storage/db/:
secrets.sqlite— rotation config and encrypted historyrailway_cache.sqlite— cached service/variable metadata (encrypted, no secret values)login_rate_limit.sqlite— login throttle state
Mount a Railway Volume to /var/www/html/storage so data persists across deploys.
PHP built-in server
php -S localhost:8080 -t publicDocker
docker build -t railway-secrets .
docker run --rm -p 8080:80 --env-file .env railway-secretsOpen http://localhost:8080 in both cases.
Deploy instantly from the Railway template marketplace:
https://railway.com/deploy/railway-secrets
Available in the Automation category — search for Railway Secrets.
Or deploy manually from source:
- Push this repository to GitHub.
- Create a Railway service from the repo.
- Set all required environment variables in the service settings.
- Create a Railway Volume and mount it to
/var/www/html/storage.
Scheduled rotation runs automatically inside the container — crond starts with the service and executes cron.php every minute. The script handles its own per-secret interval logic, so no separate cron service is needed.
GET /health
GET /healthz
{"ok":true,"status":"healthy","timestamp":"..."}- Use strong random values (32+ characters) for
ADMIN_KEY,SESSION_SECRET, andMASTER_KEY. - Set
TRUSTED_PROXY_IPSin production environments behind a proxy. - Never commit
.envor expose any of the keys above. - Rotate
SESSION_SECRETif you suspect it has been leaked. - The
RAILWAY_TOKENshould have the minimum scope needed — project-level write, not account-level.
MIT — see LICENSE.