Overview
Portless supports HTTP/2 over TLS (HTTPS) to significantly speed up dev servers that serve many unbundled files. Browsers limit HTTP/1.1 to 6 connections per host, which bottlenecks dev servers like Vite, Nuxt, and others. HTTP/2 multiplexes all requests over a single connection, eliminating this bottleneck. Portless automatically generates and manages TLS certificates using a local Certificate Authority (CA), and can trust them in your system keychain on first run.Quick Start
Start proxy with HTTPS
How It Works
When you start the proxy with--https, portless:
- Generates a local CA - Creates an elliptic curve (prime256v1) private key and self-signed CA certificate valid for 10 years
- Generates server certificates - Creates certificates signed by the CA for
localhostand*.localhost(valid for 1 year) - Starts an HTTP/2 server - Uses Node.js
http2.createSecureServerwith HTTP/1.1 fallback for WebSocket support - Handles SNI - Generates per-hostname certificates on-demand for subdomains
Portless uses Server Name Indication (SNI) to generate certificates on-demand. Each subdomain (like
myapp.localhost, api.myapp.localhost) gets its own certificate because *.localhost sits at the public-suffix boundary and TLS specs don’t permit wildcard certificates there (RFC 2606 §2).Certificate Management
Automatic Generation
Certificates are stored in your state directory:- Port < 1024 (sudo mode):
/tmp/portless/ - Port >= 1024 (user mode):
~/.portless/
Automatic Renewal
Portless checks certificate validity on startup and automatically regenerates:- Expired certificates
- Certificates expiring within 7 days
- Certificates using weak signatures (SHA-1)
Trusting the CA
If you skipped the sudo prompt on first run, trust the CA later:Supported Linux Distributions
| Distribution | CA Directory | Update Command |
|---|---|---|
| Debian/Ubuntu | /usr/local/share/ca-certificates | update-ca-certificates |
| Arch | /etc/ca-certificates/trust-source/anchors | update-ca-trust |
| Fedora/RHEL/CentOS | /etc/pki/ca-trust/source/anchors | update-ca-trust |
| openSUSE | /etc/pki/trust/anchors | update-ca-certificates |
Configuration
Using Environment Variables
Make HTTPS permanent by setting an environment variable:Disabling HTTPS
IfPORTLESS_HTTPS is set but you want to disable it for a specific session:
Using Custom Certificates
If you already have certificates (e.g., from mkcert):Using
--cert and --key automatically implies --https. You don’t need to specify both.Real-World Examples
Development Workflow
Port 443 (No Port in URL)
Run on the standard HTTPS port to eliminate the port number from URLs:Mixed HTTP/HTTPS
The proxy supports both HTTP and HTTPS connections simultaneously when started with--https. It inspects the first byte of each connection:
- 0x16 (TLS ClientHello) → routes to HTTP/2 server
- Other → routes to HTTP/1.1 server
Environment Variables
Portless injects these variables into child processes:Troubleshooting
Browser Shows Certificate Warning
The CA isn’t trusted yet. Run:Permission Denied on Linux
Make sure you’re running with sudo:Safari Not Loading HTTPS
Safari relies on the system DNS resolver. If you see certificate errors:-
Trust the CA:
-
Add routes to
/etc/hosts:
Certificate Expired
Portless automatically regenerates expired certificates on startup. If you see an expired certificate:-
Stop the proxy:
-
Start with HTTPS:
- CA: 10 years
- Server certs: 1 year
- Auto-renewal: 7 days before expiry
OpenSSL Not Found
Portless requiresopenssl to generate certificates. It ships with macOS and most Linux distributions. If it’s missing:
Technical Details
Certificate Specifications
CA Certificate:- Algorithm: ECDSA with prime256v1 curve
- Signature: SHA-256
- Validity: 10 years
- Extensions:
basicConstraints=critical,CA:TRUEkeyUsage=critical,keyCertSign,cRLSign
- Algorithm: ECDSA with prime256v1 curve
- Signature: SHA-256
- Validity: 1 year
- Extensions:
basicConstraints=CA:FALSEkeyUsage=digitalSignature,keyEnciphermentextendedKeyUsage=serverAuthsubjectAltName=DNS:localhost,DNS:*.localhost(default cert)- Per-hostname certs include exact SAN + wildcard for same level
SNI (Server Name Indication)
For each subdomain, portless generates a certificate with:- The exact hostname (e.g.,
chat.myapp.localhost) - A wildcard for siblings at the same level (e.g.,
*.myapp.localhost)
HTTP/2 + HTTP/1.1 Fallback
Portless useshttp2.createSecureServer with allowHTTP1: true, which:
- Enables HTTP/2 multiplexing for regular requests
- Falls back to HTTP/1.1 for WebSocket upgrades
- Strips hop-by-hop headers (Connection, Transfer-Encoding, etc.) when proxying to HTTP/1.1 backends