1. The problem I’m having:
I am trying to do a reverse proxy to /api/
to an internal service in Railway where it is subservice.local/api
. My current configuration is always going to the index.html for the angular app
2. Error messages and/or full log output:
No error message just not redirecting correctly
3. Caddy version:
2.7
4. How I installed and ran Caddy:
I am using the docker image FROM caddy:2.7
a. System environment:
Docker
b. Command:
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
d. My complete Caddy config:
# global options
{
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 would 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 100.0.0.0/8 # trust railway's proxy
}
}
(lb_settings) {
lb_policy round_robin
lb_retries 100
lb_try_duration 10s
lb_try_interval 250ms
}
(passive_health_checks) {
fail_duration 60s
max_fails 300
unhealthy_latency 5s
unhealthy_request_count 200
}
:{$PORT} {
# access logs
log {
format json # set access log format to json mode
}
# health check for railway
rewrite /health /*
# the handle_path directive WILL strip /api/ from the path before proxying
# use `handle` instead of `handle_path` if you dont want to strip the /api/ path
# this is needed if your backend's api routes don't start with /api/
# change paths as needed
handle_path /api/* {
# the /api/ prefix WILL be stripped from the uri sent to the proxy host
#
# proxy all requests for /api/* to the backend, configure this variable in the service settings
reverse_proxy {
# for private networking replicas are exposed as multiple dns results, use those dns results as the upstreams
dynamic a {
name {$BACKEND_DOMAIN}
port {$BACKEND_PORT}
refresh 1s
dial_timeout 30s
versions ipv4 ipv6
}
# configure load balancing settings
import lb_settings
# configure passive health checks
import passive_health_checks
# 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)
root * /dist
# enable gzipping responses
encode gzip
# serve files from 'dist'
file_server
try_files {path} /index.html @notApi
}
5. Links to relevant resources:
Trying to figure out why handle_path /api/* {
is not working