Unterstützung bei der Serverkonfiguration mit Node.js-Server, Mailcow und SSL

  • Hallo,


    Ich bin noch ziemlich unerfahren, was sysadmin-Themen angeht und bräuchte noch etwas Unterstützung.


    Mein Ziel wäre folgendes:

    • Mailcow soll über mail.meinedomain.de erreichbar sein.
    • Mein Node.js-Server soll über meinedomain.de erreichbar sein.
    • meinedomain.de soll mit HTTPS gesichert sein, für mail.meinedomain.de ist es erstmal nicht notwendig.

    Stand der Dinge ist:

    Mailcow läuft via Docker auf dem Server und ist über meinedomain.de erreichbar. Der Node.js-Server liegt theoretisch auch als Image bereit, kann aber aktuell nicht gleichzeitig mit Mailcow laufen, da beide auf Port 80 wollen.

    Ich habe ein RapidSSL DV Zertifikat, davon kann ich den CSR, das Zertifikat und den Key im Controlpanel bei Netcup abrufen. In den Tutorials, wie ich diese in Node.js einbinde wird jedoch davon ausgegangen, dass ich ein CA-Bundle habe, mir ist aber nicht ganz klar, was das ist, bzw. wie ich das bekommen/erstellen kann.


    Die erste Frage ist daher, wie ich das mit Hostname, Ports und Mailcow regeln kann, dass Mailcow unter mail.meinedomain.de erreichbar ist und meinedomain.de bzw. Port 80 frei ist für den Node.js-Server.

    Die zweite Frage wäre, wie das mit dem CA-Bundle funktioniert.


    Vielen Dank im Voraus für alle Hinweise, Tipps und weiterführende Infos!

  • Also du brauchst einen Reverse Proxy - ich kann dir hier Ngnix Proxy Manger empfehlen.


    Dieser wird dann für Port 80 und 443 eingerichtet. Des weiteren kannst du über das GUI auch direkt ein Lets Encrypt Zertifikat beantragen (einen kostenpflichtiges wie RapidSSL ist unötig)


    NodeJS und Mailcow tust du beides mal ohne Port Freigaben in docker erstellen (bzw bei Mailcow ohne Port 80)


    NPM und NodeJS und Mailcow müssen im gleichen Docker Netzwerk sein.


    Im GUI von NPM legst du dann zwei Proxies an einmal mit

    mail.meinedomain und einmal meinedomain.

    Als Ziel gibtst du Port 80 und den Namen der Docker Container an (das Auflösung übernimmt docker)

    Und wähkst aus HTTPS immer verwendet und dort das entsprechende Wildcard Zertifikat.

    Erstellung hab ich unten kurz erklärt.


    Bei den DNS Einstellung lässt du einfach eine Wildcard * auf die IP des Servers zeigen.

    Bei der Zertifikats Erstellung in NPM musst du dann eines für *.meinedomain erstellen - wichtig das geht nur mit einer Wildcard.

    NPM kann hier aber direkt mit der NC API kommunizieren.

  • Warum? Vielleicht habe ich es überlesen, aber die beiden gehören doch nicht zusammen. Und dann würde ich beide schon aus Prinzip in verschiedene Netzwerke legen.

    Das schon - aber NPM muss im gleichen Netzwerk -

    Deutlicher geschrieben

    Mailcow und NPM

    NodeJS und NPM


    Alternative wäre die ports freizugeben - will man aber normalerweise nicht dar im optimal Fall nur 80 und 443 (+SSH und Mail zeug) offen sein sollte.

    Dann könnte man über public IP + port gehen

  • Warum? Vielleicht habe ich es überlesen, aber die beiden gehören doch nicht zusammen. Und dann würde ich beide schon aus Prinzip in verschiedene Netzwerke legen.

    Weil man sie sonst nicht mit Namen in NPM adressieren kann. Alle Container, die über NPM geproxied werden sollen, sollten in einem Netzwerk mit diesem sein. Im gleichen Netzwerk sein, heißt nicht im gleichen Container oder auch nur in der gleichen docker-compose sein.

    RS Ostern L OST22 (~RS "3000" G9.5) (8C,24GB,960GB) | RS Cyber Quack (1C,2GB,40GB)

    Gefällt mir 2
  • tom434 vielen Dank für die Beschreibung und auch Danke an Loxley und TBT für die Ergänzungen.

    Ich habe jetzt den NPM installiert und kann die GUI nutzen. Zudem habe ich ein Docker-Network erstellt und das für beide Anwendungen in der docker-compose.yml hinzugefügt.


    Habe ich das richtig verstanden, dass ich die Port-Bindings einfach aus der docker-compose.yml von Mailcow sowie meiner App entfernen muss?


    Ich bin mir auch nicht ganz sicher, was ich bei NPM jetzt eintragen muss. Bei Domain Names vermutlich meinedomain.de bzw. dann mail.meinedomain.de, als Scheme vermutlich HTTPS, da das ja mein Ziel ist, was ich bei Forward Hostname / IP und Forward Port eintragen muss, ist mir nicht ganz klar.

    Meine Node.js-App läuft standardmäßig auf Port 8000, geb ich dann den an? Und bei Mailcow dann einfach 80?

  • Also ja die ports lässt du weg - aber nur für die die für Webseiten zuständig sind (http(s) Zeug).

    Ich kenne Mailcow nicht aber die Ports, die jenes für E-Mail verwendet (25,143,993,110,995 usw.) musst du weiterhin frei geben.


    Bei NPM:

    Beim Schema musst du wahrscheinlich http angeben (ausser deine Apps kommunizieren auch ohne Proxy über https wie z.B. portainer)


    Genau als port gibts du in diesem Fall 8000 und bei Mailcow wahrscheinlich 80 (wenn dass der für Webinterface ist).

    Und als Ziel den Namen des Containers


    Screenshot_2022-11-09-21-07-17-73_e4424258c8b8649f6e67d283a50a2cbc.jpg

    Auf der SSL Seite: (*) Zertifikat musst du vorher per DNS Challenge erstellt haben

    IMG_20221109_210819.jpg

  • tom434 Vielen Dank, ich habe versucht die Schritte zu befolgen. Ich wollte zunächst einmal testen, ob es ohne SSL grundsätzlich funktioniert, ich habe also meindedomain.de als Domain eingestellt, vorerst mal http ausgewählt, als hostname meine-node-docker-app-1 (wie der container laut docker ps heißt), und eben Port 8000 (die App gibt beim Starten den Port aus und es ist in der Tat 8000). Jedoch gibt es im Frontend nur einen 502 Bad Gateway Fehler.

    Wie kann ich herausfinden wo es hakt?

    Die zweite Frage betrifft das SSL-Zertifikat. Wie bereits gesagt haben wir bereits ein RapidSSL-Zertifikat, falls möglich würde ich das gerne verwenden. Ich habe auch in NPM die Option gefunden, ein "Custom" Zertifikat auszuwählen, mir ist aber nicht ganz klar, welche Dateien ich hier laden muss. Von Netcup habe ich nach wie vor CSR, Zertifikat und Key. In NPM werden Zertifikat, Key (soweit so klar) und ein Intermediate Certificate gefordert. Ist damit der CSR gemeint oder ist das etwas anderes?


    Nochmals vielen Dank für deine Unterstützung.

  • tom434 Vielen Dank, ich habe versucht die Schritte zu befolgen. Ich wollte zunächst einmal testen, ob es ohne SSL grundsätzlich funktioniert, ich habe also meindedomain.de als Domain eingestellt, vorerst mal http ausgewählt, als hostname meine-node-docker-app-1 (wie der container laut docker ps heißt), und eben Port 8000 (die App gibt beim Starten den Port aus und es ist in der Tat 8000). Jedoch gibt es im Frontend nur einen 502 Bad Gateway Fehler.

    Wie kann ich herausfinden wo es hakt?

    Die zweite Frage betrifft das SSL-Zertifikat. Wie bereits gesagt haben wir bereits ein RapidSSL-Zertifikat, falls möglich würde ich das gerne verwenden. Ich habe auch in NPM die Option gefunden, ein "Custom" Zertifikat auszuwählen, mir ist aber nicht ganz klar, welche Dateien ich hier laden muss. Von Netcup habe ich nach wie vor CSR, Zertifikat und Key. In NPM werden Zertifikat, Key (soweit so klar) und ein Intermediate Certificate gefordert. Ist damit der CSR gemeint oder ist das etwas anderes?


    Nochmals vielen Dank für deine Unterstützung.

    Ersteinmal - Die beiden Apps sind im gleichen Docker Netzwerk?

    Du kannst testweise auch mal die IP des Containers eingeben statt den Namen eventuell funktioniert es dann (Probelm die interne IP ändert sich).

    Die App erwartet auch einen HTTP aufruf? (Manche kommunizieren nur über https).

    Und du hast bei dem DNS Zeug:

    Einen * A Record auf deinen Domain und ein

    @ Record aud deine Domain

    Sonst schau die mal die Logs, von beiden Container an.

    Kommt überhaupt eine Verbindung zu stande.

    Testweise kannst du auch einen default NGNiX Webserver Container erstellen - mit einer standard Seite um zu testen ob das ganze überhaupt funktioniert.


    Intermediate Certificate ist normalerweise nicht verpflichtent (also kein Stern).

    Also sollten die ersten beiden ausreichen.

    (Hat es einen Grund, dass du ein kostenpflichtiges verwendest? Lets Encrypt hat eigentlich kaum Nachteile - ausser ein paar wenige, die aber zu 99% kaum eine Rolle spielen)

  • Meine Empfehlung: insbesondere da Du unerfahren bist: mach ausschließlich Mailcow auf einen RS/VServer und Node.JS auf einen anderen Server. Dann reicht es, der wirklich leichten Installationsanleitung auf https://docs.mailcow.email/i_u_m/i_u_m_install/ zu folgen.


    Du brauchst eigentlich kein gekauftes Zertifikat.


    Gerade für unerfahrene Admins ist es nicht dankbar bis gefährlich (Stichwort Open Relay) einen Mailserver zu betreiben. Du solltest Dir das dringend nochmal überlegen.

    RS Ostern L OST22 (~RS "3000" G9.5) (8C,24GB,960GB) | RS Cyber Quack (1C,2GB,40GB)

  • Erstmal vorweg, langfristig sollte die Node.js-App auch in der Lage sein, Mails zu senden. Hab ich zwar in PHP auf normalen Webservern schon oft genug gemacht, aber wie genau es in Node funktioniert, habe ich mir tatsächlich noch nicht angeschaut. Das wird erst später relevant. Wäre aber auch gut, wenn man über die gleiche Domain manuell Mails verschicken kann. Daher bin ich davon ausgegangen, dass es Sinn macht, den Mailserver auf dem gleichen Server zu haben.

    Währe zwar nett, während der Entwicklung den Mailserver direkt parat zu haben, wichtiger wäre aber erstmal die Node-App. Wenn es für die Node-App irrelevant wäre, auf welchem Server der Mailserver läuft, kann man das auch noch trenne. Aber gerade während der Entwicklung wäre es nützlich, alles beisammen zu haben.


    Bevor ich versucht habe, das über NPM zu machen, war die App schonmal über die Domain erreichbar. Zumindest teilweise. Die Index.html konnte man aufrufen, aber keine statischen Assets, da gab es einen Fehler aufgrund von fehlendem SSL. Sowas war mir auch neu, aber ich dachte mir, bevor ich jetzt versuche, einen Workaround zu suchen, mach ich einfach SSL drauf, dann weiß ich auch gleich, wie das geht. Hier hab ich mich vom CCP etwas in die Irre führen lassen, da unter "Kostenloses SSL" angezeigt wurde "Ihre Domain erfüllt die Anforderungen nicht", dachte ich, ich brauche ein anderes Zertifikat. Und deshalb habe ich jetzt ein RapidSSL Zertifikat. Sowas nennt man glaube ich im Fachjargon einen "Anfängerfehler". Waren nur ein paar Euro, aber da ich das Zertifikat nun schon habe, kann ich es ja auch verwenden. Ich muss es ja nicht verlängern und kann dann später auf Let's Encrypt umsteigen.


    Wenn ich mit docker inspect das Netzwerk anschaue, sehe ich meinen Container dort aufgelistet. Mailcow zwar nicht, aber das können wir wie gesagt erstmal zurückstellen.


    Das ist der Output:



    DNS sieht wie folgt aus für die Domain:

    Host Type MX Destination Gültig
    * A [IPv4 des Servers] yes
    @ A [IPv4 des Servers] yes
    @ MX 10 mail.meinedomain.de yes
    @ TXT v=spf1 +a +mx +a:mail.example.com -all yes
    dkim._domainkey TXT v=DKIM1;k=rsa;t=s;s=email;p=[...] yes
    ftp A [IPv4 des Servers] yes
    mail [IPv4 des Servers] yes
    www CNAME @ yes
    _dmarc TXT v=DMARC1; p=none yes


    Bei genauerem Hinsehen wundert mich gerade der Eintrag mit mail.example.com. War das ein automatisch generierter Platzhalter oder wo kommt der her? Muss ich daran etwas anpassen oder ihn entfernen, und sieht der Rest in Ordnung aus?


    Ich kann mich nicht genug für die kontinuierliche Unterstützung bedanken, aber trotzdem nochmal vielen Dank für die Hilfe bisher.

    tom434  TBT

  • Weil man sie sonst nicht mit Namen in NPM adressieren kann. Alle Container, die über NPM geproxied werden sollen, sollten in einem Netzwerk mit diesem sein. Im gleichen Netzwerk sein, heißt nicht im gleichen Container oder auch nur in der gleichen docker-compose sein.

    also ich expose aus bequemlichkeit oft die ports auf 127.0.0.1:port:port (-e 127.0.0.1:8080:80 zB) und mache im npm dann als ziel 127.0.0.1 PORT - klappt bisher auch gut :D

    aber das mit der namensauflösung wusst ich nicht - ist bei größeren sachen wohl bequemer einfach nur den namen des containers einzugeben :D

    - RS Brezn (Pterodactyl; Nextcloud und geheime Erotiksammlung, damit die Freundin nichts davon mitbekommt)

    - VPS 200 G10 (Mailkuh)

    - Webhosting Bestprice Classic

    Einmal editiert, zuletzt von Encore ()

  • aber das mit der namensauflösung wusst ich nicht - ist bei größeren sachen wohl bequemer einfach nur den namen des containers einzugeben :D

    Der namensbasierte Weg ist imho sicherer, da ist gar keine Öffnung von Ports nach außen nötig, die Container können sich intern beliebig und namensbasiert adressiert unterhalten als wären sie in einem geschützten LAN, das von außen nicht erreichbar ist. Das einzige was man dafür machen muss, ist alle Container (ggfalls zusätzlich) in ein Netzwerk mit dem Reverse Proxy zu packen.

    RS Ostern L OST22 (~RS "3000" G9.5) (8C,24GB,960GB) | RS Cyber Quack (1C,2GB,40GB)

  • Erstmal vorweg, langfristig sollte die Node.js-App auch in der Lage sein, Mails zu senden. Hab ich zwar in PHP auf normalen Webservern schon oft genug gemacht, aber wie genau es in Node funktioniert, habe ich mir tatsächlich noch nicht angeschaut. Das wird erst später relevant. Wäre aber auch gut, wenn man über die gleiche Domain manuell Mails verschicken kann. Daher bin ich davon ausgegangen, dass es Sinn macht, den Mailserver auf dem gleichen Server zu haben.

    Das ist imho nicht nötig, da auch die Node.js App mit Benutzeranmeldung mit dem SMTP Server auf der gleichen Kiste kommunizieren müsste. Ob Du da nun die Zugangsdaten für einen anderen Server angibst oder für einen lokalen Container, ist erst mal wurst.


    Ein Vorteil von Kompartimentierung ist, dass Du Dir nicht beides zerschießt, wenn Du ein Problem mit einem hast. Es geht definitiv, dass man Mailserver und Node.js auf einen Server packen kann, allerdings braucht man dafür schon einiges an Erfahrung im Umgang mit Docker. Und diese fehlt Dir anscheinend bisher. Daher wäre es für beide Anwendungen erst einmal einfacher, diese separat auf unterschiedlichen VServern aufzubauen. Ein Vorteil dieser Herangehensweise auch noch: sollte eine der beiden Anwendungen schneller wachsen als die andere, kannst Du einen der beiden Server skalieren.

    Zitat

    +a +mx +a:mail.example.com

    Hier soll natürlich nicht mail.example.com stehen, sonder mail.meinedomain.de . Allerdings sind die beiden Einträge +mx +a:mail.meinedomain.de in diesem Fall ohnehin redundant.

    RS Ostern L OST22 (~RS "3000" G9.5) (8C,24GB,960GB) | RS Cyber Quack (1C,2GB,40GB)

    Gefällt mir 1
  • Das ist imho nicht nötig, da auch die Node.js App mit Benutzeranmeldung mit dem SMTP Server auf der gleichen Kiste kommunizieren müsste. Ob Du da nun die Zugangsdaten für einen anderen Server angibst oder für einen lokalen Container, ist erst mal wurst.


    Ein Vorteil von Kompartimentierung ist, dass Du Dir nicht beides zerschießt, wenn Du ein Problem mit einem hast. Es geht definitiv, dass man Mailserver und Node.js auf einen Server packen kann, allerdings braucht man dafür schon einiges an Erfahrung im Umgang mit Docker. Und diese fehlt Dir anscheinend bisher. Daher wäre es für beide Anwendungen erst einmal einfacher, diese separat auf unterschiedlichen VServern aufzubauen. Ein Vorteil dieser Herangehensweise auch noch: sollte eine der beiden Anwendungen schneller wachsen als die andere, kannst Du einen der beiden Server skalieren.

    Hier soll natürlich nicht mail.example.com stehen, sonder mail.meinedomain.de . Allerdings sind die beiden Einträge +mx +a:mail.meinedomain.de in diesem Fall ohnehin redundant.

    Okay, bin überzeugt, dann mache ich es langfristig auf getrennte Server. Wie gesagt kann der Mail-Server erstmal weggelassen werden.

    Dennoch habe ich es bisher noch nicht geschafft, die Node-App erreichbar zu machen.

    Was wäre nun der einfachste Weg, diese samt SSL erreichbar zu machen? Rausfinden, warum es mit NPM nicht läuft, oder das ganze nochmal umwerfen?

  • Verlinke doch zumindest mal den Node.js Docker Container, den Du verwenden willst.


    Wie weiter oben geschrieben: NPM und der Node.js Container müssen ins gleiche Docker Netzwerk. Wie das geht solltest Du der Docker Doku entnehmen können. Beim Node.js Container muss man gar nichts zum Host rauslegen, bei NPM die Ports 80 und 443. Zudem muss die Domainauflösung stimmen, d.h. die Domain, die Du verwenden willst, sollte auf den Server zeigen (Test mit "ping meine.domain.tld" auf der Konsole).


    Dann loggst Du Dich auf dem NPM ein, holst Dir ein LE Zertifikat (entweder "normal" oder mit DNS Auth bei passenden DNS Server, z.B. Cloudflare oder https://desec.io/) und legst einen "Proxy Host" an:


    Domain Names: sub.domain.tld,www.domain.tld,domain.tld (z.B.); EDIT: ODER *.domain.tld (Wildcardzertifikat für alle Subdomains!) bei DNS Methode.

    Scheme: je nachdem wie die Node.js Anwendung rausgeht, http wäre hier vermutlich einfacher und auch fein, da ja SSL nachgeschaltet wird --> "http"

    Forward Hostname / IP: z.B. "node", oder wie auch immer der Container mit dem Argument "-name" oder in der docker-compose benannt wurde.

    Forward Port: der Port den Du in Deiner Node.js Anwendung definiert hast und auf dem Node.js im Container läuft. Das muss nicht der Port sein, der nach außen gelegt wird.

    Dann noch Cache Assets, Block Exploits und Websockets Support anmachen und bei SSL das vorher separat angelegte Zertifikat auswählen.


    Und den Container starten.


    Damit "Forward Hostname / IP: "namedescontainers" funktioniert, müssen Node.js und NPM im gleichen Netzwerk sein. Hierzu Nachlese auf https://docs.docker.com/network/

    RS Ostern L OST22 (~RS "3000" G9.5) (8C,24GB,960GB) | RS Cyber Quack (1C,2GB,40GB)

    Einmal editiert, zuletzt von TBT ()

  • Alles korrekt nur zum

    *DNS Auth bei passenden DNS Server, - Netcup NC wird auch vom NPM unterstützt (muss man nur einen API Key genieren und die Kund Nummer angeben - ist aber beides im Feld vorgeben) und als Domain *.meinedomain.de angeben und DNS Challenge auswählen und Netcup in der Liste


    Und das HTTP Zertifikat kann man auch direkt bei der Proxy Host Erstellung beantragen.


  • Alles korrekt nur zum

    *DNS Auth bei passenden DNS Server, - Netcup NC wird auch vom NPM unterstützt (muss man nur einen API Key genieren und die Kund Nummer angeben - ist aber beides im Feld vorgeben) und als Domain *.meinedomain.de angeben und DNS Challenge auswählen und Netcup in der Liste

    True. Hatte den Link zur Anleitung nicht gefunden, daher nicht genannt. ;)


    Und das HTTP Zertifikat kann man auch direkt bei der Proxy Host Erstellung beantragen.

    Auch true. Bei DNS Auth, wo man etwas mehr eingeben / machen muss, kann mans aber auch separat machen. Nebenbei kann man hier auch ein Wildcardzertifikat beantragen (das hätte ich wohl oben sinnvoller bei "Domain Names:" schreiben sollen (ich editiers grade nochmal).

    RS Ostern L OST22 (~RS "3000" G9.5) (8C,24GB,960GB) | RS Cyber Quack (1C,2GB,40GB)