How to Deploy a Static Website with Caddy on Railway

A step-by-step guide to deploying a static website with Caddy Server on Railway.

A couple of months ago, I covered the deployment of a static website with NGINX on Railway. We used NGINX for that walk-through which, while powerful, is also a fairly bloated web server, and often an overkill for simple use cases. Enter Caddy.

What is Caddy Server?

Caddy is a powerful yet simple, Go-based open-source web server. Written in a memory-safe language, it compiles to a single, static binary, making it easy to run Caddy practically anywhere, even in containers. Caddy obtains and renews TLS certificates automatically, staples OCSP responses, and even performs automatic HTTPS rewrites. The modular architecture serves a whole host of use cases from simple static file serving (which we will cover today) to more complex use cases like dynamic reverse proxying and handling Kubernetes ingress.

Image source:
Image source:

While Caddy's native config language is JSON, most users prefer the Caddyfile - a simple, human-readable config file which works well for most configurations. Caddy is also dynamically configurable using a RESTful JSON API, making it easy to automate and integrate with your applications.

What is Railway?

Railway is a modern app hosting platform that makes it easy to deploy production-ready apps quickly. Railway offers persistent database services for PostgreSQL, MySQL, MongoDB, and Redis, as well as application services with a Github repository as the deployment source. For the latter, Railway can automatically determine the application runtime and deploy the service. Railway offers several one-click starters for common applications and use cases, but they do not have one for Caddy Server at the moment, so I'll deploy from my GitHub repository instead.


Deploy Your Static Website on Railway

Log into your GitHub account and fork my caddy-on-railway repository. By default, the site/ directory gets deployed as a static site, but you can change this from the Dockerfile. Replace the default index.html and styles.css files with your own and add other files as necessary.

Sign up for an account with Railway using email or GitHub (or log in if you already have an account). If using GitHub, click Authorize Railway App when redirected. Review and agree to Railway's Terms of Service and Fair Use Policy. Click on + New Project > Deploy from GitHub repo, and select your repository.

Deploy a new Railway project
Deploy a new Railway project

The deployment will kick off immediately and complete with a Webserver detected message. You need to do two things:

  1. From the Settings tab, click Enable next to the domain name to expose the service to the internet.
  2. From the Variables tab, add a New Variable called PORT with the value 80, and click Add.

Railway will trigger a redeployment shortly. Wait a few seconds - if you click the URL before the service is ready, you may see errors. Once ready, your static website will be available at the domain.

Caddy static website deployed on Railway
Caddy static website deployed on Railway

Railway handles certificate management in this scenario, and we do not need Caddy to repeat it. By excluding hostnames or IP addresses in the Caddyfile, we have already prevented automatic HTTPS activation in Caddy. We can also disable it explicitly by adding auto_https off in the Caddyfile. This will, however, be important when running Caddy in a non-managed environment like DigitalOcean.

Configure a Custom Domain (Optional)

I covered this at length in my previous post - see the final section here.

One-Click Deployment

Finally, if you prefer a one-click deployment, simply click this button.

Deploy on Railway

Assuming you have already connected to GitHub, you'll get a service deployment prompt like this - click Deploy and you are done.

Caddy on Railway deployment template
Caddy on Railway deployment template

Subscribe to alphasec

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.