Trusted HTTPS certificates for localhost. No browser warnings.
- Zero-config HTTPS for local development
- Automatic trust store installation (macOS Keychain, Linux system store, Windows certutil)
- HTTPS reverse proxy with WebSocket support
- Auto-renewal daemon
- Backup and restore certificates
- Team CA sharing
- S/MIME email certificates
- Client authentication certificates
brew tap jayashankarvr/devssl
brew install devsslgit clone https://github.com/jayashankarvr/devssl.git
cd devssl
cargo install --path .Download from GitHub Releases.
devssl init# Initial setup (creates CA, adds to trust store, generates localhost cert)
devssl init
# Generate cert for custom domains
devssl generate myapp.local api.myapp.local
# HTTPS proxy (terminates TLS, forwards to HTTP backend)
devssl proxy 3000 # Forward to localhost:3000
devssl proxy 192.168.1.5:8080 # Forward to specific host:port
# Check status
devssl status
# List all certificates
devssl list
# Renew expiring certs
devssl renew
devssl renew --force # Force renewal even if not expiring
devssl renew --dry-run # Show what would be renewed
# Backup and restore
devssl backup # Backup CA and all certs
devssl restore ./devssl-backup # Restore from backup
# Manage trust store
devssl trust status # Check if CA is trusted
devssl trust install # Add CA to trust store
devssl trust remove # Remove CA from trust storeAll commands support these flags:
| Flag | Description |
|---|---|
-q, --quiet |
Suppress non-essential output |
-v, --verbose |
Show detailed operation logs |
Certificate files are stored in:
- Linux:
~/.local/share/devssl/ - macOS:
~/Library/Application Support/devssl/ - Windows:
%LOCALAPPDATA%\devssl\
devssl init [--force] [--skip-trust-store] [--ci] [--days N] [--node] [--encrypt] [--ca-password PWD]Creates CA, adds to system trust store, generates localhost certificate.
| Flag | Description |
|---|---|
--days N |
Days until localhost certificate expires (default: config value, 365) |
--ci |
Skip trust store installation (for CI/Docker) |
--node |
Print NODE_EXTRA_CA_CERTS export command |
--encrypt |
Encrypt CA private key with a password |
--ca-password |
Password for CA key encryption (requires --encrypt) |
devssl generate <domains...> [--days N] [--output DIR] [--force] [--ca-password PWD] [OPTIONS]Creates certificate for specified domain names or IP addresses. Supports .local, .test, .internal, and other private TLDs, as well as private IP addresses (e.g., 192.168.1.100, 10.0.0.5).
| Flag | Description |
|---|---|
--days N |
Days until certificate expires (default: 30) |
--ca-password |
Password for encrypted CA key |
--csr <FILE> |
Sign a Certificate Signing Request instead of generating new key |
--pkcs12 |
Export as PKCS12 (.p12) file alongside .crt/.key |
--password <PWD> |
Password for PKCS12 file (default: empty) |
--client |
Generate client authentication certificate |
--email <ADDR> |
Generate S/MIME certificate for email signing (can be repeated for multiple addresses) |
devssl proxy <backend> [--cert NAME] [--https-port PORT] [--redirect] [--http-port PORT] [--bind ADDR] [--max-body-size SIZE] [--ca-password PWD]Runs HTTPS reverse proxy. Forwards to HTTP backend. The <backend> parameter accepts either a port number (e.g., 3000) or a host:port address (e.g., 192.168.1.5:8080).
| Flag | Description |
|---|---|
--cert NAME |
Certificate name to use (default: localhost) |
--https-port PORT |
HTTPS port to listen on (default: same as backend port) |
--redirect |
Also listen on HTTP and redirect to HTTPS |
--http-port PORT |
HTTP port for redirects (default: 8080) |
--bind ADDR |
Address to bind the proxy to (default: 127.0.0.1). Use 0.0.0.0 for mobile/VM testing |
--max-body-size SIZE |
Maximum request/response body size (default: 10MB). Supports K/KB, M/MB, G/GB |
--ca-password |
Password for encrypted CA key |
Examples:
# Large file uploads
devssl proxy 3000 --max-body-size 100MB
# Mobile testing with specific cert
devssl proxy 3000 --bind 0.0.0.0 --cert myapp.local
# Redirect HTTP to HTTPS
devssl proxy 3000 --redirect --http-port 80Notes:
- The proxy automatically generates certificates if they don't exist
- Backend must accept proxied headers (
X-Forwarded-Proto,X-Forwarded-For,X-Forwarded-Host,X-Real-IP) - Default body size limit is 10MB (configurable with
--max-body-size)
devssl renew [NAME] [--within-days N] [--days N] [--force] [--dry-run] [--ca-password PWD]Renews certificates expiring within N days (default: 7).
| Flag | Description |
|---|---|
--within-days N |
Renew certs expiring within N days (default: 7) |
--days N |
Days for renewed certificate validity (default: 30) |
-f, --force |
Force renewal even if certificate hasn't expired |
--dry-run |
Show what would be renewed without making changes |
--ca-password |
Password for encrypted CA key |
devssl list [--verbose]List all certificates with their expiry dates, domains, and status. Use --verbose to show all domains instead of abbreviated list.
devssl inspect <NAME>Show detailed information about a specific certificate, including domains, validity period, and certificate type.
Shows CA and certificate information.
devssl uninstall [--keep-certs] [--yes]Removes CA from trust store and deletes certificate files.
devssl path [NAME]Show certificate and CA file paths. If NAME is provided, shows paths for that certificate.
devssl chain <NAME> [--output FILE]Export a certificate chain (certificate + CA) to a single file. Useful for servers that need the full chain.
| Flag | Description |
|---|---|
-o, --output FILE |
Output file path (default: stdout) |
devssl backup [--output DIR]Backup CA and all certificates to a directory. Creates a complete snapshot that can be restored later.
| Flag | Description |
|---|---|
-o, --output DIR |
Backup directory path (default: devssl-backup) |
devssl restore <DIR> [--force]Restore CA and certificates from a backup directory.
| Flag | Description |
|---|---|
--force |
Overwrite existing files |
devssl trust install # Add CA to system trust store
devssl trust remove # Remove CA from system trust store
devssl trust status # Check if CA is trustedManage the system trust store independently. Useful after restoring from backup or fixing trust store issues.
devssl doctorDiagnose trust store and certificate issues. Checks CA validity, trust store status, Firefox NSS, and NODE_EXTRA_CA_CERTS.
devssl watch --exec "COMMAND" [--name NAME] [--interval SECS]Watch certificates and restart a command when they change. Useful for development servers that need to reload on cert renewal.
| Flag | Description |
|---|---|
--exec COMMAND |
Command to run (required) |
--name NAME |
Certificate name to watch (default: localhost) |
--interval SECS |
Check interval in seconds (default: 2) |
devssl qr [--save FILE] [--port PORT] [--bind ADDR]Generate QR code for CA certificate installation on mobile devices. Starts a temporary HTTP server to serve the certificate.
| Flag | Description |
|---|---|
--save FILE |
Save QR code as PNG image instead of displaying in terminal |
--port PORT |
Port for temporary HTTP server (default: 8443) |
--bind ADDR |
Address to bind the HTTP server to (default: 0.0.0.0) |
Security Note: The default bind address 0.0.0.0 exposes the CA certificate to your entire network. Use --bind 127.0.0.1 on untrusted networks.
For reverse proxies or custom configurations, use the certificate and key files directly:
# Get certificate paths
devssl path myapp.local
# Example output:
# Certificate: ~/.local/share/devssl/myapp.local.crt
# Private Key: ~/.local/share/devssl/myapp.local.keyGeneric reverse proxy config (nginx example):
server {
listen 443 ssl;
server_name myapp.local;
ssl_certificate /home/user/.local/share/devssl/myapp.local.crt;
ssl_certificate_key /home/user/.local/share/devssl/myapp.local.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://localhost:3000;
}
}Or use the built-in proxy (recommended for development):
devssl proxy 3000 --cert myapp.localdevssl daemon start [--on-renew "COMMAND"]
devssl daemon stop
devssl daemon status
devssl daemon run [--on-renew "COMMAND"]
devssl daemon logs [-n LINES] [-f]Manage the auto-renewal daemon. The daemon runs in the background and automatically renews expiring certificates.
| Subcommand | Description |
|---|---|
start |
Start the daemon in background |
stop |
Stop the running daemon |
status |
Show daemon status and configuration |
run |
Run in foreground (for systemd/launchd) |
logs |
Show daemon log output |
| Flag | Description |
|---|---|
--on-renew "COMMAND" |
Command to execute when certificates are renewed |
-n, --lines N |
Number of log lines to show (default: 50) |
-f, --follow |
Follow log output in real-time (like tail -f) |
# Export CA for team sharing
devssl export-ca [--include-key] [--output FILE] [--format pem|der]
# Import shared CA
devssl import-ca <FILE> [--trust] [--force]Share CA certificates across a team. Use --include-key to allow the recipient to generate new certificates. Use --force to import even if the certificate is not a CA.
Note: The --include-key option is only supported with --format pem. DER format does not support bundling the certificate and private key.
# Encrypt an existing CA key
devssl encrypt-key
# Decrypt an encrypted CA key
devssl decrypt-key
# Change password on encrypted key
devssl change-passwordProtect the CA private key with password encryption.
devssl completions <SHELL>Generate shell completions. Supported shells: bash, zsh, fish, powershell, elvish.
The CA private key can sign certificates for any domain. Keep the devssl data folder secure.
Certificates are only issued for:
localhost,*.localhost- Private IPs (127.x.x.x, 10.x.x.x, 192.168.x.x, etc.)
- Reserved TLDs:
.localhost,.local,.test,.example,.invalid,.internal,.lan,.home,.corp,.intranet,.private,.devlocal
Public domains like .com, .org, .io are rejected.
| Platform | Dependencies |
|---|---|
| Linux | sudo, update-ca-certificates / update-ca-trust / trust |
| macOS | None (uses Keychain) |
| Windows | None (uses certutil) |
Optional config.toml in the devssl data directory:
cert_days = 365
ca_days = 3650
[daemon]
check_interval_hours = 1
renew_within_days = 7Note: cert_days is used by init --days when no value is specified. The generate and renew commands default to 30 days.
| Variable | Description |
|---|---|
DEVSSL_ROOT |
Custom path for certificate storage (overrides default location) |
DEVSSL_TRUST_STORES |
Comma-separated list of trust stores to use: system, nss, java |
DEVSSL_PASSWORD |
Password for encrypted CA key operations |
DEVSSL_NEW_PASSWORD |
New password when changing CA key password |
DEVSSL_RENEWED_CERT |
Name of certificate that was renewed (available in --on-renew scripts) |
SSL_CERT_FILE |
Standard env var for certificate path (set by devssl init) |
SSL_KEY_FILE |
Standard env var for key path (set by devssl init) |
NODE_EXTRA_CA_CERTS |
Path to CA cert for Node.js applications |
devssl was inspired by mkcert by @FiloSottile. We're grateful for the excellent work on mkcert which pioneered the zero-config local HTTPS approach.
devssl builds on this foundation with additional features:
- HTTPS reverse proxy with WebSocket support
- Background auto-renewal daemon with certificate watching
- Backup/restore and team CA sharing (export-ca/import-ca)
- QR code generation for mobile device setup
- Doctor command for trust store diagnostics
- Native Rust implementation for performance and safety
Both tools share the same philosophy: making local HTTPS development simple and secure.
Apache-2.0