How to Generate mkcert Certificates for IP Addresses and URIs: A Complete Guide
Use mkcert <ip> for IP addresses or mkcert <uri> for URIs, and mkcert automatically detects the type and creates the appropriate Subject Alternative Name (SAN) entries.
The mkcert tool by FiloSottile simplifies local development certificate generation by automatically handling various identifier types. When you need to generate mkcert certificates for IP addresses and URIs, the tool inspects each argument to determine whether it represents a DNS hostname, IP address, email address, or URI, then populates the certificate's SAN extension accordingly.
How mkcert Detects IP Addresses and URIs Automatically
The automatic detection logic resides in two key files: main.go for argument classification and cert.go for certificate template construction.
Argument Classification in main.go
In main.go (lines 16-27), each positional argument undergoes type detection using Go's standard library parsers:
if ip := net.ParseIP(name); ip != nil {
continue // IP address detected
}
if email, err := mail.ParseAddress(name); err == nil && email.Address == name {
continue // Email address detected
}
if uriName, err := url.Parse(name); err == nil && uriName.Scheme != "" && uriName.Host != "" {
continue // URI detected
}
If none of these parsers succeed, mkcert treats the argument as a DNS name after applying puny-code conversion for internationalized domain names.
SAN Construction in cert.go
The makeCert method in cert.go (lines 76-86) receives the classified hosts and populates the x509.Certificate template:
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
tpl.IPAddresses = append(tpl.IPAddresses, ip)
} else if email, err := mail.ParseAddress(h); err == nil && email.Address == h {
tpl.EmailAddresses = append(tpl.EmailAddresses, h)
} else if uriName, err := url.Parse(h); err == nil && uriName.Scheme != "" && uriName.Host != "" {
tpl.URIs = append(tpl.URIs, uriName)
} else {
tpl.DNSNames = append(tpl.DNSNames, h)
}
}
For URIs, mkcert stores only the scheme and host components. The path, query, and fragment are discarded because the X.509 SAN specification does not support them.
Key Usage Adjustments
According to cert.go (lines 91-96), mkcert automatically sets appropriate Extended Key Usage (EKU) flags:
- IP addresses, DNS names, and URIs: Adds
ExtKeyUsageServerAuthfor TLS server authentication. - Email addresses: Adds
ExtKeyUsageEmailProtectionfor S/MIME or email signing.
If you pass the -client flag, mkcert also adds ExtKeyUsageClientAuth for mutual TLS scenarios.
Generating Certificates for IP Addresses
IPv4 Addresses
To generate a certificate for a local development server bound to 127.0.0.1:
mkcert 127.0.0.1
This creates 127.0.0.1.pem and 127.0.0.1-key.pem with an IP Address SAN entry containing the IPv4 address.
IPv6 Addresses
mkcert supports IPv6 addresses using standard notation:
mkcert ::1
Or for a specific IPv6 address:
mkcert 2001:db8::1
The net.ParseIP function in main.go handles both IPv4 and IPv6 formats automatically.
Generating Certificates for URIs
URIs are useful for services that validate the full URI rather than just the hostname, such as certain OAuth 2.0 providers or SPIFFE-based service meshes.
Basic URI Certificate
To generate a certificate for a specific URI:
mkcert https://api.example.com
Note that mkcert extracts only https://api.example.com (scheme and host). If you include a path like https://api.example.com/v1, the path component is stripped during SAN construction in cert.go.
Multiple URIs
You can combine URIs with other name types:
mkcert https://app.local https://api.local 192.168.1.10
This generates a single certificate with URI SAN entries for both HTTPS endpoints and an IP SAN entry for the local network address.
Advanced Usage Examples
Mixed Host Types
For microservices that expose both DNS names and IP endpoints, generate a single certificate covering all endpoints:
mkcert localhost 127.0.0.1 ::1 example.com https://service.example.com
The resulting certificate includes:
- DNS names:
localhost,example.com - IP addresses:
127.0.0.1,::1 - URI:
https://service.example.com
Custom Output Filenames
When generating certificates for IP addresses, the default filename contains dots or colons that may cause issues on some filesystems. Use the -cert-file and -key-file flags:
mkcert -cert-file local-server.pem -key-file local-server-key.pem 127.0.0.1
Client Authentication Certificates
For mutual TLS (mTLS) scenarios where a service needs to authenticate clients by IP address:
mkcert -client 10.0.0.5
This adds the ExtKeyUsageClientAuth flag while still placing 10.0.0.5 in the IP Address SAN field, as implemented in cert.go lines 91-96.
Summary
- Automatic detection: mkcert uses
net.ParseIP,mail.ParseAddress, andurl.Parseinmain.goto classify arguments as IP addresses, emails, URIs, or DNS names. - SAN population: The
makeCertmethod incert.gopopulatestpl.IPAddressesfor IPs andtpl.URIsfor URIs, ensuring proper X.509 encoding. - Simple syntax: Run
mkcert <ip>ormkcert <uri>without special flags—mkcert handles the certificate structure automatically. - Key usage: Server authentication EKU is automatically added for IP and URI entries, with optional client authentication via the
-clientflag.
Frequently Asked Questions
Can mkcert generate certificates for private IP ranges?
Yes. mkcert treats any valid IP address parsed by net.ParseIP equally, whether it is a public routable address or a private range such as 192.168.x.x, 10.x.x.x, or 172.16.x.x. The certificate will contain an IP Address SAN entry that TLS clients will match against the connection address.
Does mkcert support IPv6 addresses?
Yes. mkcert fully supports IPv6 addresses in standard notation, such as ::1 for localhost or 2001:db8::1 for specific addresses. The net.ParseIP function in main.go handles both IPv4 and IPv6 formats, and cert.go appends them to the tpl.IPAddresses slice for inclusion in the final certificate.
What URI schemes are supported by mkcert?
mkcert accepts any URI that url.Parse can parse with a non-empty scheme and host, including https://, http://, spiffe://, and custom schemes. However, only the scheme and host components are preserved in the certificate's SAN extension; paths, query parameters, and fragments are stripped during processing in cert.go because the X.509 standard does not support them in URI SAN entries.
How do I install the generated certificate on a mobile device?
First, generate a PKCS#12 (PFX) bundle instead of separate PEM files using the -pkcs12 flag: mkcert -pkcs12 example.com 192.168.1.5. Then transfer the .p12 file to your mobile device. On iOS, you can email the file or use AirDrop, then install it via Settings > General > VPN & Device Management. On Android, open the file in a file manager to trigger the installation prompt. You will also need to install the mkcert root CA on the device to trust the certificate.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →