EmDash läuft auf Cloudflare mit einem einzigen Befehl – bequem, serverlos, in Minuten live. Aber was, wenn du dein CMS lieber auf deinem eigenen Server betreiben willst? Volle Kontrolle, Daten in Deutschland, kein Vendor-Lock-in. Genau so betreiben wir diese Webseite: selbst gehostet auf einem Hetzner-Server in Deutschland. In diesem Beitrag zeigen wir dir Schritt für Schritt, wie du EmDash auf einem eigenen Server oder VPS aufsetzt – mit den Handgriffen, die in der Doku stehen, und den Stolpersteinen, die erst in der Praxis auffallen.
Warum EmDash selbst hosten?
EmDash gibt dir zwei grundsätzlich verschiedene Wege: die serverlose Variante auf Cloudflare Workers oder das Self-Hosting als dauerhaft laufender Node.js-Prozess auf deinem eigenen Server. Beide sind offiziell dokumentiert und voll unterstützt. Für den eigenen Server sprechen drei Argumente:
- Kontrolle: Du bestimmst über Betriebssystem, Datenbank, Speicher und Netzwerk. Keine Plattform-Limits, keine fremde Runtime, keine Überraschungen bei Preisänderungen.
- Datenhoheit in Deutschland: Deine Inhalte, deine Medien, deine Datenbank liegen auf einem Server deiner Wahl – bei uns ein Hetzner-Root-Server in Deutschland. Das verkürzt die Datenschutzerklärung und macht die DSGVO-Argumentation gegenüber Kunden einfach.
- Kosten: Ein kleiner VPS für ein paar Euro im Monat trägt viele EmDash-Projekte locker. Bei planbarem Traffic ist das oft günstiger und vor allem berechenbarer als nutzungsbasierte Abrechnung.
Der ehrliche Gegenpunkt: Cloudflare nimmt dir Server-Wartung, Skalierung und HTTPS komplett ab. Wenn du kein DevOps machen willst und globale Reichweite brauchst, ist der serverlose Weg bequemer. Self-Hosting lohnt sich, wenn Datenhoheit, Kontrolle und ein fester Kostenrahmen für dich zählen – und du dich mit einem Linux-Server anfreunden kannst. Mehr Hintergrund zu EmDash selbst findest du in unserem Praxistest des EmDash-CMS.
Was du brauchst
Bevor du loslegst, sollten drei Dinge stehen:
- Ein Server oder VPS mit Linux. Für die meisten Blogs und Unternehmensseiten reicht die kleinste VPS-Klasse. Wichtig ist vor allem persistenter Speicher – dazu später mehr.
- Node.js in Version 22.12 oder höher. Das ist die von EmDash geforderte Mindestversion. Achtung: ungerade Node-Hauptversionen werden nicht unterstützt, bleib also bei den Even-LTS-Reihen.
- Eine Domain, die du auf die IP deines Servers zeigen lässt. Sie ist nicht nur für die Erreichbarkeit wichtig, sondern auch für die Anmeldung per Passkey – dazu am Ende mehr.
Die verbindliche Referenz ist die offizielle Node.js-Deployment-Anleitung von EmDash. Halte sie beim Einrichten offen – wir verlinken die relevanten Kapitel unterwegs.
Schritt 1: Projekt anlegen und bauen
EmDash bringt einen Projekt-Generator mit. Auf deinem Rechner oder direkt auf dem Server legst du ein neues Projekt an:
npm create emdash@latestDanach wechselst du ins Projekt, installierst die Abhängigkeiten und startest zum Testen den Entwicklungsserver:
cd my-emdash-site
npm install
npm run devFür den Server-Betrieb ist entscheidend, dass EmDash als eigenständiger Node-Prozess läuft. Dafür nutzt du den Astro-Node-Adapter im Standalone-Modus. In der astro.config sind zwei Dinge zentral:
output: "server",
adapter: node({ mode: "standalone" }),Anschließend baust du die Anwendung und startest den fertigen Server:
npm run build
node ./dist/server/entry.mjsDer Server lauscht standardmäßig auf http://localhost:4321. Über die Umgebungsvariablen HOST und PORT kannst du Adresse und Port anpassen – hinter einem Reverse Proxy bindest du ihn sinnvollerweise nur an 127.0.0.1. Ein Detail, das dir Arbeit erspart: Die Datenbank-Migrationen laufen automatisch beim ersten Aufruf. Du musst kein separates Migrations-Kommando anstoßen; EmDash bringt sein Schema selbst in Form.
Schritt 2: Die Datenbank wählen
EmDash ist bewusst flexibel bei der Datenbank. Auf einem eigenen Server hast du drei sinnvolle Optionen:
- SQLite – eine einzige Datei auf der Festplatte. Für die allermeisten Seiten die einfachste und beste Wahl: keine zusätzliche Datenbank-Software, kein Betrieb eines Datenbank-Servers. Konfiguriert wird sie schlicht mit einem Datei-Pfad, etwa
sqlite({ url: "file:./data/data.db" }). - libSQL – wenn du eine entfernte, SQLite-kompatible Datenbank anbinden willst (per URL und Auth-Token).
- PostgreSQL – wenn du eine klassische, relationale Datenbank brauchst, etwa weil du mehrere App-Server auf dieselbe Datenbank zeigen lässt oder ohnehin Postgres im Haus hast.
Unsere klare Empfehlung für den Einstieg: Fang mit SQLite an. Eine Datei, ein Backup, fertig. Erst wenn du mehrere Instanzen oder eine ausgelagerte Datenbank brauchst, lohnt der Wechsel zu libSQL oder PostgreSQL. Die Details und Konfigurations-Snippets stehen in den Datenbank-Optionen der EmDash-Doku.
Ein Wort zu Medien: Im Entwicklungsmodus landen Uploads lokal im Ordner ./data/uploads. Für den Produktivbetrieb kannst du entweder bei lokalem Speicher bleiben oder einen S3-kompatiblen Dienst anbinden (etwa MinIO auf deinem eigenen Server oder Cloudflare R2). Bleibst du lokal, gilt für den Uploads-Ordner dasselbe wie für die SQLite-Datei: Er muss auf persistentem Speicher liegen.
Kein eigenes DevOps-Team? Wir richten EmDash auf deinem Server ein – Node, Datenbank, Reverse Proxy und Backups inklusive. Buch dir ein kostenloses Erstgespräch.
Schritt 3: Umgebungsvariablen und Secrets
EmDash erwartet für den Produktivbetrieb einen Verschlüsselungs-Key. Er heißt EMDASH_ENCRYPTION_KEY und schützt Plugin-Geheimnisse in der Datenbank. Generieren kannst du ihn mit dem eingebauten CLI-Befehl:
npx emdash secrets generateDas Kommando gibt einen Schlüssel im Format emdash_enc_v1_… aus. Alternativ schreibst du ihn mit npx emdash secrets generate --write .env direkt in deine .env-Datei. EmDash prüft den Key beim Start. Behandle ihn wie ein Passwort: Sichere ihn zusätzlich in einem Passwortmanager. Geht er verloren, lassen sich damit verschlüsselte Inhalte später nicht wiederherstellen.
Zwei weitere Variablen sind optional, aber gut zu kennen: EMDASH_PREVIEW_SECRET steuert die Signatur von Vorschau-Links, EMDASH_IP_SALT den Hash für Kommentar-IP-Adressen. Beide werden bei Bedarf automatisch erzeugt; du musst sie nur setzen, wenn du sie fest vergeben willst. Details dazu stehen im Kapitel Secrets & Key Management. Wenn du OAuth-Login oder S3-Speicher nutzt, kommen deren Zugangsdaten ebenfalls als Umgebungsvariablen dazu.
Schritt 4: Den Prozess dauerhaft laufen lassen
EmDash ist kein Skript, das einmal durchläuft, sondern ein Server, der ununterbrochen erreichbar sein muss. Startest du node ./dist/server/entry.mjs von Hand, ist er beim nächsten Neustart des Servers weg. Du brauchst also ein Prozess-Management, das den Node-Prozess startet, überwacht und nach einem Reboot automatisch wieder hochfährt. Zwei bewährte Wege:
systemd ist auf jedem modernen Linux vorhanden und braucht keine Zusatzsoftware. Du legst eine Service-Unit an, die auf node ./dist/server/entry.mjs zeigt, das Arbeitsverzeichnis setzt und die Umgebungsvariablen (oder eine EnvironmentFile) einbindet. Mit systemctl enable --now emdash läuft der Dienst dauerhaft und startet nach jedem Reboot automatisch. Logs siehst du bequem über journalctl.
PM2 ist der beliebte Node-Prozessmanager. Er startet die App mit pm2 start ./dist/server/entry.mjs --name emdash, mit pm2 save und pm2 startup überlebt sie den Reboot. PM2 bringt Log-Verwaltung und Neustart-bei-Absturz von Haus aus mit.
Beide Wege funktionieren. Auf einem dedizierten Server nehmen wir systemd, weil es ohne zusätzliche Abhängigkeit auskommt und sich sauber ins System einfügt. Wichtig ist nur: Der Prozess muss automatisch wiederkommen, wenn der Server neu startet.
Schritt 5: Reverse Proxy und HTTPS
Den Node-Prozess direkt ins Internet zu stellen, willst du nicht. Davor gehört ein Reverse Proxy, der auf Port 80/443 lauscht, HTTPS terminiert und die Anfragen intern an 127.0.0.1:4321 weiterreicht. Zwei gute Optionen:
Caddy ist unser Favorit für schlanke Setups, weil er sich um die TLS-Zertifikate von Let's Encrypt vollautomatisch kümmert. Die komplette Konfiguration passt in wenige Zeilen:
deine-domain.de {
reverse_proxy 127.0.0.1:4321
}Caddy holt und erneuert das Zertifikat selbst und leitet den korrekten Host-Header weiter – das ist gleich beim nächsten Punkt wichtig.
Nginx ist der Klassiker. Hier setzt du einen server-Block mit proxy_pass http://127.0.0.1:4321; auf und gibst die Header manuell weiter – insbesondere proxy_set_header Host $host; und proxy_set_header X-Forwarded-Proto https;. Um die Zertifikate kümmerst du dich mit Certbot. Nginx bietet mehr Feinsteuerung, kostet dich aber ein paar Handgriffe mehr.
Egal welchen Proxy du nimmst: HTTPS ist Pflicht, nicht Kür. Passkeys und sichere Session-Cookies setzen eine verschlüsselte Verbindung voraus.
Schritt 6: Backups einrichten
Der schönste Vorteil von SQLite zeigt sich beim Backup: Deine gesamte Datenbank ist eine einzige Datei. Es gibt zwei sinnvolle Ebenen:
- Datenbank-Datei sichern. Am saubersten sicherst du die SQLite-Datei mit dem eingebauten Backup-Befehl, der einen konsistenten Snapshot im laufenden Betrieb erzeugt:
sqlite3 emdash.db ".backup backup.db". Alternativ kopierst du die Datei einfach, während der Server gestoppt ist. Diese Sicherung packst du am besten automatisiert per Cronjob auf einen zweiten Speicherort. - Inhalts-Backup aus dem Admin. Unter Einstellungen → Backups erzeugt EmDash eine JSON-Sicherung deines Inhaltsmodells, der Einträge und Einstellungen. Mit angebundenem Speicher lassen sich auch tägliche automatische Backups mit einstellbarer Aufbewahrung aktivieren.
Ein wichtiger Punkt aus der Praxis: Das JSON-Backup enthält keine Mediendateien. Deine Bilder und Uploads liegen im Speicher (lokaler Ordner, S3 oder R2) und müssen separat gesichert werden. Denk beim Backup-Plan also immer an beides: Datenbank und Medien. Die offizielle Übersicht steht im Backups-Guide.
Schritt 7: Updates einspielen
Updates laufen bei einem selbst gehosteten EmDash über den ganz normalen Node-Workflow. Du aktualisierst die Abhängigkeiten im Projekt, baust neu und startest den Prozess durch:
npm install
npm run buildDanach lädst du den Dienst neu – etwa mit systemctl restart emdash oder pm2 reload emdash. Weil die Migrationen automatisch beim Start laufen, bringt EmDash sein Datenbank-Schema dabei selbstständig auf den neuen Stand. Unser dringender Rat: Mach vor jedem Update ein Backup der Datenbank. So kannst du im Zweifel jederzeit zurück. Bei größeren Versionssprüngen lohnt zusätzlich ein kurzer Test auf einer Staging-Instanz, bevor die Live-Seite dran ist.
Typische Stolpersteine aus der Praxis
Die Einrichtung ist unkompliziert – aber ein paar Fallen holen fast jeden einmal ein. Diese vier solltest du kennen:
- Persistenter Speicher ist Pflicht. SQLite braucht ein Dateisystem, das erhalten bleibt. Läuft dein Server auf einem ephemeren Dateisystem – wie es manche Container- oder PaaS-Umgebungen mitbringen –, ist deine Datenbank nach dem nächsten Neustart weg. Auf einem klassischen VPS oder Root-Server ist das kein Problem, in Container-Setups musst du ein persistentes Volume einbinden. Dasselbe gilt für den lokalen Uploads-Ordner.
- Host-Header korrekt durchreichen. Der Reverse Proxy muss den echten Host-Header an EmDash weitergeben. Caddy macht das von allein, bei Nginx setzt du
proxy_set_header Host $host;. Fehlt der korrekte Host, kommt es zu Ärger bei absoluten URLs und – siehe nächster Punkt – bei der Anmeldung. - Passkeys sind an die Domain gebunden. EmDash meldet dich per Passkey (WebAuthn) an, und dieser Schlüssel gilt nur für die Domain, auf der du ihn registriert hast. Ein Passkey, den du unter
localhost:4321angelegt hast, funktioniert aufdeine-domain.deschlicht nicht. Registriere den Admin-Passkey also direkt auf deiner echten HTTPS-Domain, nicht auf localhost. - Erst live, dann anmelden. Aus demselben Grund richtest du den Setup-Assistenten am besten ein, wenn Domain, HTTPS und Reverse Proxy schon stehen. Dann bindet der erste Passkey gleich an die richtige Adresse, und du ersparst dir das spätere Neu-Registrieren.
Self-Hosting oder Cloudflare – wann was?
Zum Schluss die ehrliche Einordnung, denn beide Wege haben ihre Berechtigung:
Self-Hosting lohnt sich, wenn dir Datenhoheit wichtig ist (Server in Deutschland, alles unter deiner Kontrolle), du planbare Kosten willst, du ohnehin einen Server betreibst oder du volle Freiheit bei Datenbank und Speicher brauchst. Der Preis dafür: Du kümmerst dich um Betriebssystem, Updates, HTTPS und Backups.
Cloudflare ist bequemer, wenn du keine Server-Wartung übernehmen willst, globale Reichweite und automatische Skalierung brauchst oder einfach den schnellsten Weg zum Live-Gang suchst. Die serverlose Variante läuft auf Cloudflare Workers mit D1 als Datenbank und R2 als Speicher – du deployst mit einem Befehl und musst dich um keinen laufenden Prozess kümmern.
Es gibt kein pauschales „besser". Wir haben uns bewusst für das Self-Hosting auf Hetzner entschieden, weil Datenhoheit und Kontrolle für uns als Agentur zentral sind – und weil wir den Server-Betrieb ohnehin beherrschen. Für ein kleines Team ohne DevOps-Erfahrung kann Cloudflare der klügere Start sein.
Fazit
EmDash selbst zu hosten ist kein Hexenwerk, aber echtes Handwerk. Die einzelnen Schritte sind überschaubar: Projekt bauen, Datenbank wählen, Secrets setzen, Prozess dauerhaft laufen lassen, Reverse Proxy mit HTTPS davor, Backups einrichten. Wenn du diese Grundlagen sauber legst und die vier Stolpersteine – persistenter Speicher, Host-Header, Passkey-Domain und der richtige Zeitpunkt fürs Setup – im Blick behältst, bekommst du ein CMS, das schnell, sicher und komplett in deiner Hand liegt. Der Quellcode liegt offen auf GitHub, und die EmDash-Dokumentation begleitet dich durch jedes Detail.
Du willst EmDash auf deinem eigenen Server – ohne dich selbst durch systemd, Nginx und Backup-Skripte zu kämpfen? Wir übernehmen die komplette Einrichtung auf deiner Wunsch-Umgebung, inklusive Datenhoheit in Deutschland. Sprich mit uns über dein Projekt.
Bildnachweis: Beitragsbild — Screenshot des EmDash-Admin-Dashboards. Quelle: EmDash (emdashcms.com).
