Juanda

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:

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:

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.