Soft fork for a caddy reverse template for railway

Initial commit

+89
+31
Caddyfile
··· 1 + { # global options 2 + admin off # theres no need for the admin api in railway's environment 3 + persist_config off # storage isn't persistent anyway 4 + auto_https off # railway handles https for us, this would cause issues if left enabled 5 + log { # runtime logs 6 + format console # set runtime log format to console mode 7 + } 8 + servers { # server options 9 + trusted_proxies static private_ranges # trust railway's proxy 10 + } 11 + } 12 + 13 + :{$PORT} { # site block, listens on the $PORT environment variable, automatically assigned by railway 14 + log { # access logs 15 + format console # set access log format to console mode 16 + } 17 + 18 + reverse_proxy {$FRONTEND_HOST} # proxy all requests for /* to the frontend, configure this variable in the service settings 19 + 20 + # the handle_path directive will strip /api/ from the path before proxying 21 + # this is needed if your backend's api routes don't start with /api/ 22 + # change paths as needed 23 + handle_path /api/* { # this strips the /api/ prefix from the uri sent to the proxy address 24 + reverse_proxy {$BACKEND_HOST} # proxy all requests for /api/* to the backend, configure this variable in the service settings 25 + } 26 + 27 + # if your backend's api routes do start with /api/ then you wouldn't want to strip the path prefix 28 + # if so, comment out the above handle_path block, and uncomment this reverse_proxy directive 29 + # change paths as needed 30 + # reverse_proxy {$BACKEND_HOST} # configure this variable in the service settings 31 + }
+7
Dockerfile
··· 1 + FROM caddy:2.7.4-alpine 2 + 3 + COPY Caddyfile /etc/caddy/Caddyfile 4 + 5 + RUN caddy fmt --overwrite /etc/caddy/Caddyfile 6 + 7 + CMD caddy run --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1
+51
README.md
··· 1 + # [Caddy](https://caddyserver.com/) Frontend & Backend Reverse Proxy 2 + 3 + **Combine your **separate** frontend and backend services into one domain!** 4 + 5 + ### [View the example public project here](https://railway.app/project/35d8d571-4313-4049-9699-4e7db7f02a2f) 6 + 7 + Access the frontend from `/*` and access the backend from `/api/*` on the same domain 8 + 9 + **Frontend - Vue 3:** https://mysite.up.railway.app/ 10 + 11 + **Backend - Go Mux:** https://mysite.up.railway.app/api/ 12 + 13 + The proxy configurations are done in the [`Caddyfile`](https://github.com/brody192/reverse-proxy/blob/main/Caddyfile) everything is commented for your ease of use! 14 + 15 + When deploying your Reverse Proxy service it will require you to set two service variables: **FRONTEND_HOST** and **BACKEND_HOST** 16 + 17 + **Note:** You will first need to have set a fixed `PORT` variable in both the frontend and backend services before deploying this template 18 + 19 + These are the two template variables that you will be required to fill out during the first deployment of this service, replace the respective `<frontend service name>` and `<backend service name>` with the service names as they appear in the Railway project view 20 + 21 + ``` 22 + FRONTEND_HOST = ${{<frontend service name>.RAILWAY_PRIVATE_DOMAIN}}:${{<frontend service name>.PORT}} 23 + BACKEND_HOST = ${{<backend service name>.RAILWAY_PRIVATE_DOMAIN}}:${{<backend service name>.PORT}} 24 + ``` 25 + 26 + **Relevant Caddy documentation:** 27 + 28 + - [The Caddyfile](https://caddyserver.com/docs/caddyfile) 29 + - [Caddyfile Directives](https://caddyserver.com/docs/caddyfile/directives) 30 + - [reverse_proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) 31 + 32 + **Some prerequisites to help with common issues that could arise:** 33 + 34 + - Both the frontend and backend need to listen on fixed ports, in my Caddyfile I have used port `3000` in the proxy address, and configured my frontend and backend to both listen on port `3000` 35 + - This can be done by [configuring your frontend and backend apps to listen on the `$PORT`](https://docs.railway.app/troubleshoot/fixing-common-errors) environment variable, then setting a `PORT` service variable to `3000` 36 + 37 + - Since Railway's internal network is IPv6 only the frontend and backend apps will need to listen on `::` (all interfaces - both IPv4 and IPv6) 38 + 39 + **Start commands for some popular frameworks:** 40 + 41 + - **Gunicorn:** `gunicorn main:app -b [::]:$PORT` 42 + 43 + - **Uvicorn:** `uvicorn main:app --host :: --port $PORT` 44 + 45 + - Uvicorn does not support dual stack binding (IPv6 and IPv4) from the CLI, so while that start command will work to enable access from within the private network, this prevents you from accessing the app from the public domain if needed, I recommend using [Hypercorn](https://pgjones.gitlab.io/hypercorn/) instead 46 + 47 + - **Hypercorn:** `hypercorn main:app --bind [::]:$PORT` 48 + 49 + - **Next:** `next start -H :: --port $PORT` 50 + 51 + - **Express/Nest:** `app.listen(process.env.PORT, "::");`