Simple, ready-to-use TLS certificates for local development with the local.devhost.name domain. Skip the hassle of generating local SSL certs and dealing with CORS headaches—run everything behind a local HTTPS reverse proxy.
This is a tool provided for free by the Simply Hexagonal open source collective.
Please consider:
- Supporting Simply Hexagonal through Open Collective 💖
- Buying the maintainer a coffee ☕
- Supporting the maintainer on Patreon 🏆
- Starring this repo on Github 🌟
- Add the certificates to your project (creates a
certsfolder):
git clone https://github.com/simplyhexagonal/local-dev-host-certs.git certs
- Start a proxy and sample services with Docker Compose (place this next to the
certsfolder and rundocker compose up):
services:
proxy:
image: nginxproxy/nginx-proxy
# If port error try: sudo sysctl net.ipv4.ip_unprivileged_port_start=80
privileged: true
ports:
- 80:80
- 443:443
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs
environment:
- DEFAULT_HOST=local.devhost.name
web:
image: strm/helloworld-http
ports:
- 8080:80
environment:
- VIRTUAL_HOST=local.devhost.name
- VIRTUAL_PATH=/
api:
image: thomaspoignant/hello-world-rest-json
ports:
- 9090:8080
environment:
- VIRTUAL_HOST=local.devhost.name
- VIRTUAL_PATH=/api/
- VIRTUAL_DEST=/- Open your app at https://local.devhost.name (HTTP works too).
- The DNS for
local.devhost.nameresolves to127.0.0.1. - In the example above
nginx-proxycontainer reads certs from/etc/nginx/certs(mounted from your./certsfolder) and routes requests usingVIRTUAL_HOST/VIRTUAL_PATH. - Prefer sub-path routing when you can—it often simplifies CORS, but for cases where subdomains are needed, we also provide a wildcard
local-*.devhost.nameto127.0.0.1. Examples:local-api.devhost.namelocal-db.devhost.namelocal-admin.devhost.name
The certificates are generated using letsencrypt and expire every 90 days.
We provide a file named .scheduled-renewal that contains the date of next renewal with the format yyyy-mm-dd.
We renew the certificates a few days before expiry to avoid disruptions.
The easiest way to automatically check if you need to renew is by comparing the current .scheduled-renewal file in your certs directory against the latest one in the local-dev-host-certs repo, for example:
#!/usr/bin/env bash
# Inside certs directory
# Download latest certs to renewal-certs directory
git clone https://github.com/simplyhexagonal/local-dev-host-certs.git renewal-certs
# Exit on error
if [ $? -ne 0 ]; then
echo "Failed to clone repository"
exit 1
fi
# Compare `.scheduled-renewal` against `renewal-certs/.scheduled-renewal`
if [ ! -f ".scheduled-renewal" ] || [ ! -f "renewal-certs/.scheduled-renewal" ]; then
echo "Missing .scheduled-renewal files"
rm -rf renewal-certs
exit 1
fi
if ! cmp -s ".scheduled-renewal" "renewal-certs/.scheduled-renewal"; then
echo "Certificates need renewal. Updating..."
# Move files up (overwrite existing) and delete empty renewal-certs directory
cp -f renewal-certs/* .
rm -rf renewal-certs
echo "Certificates updated successfully"
else
echo "Certificates are up to date"
rm -rf renewal-certs
fiYou can schedule this automatic process to happen 24 hours after the scheduled renewal date to avoid having to check constantly.