HTTPS on Localhost with Next.js
Ben Burkert
Posted on April 29, 2024
Next.js is a popular framework for building web applications with great development support and tooling. However, its local development story has a plot hole: HTTPS support. While the next dev command has a --experimental-https
flag to enable HTTPS locally, it’s rather limited.
Anchor’s new lcl.host service fills this hole and even works with Docker containers. This article will explain what lcl.host is, how it compares to Next.js’ experimental HTTPS flag, and how to configure your Next.js application to work with lcl.host.
What is lcl.host?
lcl.host is an easy way to enable HTTPS in local development environments, which improves the security of the development process, ensures feature parity between development and production environments, and enables features like CORS that behave differently on localhost.
There are multiple ways to use HTTPS on a local machine. You need to get a certificate for your server, renew it when it expires, and ensure your clients trust the CA that issued that certificate. If you get a certificate from a public CA, your clients automatically trust it, but your development server must be public, too. If you set up a local CA, your server can be private, but your clients need updates to trust your CA.
lcl.host takes care of all this for you by providing a CA for development, ensuring your browsers and clients trust this CA, issuing certificates for your apps, and renewing them when they expire.
What are the Benefits of Using lcl.host over Next.js’ Experimental HTTPS Flag?
Next.js offers an experimental flag that enables HTTPS locally. While lcl.host requires a bit more setup, it also brings several benefits over the flag.
lcl.host Works With All Next.js Commands
To use the experimental HTTPS support, add the --experimental-https
flag every time you run next dev
command.
With lcl.host you can use all next
commands without a flag, and HTTPS works transparently with them.
lcl.host Works With HTTP and HTTPS
While the experimental HTTPS flag only listens on HTTPS, lcl.host allows using HTTP and HTTPS simultaneously, so you can switch without restarting your server.
lcl.host Works With Docker Containers
The experimental HTTPS flag relies on mkcert
, designed for a single development system. If you run a Docker container, the flag won’t configure your local browser to trust its certificate.
lcl.host configures your browser on your system to trust the certificates in all containers you run locally.
lcl.host Works With Subdomains
Experimental HTTPS only works with localhost
; if you have multiple applications, they all run on localhost
with different ports. lcl.host doesn’t limit you to https://localhost:<PORT>/
; you can use any subdomain of lcl.host
, allowing you to run multiple apps simultaneously.
lcl.host Renews Certificates Automatically
Experimental HTTPS might not take expired certificates into account.
lcl.host handles automatic certificate renewal for you.
lcl.host Integrates With the Experimental HTTPS Flag
The experimental HTTPS flag works with existing certificates to import the certificates generated by lcl.host with the --experimental-https-key
and --experimental-https-cert
flags.
How to Use lcl.host in a Next.js Project?
Now that you understand what lcl.host can do for you, the next step is to see how to integrate it with a Next.js app.
Prerequisites
1. Installing the Anchor CLI
First, you must install the Anchor CLI; this will handle the lcl.host setup for your project.
With Homebrew (MacOS and Linux):
brew install anchordotdev/tap/anchor
With Chocolatey (Windows):
choco install anchor --version=0.0.22
Build from source with Go:
go install github.com/anchordotdev/cli/cmd/anchor@latest
2. Using Anchor’s Next.js Starter Template
For a new project, you can use the Next.js-lcl.host starter template provided by Anchor. It comes preinstalled with dependencies for automatic certificate renewal and an update next.config.mjs
file.
You can clone it from GitHub with this command:
git clone https://github.com/anchordotdev/nextjs-lclhost-starter.git
Using this template, you can skip to step 5.
3. Installing Dependencies
For the automatic certificate renewal, you need the latest anchor-pki package. Install it as a development dependency with the following command:
npm i anchor-pki -D
lcl.host works without this package, but when your certificates expire you must manually renew them.
4. Updating the Next.js Configuration
Now, you must tell Next.js to use the anchor-pki package every time you run your app. To do so, update the content of your next.config.mjs
file:
import autoCert from "anchor-pki/auto-cert/integrations/next"
const withAutoCert = autoCert({enabledEnv: "development"})
const nextConfig = {
// Your configurations
}
export default withAutoCert(nextConfig)
You can configure your Next.js app as usual; just ensure the config object is wrapped in the withAutoCert()
call before exporting it.
5. Connecting the Project with lcl.host
To make your project available via lcl.host, open the project directory in a shell and run the following command:
anchor lcl
After the command completes, you should see a URL to a guide for the automatic renewal:
| Next Steps
| Now that you have local HTTPS setup, let's automate certificate provisioning
| so you never have to manually provision future certificates again.
|
| We've generated an Anchor.dev setup guide for your application with
| instructions for automating certificate provisioning inside your
application.
- Opened https://anchor.dev/<ACCOUNT>/services/<APP_NAME>/guide.
Open this guide in your browser, then skip to the second step, as we already performed the first two here.
Click the “Generate new tokens” button, as seen in Figure 1, and copy the tokens and other environment variables into a new .env.local
file.
The content of the env file should look similar to this:
ACME_KID=aae…zWD
ACME_HMAC_KEY=72D…dMr
ACME_DIRECTORY_URL='https://anchor.dev/<ACCOUNT>/localhost/x509/ca/acme'
ACME_CONTACT="<ACCOUNT_EMAIL>+${ACME_KID}"
ACME_ALLOW_IDENTIFIERS="<APP_NAME>.lcl.host,<APP_NAME>.localhost"
HTTPS_PORT='<RANDOM_PORT>'
Next.js will use the .env.local
file to set up environment variables before starting the web server.
6. Testing the Project
Finally, to test the whole setup, you can start the development server with this command:
npm run dev
If everything goes well, you should get an output similar to this:
[AutoCert] Starting auto-cert proxy ...
[anchor-pki] The 'sni-callback' Configuration instance is enabled
[AutoCert] Listening on https://<APP_NAME>.lcl.host:44356 -> http://127.0.0.1:3000
[AutoCert] Listening on https://<APP_NAME>.localhost:44356 -> http://127.0.0.1:3000
[anchor-pki] No Terms of Service exist so agreed : true
[anchor-pki] No Terms of Service exist so agreed : true
[anchor-pki] Certificate for <APP_NAME>.lcl.host provisioned.
[anchor-pki] Certificate for <APP_NAME>.lcl.host cached in (tmp/acme).
As the output tells, you can now access your app via two HTTPS-enabled URLs.
If you get this error instead, it indicates a missing or incomplete .env.local
file:
[AutoCert] HTTPS_PORT is not set, assuming 4333
/path/to/your/project/node_modules/anchor-pki/src/auto-cert/configuration.js:185
Return to step 5 and double-check you didn’t miss any environment variables.
Summary
Next.js has a nifty HTTPS feature, which is nice for quickly testing an app on your local machine. However, its tricky to use with Docker or multiple applications.
lcl.host is a complete solution for HTTPS-enabled development environments. It handles automatic certificate renewal and works transparently with several setups, including Docker, multiple local applications, and all Next.js commands.
Resources
Posted on April 29, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.