Setting Up Local HTTPS Development with Caddy and Rails
Modern web development often requires HTTPS even in local environments to properly test features like service workers, secure cookies, or third-party integrations. This guide shows you how to set up automatic HTTPS for your Rails application using Caddy as a reverse proxy.
Step 1: Configure Local Domain Resolution
First, we need to tell your system to resolve a custom domain to your local machine by editing the /etc/hosts
file:
# /etc/hosts
127.0.0.1 my-app.local
The hosts file acts as a local DNS override, directing requests for my-app.local
to your localhost (127.0.0.1). This allows you to use a proper domain name instead of localhost
, which is necessary for proper SSL certificate generation and makes your development environment more closely mirror production.
Step 2: Create Caddy Configuration
Create a Caddyfile
at your project root to configure the reverse proxy:
# Caddyfile
my-app.local {
tls internal
reverse_proxy localhost:3000
}
Why this configuration works:
my-app.local
tells Caddy to handle requests for this domaintls internal
automatically generates a self-signed certificate for HTTPSreverse_proxy localhost:3000
forwards all requests to your Rails server running on port 3000
This setup means Caddy will handle SSL termination and pass clean HTTP requests to your Rails application.
Step 3: Update the Procfile
Modify your Procfile.dev
to include Caddy:
web: bin/rails server
css: bin/rails tailwindcss:watch
caddy: caddy run
This ensures Caddy starts automatically alongside your Rails server when you run bin/dev
(or your preferred process manager). Having all services start together creates a development experience where HTTPS is always available.
Step 4: Configure Rails Host Verification
Update your Rails application configuration to accept requests from your custom domain:
# config/application.rb
module MyApp
class Application < Rails::Application
# ... rest of the application.rb
config.hosts << ENV.fetch("APP_HOST")
end
end
Why Rails needs this: Rails includes host header verification as a security feature to prevent DNS rebinding attacks. Since we're using a custom domain (my-app.local
) instead of localhost
, we need to explicitly allow it. Using an environment variable keeps this configuration flexible across different environments.
Step 5: Install Caddy and Set Environment Variables
Use mise (or your preferred tool manager) to install Caddy and configure the environment:
# mise.toml at the application root
[env]
APP_HOST = 'my-app.local'
[tools]
ruby = '3.4.3'
node = 'latest'
caddy = 'latest'
Why use mise for this setup:
- Tool management: Automatically installs and manages the correct version of Caddy for your project
- Environment consistency: The
APP_HOST
environment variable ensures your Rails configuration matches your Caddy setup - Team coordination: Team members get the same tools and configuration when they run
mise install
The Result
After completing these steps, you'll be able to access your Rails application at https://my-app.local
with a valid SSL certificate. Your browser may show a security warning for the self-signed certificate, but you can safely proceed for development purposes.
This setup provides a production-like HTTPS environment that's essential for testing modern web features while maintaining the simplicity of local development.