Skip to content

Vorlagen für Konfigurationsdateien in Univention

Dieser Beitrag ist auch in englischer Sprache verfügbar: Templates for configuration files in Univention

Wer uns ein wenig kennt, weiß, dass wir und Univention gute Freunde sind. Eine Linux-Distribution, angereichert mit effektiven und einfach zu nutzenden Administrationswerkzeugen, die genau ins Herz von Unternehmen zielt: Eine Domänenstruktur bereitzustellen. Find‘ ich total cool.

Wer mich ein wenig kennt, versteht auch warum. Linux ist ein offenes System. Ich kann’s anpassen. Ich kann’s analysieren. Gut, ich kann’s auch problemlos kaputt spielen, aber ohne ein wenig Risiko macht die Sache eh nur halb so viel Spaß, oder?

Aber Moment mal — passt das aber überhaupt zusammen? „Standardisiert“, „einfache Administration“, „flexibel“ und „offen“? Univention sagt: Ja klar.

Einer der Bausteine, damit das funktioniert, ist Univentions Vorlagensystem für Konfigurationsdateien. Dabei werden Vorlagen mit von uns Admins festgelegten Einstellungen kombiniert und in die tatsächliche Konfigurationsdatei gegossen. Dieser Mechanismus wird für alles verwendet, was in Univention zentral verwaltet wird: Webserver wie Apache, E-Mail-Server wie Dovecot und Postfix, Windows-Dienste wie Samba und CUPS.

Und genau darum geht’s hier: Wie funktioniert der Mechanismus überhaupt? Und vor allem: Wie passe ich Konfigurationen an, ohne mir gleich in den Fuß zu schießen? Im Univention-Forum kommt die Frage regelmäßig auf, deswegen dient sie uns hier als guter Anlass.

Los geht’s

Szenario: Meine Postfix-Konfiguration braucht eine Ergänzung.

Erster Versuch: Als gestandener Linux-Admin mache ich natürlich keine Gefangenen und bearbeite direkt mal die Postfix-Konfigurationsdatei main.cf. Postfix neu laden lassen, getestet, funktioniert. Super. Tage später: Geht nicht mehr. Autsch!

Was ich übersehen habe, ist die dicke Nachricht am Anfang der Datei: „Warning: This file is auto-generated and might be overwritten by univention-config-registry“. Erste Einsicht ist also: Finger weg, wenn die zu sehen ist! Sonst geht’s eurem Fuß bald so wie meinem.

Nächste Idee: Ich schaue, woher dieses ominöse univention-config-registry ihren Inhalt für die Datei bekommt. Ein wenig greppen später werde ich fündig: Aha, da gibt’s Dateien in /etc/univention/templates/files/etc/postfix.

Also zweiter Versuch: Meine Änderung in einer der Dateien angefügt. Hmmm, passiert aber irgendwie nichts — die /etc/postfix/main.cf enthält die Änderung schlicht nicht. Muss ich vielleicht irgendwie nachhelfen, damit die Datei neu erzeugt wird? Na gut. Eine kurze Suche später probiere ich ucr commit /etc/postfix/main.cf — und schon klappt’s auch mit der Änderung!

Nun aber konkret und auf den Punkt:

Eine Konfigurationsdatei wird entweder aus genau einer Vorlagendatei oder vielen Teildateien erzeugt. Die Vorlagen befinden sich dabei immer in Unterverzeichnissen unterhalb von /etc/univention/templates/files. Damit das System weiß, welche Zieldatei aus welchen Vorlagendateien erzeugt wird, müssen diese Vorlagen aber registriert werden. Dazu wiederum gibt es Info-Dateien im Verzeichnis /etc/univention/templates/info. Welche Variablen es gibt, steht wiederum in Dateien in /etc/univention/registry.info/variables.

Benennung und Speicherort

Im ersten Modus, genannt file, gibt es nur eine Vorlagendatei pro Zieldatei. Der Vorlagenname ist dabei identisch mit dem zu erzeugenden Dateinamen — für /etc/krb5.conf z.B. /etc/univention/templates/files/etc/krb5.conf.

Im zweiten Fall, Modus multifile, gibt’s hingegen ein Unterverzeichnis, das genau so heißt, wie die zu erzeugende Datei, nur noch mit .d als Endung — und darin liegen die Teilvorlagen. So wird /etc/postfix/main.cf aus den Dateien in /etc/univention/templates/files/etc/postfix/main.d erzeugt.

Die Dateien werden dabei in alphabetischer Reihenfolge ausgewertet. Normalerweise wird eine konkrete Reihenfolge dadurch erzwungen, dass die Dateinamen mit einem numerischen Präfix beginnen — somit kommt also z.B. 10_general vor 80_deliver dran. Ansonsten ist der Dateiname hier frei wählbar; auch die Endung spielt keine Rolle.

Einbetten von Variablen und Python-Code

Vorlagendateien sind dynamisch: es können Werte direkt aus der Config Registry eingefügt werden. Man kann auch Python-Code einbetten, der die gewünschte Ausgabe erzeugt.

Die Syntax für einfache Variablen lautet: @%@variable@%@, z. B. @%@ldap/base@%@ für LDAP-Basis-DN. Python-Blöcke werden hingegen durch zwei Zeilen eingerahmt, in denen nur Folgendes steht: @!@. Man hat dort über das Objekt configRegistry Zugriff auf die Config Registry. Als Python-Version kommt 2.7 zum Einsatz.

Alles außerhalb von Python-Blöcken wird bis auf die erwähnte Variableninterpolation unverändert in die Zieldatei geschrieben.

Zieldateien erzeugen

Das Tool, mit dem die Konfigurationsdatei erzeugt wird, ist das gleiche, mit dem auch die Config Registry verändert wird: univention-config-registry, oder für Faulpelze wie mich: ucr. Dateien erzeugt man mit ucr commit Zieldateinamen, also z. B. ucr commit /etc/postfix/main.cf /etc/postfix/master.cf. Hier müssen die vollständigen Pfade und Namen zu den zu erzeugenden Dateien angegeben werden, nicht die zu den Vorlagen. Ein ucr commit ohne Dateinamen erzeugt alle bekannten Dateien neu.

Den anschließenden Neustart der Dienste übernimmt ucr übrigens nicht. Also dran denken und nicht schon die Füße hochlegen.

Variablen registrieren

Möchte man eine neue Variable einführen, so muss auch die dem System bekannt gemacht werden. Dafür gibt’s Dateien in /etc/univention/registry.info/variables/. Die folgen einer Art Ini-Format und stellen neben dem Namen der Variablen auch eine menschenlesbare Beschreibung bereit, die z. B. bei der Suche mit ucr search … ausgegeben wird.

Die Dateien in diesem Verzeichnis müssen .cfg als Endung haben.

Vorlagen registrieren

Damit ucr die Vorlagen auch findet, müssen sie dem System bekannt gemacht werden. Andernfalls werden sie nicht ausgewertet. Diese Bekanntmachung geschieht über Dateien im Verzeichnis /etc/univention/templates/info. Der Name der jeweiligen Datei ist relativ egal, aber sie muss auf .info enden — andernfalls wird sie nicht ausgewertet. Außerdem müssen sowohl für die .cfg von oben als auch für diese .info die gleiche Basisnamen verwendet werden.

Bestehende Dateien sollten nicht verändert, sondern nur ergänzt werden. Ein eigenes Präfix, z.b. my-, ist hilfreich, um den Überblick zu bewahren.

In diesen Info-Dateien stehen drin:

  1. Welcher Modus kommt zum Einsatz (Type: file bzw. Type: multifile)?
  2. Wie lautet der Pfad der zu erzeugenden Datei (z. B. Multifile: etc/postfix/main.cf)?
  3. Welche Variablen werden in der Vorlage verwendet?
  4. Welche Teil-Vorlagendatei wird im Modus multifile gelesen?

Als Letztes muss man dem System bekanntgeben, dass es diese .info und die .cfg gibt. Das geschieht mit dem Befehl ucr register BasisnameMeinerDatei, also z. B. ucr register my-postfix.

Dank der Informationen aus 3. weiß ucr, welche Zieldateien es automatisch aus Vorlagen neu erzeugen muss, wenn eine Variable verändert wird. Das klappt aber nur, wenn die Variable selbst, wie oben beschrieben, registriert ist.

Upgrade-Katastrophen vermeiden

Um möglichst upgradesicher zu sein, ist es also am besten, bei Vorlagen vom Typ multifile eine eigene Teil-Vorlagendatei anzulegen. Diese sollte über eine eigene Info-Datei registriert werden. Nehmt euch einfach z. B. univention-mail-postfix.info als Vorlage.

Bei Vorlagen vom Typ file hingegen führt kein Weg daran vorbei, diese einzelne Vorlagendatei anzufassen. Nach einem Upgrade sollte daher unbedingt immer anschließend mit dem Befehl univention-check-templates geprüft werden, ob es von mir modifizierte Vorlagendateien gibt, für die es von Univention neuere Versionen gibt. Falls ja, müssen beide manuell zusammengeführt werden.

Muss das sein?

Man sollte sich auch die Frage stellen, ob die Änderung wirklich nötig ist. Für viele Einstellungen bietet Univention bereits Konfigurationsvariablen an. Welche es gibt, kann auf zwei Arten herausgefunden werden:

  1. ucr search Begriff — dies durchsucht die dokumentierten Variablen. Aber da werden nicht immer alle aufgelistet. Daher:
  2. Direkte Suche in den Vorlagendateien in /etc/univention/templates/files/…. Hier hilft gesunder Menschenverstand, um zu erkennen, ob die gewünschte Einstellung bereits unterstützt wird.

Konkretes Beispiel

Wenn ich z. B. in der Postfix-Konfiguration die Einstellung milter_default_action ändern möchte, für die Univention keine direkte Unterstützung vorsieht, so lege ich zuerst die Info-Datei an, z. B. /etc/univention/templates/info/my-postfix.info:

Type: subfile
Multifile: etc/postfix/main.cf
Subfile: etc/postfix/main.cf.d/99_my_milter
Variables: mail/postfix/milter_default_action

Anschließend lege ich die Teil-Vorlagendatei /etc/univention/templates/files/etc/postfix/main.cf.d/99_my_milter an, z. B. mit folgendem Inhalt:

@!@
print 'milter_default_action = %s' % configRegistry.get('mail/postfix/milter_default_action', 'tempfail')
@!@

Da das keine Standardvariable ist, registriere ich sie in /etc/univention/registry.info/variables/my-postfix.cfg:

[mail/postfix/milter_default_action]
Description[de]=Legt fest, wie Postfix auf Milter-Anwendungsfehler reagiert (default=tempfail)
Description[en]=This parameter specifies how Postfix handles Milter application errors (default=tempfail)
Type=str
Categories=service-mail

Noch schnell die Dateien mit ucr register my-postfix registrieren.

Nun setze ich die Variable mit ucr set mail/postfix/milter_default_action=reject und sehe, dass die Datei neu erzeugt wird. Zu guter Letzt folgt noch ein Reload vom Postfix und ich hab’s geschafft.