ntfy does one thing: PUT or POST a message to a topic URL, and every phone, script, or browser tab subscribed to it gets that message within a second or two. No API keys per app, no account tiers, no per-message billing — just a URL you make up. Run it yourself and the real work is making sure that URL isn't wide open to the internet.ntfy kann eine Sache: eine Nachricht per PUT oder POST an eine Topic-URL schicken, und jedes Handy, Skript oder Browser-Tab, das dieses Topic abonniert hat, bekommt die Nachricht innerhalb von ein, zwei Sekunden. Keine API-Keys pro App, keine Account-Stufen, keine Abrechnung pro Nachricht — nur eine URL, die du dir selbst ausdenkst. Hostest du es selbst, besteht die eigentliche Arbeit darin, sicherzustellen, dass diese URL nicht offen für das gesamte Internet steht.
ntfy ships two ways: a single static Go binary with .deb/.rpm packages, or a Docker image. On a VPS you already run Docker on, the container is the path of least friction and the one this guide uses — start from a box you've already reached over connect to your VPS over SSH, with a non-root user and a firewall on before anything touches the internet.ntfy kommt auf zwei Wegen: als einzelne statische Go-Binary mit .deb/.rpm-Paketen oder als Docker-Image. Läuft auf deinem VPS bereits Docker, ist der Container der Weg des geringsten Widerstands und der, den diese Anleitung verwendet — starte von einer Maschine, die du bereits erreicht hast über Über SSH mit deinem VPS verbinden, mit einem Non-Root-User und einer aktiven Firewall, bevor irgendetwas das Internet berührt.
Pin a real tag rather than latest — an unpinned tag lets the next docker compose pull hand you a new major version and a changed config key with no warning:Pinne einen echten Tag statt latest — ein ungepinnter Tag lässt den nächsten docker compose pull dir kommentarlos eine neue Major-Version und einen geänderten Config-Key unterjubeln:
services:
ntfy:
image: binwiederhajo/ntfy:v2.11.0 # pin a real tag — check the image's tag list on Docker Hub for the current release
command: serve
environment:
- TZ=UTC
volumes:
- /etc/ntfy:/etc/ntfy
- /var/cache/ntfy:/var/cache/ntfy
- /var/lib/ntfy:/var/lib/ntfy
ports:
- "127.0.0.1:8080:80"
restart: unless-stopped
Bind the published port to 127.0.0.1 — the only thing that should reach it directly is the reverse proxy on the same host, not the open internet, same as any other app behind Caddy.Binde den veröffentlichten Port an 127.0.0.1 — das Einzige, was ihn direkt erreichen soll, ist der Reverse-Proxy auf demselben Host, nicht das offene Internet, genau wie bei jeder anderen App hinter Caddy.
Prefer the binary under systemd instead? The install docs cover the .deb package and the ntfy.service unit it installs — everything about server.yml below is identical either way, only the host path differs.Bevorzugst du stattdessen die Binary unter systemd? Die Install-Dokumentation behandelt das .deb-Paket und die ntfy.service-Unit, die es installiert — alles rund um server.yml weiter unten ist so oder so identisch, nur der Pfad auf dem Host unterscheidet sich.
ntfy reads one YAML file, and most of its defaults are already sane. The ones worth setting deliberately on day one:ntfy liest eine einzige YAML-Datei, und die meisten ihrer Standardwerte sind bereits sinnvoll. Diejenigen, die du am ersten Tag bewusst setzen solltest:
base-url: "https://ntfy.example.com"
cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "12h"
attachment-cache-dir: "/var/cache/ntfy/attachments"
auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"
behind-proxy: true
base-url must be the exact public HTTPS URL you'll use — it's stamped into links ntfy hands back in its own API and the phone app's server list, so a mismatch shows up as broken links in the app, not a server error. cache-file is a SQLite database holding recent messages so a client that was briefly offline can catch up; cache-duration controls how long a message sits there before ntfy drops it, and 12 hours is plenty since the whole point is that messages arrive live. attachment-cache-dir is where uploaded files land; give it its own path so you can watch its size apart from the message cache, and check the server config reference for the size and expiry keys before you let people attach anything large. behind-proxy: true matters the moment Caddy sits in front: without it, ntfy sees every request coming from 127.0.0.1, and rate limiting and logging track the proxy instead of the actual sender.base-url muss exakt die öffentliche HTTPS-URL sein, die du verwendest — sie wird in Links eingestempelt, die ntfy über seine eigene API und die Serverliste der Handy-App zurückgibt, sodass ein Mismatch sich als kaputte Links in der App zeigt, nicht als Serverfehler. cache-file ist eine SQLite-Datenbank, die kürzliche Nachrichten vorhält, damit ein Client, der kurz offline war, aufholen kann; cache-duration bestimmt, wie lange eine Nachricht dort liegt, bevor ntfy sie verwirft, und 12 Stunden reichen völlig, da der ganze Sinn darin besteht, dass Nachrichten live ankommen. attachment-cache-dir ist der Ort, an dem hochgeladene Dateien landen; gib ihm einen eigenen Pfad, damit du seine Größe getrennt vom Nachrichten-Cache beobachten kannst, und prüfe die Server-Konfigurationsreferenz auf die Größen- und Ablauf-Keys, bevor du Leute irgendetwas Großes anhängen lässt. behind-proxy: true wird wichtig, sobald Caddy davorsteht: Ohne diese Einstellung sieht ntfy jede Anfrage als von 127.0.0.1 kommend, und Rate-Limiting sowie Logging verfolgen den Proxy statt des tatsächlichen Absenders.
Create the directories first, since a bind mount to a nonexistent host path is just an empty directory Docker created as root:Lege zuerst die Verzeichnisse an, denn ein Bind-Mount auf einen nicht existierenden Host-Pfad ist nur ein leeres Verzeichnis, das Docker als root erstellt hat:
sudo mkdir -p /etc/ntfy /var/cache/ntfy /var/lib/ntfy
sudo touch /etc/ntfy/server.yml
Paste the config above into server.yml, then docker compose up -d.Füge die Konfiguration von oben in server.yml ein und führe dann docker compose up -d aus.
This is the one setting in the entire guide that actually matters for security. ntfy topics are just URLs — anyone who knows or guesses ntfy.example.com/alerts can publish to it and, by default, subscribe too. That's fine on the public ntfy.sh, where everyone assumes it's open. On your own server with the default wide-open access, a stranger can spam your phone or read whatever you're pushing through it.Das ist die eine Einstellung in dieser gesamten Anleitung, die für die Sicherheit wirklich zählt. ntfy-Topics sind einfach URLs — wer ntfy.example.com/alerts kennt oder errät, kann dort veröffentlichen und standardmäßig auch abonnieren. Auf dem öffentlichen ntfy.sh ist das in Ordnung, dort geht jeder davon aus, dass es offen ist. Auf deinem eigenen Server mit dem standardmäßig weit offenen Zugriff kann ein Fremder dein Handy zuspammen oder mitlesen, was auch immer du dadurch schickst.
auth-default-access: "deny-all" flips that: nobody can read or write any topic unless you say so explicitly. Create yourself an admin user, then grant access per topic:auth-default-access: "deny-all" dreht das um: Niemand kann irgendein Topic lesen oder schreiben, außer du erlaubst es ausdrücklich. Leg dir selbst einen Admin-User an und vergib dann Zugriff pro Topic:
docker compose exec ntfy ntfy user add --role=admin phil
docker compose exec ntfy ntfy access phil 'alerts' read-write
docker compose exec ntfy ntfy access '*' 'public-status' read-only
The last line is the pattern for a topic you want anyone to read without an account — a status feed — while everything else stays locked to named users. For scripts and cron jobs, issue a token instead of using a username, so a leaked credential can be revoked without changing your own login:Die letzte Zeile ist das Muster für ein Topic, das jeder ohne Account lesen soll — etwa ein Status-Feed —, während alles andere auf namentliche Nutzer beschränkt bleibt. Für Skripte und Cronjobs vergib ein Token statt einen Benutzernamen zu verwenden, damit sich ein geleaktes Credential widerrufen lässt, ohne dein eigenes Login zu ändern:
docker compose exec ntfy ntfy token add phil
Use the printed token as a bearer credential: curl -H "Authorization: Bearer tk_xxxxxxxxxxxx" -d "backup finished" https://ntfy.example.com/alerts. Anyone with that token can publish to whatever phil can write to and nothing else — the right blast radius for a token embedded in a shell script.Verwende das ausgegebene Token als Bearer-Credential: curl -H "Authorization: Bearer tk_xxxxxxxxxxxx" -d "backup finished" https://ntfy.example.com/alerts. Wer dieses Token hat, kann veröffentlichen, wozu auch immer phil schreiben darf, und sonst nichts — der richtige Schadensradius für ein Token, das in einem Shell-Skript eingebettet ist.
Caddy's automatic HTTPS makes this close to a non-event:Caddys automatisches HTTPS macht daraus fast ein Nicht-Ereignis:
ntfy.example.com {
reverse_proxy 127.0.0.1:8080
}
That's the whole file — ntfy's live subscriptions use a long-lived HTTP connection (chunked streaming, or a WebSocket at /<topic>/ws), and Caddy proxies both transparently. Point an A record at the box, let it propagate, and Caddy requests the certificate itself on first traffic.Das ist die ganze Datei — ntfys Live-Abonnements nutzen eine langlebige HTTP-Verbindung (Chunked Streaming oder ein WebSocket unter /<topic>/ws), und Caddy proxied beides transparent. Richte einen A-Eintrag auf die Maschine, lass ihn sich verbreiten, und Caddy fordert das Zertifikat selbst beim ersten Traffic an.
Publishing and subscribing both need something to reach your server from the outside — a script PUTs a message in, your phone holds a connection open to receive it. That's inbound, and it's exactly where a shared IPv4 address bites.Sowohl Veröffentlichen als auch Abonnieren brauchen etwas, das deinen Server von außen erreicht — ein Skript schickt eine Nachricht per PUT hinein, dein Handy hält eine Verbindung offen, um sie zu empfangen. Das ist eingehender Traffic, und genau da beißt eine geteilte IPv4-Adresse.
If your plan gives you NAT IPv4 — a shared address with a dedicated SSH port and a small number of other forwarded ports, rather than 80 and 443 of your own — a plain https://ntfy.example.com on the standard port won't reach your box. Whether 443 is among your plan's forwarded ports varies, so check before you build around it. Three honest ways to handle it:Gibt dir dein Plan NAT-IPv4 — eine geteilte Adresse mit einem dedizierten SSH-Port und einer kleinen Anzahl weiterer weitergeleiteter Ports, statt eigenen 80 und 443 —, erreicht ein einfaches https://ntfy.example.com auf dem Standardport deine Maschine nicht. Ob 443 zu den weitergeleiteten Ports deines Plans gehört, variiert, also prüfe das, bevor du darauf aufbaust. Drei ehrliche Wege, damit umzugehen:
https://ntfy.example.com:41022. Automatic HTTPS still needs port 80 or 443 reachable for the ACME challenge, so a forwarded high port alone won't get Caddy a certificate — either get 443 forwarded specifically, or switch to a DNS-01 challenge so issuance stops depending on any inbound port. The stock caddy package and the official Docker image ship with no DNS provider plugins built in, though — a tls { dns <provider> <api-token> } block only works on a build that has that provider's module compiled in, e.g. xcaddy build --with github.com/caddy-dns/<provider>, or a community image already built that way. Paste it into a stock Caddyfile and Caddy refuses to start over the unrecognized dns subdirective. Every client then needs the non-standard port typed in explicitly, phone apps included.Nutze den weitergeleiteten Port, den du hast, z. B. https://ntfy.example.com:41022. Automatisches HTTPS braucht trotzdem Port 80 oder 443 erreichbar für die ACME-Challenge, sodass ein weitergeleiteter hoher Port allein Caddy kein Zertifikat verschafft — entweder lässt du dir gezielt 443 weiterleiten, oder du wechselst zu einer DNS-01-Challenge, damit die Ausstellung von keinem eingehenden Port mehr abhängt. Das Standard-caddy-Paket und das offizielle Docker-Image bringen allerdings keine DNS-Provider-Plugins eingebaut mit — ein tls { dns <provider> <api-token> }-Block funktioniert nur auf einem Build, in das das Modul dieses Providers einkompiliert ist, z. B. xcaddy build --with github.com/caddy-dns/<provider>, oder einem Community-Image, das schon so gebaut ist. Fügst du das in ein Standard-Caddyfile ein, weigert sich Caddy, wegen der nicht erkannten dns-Unterdirektive zu starten. Jeder Client braucht dann den nicht standardmäßigen Port explizit eingetippt, Handy-Apps eingeschlossen.NAT IPv4 vs a dedicated IP and NAT IPv4, ports and forwarding cover what your plan's NAT setup actually gives you before you commit to one of these.NAT IPv4 vs. dedizierte IP und NAT IPv4, Ports und Weiterleitung zeigen, was das NAT-Setup deines Plans tatsächlich hergibt, bevor du dich für eine dieser Optionen entscheidest.
Android and the desktop clients connect to any server you type in, behaving exactly as they do against ntfy.sh — add your server's URL when you subscribe to a topic, and that's the whole setup.Android und die Desktop-Clients verbinden sich mit jedem Server, den du eingibst, und verhalten sich dabei genau so wie gegen ntfy.sh — trag die URL deines Servers ein, wenn du ein Topic abonnierst, und das ist schon das gesamte Setup.
iOS is the one documented exception. Apple's push system requires every app to route notifications through APNs, and a self-hosted server has no way to talk to APNs directly. To get instant delivery on iOS against your own server, the ntfy docs describe pointing your instance at an upstream relay — upstream-base-url: "https://ntfy.sh" in server.yml — so your server forwards just enough of a poll to ntfy.sh to trigger the actual Apple push, without ntfy.sh seeing your message content. It's documented behavior, worth reading in the iOS section of the subscribe docs before deciding it's a trade-off you want for a given topic.iOS ist die eine dokumentierte Ausnahme. Apples Push-System verlangt, dass jede App Benachrichtigungen über APNs leitet, und ein selbst gehosteter Server hat keine Möglichkeit, direkt mit APNs zu sprechen. Um auf iOS gegen deinen eigenen Server sofortige Zustellung zu bekommen, beschreibt die ntfy-Dokumentation, deine Instanz auf ein Upstream-Relay zeigen zu lassen — upstream-base-url: "https://ntfy.sh" in server.yml —, sodass dein Server gerade genug von einem Poll an ntfy.sh weiterleitet, um den eigentlichen Apple-Push auszulösen, ohne dass ntfy.sh deinen Nachrichteninhalt sieht. Das ist dokumentiertes Verhalten, lesenswert im iOS-Abschnitt der Subscribe-Dokumentation, bevor du entscheidest, ob das ein Trade-off ist, den du für ein bestimmtes Topic eingehen willst.
A publish is one HTTP request, so anything running curl is an integration:Eine Veröffentlichung ist ein einziger HTTP-Request, also ist alles, was curl ausführen kann, eine Integration:
* * * * * /opt/backup.sh || curl -H "Authorization: Bearer tk_xxxxxxxxxxxx" -d "backup.sh failed on $(hostname)" https://ntfy.example.com/alerts
For Uptime Kuma, there's no dedicated setup beyond pointing its generic Webhook notification (see self-hosting Uptime Kuma on a VPS) at a topic URL with your token in the header — Kuma sends a JSON POST and ntfy expects a plain-text body by default, so add a short message template in Kuma's webhook settings rather than forwarding the raw JSON. For a priority or a title on any of these, add the X-Priority and X-Title headers documented on ntfy's publish docs.Für Uptime Kuma gibt es kein eigenes Setup, außer seine generische Webhook-Benachrichtigung (siehe Uptime Kuma selbst hosten auf einem VPS) auf eine Topic-URL mit deinem Token im Header zu richten — Kuma schickt einen JSON-POST, und ntfy erwartet standardmäßig einen Plain-Text-Body, füge also in Kumas Webhook-Einstellungen eine kurze Nachrichtenvorlage hinzu, statt das rohe JSON weiterzuleiten. Für eine Priorität oder einen Titel bei jedem davon füge die X-Priority- und X-Title-Header hinzu, die in ntfys Publish-Dokumentation dokumentiert sind.
Everything that matters lives in two SQLite files and a directory: cache.db (recent message metadata, not the files themselves), user.db (accounts, tokens, access rules), and attachment-cache-dir — the actual uploaded attachments sit there as plain files, not as blobs inside cache.db. Losing cache.db costs only in-flight messages; losing user.db means rebuilding every grant by hand; skip the attachments directory and every uploaded file is gone even though both databases restored cleanly. The compose file above bind-mounts /etc/ntfy, /var/cache/ntfy, and /var/lib/ntfy from the host rather than using named volumes, so both databases are already plain files at those exact paths — back them up on the host, no docker compose exec needed:Alles, was zählt, steckt in zwei SQLite-Dateien und einem Verzeichnis: cache.db (Metadaten kürzlicher Nachrichten, nicht die Dateien selbst), user.db (Accounts, Tokens, Zugriffsregeln) und attachment-cache-dir — die tatsächlich hochgeladenen Anhänge liegen dort als einfache Dateien, nicht als Blobs innerhalb von cache.db. Verlierst du cache.db, kostet das nur Nachrichten, die gerade unterwegs waren; verlierst du user.db, musst du jede Berechtigung von Hand neu aufbauen; lässt du das Attachments-Verzeichnis aus, ist jede hochgeladene Datei weg, obwohl beide Datenbanken sauber wiederhergestellt wurden. Die Compose-Datei von oben bindet /etc/ntfy, /var/cache/ntfy und /var/lib/ntfy per Bind-Mount vom Host ein, statt Named Volumes zu verwenden, sodass beide Datenbanken bereits als einfache Dateien an genau diesen Pfaden liegen — sichere sie auf dem Host, ganz ohne docker compose exec:
sudo apt install -y sqlite3
sqlite3 /var/cache/ntfy/cache.db ".backup /var/cache/ntfy/cache-backup.db"
sqlite3 /var/lib/ntfy/user.db ".backup /var/lib/ntfy/user-backup.db"
tar czf ntfy-attachments-backup.tar.gz -C /var/cache/ntfy attachments
Copy those files off the VPS — back up your VPS covers what off-box backup means, and a copy on the same disk as the server it backs up isn't one.Kopiere diese Dateien vom VPS herunter — Backup deines VPS beschreibt, was Backup abseits der Maschine bedeutet, und eine Kopie auf derselben Platte wie der Server, den sie sichert, ist keins.
ntfy is written in Go with no external database and no build step at runtime: a handful of topics and a few dozen connected subscribers idles well under 100 MB of RAM. Disk is dominated by cache-duration and attachment settings, not the software itself — with the defaults above and no large attachments, the whole thing fits inside a few hundred MB. The 1 GiB Starter tier and its 25 GB of disk cover this with room for the OS, Docker, and Caddy alongside it. What pushes you up a tier is attachments — if people routinely push multi-megabyte files through it, budget the disk for that, or move to a machine with more of both.ntfy ist in Go geschrieben, ohne externe Datenbank und ohne Build-Schritt zur Laufzeit: eine Handvoll Topics und ein paar Dutzend verbundene Abonnenten laufen im Leerlauf deutlich unter 100 MB RAM. Der Speicherplatz wird von cache-duration und den Attachment-Einstellungen dominiert, nicht von der Software selbst — mit den Standardwerten von oben und ohne große Anhänge passt das Ganze in ein paar hundert MB. Der 1-GiB-Starter-Tarif und seine 25 GB Speicher decken das mit Raum für OS, Docker und Caddy daneben. Was dich eine Stufe höher treibt, sind Anhänge — schieben Leute regelmäßig mehrere Megabyte große Dateien durch, plane den Speicherplatz dafür ein oder wechsle auf eine Maschine mit mehr von beidem.
Full disclosure: this is what we sell. ntfy idles under 100 MB even with a handful of subscribers and topics, so the 1 vCPU / 1 GiB / 25 GB Starter tier runs it with room to spare; move up only once you're storing many large attachments or stacking several other self-hosted services on the same box.Zur vollen Transparenz: Das ist, was wir verkaufen. ntfy läuft selbst mit einer Handvoll Abonnenten und Topics unter 100 MB, sodass der Starter-Tarif mit 1 vCPU / 1 GiB / 25 GB ihn mit Luft nach oben betreibt; steig erst höher, sobald du viele große Anhänge speicherst oder mehrere andere selbst gehostete Dienste auf derselben Maschine stapelst.
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.
Yes, as long as auth-default-access is deny-all and you grant access per topic and per user rather than leaving it open. The upstream default is more permissive than that, which is why setting it explicitly belongs in your first server.yml, not an afterthought.Ja, solange auth-default-access auf deny-all steht und du Zugriff pro Topic und pro Nutzer vergibst, statt es offen zu lassen. Der Upstream-Standard ist freizügiger als das, weshalb diese Einstellung explizit in deine erste server.yml gehört und nicht nachträglich.
No, but you need something reachable on 443 for a normal HTTPS domain, since both publishing and subscribing are inbound. A forwarded high port with a DNS-01 Caddy config works too; a dedicated IPv4 just makes the URL ordinary, and on our plans it's arranged by e-mail rather than picked at checkout.Nein, aber du brauchst etwas Erreichbares auf 443 für eine normale HTTPS-Domain, da sowohl Veröffentlichen als auch Abonnieren eingehend sind. Ein weitergeleiteter hoher Port mit einer DNS-01-Caddy-Konfiguration funktioniert ebenfalls; eine dedizierte IPv4 macht nur die URL gewöhnlich, und bei unseren Plänen wird sie per E-Mail geregelt statt beim Checkout ausgewählt.
Because Apple requires every iOS push to go through APNs, and only Apple's own infrastructure can trigger that — a self-hosted server has no way around it. The documented workaround forwards a bare poll signal to ntfy.sh's relay to wake the app; your message content stays on your own server.Weil Apple verlangt, dass jeder iOS-Push über APNs läuft, und nur Apples eigene Infrastruktur das auslösen kann — ein selbst gehosteter Server kommt daran nicht vorbei. Der dokumentierte Workaround leitet ein bloßes Poll-Signal an das Relay von ntfy.sh weiter, um die App aufzuwecken; dein Nachrichteninhalt bleibt auf deinem eigenen Server.
Every account, token, and topic permission is gone, and deny-all means the server locks everyone out until you recreate them. It's a small file and the backup above takes seconds, which is the whole argument for doing it on day one, not after a disk fills up.Jeder Account, jedes Token und jede Topic-Berechtigung ist weg, und deny-all bedeutet, dass der Server jeden aussperrt, bis du sie neu anlegst. Es ist eine kleine Datei, und das Backup von oben dauert Sekunden — genau deshalb solltest du es am ersten Tag machen, nicht erst, nachdem eine Platte vollgelaufen ist.
Not usefully with SQLite as the backing store — cache.db and user.db are single-writer files, and two ntfy processes on the same volume will corrupt them, not fail over. Real resilience means a second VPS with its own domain and its own database, not a second container sharing one.Mit SQLite als Backing-Store nicht sinnvoll — cache.db und user.db sind Single-Writer-Dateien, und zwei ntfy-Prozesse auf demselben Volume beschädigen sie, statt einen Failover durchzuführen. Echte Resilienz bedeutet ein zweiter VPS mit eigener Domain und eigener Datenbank, nicht ein zweiter Container, der sich eine teilt.
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