lan-ca: Local HTTPS in 300 Lines of Go

Copied to clipboard! Copies a prompt to paste into ChatGPT, Claude, etc.

Getting HTTPS working on .lan domains is annoying. Let’s Encrypt won’t issue certs for non-public domains. Self-signed certs trigger browser warnings. mkcert exists but felt like overkill for my needs.

So I wrote a 300-line Go tool that does exactly what I need: create a root CA once, generate certs for any .lan domain, trust it on macOS with one command.

The Tool

# Initialize (creates ~/.lan-ca/ca.crt and ca.key)
lan-ca init

# Generate cert for specific domains
lan-ca generate grafana.lan prometheus.lan

# Or generate a wildcard for all .lan domains
lan-ca wildcard

# Trust the CA on macOS
sudo security add-trusted-cert -d -r trustRoot -p ssl \
  -k /Library/Keychains/System.keychain $(lan-ca ca-path)

That’s it. After trusting the CA once, any cert you generate is automatically trusted.

How It Works

The core is straightforward Go crypto:

// Generate ECDSA P-384 key
key, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)

// Create certificate template
template := &x509.Certificate{
    SerialNumber: serialNumber,
    Subject:      pkix.Name{CommonName: "grafana.lan"},
    NotBefore:    time.Now(),
    NotAfter:     time.Now().AddDate(0, 0, 365),
    DNSNames:     []string{"grafana.lan"},
    ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
}

// Sign with CA
certDER, _ := x509.CreateCertificate(rand.Reader, template, caCert, &key.PublicKey, caKey)

The tool outputs fullchain certs (server cert + CA cert bundled) so nginx/traefik/caddy just work.

My Setup

I run ~30 services on my homelab, all behind Traefik with a wildcard cert:

# traefik config
tls:
  certificates:
    - certFile: /certs/wildcard.lan.crt
      keyFile: /certs/wildcard.lan.key

One cert, all services. grafana.lan, prometheus.lan, home.lan—all green padlock, no warnings.

Trusting on iOS

For accessing services from my phone:

  1. AirDrop ~/.lan-ca/ca.crt to the device
  2. Install the profile in Settings
  3. Settings → General → About → Certificate Trust Settings
  4. Enable trust for “Homelab Root CA”

Now Safari shows the green padlock for all my .lan services.

Why Not mkcert?

mkcert is great, but:

  • It’s 2000+ lines vs my 300
  • It auto-installs the CA (I wanted explicit control)
  • It doesn’t do wildcards easily
  • I wanted to understand exactly what’s happening

Sometimes the best tool is the one you wrote yourself.


300 lines of Go. No dependencies. Just crypto/x509 and the standard library.

Copied to clipboard!