HTTPS on Localhost with Next.js

benburkert

Ben Burkert

Posted on April 29, 2024

HTTPS on Localhost with Next.js

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)
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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.

generate-new-tokens-button

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>'
Enter fullscreen mode Exit fullscreen mode

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).
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
benburkert
Ben Burkert

Posted on April 29, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related