1. The problem I’m having:
I’m using railway for a vue SPA and a reverse proxy to our back-end.
Every call works fine, except after exactly 5 minutes, i receive an error on the SSE (socket) in my chrome console. No error in the log of the caddy server
2. Error messages and/or full log output:
net::ERR_HTTP2_PROTOCOL_ERROR
3. Caddy version:
v2.8.4
4. How I installed and ran Caddy:
using railway nixpacks
Configuration File Reference | Nixpacks
# set up some variables to minimize annoyance
[variables]
NPM_CONFIG_UPDATE_NOTIFIER = 'false' # the update notification is relatively useless in a production environment
NPM_CONFIG_FUND = 'false' # the fund notification is also pretty useless in a production environment
NIXPACKS_NODE_VERSION = '20'
# https://github.com/railwayapp/nixpacks/issues/1091
[phases.install]
cmds = ["echo \"$NPM_RC\" > .npmrc", "npm install -g corepack", "corepack enable", "corepack prepare pnpm@9.1.0 --activate", "pnpm i --frozen-lockfile", "pnpm run build"]
# download caddy from nix
[phases.caddy]
dependsOn = ['setup'] # make sure this phase runs after the default 'setup' phase
nixpkgsArchive = 'ba913eda2df8eb72147259189d55932012df6301' # Caddy v2.8.4 - https://github.com/NixOS/nixpkgs/commit/ba913eda2df8eb72147259189d55932012df6301
nixPkgs = ['caddy'] # install caddy as a nix package
# format the Caddyfile with fmt
[phases.fmt]
dependsOn = ['caddy'] # make sure this phase runs after the 'caddy' phase so that we know we have caddy downloaded
cmds = ['caddy fmt --overwrite Caddyfile'] # format the Caddyfile to fix any formatting inconsistencies
# start the caddy web server
[start]
cmd = 'exec caddy run --config Caddyfile --adapter caddyfile 2>&1' # start caddy using the Caddyfile config and caddyfile adapter
a. System environment:
railway with nix
d. My complete Caddy config:
{
debug
admin off # theres no need for the admin api in railway's environment
persist_config off # storage isn't persistent anyway
auto_https off # railway handles https for us, this could in some cases cause issues if left enabled
# runtime logs
log {
format json # set runtime log format to json mode
}
# server options
servers {
trusted_proxies static private_ranges # trust railway's proxy
}
}
(lb_settings) {
lb_policy round_robin
lb_retries 100
lb_try_duration 10s
lb_try_interval 250ms
}
:{$PORT} {
# site block, listens on the $PORT environment variable, automatically assigned by Railway
log {
# access logs
format json # set access log format to JSON mode
}
# health check for Railway
respond /health 200
# Reverse proxy configuration using environment variables
handle_path /api/* {
reverse_proxy {
# for private networking replicas are exposed as multiple dns results, use those dns results as the upstreams
dynamic a {
name {$BACKEND_SERVICE}
port {$BACKEND_PORT}
refresh 1s
dial_timeout 30s
versions ipv4 ipv6
}
# configure load balancing settings
import lb_settings
# sets the Host header to the header to the dynamic name and port options
header_up Host {upstream_hostport}
}
}
# serve from the 'dist' folder (Vite builds into the 'dist' folder)
handle {
root * dist
# enable gzipping responses
encode gzip
# serve files from 'dist'
file_server
# if path doesn't exist, redirect it to 'index.html' for client-side routing
try_files {path} /index.html
}
}