Modern web applications increasingly rely on HTTPS for security and functionality. Features like service workers, WebAuthn, geolocation, and SameSite cookies all require a secure origin to function properly.

If your local development environment only runs on http://localhost, you’ll miss out on testing these critical features during development. This can lead to unexpected issues when deploying to production.

In this tutorial, we’re going to use Caddy — a developer-friendly web server that makes HTTPS on localhost as simple as writing a few lines in a configuration file. Caddy automatically handles certificate generation and management, making it perfect for local development.

Why Use .localhost Domains?

  • Before diving in, it’s worth understanding why .localhost domains work seamlessly.
  • The .localhost top-level domain is reserved by RFC 6761 and always resolves to your local machine (127.0.0.1).
  • This means api.localhost, hugo.localhost, or any subdomain you create will automatically point to your development machine without any DNS configuration.

Install Caddy

Linux

Arch Linux

1
sudo pacman -Syu caddy

Debian/Ubuntu

1
2
3
4
5
6
7
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Fedora/RHEL

1
2
3
sudo dnf install 'dnf-command(copr)'
sudo dnf copr enable @caddy/caddy
sudo dnf install caddy

macOS

1
brew install caddy

Windows

1
winget install CaddyServer.Caddy

Verify Installation

Check that Caddy is installed correctly:

1
caddy version

You should see output showing the Caddy version and build information.

Configuration Options

You have two main approaches depending on your workflow:

Option 1: Single Project Setup

If you’re working on one project at a time, you can create a project-specific Caddyfile.

Create a Caddyfile

In your project directory, create a file named Caddyfile (no extension):

1
2
3
hugo.localhost {
    reverse_proxy localhost:1313
}

This configuration proxies https://hugo.localhosthttp://localhost:1313 (your Hugo development server).

Start Your Development Server

When running Hugo (or any development server), you need to configure it to work with your custom domain:

1
hugo server --baseURL="https://hugo.localhost" --appendPort=false

Run Caddy

In the same directory as your Caddyfile:

1
caddy run

Now you can access your Hugo site at https://hugo.localhost with a valid SSL certificate!

Why not use Hugo’s built-in –trust flag?

hugo server --trust

Because it only provides SSL on localhost:1313 and doesn’t allow custom domains or work across multiple frameworks.

Option 2: Global Multi-Project Setup

For developers juggling multiple projects, a global Caddyfile is more efficient.

Create a Global Caddyfile

Create a Caddyfile in your home directory:

  • macOS/Linux: ~/Caddyfile
  • Windows: C:\Users\<username>\Caddyfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# API Development Server
api.localhost {
    reverse_proxy localhost:5000
}

# Astro Development Server
astro.localhost {
    reverse_proxy localhost:4321
}

# VS Code Live Server (Live Server Extension)
code.localhost {
    reverse_proxy localhost:5500
}

# Hugo Development Server
hugo.localhost {
    reverse_proxy localhost:1313
}

# Next.js Development Server
nextjs.localhost {
    reverse_proxy localhost:3000
}

# Zola Development Server
zola.localhost {
    reverse_proxy localhost:1111
}

# Custom Port Example
custom.localhost {
    reverse_proxy localhost:1337
}

Run the Global Configuration

1
caddy start --config ~/Caddyfile

This runs Caddy in the background, allowing you to access all your projects through clean HTTPS URLs.

Managing the Global Setup

Start Caddy:

1
caddy start --config ~/Caddyfile

Stop Caddy:

1
caddy stop

Reload Configuration (after making changes):

1
caddy reload --config ~/Caddyfile

Optional: Create Convenient Aliases

To make management easier, you can create shell aliases:

macOS/Linux (Bash/Zsh)

Add these to your shell configuration file (~/.zshrc, ~/.bashrc, or ~/.profile):

1
2
3
alias caddy-dev-start="caddy start --config ~/Caddyfile"
alias caddy-dev-stop="caddy stop"
alias caddy-dev-reload="caddy reload --config ~/Caddyfile"

Reload your shell configuration:

1
source ~/.zshrc   # or your shell config file

Windows (PowerShell)

Add these functions to your PowerShell profile. First, find your profile location:

1
echo $PROFILE

Then edit that file and add:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function Start-CaddyDev {
    caddy start --config "$env:USERPROFILE\Caddyfile"
}

function Stop-CaddyDev {
    caddy stop
}

function Reload-CaddyDev {
    caddy reload --config "$env:USERPROFILE\Caddyfile"
}

# Create aliases
Set-Alias caddy-dev-start Start-CaddyDev
Set-Alias caddy-dev-stop Stop-CaddyDev
Set-Alias caddy-dev-reload Reload-CaddyDev

Restart PowerShell or run:

1
. $PROFILE

Development Workflow

With your global Caddyfile running, your typical development workflow becomes:

  1. Start Caddy (once): caddy-dev-start
  2. Start your development server on its usual port
  3. Access via HTTPS: Visit https://yourproject.localhost
  4. Develop normally with full HTTPS functionality

When you’re done:

1
caddy-dev-stop

Troubleshooting

Port Already in Use

If you get a “port already in use” error, check what’s running:

1
2
3
4
5
6
7
# macOS/Linux
lsof -i :80
lsof -i :443

# Windows
netstat -ano | findstr :80
netstat -ano | findstr :443

Certificate Issues

Caddy automatically generates certificates, but if you have issues:

  1. Clear Caddy’s data directory:

    • macOS/Linux: rm -rf ~/.local/share/caddy
    • Windows: Delete %APPDATA%\Caddy
  2. Restart Caddy

Configuration Errors

Test your Caddyfile syntax:

1
caddy validate --config ~/Caddyfile

Advanced Configuration

Custom Headers

1
2
3
4
5
6
7
api.localhost {
    reverse_proxy localhost:5000
    header {
        Access-Control-Allow-Origin *
        X-Custom-Header "Development"
    }
}

Path-Based Routing

1
2
3
4
5
6
7
dev.localhost {
    # Route /api/* to backend server
    reverse_proxy /api/* localhost:5000

    # Route everything else to frontend
    reverse_proxy localhost:3000
}

Static File Serving

1
2
3
4
static.localhost {
    root * /path/to/your/static/files
    file_server
}

Security Notes

  • The certificates Caddy generates are self-signed and only trusted locally
  • Never use these certificates in production
  • The .localhost domain only resolves locally and won’t work for external access

Benefits

Test HTTPS-only features like service workers and secure cookies
Clean URLs without port numbers
Automatic certificate management — no manual SSL setup
Multiple projects can run simultaneously
Consistent environment between development and production
No hosts file editing required

Conclusion

Using Caddy for local HTTPS development eliminates the friction of testing secure features during development. With automatic certificate generation and simple configuration, you can focus on building your application instead of wrestling with SSL certificates.

The global multi-project setup is particularly powerful for full-stack developers who regularly switch between different frameworks and tools. Once configured, it provides a seamless HTTPS development environment for all your projects.

Inspiration and Credits

This tutorial builds upon the excellent work of several developers in the community:

The developer community’s willingness to share knowledge makes techniques like this accessible to everyone. This post aims to expand on their work with additional configurations, troubleshooting, and workflow tips.

For more advanced configurations, middleware options, and deployment strategies, check out the comprehensive Caddy Documentation.