Docker KISS + linuxmuster-mrbs

Hallo,

ich habe die meine Docker-Entwicklungen aus den letzten Tagen mal etwas sortiert und denke, dass das jetzt ganz gut funktioniert. Alles was dazugehört liegt jetzt hier, die URLs aus dem anderen Thread gibt es zum größten Teil nimmer.

Exemplarisch möchte ich das mal für das MRBS Image und die dazugehörige App erklären:

Ausgangspunkt:

  • Ein „nacktes“ Ubuntu 18.04 Server als Basis.
  • Es wird git und ansible installiert: apt install git ansible
  • Passwortloser SSH-Zugang auf Port 22, wenn man nicht direkt an der Konsole sitzt, muss vorhanden sein, weil das Ansible-Playbook die Passwort Authentifizierung per SSH abschält.

Erzeugen eines Dockerhosts:

  • git clone https://github.com/linuxmuster-ext-docker/create-docker-host.git
  • cd create-docker-host
  • ansible-playbook dockerhost.yml

Das ansible Playbook macht aus dem Ubuntu in ca. 7 Minuten einen dockerfähigen Server mit Grundabsicherung, einem einfachen Weg Zertifikate zu holen und einem Nginx Reverse Proxy.

Die wichtigsten installierten Pakete:

  • docker-ce aus den Docker-Repositorys
  • docker-compose direkt von Github
  • ufw
  • nginx
  • dehydrated
Anmerkungen:
  • Die Firewall ufw hat als default policy deny, erlaubt sind per default nur die Ports 80, 443 und 22. Man muss davon abweichende Ports von Containern also später explizit freigeben, damit nicht versehentlich beim Starten von Containern Dienste unbeabsichtigt exposed werden.
  • Die SSH Anmeldung per Passwort wird durch das Playbook deaktiviert, man muss also vorher sicherstellen, dass man mit einem SSH Key auf den Server kommt.

Dienstenamen und Zertifikat

Jetzt muss man sich einen Dienstenamen ausdenken und ein SSL-Zertifikat besorgen. Also z.B. mrbs.meine-schule.tld

  • Lege einen DNS Eintrag für deine Dockerapp, z.B. mrbs.meine-schule.tld, der auf die IP des Dockerhosts zeigt. Das darf auch ein CNAME sein.
  • Trage diesen Host in die Datei /etc/dehydrated/domains.txt ein.
  • Führe den Befehl dehydrated -c aus. Jetzt hast du die Zertifikate im Verzeichnis /var/lib/dehydrated/certs/ zur Verfügung, der Docker Host aktualisiert diese per Cronjob.

App herunterladen, konfigurieren und starten

  • Klone das App-Repo auf deinen Dockerhost nach /srv/docker
    • cd /srv/docker
    • git clone https://github.com/linuxmuster-ext-docker/linuxmuster-mrbs
  • Wechsle in das App-Verzeichnis: cd linuxmuster-mrbs
  • Passe die Werte in der Datei mrbs.ini an.
  • Erzeuge eine Konfiguration mit: ./deploy/bin/turnkey -c mrbs.ini
  • Starte die App mit dem Befehl docker-compose up -d

Jetzt solltest du dich an deinem MRBS unter der Adresse https://mrbs.meine-schule.tld/ anmelden können, so wie du deinen Service-Host und deine Service-Domain gewählt und konfiguriert hast.

Vom nackten Ubuntu bis zur Anmeldung am MRBS weniger als 15 Minuten, obwohl ich nebenher noch Zeug erzähle, das Video zeigt ungeschnitten den Weg von einem „nackten“ Ubuntu 18.04 bis zum Login am hinter einem mit SSL abgesicherten Reverse Proxy laufenden MRBS Container. Keine Didaktik, auch ein paar kleinere Flüche :wink:

Nachbemerkungen

  • Was dieser „Dockerhost-KISS“ nicht macht, ist, dass er für jeden Aufgabe wieder einen Container vorhält, die dann alle zusammenarbeiten müssen (nginx, letzencrypt u.s.w.) sondern eine Basis bietet, die es super einfach ermöglicht, Zertifikate für seine Dienste zu bekommen und den Nginx des Hosts als Reverse Proxy benutzt. Er ist insofern also nicht „Professionell“, aber das finde ich nicht schlimm, weil ich glaube, dass wir eher selten im laufenden Betrieb Container über Server schieben werden, und wer das machen will soll es halt selber anders konfigurieren.
  • Man kann sehr einfach mehrere Docker Hosts haben, die sich dann jeweils in dem Netzwerksegment befinden, in dem man sie braucht.
  • Jeder der mag und es lernen mag oder schon kann, kann Docker Apps dafür machen, indem er das – wie meist üblich – einfach in einem Verzeichnis analog zu der linuxmuster-mrbs-App macht, das auf Github tut und dazu dokumentiert, wie man die App in Betrieb nimmt. Ob man dann die nginx Konfiguration wie in meinem Paket automagisch erzeugt und verlinkt, oder aufschreibt, was der Anwender tun muss, um den Container ans laufen zu bekommen ist dabei zweitrangig. Man muss keine Debian Pakete erstellen :wink:
  • Es können auch „offizielle“ Erweiterungen zur Verfügung gestellt werden, als solche betrachte ich mrbs und openSchulportfolio (coming soon).
  • Alles, was zu einer App gehört ist in einem Verzeichnis gekapselt, der Docker Host ist austauschbar (keine externen Debian-Pakete o.ä.), Datensicherung ist einfach.
  • Als Ergänzung wäre noch ein systemd-Service denkbar, der in jedem Verzeichnis unter /srv/docker/ z:B. nach einem UVZ systemd sucht, wo der App Ersteller entsprechende Befehle zum Autostart ablegen könnte.
  • Man könnte außerdem noch einen wie auch immer gearteten „Link“ zum LMN7 Server definieren, mit dem man eine zentrale ini-Datei mit Konfigurationsparametern des Mutterschiffs auf dem Dockerhost erzeugt, so dass App-Ersteller darauf zugreifen könnten, um z.B,. automatisch basedn und Bind User Daten u.ä. in die Konfiguration der Apps übernehmen zu können. (Auf diese Weise könnte man sogar Docker Erweiterungen aus der WebUI konfigurieren - egal auf welchem Host die laufen – das fände ich persönlich zwar vollkommen unnötig, aber gut…)

Das Ding ist relativ einfach, hat dadurch eine niedrige Einstiegshürde, hat eine klare Struktur und ermöglicht hoffentlich die Mitarbeit vieler Communitymitglieder bei der Erstellung von Diensten für linuxmuster.

Außerdem ermöglicht es, jetzt schon Dienste vom Server weg zu migrieren, das erleichtert wahrscheinlich die eigentliche Migration des Servers von 6 nach 7 sehr, wenn man vorher mit der 6.2 schon dafür gesorgt hat, dass der Server nur noch Benutzer und Fileablage macht.

VG Frank

5 „Gefällt mir“

Hi Frank,

Hut ab!

Eine Verständnisfrage bleibt für mich noch: Wie machst du das mit den IPs/DNS-Einträgen? Braucht der Dockerhost dann immer eine öffentliche IP? Oder zeigen die DNS Einträge auf deine Firewall?

vG Stephan

Hallo Stephan,

Das ist eigentlich egal.

  • Im grünen Netz hat der Docker Host, wenn er tatsächlich öffentliche Dienste anbietet aus Sicherheitsgünden nichts verloren: Du musst davon ausgehen, dass die Software wie mrbs angreifbar ist, und wenn es einem Angreifer gelingt, Zugang auf den Docker Host zu bekommen, ist es besser, wenn der nicht in grün steht, sondern, z.B. in eine DMZ oder gleich in Rot.
  • Für das dargestellte Setup ist das aber letztlich uninteressant. Wenn du deinen Mailserver in grün betreiben willst, und die Ports durch die FW durchreichst, musst du eben dafür sorgen, dass die DNS Cnames der Dienste, die auf dem Docker Server laufen auf die öffentliche IP deiner Firewall zeigen. Ein voll funktionales Mailserversetup auf diese Weise ist aber nur eingeschränkt möglich, vor allem wenn man keinen Smarthost für den Versand hat.
  • Was Probleme bereiten könnte, ist die Zertifikatsbeschaffung hinter einer NAT FW, da letsencrypt ja auf Port 80 die Zertifikate erneuern will. Wenn du jetzt hinter deiner FW mehr als einen Server auf Port 80 erreichen willst, bräuchtest du in rot schon einen Reverse Proxy. Man kann die Zertifikatsbeschaffung, z.B… für einen Mailserver in grün, aber natürlich an den per Port 80 erreichbaren Host delegieren.

Ich gehe aber auch davon aus, dass für eine große Schule mit vielen Diensten ein Dockerhost nicht ausreicht, weil es da schon Sinn machen kann, dicke Apps wie Nextcloud/Collabora speicher- und ressourcentechnisch auf eine eigene VM auszulagern und kleine Dienste wie mrbs, osp, mail u.ä auf einem zweiten zu sammeln. Man braucht dann eben auch entweder mehr als eine IP oder Knowhow für einen „zentralen“ Reverse Proxy, zumindest wenn Dienste per http(s) angeboten werden, was meist der Fall sein dürfte.

Ansonsten würde ich die Strategie verfolgen, für jeden Dienst einen Host zu verwenden und kein UVZ, also posrtfolio.meine.schule.tld, mrbs.meine.schule.tld u.s.w., da es manchmal nicht trivial ist, den reverse Proxy für den Zugang über service.meine.schule.tld/dienst/ zu konfigurieren.

VG

Frank

Hallo Frank,

Jpp, so machen wir es bei uns auch (halt mit LXC, statt Docker). HAPRoxy läuft bei uns in „ROT“ und verteilt dann entsprechend.

:+1:

Das sehe ich auch als ein Problem an, da man ja idealerweise für alles ein Zertifikat haben will um weg von den selbstsignierten zu kommen (sei es das Captive Portal oder andere interne Dienste). Auch wenn das Setup nicht ganz trivial ist, wäre der „einfachste“ Weg ein Reverse Proxy in Rot/DMZ. Wenn er direkt auf der Firewall läuft, reicht eine öffentliche IP, ansonsten braucht man schon mindestens zwei. Aber das wäre ein weiterer großer Schritt weg von einem KISS-Setup…

vG Stephan

Hallo,

ich will KISS, ich finde, die LMN7 ist schon in (zu) vielen Aspekten - anders als die bisherige Philosophie - nicht KISS. Und viele komplexe Dinge die dann automatisiert werden, sind unflexibel und für alle Nicht-Entwickler (dazu zähle ich mich auch) als Black Box nicht mehr zu durchschauen. Das reduziert die Chance, neue Entwickler für das Projekt zu gewinnen stark. Und besonders bei so was wie Docker, wo die Überlegungen von einem schnell zu einem Riesenvorteil für alle werden kann (denke mal an den LimeSurvey Thread, wenn man man weiß wie das mit dem LDAP am besten geht, hat man wahrscheinlich in 3 Stunden eine Docker App gebaut, für alle…), kann man vielleicht Mitarbeiter gewinnen und motivieren.

Deswegen würde ich von einem vorgegebenen linuxmuster-reverse-proxy absehen. Wenn deine Schule das braucht, kannst du beim vorgestellten Docker Host einfach die ufw anpassen und deinen Proxy vorschalten, fertig.

Für viele Dienste reicht auch ein kleiner Cloud-Server: Wenn du das Portfolio betrachtest, kannst du das auf dem kleinsten Cloudserver bei H. für 5 EUR im Monat betreiben, inklusive täglicher Backup-Snapshots.

Oder denke an ein kommunales RZ, die haben vms und IPs und können so super einfach alle linuxmuster-docker-Apps auf ihre eigenen Server verteilen, mit oder ohne Reverse Proxy, schnell und gut dokumentiert.

Das hatte ich beim vorgestellten Vorgehen auch im Sinn
Du bist als Schule und Admin maximal flexibel in deinen Entscheidungen – und nicht an Entscheidungen gebunden, die die Entwickler des Vereins aus Ihrer Sicht auf die Dinge für dich getroffen haben. Und gerade bei der Ausgestaltung der “Mehrwertdienste” rund um den zentralen Server finde ich das (auch für mich persönlich) maximal wichtig.

VG
Frank

2 „Gefällt mir“

Hi Frank,
ich hoffe, dass es das ist. Wenn ich vor KA noch zeit habe mir das anzuschauen, kann ich dir vllt. auch folgen, wenn du drüber redest. Was ich sagen will: Ich hoffe, dass es einfacher ist, als das was ich bisher zusammengegurkt habe.
V.a. dass du auch ein RZ im Sinn hast gefällt mir, vielleicht kannst du das der Stadt KA mal vorstellen (inkl. deren Handlanger-Firma).
Mal sehn, wer die Limesurvey-App zuerst gebaut hat: @Michael oder ich. (Du bist nicht im Rennen!)

Vg, tobias

Hai,

Ich glaube schon. Also ainfacher als traefik ist es sicherlich, ob man den Reverse Proxy jetzt auf den Docker Host hat oder mit jwilder/nginx plus letsencrypt-Helper in einem Container kann man sicher diskutieren. Das hat vor allem Auswirkungen, wenn die Reverse-Proxy Konfiguration komplizierter ist, z.B. wenn man Apps wie Mattermost verwendet, die Websockets ist dergleichen verwenden.

Habe verstanden :yum:

Bei der Erstellung des Images könnt ihr ja durchaus mal in den Dockerfiles der OSP und MRBS Images spicken, die sind ja auch beide PHP. Wichtig ist vor allem, dran zu denken, dass man die LDAP Erweiterung für PHP ins Image aufnimmt, die kommt bei den PHP Basisimages nicht mit.

Wenn ihr euch beim docker hub Registriert, kann ich aus linuxmuster eine Organisation machen, dann könnt ihr die Continerimages dort zur verfügung stellen. linuxmuster/limesurvey :slight_smile:

Hat @Michael einen github Account?

VG

Frank

Hi. Wusste bisher nicht, dass es da ein Wettrennen gibt :slight_smile: … aber auf dockerhub gibt es ja bereits limesurvey-container. Hattest du nicht in einem deiner Videos auch gezeigt, dass man einen bestehenden Container nutzen und abwandeln kann?
Schönen Gruß,
Michael

Hallo,

ja, schau dir mal meine Dockerfiles an, ich nehme ja auch nur ein php7.3.3 Image und passe das an. Genau so kannst du natürlich da hinschreiben From limesurvey/latest und das dann anpassen. Evtl. Kommt man auch ohne selbst gemachtes Image hin, so wie beim Mailserver und kann sich auf dir App Komponente beschränken.

Und man muss genau hischauen, was das für Images sinf und ob und von wem die gepflegt werden. Für MRBS gi ts auch ein paar auf dem Hub, aber mein offizielles und kein ordentlich gepflegtes.

Und für die App musst du das ja dann noch mit einem Datenbank Container zusammenbündeln, da reicht MRBS alleine nicht.

VG

Frank

Hi Frank,

Max und ich haben das jetzt mal nicht für limesurvey, sondern für was viel einfacheres durchgespielt: apt-cacher-ng.
Der feine Unterschied ist, dass der apt-cacher-ng nicht auf 80/443 normalerweise läuft, also auch gar keine nginx-config braucht. Hab mich für den einfach Weg entschieden und die default-port 3142 durch den dockerhost durchreiche.
Alleine fehlt uns, dass man die ufw wohl noch in das deploy-skript stecken muss.

Hier also die zwei Repos, die man gerne in linuxmuster-ext-docker übernehmen (forken?) kann:

und das Image hab ich auch hochgeladen, was man natürlich dann für Docker nochmal machen muss.

https://hub.docker.com/r/hgkvplan/apt-cacher-ng

Mit „man“ meine ich entweder dich, @ironiemix, oder jemand aus deinem Infra-Team?

VG, Tobias

Hallo,

das mache ich gerne.

Ich habe mir noch ein paar Gedanken zu einem etwas einheitlicheren Gerüst für Dockerhost und Apps gemacht, das folgende Bildchen zeigt das:

Im Wesentlichen sind das zwei ini-Dateien, die im Dockerhost vorhanden sein müssen:

  • server.ini Enthält alle Infos zum linuxmuster.net Server. Besonders auch die Version des Servers - damit kann man die Migration gestalten.
  • docker.ini damit kann man z.B. für den ganzen Dockerhost eine Rolle definieren, ob der z.B. selbst Revers Proxy Dienste machen soll oder ob dieser Docker Host generell “extern” angsteuert wird.
  • Dann würde ich noch Skripte mitliefern, die App-Erstellern bei der Konfiguration nutzen können, so als eine Art API. Beispiel: check_dns service.host.tld könnte überprüfen, ob es einen DNS Eintrag für service.host.tld gibt, der auf den aktuellen Dockerhost zeigt. Im Setup Skript der App könnte man das dann benutzen, um das zu überprüfen, ebenso z.B. für das Zertifikat.

Die Apps sollten zwei Bedingungen erfüllen:

  • App spezifische Konfiguration sollte in app.ini im Verzeichnis der App liegen. Die Datei wird wenn nötig von der setup-Routine der App (s.u.) ausgewertet und kann auch fehlen.
  • Jede App sollte ein Skript setup haben, das in mindestens zwei Varianten funktionieren sollte: setup first zur Erstkonfiguration und setup update zum Update der App. Wenns gut läuft, kann das Skript beides mal dasselbe tun, wenn nötig kann man aber eben zwischen Erstkonfiguration und Update differenzieren. Außerdem sind weitere Funktionen denkbar wie setup migrate, um z.B. die MRBS DB in die Docker App zu migrieren.

Lasst mich mal wissen, was ihr dazu so denkt. CC: @thomas ich würde den mailserver/Hauptdockerhost auch in diese Richtung vereinheitlichen wollen, um die Dokumetation zu vereinfachen - deine Einschätzung ist also wichtig, was die Konfiguration im Zuge des Serversetups angeht - welche Probleme siehst du diesbezüglich?

VG

Frank

Hi,
ich finds gut. sowohl die pseudo-API als auch einheitliche Ablage.

Ich gebe zu Bedenken, dass momentan jeder Beta-tester mindestens einmal über das Setup stolpert, aus verschiedensten Gründen - und dann muss man von vorne anfangen.
Ist nicht weiter schlimm, aber an der Stelle könnte man auch sagen, dass bei der Erstkonfiguration zumindest der Docker-host auch außen vor bleiben könnte. Dann hätten mehr leute sowohl die Beta als auch die Final schneller in einem Grundsystem am Laufen.

Für den Dockerhost muss man eh auf die wahrscheinlich auf die Konsole, ich sehe also weniger Fehlerquellen, wenn man sagt, den Dockerhost inkl. mail und allen erweiterungen, die man haben möchte installiert man nachgelagert in sein System - a.k.a. ohne SELMA.

Evtl. findet ihr das ein schritt zurück. Daher nur m.M.
vG, Tobias

Hallo,

man muss natürlich unterscheiden zwischen „DEM“ Dockerhost und allen Dockerhosts.

Letztlich ist es egal, es sollte mittelfristig eben nur so sein, dass „DER“ Dockerhost genauso aussieht, wie alle anderen Dockerhosts und der Mailservercontainer sich eben auch an die dargestellten Regeln hält. Dann kann man eben auch auf „DEM“ Dockerhost, die anderen Docker Apps istallieren oder den Mailcontainer selbst auf einem anderen Dockerhost.
Wer das Setup-Sktipt dann wann woher aufruft ist letztlich ja egal, das kann durchaus auch beim Erstsetup des Servers geschehen.

Ich finde auch, das das Erstsetup hier gesplittet werden könnte, aber ich finde ja auch die Bemühungen, die (ein einziges Mal durchzuführende) Installation vollständig in der Selma abzubilden komplette Zweitverschwendung, das heißt ich bin da eher nicht der Maßstab :wink:

VG

Frank

:slight_smile:
Also wäre doch ein Zweitnutzung gut: wenn man linuxmuster-setup-ext mehrfach aufrufen könnte, weil es
a.) mal DEN dockerhost (in grün) konfiguriert oder dekommisioniert
b.) mal einen anderen dockerhost bereitstellt
c.) eine ankreuzliste von diensten bereitstellt, die man haben können wollte: Mail, MRBS, OSP, nginx-RP

Dann kann sich die Abteilung SELMA auch um eine GUI bemühen, wenn schick wichtig ist.
VG, Tobias

1 „Gefällt mir“

nochmal hi: an der stelle nochmal verlinkt:

https://medium.com/@decrocksam/deploying-lets-encrypt-certificates-using-tls-alpn-01-https-18b9b1e05edf

falls wir das tls-alpn-01 benutzen wollen, dann braucht man kein port 80, nur noch 443? vermute ich jedenfalls.

VG, Tobias

1 „Gefällt mir“

Hallo,

Ja, allerdings finde ich den Port 80 erst mal nicht schlimm.

  • Dehydrated nimmt den nur für den allerersten Request
  • Anschließend wird http sowieso via 301 (Moved Permanently) auf https geleitet.

Interessanter sind die DNS Validierungen, weil du da WildCard Zertifikate bekommen kannst. Allerding erfordern die DNS Provider spezifische Skripte und Schnittstellen, da kann man also wahrscheinlich auch nur eine Auswahl anbieten. Damit hättest du aber mit einem Schlag „alle“ Docker Zertifikate :wink:

VG

Frank

oh, noch ein Argument gegen die nginx-le-companion Variante:

Belwue hat mir, vermutlich aus missverständnis, eine (nicht benutzte) domäne auf eine andere IP gelenkt.

ich habe die Domäne aber doch in Benutzung, nämlich als CNAME für ein anderes LE-Zertifikat.
Bis ich herausgefunden habe, wo das Problem lag … ich habe es gar nicht gesehen, erst als das alte ZErt auslief (übrigens während der Tagung).
Es muss also für den nginx-le-companion noch eine art email-monitoring oder ein moni-pi-script her, das die Geschichte überprüft.
Das intern verwendete python-script des ACME-clients steigt übrigens mit einer Fehlermeldung aus, das ist auch nicht fein.

ich musste meine kompletten apps runter und wieder hochfahren. Jetzt hat es immerhin wieder funktioniert.
Vg, Tobias

Interessant, in der Tat.

Ein Haken: wenn irgendwas schief geht beim wildcard, was propagiert wird, hat man gleich alle Dienste außer Gefecht gesetzt…
VG, Tobias

Hi Frank,

das Serversetup macht folgendes:

  • initiiert den ssh-Link zum Dockerhost,
  • kopiert die selbstsignierten Server-Root- und Dockerhost-Zertifikate nach /etclinuxmuster/ssl und
  • führt danach linuxmuster-prepare aus, was den Domainname und das root-Passwort setzt.
  • Reboot.

Falls beim Setup die Mailserver-Option gesetzt wurde, werden in einem zweiten Schritt

  • die setup.ini-Datei und ein Mailserver-Setup-Skript nach /tmp und
  • die Mailserver-Zertifikate nach /etclinuxmuster/ssl kopiert und
  • schließlich das Mailserver-Setupskript ausgeführt.

Das alles kann mit wenig Aufwand angepasst werden, seh ich also unkritisch. Die Serverversion müsste ich halt noch zusätzlich in die setup.ini eintragen.

VG, Thomas

2 „Gefällt mir“

Hallo,

super, danke für die Infos. Ich denk mal nach, wie wir das dann am geschicktesten hinbekommen und schick nen Pull Request :wink:

VG

Frank

1 „Gefällt mir“