AdGuard Home on a VPS is a genuinely good idea, and almost every tutorial for it quietly sets you up to run an open DNS resolver on the public internet, which is a bad idea twice over: it invites abuse, and on a NAT IPv4 plan you cannot assume plain port 53 is one of your forwarded ports. The version that actually works here skips plain DNS entirely and serves encrypted DNS instead — DNS-over-HTTPS on 443, DNS-over-TLS on 853 — with port 53 kept off the public internet altogether.AdGuard Home auf einem VPS ist eine wirklich gute Idee, und fast jedes Tutorial dazu bringt dich stillschweigend dazu, einen offenen DNS-Resolver im öffentlichen Internet zu betreiben, was gleich doppelt eine schlechte Idee ist: Es lädt zu Missbrauch ein, und bei einem NAT-IPv4-Tarif kannst du nicht davon ausgehen, dass der einfache Port 53 zu deinen weitergeleiteten Ports gehört. Die Version, die hier tatsächlich funktioniert, überspringt einfaches DNS vollständig und liefert stattdessen verschlüsseltes DNS — DNS-over-HTTPS auf 443, DNS-over-TLS auf 853 —, wobei Port 53 komplett vom öffentlichen Internet ferngehalten wird.
A DNS resolver that anyone on the internet can query on UDP/TCP 53 is an open resolver, and open resolvers get abused for DNS amplification: an attacker spoofs your VPS's address into a small query, your server answers with a much larger response, and that response lands on the spoofed target instead of on the attacker. You do not have to misconfigure anything exotic to get here — "install AdGuard Home, open port 53, done" is exactly this failure mode, and the fix is not clever firewall rules, it is not exposing 53 publicly at all.Ein DNS-Resolver, den jeder im Internet auf UDP/TCP 53 abfragen kann, ist ein offener Resolver, und offene Resolver werden für DNS-Amplification missbraucht: Ein Angreifer fälscht die Adresse deines VPS in eine kleine Anfrage, dein Server antwortet mit einer viel größeren Antwort, und diese Antwort landet beim gefälschten Ziel statt beim Angreifer. Du musst dafür nichts Exotisches falsch konfigurieren — „AdGuard Home installieren, Port 53 öffnen, fertig“ ist genau dieses Fehlermuster, und die Lösung sind nicht clevere Firewall-Regeln, sondern 53 überhaupt nicht öffentlich zu exponieren.
There is also a plainer reason it does not fit a NAT VPS: NAT IPv4 gives you a shared address with a small, fixed set of forwarded ports, and whether 53 is among them is something you check in your own panel, not something to assume. The honest use of AdGuard Home here is as an encrypted DNS server reached over 443 or 853, with plain 53 bound to 127.0.0.1 or to a private VPN interface, never to the internet. Read NAT IPv4 vs a dedicated IP and NAT IPv4, ports and forwarding before you commit — they decide which of the two encrypted protocols you can actually expose.Es gibt auch einen schlichteren Grund, warum das nicht zu einem NAT-VPS passt: NAT-IPv4 gibt dir eine geteilte Adresse mit einer kleinen, festen Menge weitergeleiteter Ports, und ob 53 darunter ist, prüfst du in deinem eigenen Panel, statt es anzunehmen. Die ehrliche Nutzung von AdGuard Home hier ist als verschlüsselter DNS-Server, erreichbar über 443 oder 853, mit einfachem 53 gebunden an 127.0.0.1 oder eine private VPN-Schnittstelle, niemals ans Internet. Lies NAT IPv4 vs. dedizierte IP und NAT IPv4, Ports und Weiterleitung, bevor du dich festlegst — sie entscheiden, welches der beiden verschlüsselten Protokolle du überhaupt exponieren kannst.
Deploy Ubuntu 24.04 LTS, create a non-root user with your SSH key on it, disable password login, and default the firewall to deny before anything is exposed — connect to your VPS over SSH and secure your VPS cover that part. Then install Docker Engine from Docker's own apt repository, not the older package in the Ubuntu archive:Setze Ubuntu 24.04 LTS auf, lege einen Non-Root-User mit deinem SSH-Key darauf an, deaktiviere Passwort-Login, und setze die Firewall standardmäßig auf Ablehnen, bevor irgendetwas exponiert ist — über SSH mit deinem VPS verbinden und deinen VPS absichern decken diesen Teil ab. Installiere dann Docker Engine aus Dockers eigenem apt-Repository, nicht dem älteren Paket im Ubuntu-Archiv:
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
That last package gives you docker compose as a CLI plugin — never the standalone docker-compose script.Dieses letzte Paket gibt dir docker compose als CLI-Plugin — niemals das eigenständige docker-compose-Skript.
Add your non-root user to the docker group so docker compose works without sudo in front of it, then start a new shell for that to take effect:Füge deinen Non-Root-User der Gruppe docker hinzu, damit docker compose ohne vorangestelltes sudo funktioniert, und starte dann eine neue Shell, damit das wirksam wird:
sudo usermod -aG docker "$USER"
newgrp docker
Skip this and every docker compose command below fails with a permission error on /var/run/docker.sock, since that socket is owned root:docker on a fresh install.Überspringst du das, schlägt jeder docker compose-Befehl weiter unten mit einem Berechtigungsfehler auf /var/run/docker.sock fehl, da dieser Socket bei einer frischen Installation root:docker gehört.
One thing worth knowing before you write a compose file: Ubuntu 24.04 runs systemd-resolved by default, and it already listens on 127.0.0.53:53 for the host's own lookups. That does not block AdGuard Home from binding 53 on a different address, but it does mean a container asking for 53 on every interface can collide with it. You almost never need to fight this — the point of this setup is that AdGuard Home's public surface is 443 and 853, not 53. Only disable systemd-resolved if you specifically need AdGuard Home to own 127.0.0.1:53 for the host itself, and expect to redo /etc/resolv.conf by hand afterward.Eine Sache, die es sich zu wissen lohnt, bevor du eine Compose-Datei schreibst: Ubuntu 24.04 lässt standardmäßig systemd-resolved laufen, und das lauscht bereits auf 127.0.0.53:53 für die eigenen Lookups des Hosts. Das hindert AdGuard Home nicht daran, 53 auf einer anderen Adresse zu binden, bedeutet aber, dass ein Container, der 53 auf jeder Schnittstelle anfragt, damit kollidieren kann. Du musst das fast nie ausfechten — der Sinn dieses Setups ist ja gerade, dass die öffentliche Oberfläche von AdGuard Home 443 und 853 ist, nicht 53. Deaktiviere systemd-resolved nur, wenn du speziell willst, dass AdGuard Home 127.0.0.1:53 für den Host selbst besitzt, und rechne damit, /etc/resolv.conf danach von Hand neu einzurichten.
services:
adguardhome:
image: adguard/adguardhome:v0.107.55 # verify this exact tag exists on Docker Hub before you deploy — do not assume the version above is still current
restart: unless-stopped
volumes:
- ./conf:/opt/adguardhome/conf
- ./work:/opt/adguardhome/work
ports:
- "127.0.0.1:3000:3000"
- "443:443"
- "853:853"
- "127.0.0.1:53:53/tcp"
- "127.0.0.1:53:53/udp"
conf holds AdGuardHome.yaml, the whole configuration; work holds the query log and stats database. Bind-mount both to a real directory next to the compose file, not a named volume, so a backup is just copying ./conf and ./work with the container stopped. Port 3000 is the setup wizard and admin UI and it stays on loopback permanently — bring it up with docker compose up -d, then reach it the same way you would any other first-run admin panel on this box:conf enthält AdGuardHome.yaml, die gesamte Konfiguration; work enthält das Query-Log und die Statistik-Datenbank. Bind-mounte beide in ein echtes Verzeichnis neben der Compose-Datei, nicht als benanntes Volume, sodass ein Backup schlicht das Kopieren von ./conf und ./work bei gestopptem Container ist. Port 3000 ist der Einrichtungsassistent und die Admin-Oberfläche, und der bleibt dauerhaft auf Loopback — bring es mit docker compose up -d hoch, und erreiche es dann genauso, wie du jedes andere Erststart-Admin-Panel auf dieser Maschine erreichen würdest:
ssh -L 3000:127.0.0.1:3000 youruser@your-vps-ip
With that tunnel open, visit http://127.0.0.1:3000. The wizard asks for the web and DNS ports (leave the web one on 3000) and then the admin account — set a real password here, since this account can read every device's query history. Everything after this point, including encryption, gets configured through the same tunneled interface.Mit diesem geöffneten Tunnel besuche http://127.0.0.1:3000. Der Assistent fragt nach dem Web- und dem DNS-Port (lass den Web-Port auf 3000) und dann nach dem Admin-Konto — setze hier ein echtes Passwort, denn dieses Konto kann die Query-Historie jedes Geräts lesen. Alles danach, einschließlich Verschlüsselung, wird über dieselbe getunnelte Oberfläche konfiguriert.
Under Settings → Encryption, enable HTTPS/TLS with a real certificate rather than a self-signed one, since every client needs to trust it. Two honest routes: put Caddy in front for DNS-over-HTTPS specifically, letting it handle the certificate and reverse-proxy the DoH path to AdGuard Home; or hand AdGuard Home the certificate and key directly in the Encryption settings and let it terminate TLS itself for both DoH and DoT — the more direct route when DNS is the only thing this VPS does, since DoT is not an HTTP protocol a proxy like Caddy speaks. Either way you need a domain pointed at the VPS first; point your domain to your service covers the A record and propagation wait.Unter Settings → Encryption aktivierst du HTTPS/TLS mit einem echten Zertifikat statt einem selbstsignierten, denn jeder Client muss ihm vertrauen. Zwei ehrliche Wege: Caddy davorschalten, speziell für DNS-over-HTTPS, und es das Zertifikat handhaben und den DoH-Pfad per Reverse-Proxy zu AdGuard Home leiten lassen; oder AdGuard Home das Zertifikat und den Key direkt übergeben in den Encryption-Einstellungen und es TLS selbst terminieren lassen, für DoH und DoT gleichermaßen — der direktere Weg, wenn DNS das Einzige ist, was dieser VPS tut, denn DoT ist kein HTTP-Protokoll, das ein Proxy wie Caddy spricht. So oder so brauchst du zuerst eine Domain, die auf den VPS zeigt; deine Domain auf deinen Dienst zeigen lassen deckt den A-Eintrag und die Wartezeit auf die Propagierung ab.
The compose file above already picked a route: it publishes host 443 and 853 straight into the adguardhome service, which is the direct-TLS path. If you want Caddy in front instead, drop "443:443" from that service, add a separate caddy service that publishes 443, and point its reverse_proxy at AdGuard Home's DoH port over the compose network rather than at a published host port — DoT on 853 still has to reach AdGuard Home directly either way, since Caddy cannot terminate it.Die Compose-Datei oben hat sich bereits für einen Weg entschieden: Sie veröffentlicht die Host-Ports 443 und 853 direkt in den adguardhome-Dienst, was der direkte TLS-Weg ist. Willst du stattdessen Caddy davor haben, entferne "443:443" aus diesem Dienst, füge einen separaten caddy-Dienst hinzu, der 443 veröffentlicht, und richte dessen reverse_proxy auf den DoH-Port von AdGuard Home über das Compose-Netzwerk statt auf einen veröffentlichten Host-Port — DoT auf 853 muss so oder so weiterhin AdGuard Home direkt erreichen, da Caddy es nicht terminieren kann.
Whether either protocol is actually reachable from outside depends entirely on your plan's forwarded ports, which is the part most AdGuard Home tutorials skip:Ob eines der beiden Protokolle von außen überhaupt erreichbar ist, hängt vollständig von den weitergeleiteten Ports deines Tarifs ab, was der Teil ist, den die meisten AdGuard-Home-Tutorials überspringen:
Read NAT IPv4 vs a dedicated IP before assuming either port is available — check your own panel rather than a tutorial.Lies NAT IPv4 vs. dedizierte IP, bevor du annimmst, dass einer der beiden Ports verfügbar ist — prüfe dein eigenes Panel, nicht ein Tutorial.
Under Filters → DNS blocklists, AdGuard Home ships with well-known public blocklists you enable with a checkbox, and you can add any other list by URL the same way. Filters → Allowlists take priority over blocklists, which matters the first time a legitimate service gets caught by an overzealous list and needs an exception without disabling the whole list.Unter Filters → DNS blocklists liefert AdGuard Home bekannte öffentliche Blocklisten mit, die du per Checkbox aktivierst, und du kannst jede weitere Liste genauso per URL hinzufügen. Filters → Allowlists haben Vorrang vor Blocklisten, was wichtig wird, sobald ein legitimer Dienst das erste Mal von einer übereifrigen Liste erfasst wird und eine Ausnahme braucht, ohne die ganze Liste zu deaktivieren.
The query log records every lookup AdGuard Home makes on your behalf — domain, client, timestamp, decision. That visibility is the actual reason to self-host this instead of trusting a third party's resolver, and it is also, for the same reason, the most sensitive data the setup produces: a full history of what every device looked up. Retention is configurable under Settings → General settings, down to a short window or off entirely. Set it to whatever period you would be comfortable someone else reading, and remember it lives in the work volume alongside the stats database.Das Query-Log verzeichnet jede Abfrage, die AdGuard Home in deinem Auftrag macht — Domain, Client, Zeitstempel, Entscheidung. Diese Sichtbarkeit ist der eigentliche Grund, das selbst zu hosten, statt dem Resolver eines Dritten zu vertrauen, und aus demselben Grund sind es auch die sensibelsten Daten, die das Setup erzeugt: eine vollständige Historie dessen, wonach jedes Gerät gesucht hat. Die Aufbewahrung ist unter Settings → General settings konfigurierbar, bis hinunter zu einem kurzen Fenster oder ganz aus. Setze sie auf eine Dauer, bei der es dir recht wäre, wenn jemand anderes sie läse, und denk daran, dass sie im work-Volume neben der Statistik-Datenbank liegt.
Stop the container before copying conf and work off the box, so you are not reading a file mid-write:Stoppe den Container, bevor du conf und work von der Maschine kopierst, damit du keine Datei mitten im Schreiben liest:
docker compose stop adguardhome
tar czf adguard-backup-$(date +%F).tar.gz conf work
docker compose start adguardhome
Move that archive off the VPS itself — a copy on the same disk as the thing it backs up is not a backup, and back up your VPS covers what we actually do and do not provide by default.Schaffe dieses Archiv vom VPS selbst weg — eine Kopie auf derselben Festplatte wie das, was sie sichert, ist kein Backup, und Backup deines VPS beschreibt, was wir tatsächlich standardmäßig bereitstellen und was nicht.
Update by bumping the pinned tag, never by tracking latest:Aktualisiere, indem du das gepinnte Tag anhebst, niemals indem du latest verfolgst:
image: adguard/adguardhome:v0.107.56 # verify this exact tag exists on Docker Hub before you deploy — do not assume the version above is still current
docker compose pull
docker compose up -d
The thing that bites later: latest looks convenient until an unattended pull picks up a new major version with a changed default, on a service every device depends on for DNS. Pin an explicit tag and read the release notes before you bump it, so you control when that risk shows up instead of finding out when a phone stops resolving anything.Die Sache, die später zubeißt: latest wirkt bequem, bis ein unbeaufsichtigtes Pull eine neue Major-Version mit geändertem Standardverhalten zieht, bei einem Dienst, von dem jedes Gerät für DNS abhängt. Pinne ein explizites Tag und lies die Release-Notes, bevor du es anhebst, damit du kontrollierst, wann dieses Risiko auftaucht, statt es zu bemerken, wenn ein Handy nichts mehr auflöst.
Once encryption is live, each client needs one of two things: a DoH URL (https://dns.example.com/dns-query) for apps and operating systems that support it natively, or a DoT hostname (dns.example.com, port 853) for the "private DNS" setting most modern phones already expose. Support varies by platform: Android has a native Private DNS field under network settings that takes a DoT hostname directly, no install needed. iOS has no equivalent toggle — pointing it at your own DoH or DoT server means installing a small signed DNS-settings configuration profile once, still not an app, just a profile you generate or download and confirm in Settings. Desktop browsers with a Secure DNS or DNS-over-HTTPS toggle just need the DoH URL typed in; nothing extra to install there either.Sobald die Verschlüsselung läuft, braucht jeder Client eines von zwei Dingen: eine DoH-URL (https://dns.example.com/dns-query) für Apps und Betriebssysteme, die das nativ unterstützen, oder einen DoT-Hostnamen (dns.example.com, Port 853) für die „Privates DNS“-Einstellung, die die meisten modernen Telefone bereits mitbringen. Die Unterstützung variiert je nach Plattform: Android hat unter den Netzwerkeinstellungen ein natives Private-DNS-Feld, das direkt einen DoT-Hostnamen entgegennimmt, keine Installation nötig. iOS hat keinen entsprechenden Schalter — es auf deinen eigenen DoH- oder DoT-Server zu richten bedeutet, einmalig ein kleines signiertes DNS-Einstellungsprofil zu installieren, immer noch keine App, sondern nur ein Profil, das du generierst oder herunterlädst und in den Einstellungen bestätigst. Desktop-Browser mit einem Secure-DNS- oder DNS-over-HTTPS-Schalter brauchen nur die eingetippte DoH-URL; auch dort ist nichts zusätzlich zu installieren.
AdGuard Home is a single static Go binary with no separate database process, and it idles in tens of MiB of RAM even with a full query log running. Disk is dominated entirely by retention length, and a short window on even a busy home's worth of devices stays a rounding error against a 25 GB disk. A 1 vCPU, 1 GiB Starter runs this without noticing; moving up a tier only matters if the same box is also doing other work.AdGuard Home ist eine einzelne statische Go-Binärdatei ohne separaten Datenbankprozess, und sie läuft im Leerlauf mit zweistelligen MiB an RAM, selbst mit vollständig laufendem Query-Log. Der Speicherplatz wird vollständig von der Aufbewahrungsdauer dominiert, und ein kurzes Fenster bleibt selbst für die Geräte eines geschäftigen Haushalts ein Rundungsfehler gegenüber einer 25-GB-Festplatte. Ein 1-vCPU-1-GiB-Starter betreibt das, ohne es zu merken; eine Stufe höher zu gehen ist nur relevant, wenn dieselbe Maschine noch andere Arbeit erledigt.
Full disclosure: this is what we sell. AdGuard Home idles in tens of MiB of RAM, so a 1 vCPU, 1 GiB Starter runs it with room to spare; move up only if the same box is also doing other work.Zur vollen Transparenz: Das ist, was wir verkaufen. AdGuard Home läuft im Leerlauf mit zweistelligen MiB an RAM, ein 1-vCPU-1-GiB-Starter betreibt es also mit Reserven; steige nur höher, wenn dieselbe Maschine noch andere Arbeit erledigt.
Linux KVM VPS — EUR 4.99 to EUR 59.99 a month, on our own single-tenant bare metal in Dallas, TX and Charlotte, NC. Full hardware virtualisation (KVM), your own kernel, full root. Six tiers, vps-starter to vps-ultra. Starter is 1 vCPU, 1 GiB RAM, 25 GB disk.Linux-KVM-VPS — 4,99 bis 59,99 EUR im Monat, auf unserer eigenen Single-Tenant-Bare-Metal-Hardware in Dallas, TX und Charlotte, NC. Vollständige Hardware-Virtualisierung (KVM), eigener Kernel, volles Root. Sechs Tarife, vps-starter bis vps-ultra. Starter hat 1 vCPU, 1 GiB RAM, 25 GB Speicher.
You order in the shop, pay by card (Stripe) or SEPA bank transfer, and your login details are e-mailed to you once the service is set up. Support is e-mail, run by one person, with no guaranteed response time. All prices are final totals under the German small-business rule (§19 UStG); no VAT is added or shown.Du bestellst im Shop, zahlst per Karte (Stripe) oder SEPA-Überweisung, und deine Zugangsdaten werden dir per E-Mail zugeschickt, sobald der Dienst eingerichtet ist. Support läuft per E-Mail, von einer einzelnen Person betrieben, ohne garantierte Reaktionszeit. Alle Preise sind Endpreise. Gemäß § 19 UStG wird keine Umsatzsteuer ausgewiesen.
Order vps-starter → · Linux KVM VPS overviewvps-starter bestellen → · Übersicht Linux-KVM-VPS
Written by the person who runs overnight.host: a small, honest hosting company on dedicated bare metal — Linux VPS, game servers, web hosting. Live status at up.overnight.host.Geschrieben von der Person, die overnight.host betreibt: ein kleines, ehrliches Hosting-Unternehmen auf dedizierter Bare-Metal-Hardware — Linux-VPS, Gameserver, Webhosting. Live-Status unter up.overnight.host.
You can, but you should not. An open resolver on 53 gets scanned and abused for DNS amplification attacks, and on most NAT IPv4 plans you cannot forward that port to yourself anyway. Encrypted DNS on 443 or 853 avoids both problems.Du kannst, aber du solltest nicht. Ein offener Resolver auf 53 wird gescannt und für DNS-Amplification-Angriffe missbraucht, und bei den meisten NAT-IPv4-Tarifen kannst du diesen Port ohnehin nicht zu dir weiterleiten. Verschlüsseltes DNS auf 443 oder 853 vermeidet beide Probleme.
Not for DoH or DoT. Both work over a plain NAT IPv4 plan as long as 443 or 853 is among your provider's forwarded ports — check NAT IPv4 vs a dedicated IP for your plan. A dedicated IPv4 only becomes relevant if you specifically want plain port 53 open, and even then it should stay private.Nicht für DoH oder DoT. Beide funktionieren über einen einfachen NAT-IPv4-Tarif, solange 443 oder 853 zu den weitergeleiteten Ports deines Providers gehört — prüfe NAT IPv4 vs. dedizierte IP für deinen Tarif. Eine dedizierte IPv4 wird erst relevant, wenn du speziell den einfachen Port 53 offen haben willst, und selbst dann sollte er privat bleiben.
systemd-resolved already holds 127.0.0.53:53 for the host's own lookups on Ubuntu 24.04, so a container asking for 53 on every interface can collide with it. This setup almost never needs plain 53 at all; if you do, bind it to a specific private interface instead of fighting systemd-resolved for loopback.systemd-resolved hält auf Ubuntu 24.04 bereits 127.0.0.53:53 für die eigenen Lookups des Hosts, sodass ein Container, der 53 auf jeder Schnittstelle anfragt, damit kollidieren kann. Dieses Setup braucht so gut wie nie überhaupt einfaches 53; falls doch, binde es an eine bestimmte private Schnittstelle, statt mit systemd-resolved um Loopback zu kämpfen.
The opposite: the log stays on your own VPS, under your own retention setting, readable only by whoever can access that box. That is the point of running it yourself — you decide how long it exists and who can see it, instead of taking a provider's policy on faith.Das Gegenteil: Das Log bleibt auf deinem eigenen VPS, unter deiner eigenen Aufbewahrungseinstellung, lesbar nur von dem, der Zugriff auf diese Maschine hat. Das ist der Sinn davon, es selbst zu betreiben — du entscheidest, wie lange es existiert und wer es sehen kann, statt der Richtlinie eines Anbieters blind zu vertrauen.
No. Filtering happens when AdGuard Home answers a query, so a device has to actually send it queries — over DoH, DoT, or plain DNS on a private interface — to get filtered answers back.Nein. Filterung passiert, wenn AdGuard Home eine Anfrage beantwortet; ein Gerät muss ihm also tatsächlich Anfragen schicken — über DoH, DoT oder einfaches DNS auf einer privaten Schnittstelle —, um gefilterte Antworten zurückzubekommen.
Prices are final totals; no VAT is shown (§19 UStG). Need something the shop does not list? Email us for a written offer.Alle Preise sind Endpreise ohne ausgewiesene USt. (§19 UStG). Du brauchst etwas, das nicht im Shop steht? Schreib uns für ein schriftliches Angebot.
Order now →Jetzt bestellen → Request a custom configIndividuelle Konfiguration anfragen