Local HTTPS
Serve local apps over trusted HTTPS, configure hostnames, and manage device trust and certificate renewal.
Local HTTPS gives your development site a browser-trusted HTTPS URL. LPM CLI handles TLS in front of your application.
Your application continues to use plain HTTP. Use local HTTPS for secure cookies, OAuth callbacks, service workers, secure WebSockets, and browser features that require a trusted origin.
The trust applies only to devices that trust your local certificate authority (CA).
# Enable HTTPS for this run
lpm dev --https
# Prepare trust before a development run
lpm cert trustHow local HTTPS works
LPM CLI accepts the HTTPS or secure WebSocket connection. It sends the request to your application over plain HTTP or WebSocket.
Browser HTTPS/WSS → LPM CLI → Application HTTP/WSLPM CLI creates a local root CA in your user profile. This CA signs the certificates for your projects.
Local root CA → Project certificate → Browser trustEach user profile generates its own root key. LPM CLI does not ship or download a shared root key.
If you run lpm dev --https --port 4000, the browser connects to port 4000. LPM CLI gives the application a separate managed port.
Your application must use plain HTTP in this workflow. Disable framework HTTPS and let LPM CLI manage TLS.
Choose a workflow
| Goal | Configuration or command |
|---|---|
| Use HTTPS for the project | "https": true in lpm.json |
| Use HTTPS for one run | lpm dev --https |
| Disable the direct HTTPS frontend for one run | lpm dev --no-https |
| Prepare trust before development | lpm cert trust |
Enable HTTPS in lpm.json
Add https: true to the lpm.json file next to package.json:
{
"$schema": "https://cli.lpm.dev/schemas/lpm.json",
"https": true
}Start the project:
lpm devLPM CLI prepares the project certificate and starts the HTTPS frontend. Certificate renewal occurs during setup, when the certificate is within 30 days of expiry.
Use a command-line override for one run:
lpm dev --https # enable HTTPS for this run
lpm dev --no-https # disable the direct HTTPS frontend--no-https does not disable named-host proxy routes. A configured proxy.host or service hostname still requires certificates and local trust.
Approve the local CA
The first HTTPS run can require approval to install the local CA. LPM CLI asks only when the trust-store installation is necessary.
Approve the installation in an interactive terminal. If you decline, LPM CLI stops the HTTPS development run.
For an approved non-interactive run, use --yes:
lpm dev --https --yesIf lpm.json enables HTTPS, use this command:
lpm dev --yesYou can also prepare the machine before a development run:
lpm cert trust
lpm devTo remove the CA from the trust store, run:
lpm cert uninstallThis command keeps the CA files on disk. Stop runtimes that serve this CA before uninstall. You can trust the same CA again with lpm cert trust.
Use project hostnames
If one local service needs a project hostname, use proxy.host:
{
"https": true,
"proxy": {
"host": "app.localhost",
"port": 9443,
"httpRedirect": false
}
}lpm devOpen the HTTPS URL that lpm dev prints. For a project with multiple services, give each service a different services.<name>.host value.
Names below .localhost usually need no hosts-file entry. Names below these suffixes can require a managed hosts-file entry:
.local.test.internal.home.arpa
See lpm proxy and lpm hosts for local routing and hosts-file management.
You can add a certificate hostname manually:
lpm cert generate --host api.app.localThis command adds a certificate name. It does not create a proxy route or a hosts-file entry.
Permit more DNS names
The cert block controls the DNS subtrees that a project certificate can cover:
{
"https": true,
"cert": {
"extraPermittedDns": ["myapp.internal"],
"allowPublicDns": false
}
}extraPermittedDns expands the permitted DNS subtrees. It does not add a certificate hostname, browser URL, proxy route, or hosts-file entry.
Add the actual browser hostname with one of these options:
proxy.hostservices.<name>.hostlpm cert generate --host
Public DNS names require an explicit opt-in:
{
"cert": {
"extraPermittedDns": ["staging.example.com"],
"allowPublicDns": true
}
}CAUTION: Enable
allowPublicDnsonly for DNS names that you control. This field expands the permitted names in the project certificate chain.
Existing root restrictions
LPM_CERT_NAME_CONSTRAINTS=1 creates a root restricted to local DNS names and private IP ranges. The restriction applies at root creation or rotation.
That root permits localhost, subdomains of .localhost, .local, and .test, plus loopback, private, and link-local IP ranges. It does not permit .internal, .home.arpa, or public DNS names.
The permitted IP ranges are 127.0.0.0/8, ::1/128, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, fc00::/7, and fe80::/10.
Project configuration cannot expand an existing root's authority. LPM CLI rejects certificate issuance and TLS publication when a requested name is outside those restrictions.
Use a permitted hostname such as app.test. If you need a different root policy, review it before an explicit CA rotation.
Protect the local CA
The local root CA belongs to the user profile that created it. Other profiles or devices can have different root CAs.
Anyone with the root CA private key can create certificates that your machine trusts. Do not copy or commit this key.
On Unix systems, certificate directories must use mode 0700. Private keys must use mode 0600.
LPM CLI refuses to sign with a group-readable or world-readable CA private key. Run lpm cert status to get the repair command.
Project certificates for custom hostnames use a constrained project chain. The requested DNS permissions limit that project chain.
Platform and browser behavior
| Platform | Trust-store behavior |
|---|---|
| macOS | LPM CLI uses the user login Keychain. The operation does not require sudo. |
| Linux | Supported system CA stores require elevated privileges. Non-root users use sudo. |
| Windows | LPM CLI uses the Root certificate store. Windows can request UAC approval. |
Automatic Linux installation supports update-ca-certificates and update-ca-trust layouts. Other layouts require manual CA installation.
Chrome, Edge, Safari, and many Linux browsers use the operating-system trust store.
Firefox can use a separate trust store. If Firefox shows a warning, use one of these options:
- Set
security.enterprise_roots.enabledtotrueinabout:config. - Import
~/.lpm/certs/rootCA.pemas a certificate authority in Firefox.
Use HTTPS on another device
A phone or another computer must trust your local CA before it accepts the project certificate.
Start a network development server with CA bootstrap enabled:
lpm dev --https --network --allow-ca-bootstrapLPM CLI prints a plain HTTP URL for CA installation. Open that URL on the other device, then install and trust the CA.
CA bootstrap is off by default. The operating system selects its LAN port.
CAUTION: Anyone on the local network can download the CA certificate while the bootstrap server runs. The private key does not leave your machine.
Without CA bootstrap, copy ~/.lpm/certs/rootCA.pem to the device through a trusted method. Then install and trust the certificate manually.
Certificate files
| Scope | Files |
|---|---|
| User profile | ~/.lpm/certs/rootCA.pem and ~/.lpm/certs/rootCA-key.pem. With LPM_HOME set, certs/ is under that directory. |
| Project | <project>/.lpm/certs/cert.pem and the private key <project>/.lpm/certs/key.pem |
The project's .lpm/ directory keeps itself out of Git through .lpm/.gitignore, so the project certificate and its private key are never committed. You don't need a .gitignore entry. If an earlier checkout committed .lpm/, lpm doctor --all reports project_state_tracked with the git rm --cached command that untracks it. Run it and commit. See Files LPM CLI creates.
The default project certificate contains these names:
localhost127.0.0.1::1
Renewal and rotation
LPM CLI creates a new project certificate in these cases:
- The certificate is missing.
- The certificate expires soon.
- The certificate does not contain a requested hostname.
- The certificate is not compatible with the active CA.
On the next HTTPS setup within 30 days of expiry, LPM CLI renews the project certificate. An active frontend retains its loaded certificate.
Root CA warnings start within 60 days and become urgent within 30 days.
LPM CLI never rotates the root CA automatically because rotation changes local trust.
If the root needs replacement, stop active TLS runtimes and rotate it:
lpm cert rotateIf rotation stops before it is complete, reconcile its state:
lpm cert reconcile --dry-run
lpm cert reconcileThe reconcile command also removes expired grace entries. Destructive trust changes stop while a runtime still serves the affected CA generation.
For a transition that retains the previous CA temporarily, see grace rotation.
Common problems
The browser shows a certificate warning
Show the trust and certificate status:
lpm cert statusIf the CA is not trusted, install it:
lpm cert trustIf only Firefox shows the warning, configure Firefox to use the operating-system trust store or import the CA.
The browser reports a hostname mismatch
Make sure that the URL hostname is in the project certificate. Add it with proxy.host, services.<name>.host, or lpm cert generate --host.
extraPermittedDns is not a certificate hostname. It only permits certificates below the configured DNS subtree.
LPM CLI reports unsafe permissions
Run lpm cert status. Then run the exact permission-repair command from its output.
The root CA expires soon
Run lpm cert rotate. LPM CLI replaces the CA and reissues the known project certificates.
Root CA rotation stopped
Stop the runtime named in the error. Preview the repair with lpm cert reconcile --dry-run. Then run lpm cert reconcile.
Another device does not trust the site
Install and trust rootCA.pem on that device. Use CA bootstrap or copy the certificate through a trusted method.
Local HTTPS or a tunnel?
If the site stays on your computer or local network, use local HTTPS. Each client device must trust your local CA.
If a remote person or service needs a public URL, use a tunnel.