A bit of privacy please


Table of content:


I like privacy. Don’t we all?

But still, when I am talking with friends, family or colleagues about blocking tracking, and otherwise protecting online privacy, I am sometimes met with a variant of “if you’ve got nothing to hide, you’ve got nothing to fear”. This article by Alex Abdo goes into depth on why that is a silly statement.

Aside from government agencies, your ISP can also do a lot of tracking, and in some countries they are even allowed to sell your data or they can apply censorship of information. This article from ProtonVPN goes in depth with some of the things your ISP can do, and provides links to further reading.

In this article I will explain how to set up your own DNS server, to increase your privacy while optionally blocking tracking and advertisements from working on your devices. It is going to be technical, so it is not for everyone. If you go to this section, I will give some tips for the less tech savvy among you.


You will need the following to benefit from this guide.

  • Router with support for DNS over HTTPS, or DNS over TLS, or DNS over QUIC
  • Android 9+ devices or Iphone/Ipad with iOS 14+
  • Cloud hosted VM or Raspberry Pi. VM preferred.

I don’t own any apple products, but according to some articles i found encrypted DNS is supported if your device is running iOS 14 or above. However, it seems that you will need some technical knowledge to create a configuration profile. Unfortunately i cannot be of assistance here, since i don’t own an iphone. I found a blog post with some premade configuration files that you can modify. The link is in the Connecting to the DNS server section.

Setting up a server

Adguard Home does not require a lot of resources, so you can follow this guide using a raspberry pi if you wish. However, if you want to get the benefit of the server while also outside your home, I recommend renting a VM at a cloud provider of your choice.

In your cloud providers interface, pick a VM with very low resources. Mine has 2 vCPUs and 1 GB ram, and I am getting an average processing time of 6 ms on DNS lookups according to the adguard interface.
Personally I am using Google Cloud Platform (GCP), where it costs me approximately $8 pr month. GCP also have some free VM sizes. But they are not available in my region.

I have tried using Azure too. But the cost was higher, with worse performance. I assume because of heavy slicing.

Which ever cloud provider you choose. Select a linux variant when you get to the point where you are asked to pick an operation system. If you have a preference, go with that. I am using Debian.


If you are going to host Adguard Home on a Raspberry Pi, i would recommend that you do NOT open your firewall to the world, unless you know what you are doing.

For a VM hosted at a cloud provider, I recommend this firewall configuration:

  • tcp: 22 – only to your IP
  • tcp: 443 – only to your IP
  • tcp: 3000 – only to your IP, and only during initial setup.
  • tcp: 853 – open to the world
  • tcp: 80 – open to the world
  • udp: 784 – open to the world, if you are going to use it
  • icmp: – only your IP

Port 22

You will be using port 22 to connect to your VM through SSH. Your cloud provider will have information specific for how you need to connect to their VM.

By limiting the access to the port to your IP you will make it harder for potential attackers to get into your VM.

Port 443

This port can serve DNS over HTTPS. But it also provides the login interface to manage the Adguard Home instance.
I am a cautious guy. So i have personally decided to effectively disable DoH when on the go, to increase my security

I did open a github issue where the CTO of Adguard told me that it should be safe – provided you have a strong username/password. I trust his professional opinion. But with no rate limit, no way to monitor bruteforce attempts and no way to know if someone was successful i have decided, that for me, the right thing to do is limit the port to my own IP. Maybe it’s okay for you.

According to him, an other option would be to setup reverse proxy. But i have not explored that yet.

Port 3000

This port is used for first time configuration of Adguard Home. It is possible to do that configuration by pointing a docker volume to a local path, where you have a preconfigured config file waiting.
After the initial setup, you wont need to access the port again, and it should be closed in the firewall.

Port 583

Port 853 will be used to serve DNS over TLS. Devices running Android 9 and up natively supports DoT. This applies to all devices in our family. Which is why its not a problem that i block DNS over HTTPS in the firewall.

Port 80

This port will be used for certificate renewal. However, it also serves the Adguard Home UI. For this reason, I recommend that you enable the “Redirect to HTTPS automatically”. I will describe where that is done in the Installing Adguard Home section.

I am no security expert, but in my mind that provides some measure of security – provided that port 443 is only open to your IP.

Port 784

This is the only UDP port that you will be adding to the firewall. It is meant for the new DNS over QUIC, which Adguard has experimental support for. I like new and shiny stuff, so despite not having anything that can use it, I’ve got it configured so I’m ready. Don’t open it if you do not plan on using it.


No one but you need this, so you might as well keep it open only to your IP. Read more here.


You will need to buy a domain. There are lots of providers out there. Follow the documentation of the provider, and configure the domain – or a subdomain – to point to the IP of your server.

If you are not sending emails from your domain, you might want to add a txt record to disable emails from your domain to prevent email spoofing. Add this as a txt record.

v=spf1 -all

Installing docker

This might be the easiest part of the tutorial. If you visit https://get.docker.com you can see a convenience script they provide. In the first part, you will see these commands:

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sh get-docker.sh
$ sudo usermod -aG docker <your-user>Code language: Bash (bash)

SSH into your VM, or Raspberry PI, and run them Log out and back in for the user group change to take effect. When it is done, you have docker. Tadaa!

Next thing is configuring the log driver. You can read more about that here.

sudo nano /etc/docker/daemon.jsonCode language: Bash (bash)

Insert the following text, and save.

"log-driver": "local"
}Code language: JSON / JSON with Comments (json)

Docker recently started supporting rootless mode, which increases your security. The script for installing it can be found here. Same procedure as the other script. I have not had time to try it out. If you have problems, use the way I first described. If you do need to remove it, you need to follow the instructions found here.

Installing docker-compose

Next up, is installing docker-compose. Newest instructions can be found here.
At the time of this writing, the current version is 1.28.5. It can be installed like this:

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose Code language: JavaScript (javascript)

The last command, will mark the downloaded docker-compose binary as executable.

Installing Adguard Home

Thanks to docker-compose, it is super simple to get adguard up and running. First thing to do, we need to create some folders. SSH into your server, and run these commands.

$ mkdir ~/adguard/work -p
$ mkdir ~/adguard/conf -pCode language: JavaScript (javascript)

Then you need to create a docker-compose.yml file using the following command.

$ nano docker-compose.yml

Paste in this text and save it by pressing CTRL + X. Confirm with Y and enter.

version: '3'
container_name: adguardhome
image: 'adguard/adguardhome:v0.105.2'
- '~/adguard/work:/opt/adguardhome/work'
- '~/adguard/conf:/opt/adguardhome/conf'
- '80:80/tcp'
- '443:443/tcp'
- '853:853/tcp'
- '3000:3000/tcp'
- '784:784/udp'
restart: alwaysCode language: YAML (yaml)

It sets a name, picks an image, binds a folder in the container to the folders you just created and opens ports between the container and the host – and ensures that the container will restart by it self.

Run this command to start Adguard home

$ docker-compose up -d

If you ever need to update Adguard home, just change the image tag in the docker compose. E.g. from v0.105.1 to v0.105.2 and run the docker-compose command again.

Configuring Adguard

Now open a browser, and go to yourdomain.com:3000

There you will be met with the initial configuration guide of Adguard home. You do not need to modify any settings.
When you get to the section where you set the username/password make sure you get a good combination. Either use a password vault + generator or be sure to follow this tip from XKDC.


If you are considering exposing port 443 to the world then you could also pick a long username like you pick your password, to increase the difficulty of a brute force attempt.

You can read about the settings interface here.

Here are some of my settings:

Upstream DNS: https://security.cloudflare-dns.com/dns-query
Cloudflare hosts one of the fastest, if not the fastest, dns reslover in the world. Privacy is important to them and using the security version also provides protection against known malicious domains.
If you use this one, you do not need to enable “Adguard browsing security web service”.
Follow the link in the menu if you want to see a list of DNS providers, that Adguard has collected for your convenience.

Bootstrap DNS: Also Cloudflare DNS

Tick the box the Enable DNSSEC

After the initial configuration is done, go to your firewall – and block port 3000. You won’t need it again. You can also update the docker-compose.yml and remove port 3000 from the list of open ports.

Do not enable encryption yet or HTTPS redirect. We need to get a certificate.

Setting up a certificate

You can get a free certificate from letsencrypt.org using certbot.

Follow the instructions found here.

Select “None of the above” and then the linux variant you picked initially.
Stop after completing step 6. Prepare the Certbot command. Run the following commands

$ docker container stop adguardhome
$ sudo certbot certonly --standalone --preferred-chain "ISRG Root X1"Code language: JavaScript (javascript)

Follow the instructions from certbot. When it is done, you have got a certificate, with automatic renewal. Start Adguard again.

$ docker container start adguardhome

Now we need to create post and pre renewal scripts. First up, the pre renewal script.

$ sudo nano /etc/letsencrypt/renewal-hooks/pre/adguard.sh

The pre script should stop the container. So it must contain:

docker container stop adguardhome

Then the post script. It should copy the generated certificates to the volumes we created for Adguard and then it should start the container again.

$ sudo nano /etc/letsencrypt/renewal-hooks/post/adguard.sh

Replace <yourdomain.com> and <username> with the appropriate values. No angel brackets.

cp /etc/letsencrypt/live/<yourdomain.com>/fullchain.pem /home/<username>/adguard/work/fullchain.pem
cp /etc/letsencrypt/live/<yourdomain.com>/privkey.pem /home/<username>/adguard/work/privkey.pem
docker container start adguardhomeCode language: HTML, XML (xml)

Then assign the correct permissions to the newly created files.

$ sudo chmod 755 /etc/letsencrypt/renewal-hooks/pre/adguard.sh
$ sudo chmod 755 /etc/letsencrypt/renewal-hooks/post/adguard.sh

Test that it works.

$ sudo certbot renew --dry-run

So now, theres a certificate. Automatic renewal with pre and post scripts. Go to yourdomain.com and log into Adguard.

In the encryption settings, click the checkbox to enable it. Make sure the redirect option is enabled.

In the certificates section, check the option to Set a certificates file path.
Insert /opt/adguardhome/work/fullchain.pem in the first input box and /opt/adguardhome/work/privkey.pem in the 2nd. Adguard should check it, and inform you that you now have valid certificates.
Save the changes.

Connecting to the DNS server

If your router supports DoT, DoH or DoQ – go to your router settings and configure it to use your new DNS server. There are too many different routers to try and help you with that.
When you have it configured, you will now have network wide adblocking for any device connected to your network.

But, we want it on the go too. That’s why we went thru all the hassle of setting this up on a server after all. This article describes how to do it on android devices.

I don’t own any apple products, but iPhones etc also supports encrypted DNS if you use iOS 14+. This article here, gives some details. At the end of it there are configuration profile examples. You need to take one and modify it to work with your server. Unfortunately I don’t know anything about that subject, so you are on your own there.

This is too much. What options do i have?

If all of this is too much for your. You could always use some of the public encrypted DNS servers. Adguard has a list of known DNS providers. Some of them provide encrypted DNS.
You could also use Adguards own service. They will also block trackers and advertisements for you.

Thanks for reading – and good luck!