Skip to content

Instantly share code, notes, and snippets.

@mranv
Created April 3, 2025 17:58
Show Gist options
  • Save mranv/214124bc98d998245cebcef66ca12849 to your computer and use it in GitHub Desktop.
Save mranv/214124bc98d998245cebcef66ca12849 to your computer and use it in GitHub Desktop.

Setting up HTTPS for Local VMs with Custom Domains

This guide will walk you through setting up a system to serve your local VMs over HTTPS using custom domain names (e.g., https://xyz.local). We'll use the following components:

  1. Hypervisor (e.g., VirtualBox, VMware, or Hyper-V)
  2. CoreDNS for local DNS resolution
  3. NGINX as a reverse proxy
  4. Smallstep/certificates for certificate management

1. Set up your Hypervisor and VMs

  1. Install your chosen hypervisor (VirtualBox, VMware, or Hyper-V).
  2. Create VMs for each service you want to run.
  3. Configure the VMs to use bridged networking so they're accessible on your local network.
  4. Note down the IP addresses assigned to each VM.

2. Set up CoreDNS

  1. Create a new VM to act as your DNS server.

  2. Install CoreDNS on this VM.

  3. Configure CoreDNS:

    xyz.local:53 {
      hosts {
        192.168.1.101 app1.xyz.local
        192.168.1.102 app2.xyz.local
        192.168.1.103 ca.xyz.local
        fallthrough
      }
      log
    }
    
    .:53 {
      forward . 8.8.8.8 8.8.4.4
      log
    }
    
  4. Configure your router to use this VM's IP address as the primary DNS server.

3. Set up NGINX Reverse Proxy

  1. Create a new VM to act as your reverse proxy.

  2. Install NGINX on this VM.

  3. Configure NGINX as a reverse proxy:

    http {
      server {
        listen 80;
        server_name *.xyz.local;
        return 301 https://$host$request_uri;
      }
    
      server {
        listen 443 ssl;
        server_name app1.xyz.local;
    
        ssl_certificate /path/to/app1.xyz.local.crt;
        ssl_certificate_key /path/to/app1.xyz.local.key;
    
        location / {
          proxy_pass http://192.168.1.101;
        }
      }
    
      # Repeat for other apps...
    }

4. Set up Smallstep/certificates

  1. Create a new VM to act as your Certificate Authority (CA).

  2. Install Smallstep/certificates on this VM.

  3. Initialize the CA:

    step ca init --name "Local CA" --dns ca.xyz.local --address :443
  4. Configure the CA for long-lived certificates:

    {
      "claims": {
        "minTLSCertDuration": "5s",
        "maxTLSCertDuration": "8760h",
        "defaultTLSCertDuration": "8760h"
      }
    }
  5. Generate certificates for each domain:

    step ca certificate app1.xyz.local app1.xyz.local.crt app1.xyz.local.key
  6. Copy the certificates to your NGINX VM.

5. Trust the Root Certificate

  1. Export the root certificate from your CA VM.
  2. Import the root certificate into the trust store of each client device.

6. Configure Client Devices

  1. Ensure all client devices are using your CoreDNS server for DNS resolution.
  2. Import the root CA certificate into each client device's trust store.

Now, when you access https://app1.xyz.local from a client device on your network, it should:

  1. Resolve to your NGINX VM's IP address
  2. Connect securely using the custom certificate
  3. Be proxied to the correct application VM

Remember to keep your CA and certificates secure, and renew certificates before they expire.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment