> For the complete documentation index, see [llms.txt](https://docs.glesys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.glesys.com/products/compute/guides-for-server-management/set-up-a-dns-over-https-server.md).

# Set up a DNS-over-HTTPS server

***

In this guide, we’ll show you how to set up your own DoH (DNS‑over‑HTTPS) server and start sending encrypted DNS queries in less than half an hour using Glesys Cloud.

We’ll be using a Debian server with nginx, a DoH proxy, and Unbound, along with Let’s Encrypt and a domain name that you’ll need to provide.

## Setting up the DNS-over-HTTPS server

Start by logging in to our control panel and provisioning a server running Debian 12 or later. After you have selected an IP address for your server, go to the DNS in Glesys Cloud and point `doh.example.com` (replace `example.com` with your own domain) to the IPv4 and IPv6 addresses assigned to your server.

Start by updating your server:

{% code title="Commands" %}

```
sudo apt update
sudo apt upgrade
```

{% endcode %}

Once that’s done, it’s time to begin the installation.

We start by installing `unbound` . Unbound is a recursive and caching name server. This is what will make the actual DNS look-ups.

{% code title="Commands" %}

```
sudo apt install unbound
sudo systemctl enable unbound
sudo systemctl start unbound
```

{% endcode %}

Then, download the latest version of `doh-proxy` for Debian amd64 from this site <https://github.com/DNSCrypt/doh-server/releases>.

Once downloaded, install it with (replace the version with the version you downloaded):

{% code title="Command" %}

```
sudo apt install ./doh-proxy_0.9.15-1_amd64.deb
```

{% endcode %}

Next, you need to create a user to run `doh-proxy` (to avoid having it run as root):

{% code title="Command" %}

```
sudo adduser --home /var/lib/proxy --comment "Homer says DOH" --shell /sbin/nologin --system --group doh-proxy
```

{% endcode %}

To make `doh-proxy` start automatically when the server boots, create a systemd service for it in `/etc/systemd/system/doh-proxy.service`.

{% code title="/etc/systemd/system/doh-proxy.service" %}

```
[Unit]
Description=DOH Proxy
Before=nginx.target

[Service]
Type=simple
ExecStart=/usr/bin/doh-proxy -H 'doh.example.com' -u 127.0.0.1:53
Restart=always
User=doh-proxy
Group=doh-proxy

[Install]
WantedBy=multi-user.target
```

{% endcode %}

To make the system recognize this new service, reload the systemd daemon:

{% code title="Command" %}

```
sudo systemctl daemon-reload
```

{% endcode %}

Next, install Nginx and Certbot for Nginx:

{% code title="Command" %}

```
sudo apt install python3-certbot-nginx nginx
```

{% endcode %}

Now it's time to issue a Let's Encrypt certificate for the Nginx server using Certbot (replace `example.com` with your real domain):

```
sudo certbot --nginx -d doh.example.com
```

If you try accessing `https://doh.example.com` now, you should see Nginx default welcome page.

Now it's time to configure HTTP/2 and Nginx with doh-proxy. Edit the file `/etc/nginx/sites-available/default`. Find the following two lines in that file:

{% code title="Lines in /etc/nginx/sites-available/default" %}

```
  listen [::]:443 ssl ipv6only=on; # managed by Certbot
  listen 443 ssl; # managed by Certbot
```

{% endcode %}

Add `http2` to those line so that they instead look like this:

{% code title="Lines in /etc/nginx/sites-available/default" %}

```
   listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
   listen 443 ssl http2; # managed by Certbot
```

{% endcode %}

Then find the line that reads:

{% code title="Line in /etc/nginx/sites-available/default" %}

```
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
```

{% endcode %}

Right below that line, add the following to tell Nginx that we only accept HEAD, GET, and POST requests:

{% code title="Lines to add to /etc/nginx/sites-available/default" %}

```
    if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
        return 501;
    }
```

{% endcode %}

The next step is to configure the backend. Find the lines that read something like the example below. Remember that this should be inside the server block for HTTPS.

{% code title="Lines to replace in /etc/nginx/sites-available/default" %}

```
    location / {
        try_files $uri $uri/ =404;
    }
```

{% endcode %}

Replace that entire block with this code:

{% code title="Lines to add in /etc/nginx/sites-available/default" %}

```
       location /dns-query {
              proxy_set_header Host $http_host;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_redirect off;
              proxy_buffering off;
              proxy_pass http://dohproxy_backend;
        }
```

{% endcode %}

Next, at the very end of the file, after the final bracket, add the following:

{% code title="Lines to add in /etc/nginx/sites-available/default" %}

```
upstream dohproxy_backend {
    server 127.0.0.1:3000;
}
```

{% endcode %}

That's it. Now, save the file, exit the editor, and restart Nginx:

{% code title="Command" %}

```
sudo systemctl restart nginx
```

{% endcode %}

Next, start and enable the `doh-proxy` service:

```
sudo systemctl start doh-proxy
sudo systemctl enable doh-proxy
```

## Testing the DNS-over-HTTPS server

Congratulations! Everything is now set up, and you can try out your DoH server. To test it, you can use cURL, preferably from your own computer. Remember to use your own domain, not `example.com`.

{% code title="Command" %}

```
curl -H "Accept: application/dns-json" "https://doh.example.com/dns-query?name=glesys.se"
```

{% endcode %}

If it worked, you should get a reply like this:

{% code title="Output" %}

```
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"glesys.se","type":1}],"Answer":[{"name":"glesys.se","type":1,"TTL":517,"data":"185.39.145.232"}]}
```

{% endcode %}

Now, you can add your DNS-over-HTTPS server to Firefox:

<figure><img src="/files/ZymEyzEWQhqtsaLlwDPV" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.glesys.com/products/compute/guides-for-server-management/set-up-a-dns-over-https-server.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
