# How to Generate mkcert Certificates for IP Addresses and URIs: A Complete Guide

> Generate mkcert certificates for IP addresses and URIs effortlessly. Learn how mkcert automatically adds Subject Alternative Name entries for seamless SSL/TLS configuration.

- Repository: [Filippo Valsorda/mkcert](https://github.com/FiloSottile/mkcert)
- Tags: how-to-guide
- Published: 2026-03-05

---

**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`](https://github.com/FiloSottile/mkcert/blob/main/main.go) for argument classification and [`cert.go`](https://github.com/FiloSottile/mkcert/blob/main/cert.go) for certificate template construction.

### Argument Classification in main.go

In [`main.go`](https://github.com/FiloSottile/mkcert/blob/main/main.go) (lines 16-27), each positional argument undergoes type detection using Go's standard library parsers:

```go
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`](https://github.com/FiloSottile/mkcert/blob/main/cert.go) (lines 76-86) receives the classified hosts and populates the `x509.Certificate` template:

```go
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`](https://github.com/FiloSottile/mkcert/blob/main/cert.go) (lines 91-96), mkcert automatically sets appropriate Extended Key Usage (EKU) flags:

- **IP addresses, DNS names, and URIs**: Adds `ExtKeyUsageServerAuth` for TLS server authentication.
- **Email addresses**: Adds `ExtKeyUsageEmailProtection` for 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`:

```bash
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:

```bash
mkcert ::1

```

Or for a specific IPv6 address:

```bash
mkcert 2001:db8::1

```

The `net.ParseIP` function in [`main.go`](https://github.com/FiloSottile/mkcert/blob/main/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:

```bash
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`](https://github.com/FiloSottile/mkcert/blob/main/cert.go).

### Multiple URIs

You can combine URIs with other name types:

```bash
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:

```bash
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:

```bash
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:

```bash
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`](https://github.com/FiloSottile/mkcert/blob/main/cert.go) lines 91-96.

## Summary

- **Automatic detection**: mkcert uses `net.ParseIP`, `mail.ParseAddress`, and `url.Parse` in [`main.go`](https://github.com/FiloSottile/mkcert/blob/main/main.go) to classify arguments as IP addresses, emails, URIs, or DNS names.
- **SAN population**: The `makeCert` method in [`cert.go`](https://github.com/FiloSottile/mkcert/blob/main/cert.go) populates `tpl.IPAddresses` for IPs and `tpl.URIs` for URIs, ensuring proper X.509 encoding.
- **Simple syntax**: Run `mkcert <ip>` or `mkcert <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 `-client` flag.

## 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`](https://github.com/FiloSottile/mkcert/blob/main/main.go) handles both IPv4 and IPv6 formats, and [`cert.go`](https://github.com/FiloSottile/mkcert/blob/main/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`](https://github.com/FiloSottile/mkcert/blob/main/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.