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
.localhostdomains work seamlessly. - The
.localhosttop-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
| |
Debian/Ubuntu
| |
Fedora/RHEL
| |
macOS
| |
Windows
| |
Verify Installation
Check that Caddy is installed correctly:
| |
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):
| |
This configuration proxies https://hugo.localhost → http://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:
| |
Run Caddy
In the same directory as your Caddyfile:
| |
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 --trustBecause 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
| |
Run the Global Configuration
| |
This runs Caddy in the background, allowing you to access all your projects through clean HTTPS URLs.
Managing the Global Setup
Start Caddy:
| |
Stop Caddy:
| |
Reload Configuration (after making changes):
| |
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):
| |
Reload your shell configuration:
| |
Windows (PowerShell)
Add these functions to your PowerShell profile. First, find your profile location:
| |
Then edit that file and add:
| |
Restart PowerShell or run:
| |
Development Workflow
With your global Caddyfile running, your typical development workflow becomes:
- Start Caddy (once):
caddy-dev-start - Start your development server on its usual port
- Access via HTTPS: Visit
https://yourproject.localhost - Develop normally with full HTTPS functionality
When you’re done:
| |
Troubleshooting
Port Already in Use
If you get a “port already in use” error, check what’s running:
| |
Certificate Issues
Caddy automatically generates certificates, but if you have issues:
Clear Caddy’s data directory:
- macOS/Linux:
rm -rf ~/.local/share/caddy - Windows: Delete
%APPDATA%\Caddy
- macOS/Linux:
Restart Caddy
Configuration Errors
Test your Caddyfile syntax:
| |
Advanced Configuration
Custom Headers
| |
Path-Based Routing
| |
Static File Serving
| |
Security Notes
- The certificates Caddy generates are self-signed and only trusted locally
- Never use these certificates in production
- The
.localhostdomain 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:
- Original inspiration: Deepak’s concise notes
- Video demonstration: Wes Bos’s 1-minute video
- Community discovery: @ImSh4yy’s tweet
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.