Edge rules
Redirects, response headers and CORS, error and maintenance pages, path routing, your own certificates, passwords, IP rules, rate limits, country blocks and a WAF.
Every server runs one web proxy (Caddy) in front of its apps. The rules below run in that proxy, before a request reaches your app. Most of them live on the app’s Settings → Networking tab and apply on the next deploy.
You can also set them through the API (GET / PATCH /api/applications/:id/edge, which merges the keys you send) or in the edge: section of railyard.yml.
Access: password and IP rules
The Access card does three things:
- Password. Puts a password on the app, which suits stagings, previews and admin tools.
- IP rules. Allow or deny one address or CIDR range per line. Everyone else gets
403. - No indexing. Default and preview addresses already tell search engines not to index them.
Redirects and rewrites
Redirects and rewrites takes one rule per line. Rules are checked in order, and the first match wins:
/blog/* https://blog.example.com/*{?query} 301
www.shop.example.com/promo /sale 302
/old-api/* /api rewrite
/legacy /new
- Type:
301,302,307,308orrewrite. It defaults to301. - Host: a host in front of the path limits the rule to that address.
- Trailing
*: carries the rest of the path across. - Rewrites serve another path of the same app and keep the query string.
You can have up to 100 rules. They’re off during maintenance mode.
Response headers and CORS
Response headers and CORS takes one header rule per line:
* X-Frame-Options: DENY
/api/* Cache-Control: no-store
* -X-Powered-By
A header you set replaces the value your app sent, and -Name removes the header. You can have up to 50 rules.
For CORS, list the allowed origins, then the methods, the headers, whether credentials are allowed and a max age. The proxy answers preflight requests itself, so they never reach the app, and other origins get no CORS headers. If the app has a password, preflights get 401.
Error and maintenance pages
- Error page: shown with the real status (502, 503 or 504) when the app can’t answer because it crashed, is restarting or is too slow.
- Maintenance page: replaces Railyard’s built-in page while maintenance mode is on. It’s still sent with a 503.
Paste the HTML, or give an address and Railyard copies the page each time you save. A copied page can be up to 64 KB and must be on a public address. Pages are served as they are, so use full URLs for images and styles. The card has a preview link.
Path routing
Path routing serves this app under a path of another app’s address, such as shop.example.com/api for your API, on one certificate. You can keep the prefix or strip it.
Both apps must be on the same server. Routing across servers isn’t supported yet.
Your own SSL certificate
Settings → Domains → Your own certificates. Paste a PEM certificate, with its chain, and an unencrypted PEM key. Before saving, Railyard checks that:
- the key matches the certificate;
- the certificate is valid now;
- it covers at least one of the app’s addresses.
The certificate and key are stored encrypted, and the API never returns the key. The card shows the expiry date, and Railyard sends a warning through the app’s app down rules 14 days before it expires. Once it expires, the next deploy goes back to automatic Let’s Encrypt certificates. Certificates can’t go in railyard.yml, because that would put a private key in git.
API: GET / POST /api/applications/:id/certificates, DELETE …/certificates/:cert_id.
Rate limiting (beta)
Rate limiting sets requests per minute per client IP. You can set one limit for the whole app and add limits per path:
Whole app: 600
/login 10
/api/* 120
A request over the limit gets 429 with Retry-After.
Beta: rate limits need Railyard’s own edge proxy image on the server, and that image is still rolling out. Until your server has it, the rules are saved but not applied, and both the card and the deploy log say so.
Other limits:
- Counters live in each server’s memory, so an app on several servers gets the limit per server.
- Behind Cloudflare or another proxy, every visitor looks like that proxy’s IP, and trusted proxies can’t be configured yet.
Country blocking (beta)
Countries takes two-letter country codes in two lists, allow only and block. UNK covers addresses with no known country.
- Blocked visitors get
403, before rate limits, redirects or your app. - Private and internal addresses always get through.
- The country data comes from DB-IP Lite.
It needs the same edge proxy image as rate limiting, so today the rules are saved but not applied. The same Cloudflare limitation applies.
Web application firewall (beta)
Web application firewall runs every request through the OWASP Core Rule Set (SQL injection, XSS and the other CRS categories) before it reaches the app. Set the mode: Off (no checks), Detect (logged, never blocks — use this first to see what it would have stopped) or Block (enforced, returns 403). Applies on the next deploy; a blocked request shows up in the app’s logs like any other edge block.
It needs the same edge proxy image as rate limiting and country blocking, so until your server has it the setting is saved but not applied, and the card says so.
Custom domains
Adding domains, www and bare-domain pairs, wildcard subdomains and the ownership check is covered in Domains.