> For the complete documentation index, see [llms.txt](https://docs.hivel.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hivel.ai/self-managed-hivel-deployment/virtual-private-cloud/azure/dns-setup-azure/setup-and-prerequisites/option-a-domain-+-lets-encrypt-recommended.md).

# Option A - Domain + Let's Encrypt (Recommended)

DNS Setup (Azure)

Choose this whenever you have a domain available. Caddy automatically obtains and renews a trusted certificate from [Let's Encrypt](https://letsencrypt.org/) - no manual certificate management required.

### Step 1: Point DNS at VM

**Goal:** get a DNS name resolving to VM before requesting a certificate for it.

Create an **A record** for your chosen subdomain pointing at VM's public IP. Use an **Azure Static** **Public IP** if you haven't allocated one, so the address doesn't change on instance restart.

| **Record Type** | **Name**              | **Value**         |
| --------------- | --------------------- | ----------------- |
| A               | hivel.yourcompany.com | \\\<vm-public-ip> |

**Expected result:** dig +short hivel.yourcompany.com returns VM's IP. Allow a few minutes for DNS propagation before continuing.

### Step 2: Open Required Ports

On VM's Network Security Group, add:

| **Type**     | **Port** | **Source**                   | **Purpose**                                                 |
| ------------ | -------- | ---------------------------- | ----------------------------------------------------------- |
| Custom (TCP) | 80       | Any                          | Required for the Let's Encrypt HTTP-01 validation challenge |
| Custom (TCP) | 443      | Any, or your office/VPN CIDR | HTTPS traffic to the UI                                     |

***Note:** Port 80 must be reachable from the public internet for certificate issuance to succeed, even if all application traffic will use HTTPS.*

### &#x20;Step 3: Configure and Start Caddy

**Goal:** run Caddy as a Docker container that terminates TLS and forwards to the UI on port 3000.

**Prerequisites:** DNS resolving (Step 1) and ports open (Step 2).

On VM, replace hivel.yourcompany.com with your actual domain:

```
mkdir -p ~/caddy && cd ~/caddy
 
cat > Caddyfile <<'EOF'
hivel.yourcompany.com {
    reverse_proxy localhost:3000
}
EOF
 
docker run -d --name caddy --restart unless-stopped --network host \
  -v $(pwd)/Caddyfile:/etc/caddy/Caddyfile \
  -v caddy_data:/data \
  caddy:2


```

\--network host lets Caddy reach the UI container via the port it already publishes on the host (localhost:3000), with no additional Docker network configuration.

### Step 4: Verify

```
docker logs -f caddy
```

**Expected result:** a log line confirming certificate issuance (certificate obtained successfully), then open:

```
https://hivel.yourcompany.com
```

The connection should show a trusted certificate with no browser warning.

**If it fails:** see [Certificate not issued](/self-managed-hivel-deployment/virtual-private-cloud/azure/dns-setup-azure/troubleshooting.md).

{% columns %}
{% column %} <a href="/self-managed-hivel-deployment/virtual-private-cloud/azure/dns-setup-azure/setup-and-prerequisites.md" class="button primary" data-icon="backward">Setup and Prerequisites</a>
{% endcolumn %}

{% column %}

{% endcolumn %}

{% column %} <a href="/self-managed-hivel-deployment/virtual-private-cloud/azure/dns-setup-azure/setup-and-prerequisites/option-a-domain-+-lets-encrypt-recommended.md" class="button primary" data-icon="forward">Option B - Self-Signed</a>
{% endcolumn %}
{% endcolumns %}
