Linux

Samba Active Directory unter Debian 13: zwei Domain Controller mit Zeitserver

Eine eigene AD-Domäne mit Samba unter Debian 13: erster Domain Controller, zweiter DC mit Replikation und SYSVOL-Abgleich, dazu chrony als signierter Zeitserver für Windows- und Linux-Clients.

Thomas 10. Oktober 2026 12 Min. Lesezeit 2 Aufrufe 10. Oktober 2026

Serverschränke mit Netzwerkkabeln und Status-LEDs
Foto: Taylor Vick auf Unsplash

Übersicht

Zwei Samba-Domain-Controller mit AD-Replikation, SYSVOL-Abgleich und chrony als Zeitserver für Windows- und Linux-Clients

Dieser Artikel zeigt, wie man unter Debian 13 eine eigene Active-Directory-Domäne mit Samba aufbaut: zuerst einen einzelnen Domain Controller, dann einen zweiten für die Ausfallsicherheit, und zum Schluss beide als Zeitserver für das Netz. Windows-Clients melden sich an der Domäne an wie an einem Windows-Server, Linux-Clients über SSSD und Kerberos.

Nicht alles davon ist Pflicht:

Teil Nötig?
Teil 1: erster Domain Controller Pflicht. Ein DC reicht für eine voll funktionsfähige Domäne.
Teil 2: zweiter Domain Controller Optional, nur für Ausfallsicherheit.
Teil 3: Zeitserver Empfohlen, auch mit nur einem DC.

Einzelne Schritte, die nur in bestimmten Fällen nötig sind, sind im Text als optional markiert. Mit beiden DCs stehen am Ende zwei gleichwertige Server: Beide beantworten DNS, Kerberos und LDAP, beide liefern die Zeit, und fällt einer aus, arbeiten die Clients mit dem anderen weiter.

Beispielwerte

Alle Namen und Adressen im Artikel sind Beispiele und durch die eigenen zu ersetzen.

Was Wert
DNS-Domäne / Realm example.lan / EXAMPLE.LAN
NetBIOS-Name EXAMPLE
Erster DC dc1.example.lan, 192.168.1.11
Zweiter DC (optional) dc2.example.lan, 192.168.1.12
Netzwerk-Interface eth0, den eigenen Namen zeigt ip -br link
DNS-Forwarder <dns-forwarder>, z. B. der Router oder ein vorhandener DNS-Server

Jeder DC braucht Debian 13 und eine feste IP-Adresse. Die Clients müssen später die DCs als DNS-Server nutzen, entweder direkt per DHCP oder über eine bedingte Weiterleitung für example.lan im vorhandenen DNS. Nur so finden sie die SRV-Einträge, über die sich Windows und SSSD die Domain Controller suchen.

Benötigte Ports

Eingehend auf jedem DC offen, mit welcher Firewall auch immer:

Protokoll Ports Dienst
TCP + UDP 53 DNS
TCP + UDP 88 Kerberos
UDP 123 NTP (Teil 3)
TCP + UDP 389 LDAP
TCP + UDP 464 Kerberos-Passwortänderung
TCP 135 RPC Endpoint Mapper
TCP 139, 445 SMB (SYSVOL, NETLOGON)
TCP 636 LDAPS
TCP 3268, 3269 Global Catalog (LDAP / LDAPS)
TCP 49152-65535 RPC dynamisch

Der letzte Bereich wird gern vergessen. Samba vergibt dynamische RPC-Ports standardmäßig aus 49152-65535 (Parameter rpc server dynamic port range). Wer nur die ersten paar Ports freigibt, hat ein Setup, das funktioniert, solange Samba zufällig die niedrigsten Ports belegt.

Teil 1: Der erste Domain Controller

Schritt 1: Vorbereitung

Samba muss den eigenen vollständigen Namen auf die LAN-IP auflösen können, nicht auf 127.0.1.1, das Debian je nach Installation einträgt. In /etc/hosts:

192.168.1.11    dc1.example.lan dc1

Optional: Wer im LAN kein IPv6 nutzt, schaltet es auf dem Interface ab. Sonst trägt Samba auch eine per SLAAC bezogene IPv6-Adresse im DNS ein, und die Clients bekommen für den DC eine Adresse, die im Netz eigentlich keine Rolle spielt:

echo "net.ipv6.conf.eth0.disable_ipv6=1" > /etc/sysctl.d/99-disable-ipv6-eth0.conf
sysctl -p /etc/sysctl.d/99-disable-ipv6-eth0.conf

Schritt 2: Pakete

Der AD-DC bringt eigene Dienste mit. Die Einzeldienste smbd, nmbd und winbind werden deshalb abgeschaltet und maskiert, und die mitgelieferte smb.conf muss weg, sonst bricht die Einrichtung im nächsten Schritt ab:

apt install samba-ad-dc samba-dsdb-modules winbind libnss-winbind libpam-winbind ldb-tools krb5-user rsync
systemctl disable --now smbd nmbd winbind
systemctl mask smbd nmbd winbind
systemctl unmask samba-ad-dc
rm /etc/samba/smb.conf

rsync ist nur nötig, wenn später ein zweiter DC dazukommt (Teil 2). Der holt sich damit Daten vom ersten, deshalb muss es auf beiden installiert sein. Bei nur einem DC kann es weg.

Schritt 3: Domäne anlegen

samba-tool domain provision \
  --realm=EXAMPLE.LAN \
  --domain=EXAMPLE \
  --server-role=dc \
  --dns-backend=SAMBA_INTERNAL \
  --use-rfc2307 \
  --option="dns forwarder = <dns-forwarder>"

cp /var/lib/samba/private/krb5.conf /etc/krb5.conf
samba-tool user setpassword Administrator

SAMBA_INTERNAL ist der in Samba eingebaute DNS-Server. Er reicht für die meisten Umgebungen und erspart die Kopplung mit BIND. Alles, was nicht zur Domäne gehört, gibt er an den Forwarder weiter. --use-rfc2307 legt in AD die Attribute für UID, GID und Login-Shell an. Die braucht man, sobald Linux-Clients feste, auf allen Systemen gleiche Benutzer-IDs bekommen sollen.

Der DC fragt ab jetzt nur noch sich selbst. /etc/resolv.conf:

search example.lan
nameserver 127.0.0.1

Schritt 4: Eigenes Zertifikat für LDAPS (optional)

Nur nötig, wenn Anwendungen per LDAPS (Port 636) gegen das AD prüfen. Ohne eigenes Zertifikat erzeugt Samba beim ersten Start selbst eines. Mit einem eigenen legt man fest, auf welche Namen es ausgestellt ist und wie lange es gilt. Das ist wichtig für Anwendungen, die per LDAPS gegen das AD prüfen und den Namen im Zertifikat kontrollieren. Deshalb kommt es vor den ersten Start:

cd /var/lib/samba/private/tls
openssl req -x509 -newkey rsa:4096 -nodes -days 3650 \
  -subj "/CN=dc1.example.lan" \
  -addext "subjectAltName=DNS:dc1.example.lan,DNS:dc1" \
  -keyout key.pem -out cert.pem
chmod 600 key.pem

Das Zertifikat ist selbstsigniert und zehn Jahre gültig. Anwendungen, die sich per LDAPS verbinden, muss man cert.pem als vertrauenswürdig mitgeben. Wer eine eigene CA betreibt, signiert stattdessen dort.

In /etc/samba/smb.conf unter [global] das Zertifikat einbinden und Samba auf das LAN-Interface beschränken. Ohne eigenes Zertifikat entfallen die vier tls-Zeilen, die beiden interfaces-Zeilen bleiben:

interfaces = lo eth0
bind interfaces only = yes
tls enabled = yes
tls keyfile = tls/key.pem
tls certfile = tls/cert.pem
tls cafile =

interfaces allein bewirkt wenig, erst zusammen mit bind interfaces only = yes lauscht Samba wirklich nur auf den genannten Interfaces. Das leere tls cafile verhindert, dass Samba nach einer CA-Datei sucht, die es bei einem selbstsignierten Zertifikat nicht gibt.

Schritt 5: Starten und prüfen

systemctl enable --now samba-ad-dc
host -t SRV _ldap._tcp.example.lan                                  # DNS-Einträge der Domäne
kinit administrator && klist                                        # Kerberos-Anmeldung
openssl s_client -connect localhost:636 </dev/null | grep subject   # LDAPS antwortet, zeigt das Zertifikat

Damit ist die Domäne einsatzbereit. Für ein Homelab oder ein kleines Netz reicht ein DC. Er ist allerdings ein Single Point of Failure: Fällt er aus, kann sich niemand mehr anmelden. Wer das absichern will, ergänzt Teil 2, alle anderen springen direkt zu Teil 3.

Teil 2: Der zweite Domain Controller (optional)

Schritt 1: Vorbereitung

Auf dem neuen Server dieselbe Vorbereitung wie beim ersten, mit dessen Namen und IP:

192.168.1.12    dc2.example.lan dc2
echo "net.ipv6.conf.eth0.disable_ipv6=1" > /etc/sysctl.d/99-disable-ipv6-eth0.conf
sysctl -p /etc/sysctl.d/99-disable-ipv6-eth0.conf

Für den Beitritt muss dc2 die Domäne finden, also fragt er zuerst den bestehenden DC. /etc/resolv.conf auf dc2:

search example.lan
nameserver 192.168.1.11
nameserver 127.0.0.1

Auf dc1 kommt im Gegenzug dc2 als erster Nameserver vor 127.0.0.1. So überleben beide DCs den Ausfall des jeweils anderen beim Auflösen.

Schritt 2: Pakete und Kerberos

Pakete wie in Teil 1, Schritt 2, inklusive dem Entfernen der smb.conf. Die krb5.conf schreibt man hier von Hand, weil es auf dc2 noch keine Domäne gibt, aus der man sie kopieren könnte. Kerberos zeigt zunächst auf dc1:

[libdefaults]
    default_realm = EXAMPLE.LAN
    dns_lookup_realm = false
    dns_lookup_kdc = true

[realms]
    EXAMPLE.LAN = {
        kdc = dc1.example.lan
        admin_server = dc1.example.lan
    }

[domain_realm]
    .example.lan = EXAMPLE.LAN
    example.lan = EXAMPLE.LAN

Schritt 3: Der Domäne beitreten

dc2 tritt als vollwertiger DC bei, mit denselben RFC2307-Einstellungen wie dc1:

samba-tool domain join example.lan DC \
  -U Administrator \
  --server=dc1.example.lan \
  --dns-backend=SAMBA_INTERNAL \
  --option="dns forwarder = <dns-forwarder>" \
  --option="idmap_ldb:use rfc2307 = yes"

Schritt 4: idmap von dc1 übernehmen

Jeder DC vergibt für eingebaute Gruppen und Konten eigene interne IDs. Ohne Abgleich hat dieselbe Gruppe auf dc1 eine andere ID als auf dc2, und die Dateirechte im SYSVOL stimmen nicht mehr. Die Lösung ist, die Zuordnungstabelle einmalig von dc1 zu kopieren. Auf dc1:

tdbbackup -s .bak /var/lib/samba/private/idmap.ldb
scp /var/lib/samba/private/idmap.ldb.bak root@dc2.example.lan:/var/lib/samba/private/idmap.ldb
rm /var/lib/samba/private/idmap.ldb.bak

tdbbackup erstellt eine konsistente Kopie im laufenden Betrieb, ein einfaches cp könnte eine halb geschriebene Datei erwischen.

Schritt 5: Zertifikat und Start

Falls in Teil 1 ein eigenes Zertifikat angelegt wurde, hier dasselbe auf die Namen von dc2:

cd /var/lib/samba/private/tls
openssl req -x509 -newkey rsa:4096 -nodes -days 3650 \
  -subj "/CN=dc2.example.lan" \
  -addext "subjectAltName=DNS:dc2.example.lan,DNS:dc2" \
  -keyout key.pem -out cert.pem
chmod 600 key.pem

Dieselben Zeilen in /etc/samba/smb.conf unter [global] wie auf dc1. Danach Samba starten und den Cache leeren, damit die übernommene idmap sofort gilt:

systemctl enable --now samba-ad-dc
net cache flush

Schritt 6: SYSVOL abgleichen

Samba repliziert Benutzer, Gruppen und DNS zwischen den DCs von selbst, das SYSVOL-Verzeichnis mit Gruppenrichtlinien und Anmeldeskripten aber nicht. Windows-DCs nutzen dafür DFS-R, das Samba nicht kann. Der übliche Weg ist ein einseitiger Abgleich: dc1 ist die Quelle, dc2 holt sich regelmäßig eine Kopie. Gruppenrichtlinien bearbeitet man dann immer auf dc1.

Achtung bei den Pfaden: Debian legt SYSVOL auf einem per provision angelegten DC unter /var/lib/samba/state/sysvol an, auf einem beigetretenen unter /var/lib/samba/sysvol. Quelle und Ziel heißen deshalb unten verschieden. Auf beiden DCs zeigt testparm -sv | grep 'path = .*sysvol', wo es tatsächlich liegt.

Auf dc2 einen eigenen SSH-Schlüssel nur für diesen Abgleich erzeugen:

ssh-keygen -t ed25519 -N "" -C "sysvol-sync@dc2" -f /root/.ssh/sysvol-sync

Auf dc1 in /root/.ssh/authorized_keys den öffentlichen Schlüssel eintragen, aber eingeschränkt. Er darf nur SYSVOL lesen und nur von dc2 aus genutzt werden:

command="/usr/bin/rrsync -ro /var/lib/samba/state/sysvol/",restrict,from="192.168.1.12" ssh-ed25519 AAAA... sysvol-sync@dc2

rrsync gehört zum rsync-Paket und erzwingt, dass über diesen Schlüssel nur ein rsync auf genau dieses Verzeichnis möglich ist, mit -ro nur lesend. Selbst wenn der Schlüssel auf dc2 abhandenkommt, lässt sich damit auf dc1 weder eine Shell öffnen noch etwas verändern.

Das Abgleich-Skript auf dc2, zum Beispiel unter /usr/local/sbin/sysvol-sync.sh, schreibt sein Ergebnis ins Syslog:

#!/bin/bash
SOURCE="root@192.168.1.11:/"
TARGET="/var/lib/samba/sysvol/"
KEY="/root/.ssh/sysvol-sync"

if output=$(rsync -aXA --delete-after -e "ssh -i $KEY -o BatchMode=yes" "$SOURCE" "$TARGET" 2>&1); then
    logger -t sysvol-sync "sync from $SOURCE ok"
else
    logger -t sysvol-sync -p user.err "sync from $SOURCE failed: $output"
    exit 1
fi

-aXA überträgt neben den Dateien auch die erweiterten Attribute und ACLs, in denen Samba die Windows-Rechte speichert. Ohne die beiden Optionen kommen die Dateien zwar an, aber ohne Windows-Rechte, und samba-tool ntacl sysvolcheck schlägt fehl. Die Quelle ist nur /, weil rrsync auf dc1 den Pfad ohnehin festlegt.

Das Skript läuft mit BatchMode=yes und bricht deshalb ab, solange der Host-Schlüssel von dc1 unbekannt ist. Also den Schlüssel einmal hinterlegen, das Skript ausführbar machen und von Hand testen:

ssh-keyscan -t ed25519 192.168.1.11 >> /root/.ssh/known_hosts
chmod 750 /usr/local/sbin/sysvol-sync.sh
/usr/local/sbin/sysvol-sync.sh && journalctl -t sysvol-sync -n 1

Den Fingerprint dabei mit ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub auf dc1 vergleichen. Steht im Log ok, per Cron alle 15 Minuten starten:

echo "*/15 * * * * root /usr/local/sbin/sysvol-sync.sh" > /etc/cron.d/sysvol-sync

Schritt 7: Prüfen

samba-tool drs showrepl meldet ALL GOOD, beide DCs stehen im DNS, der SYSVOL-Abgleich läuft alle 15 Minuten

samba-tool drs showrepl --summary       # Replikation zwischen den DCs
host -t SRV _ldap._tcp.example.lan      # beide DCs im DNS
samba-tool ntacl sysvolcheck            # SYSVOL-Rechte
journalctl -t sysvol-sync -n 5          # letzte Abgleiche

Teil 3: Die DCs als Zeitserver

Zifferblatt einer Uhr in Schwarzweiß
Foto: Ximena Balderas auf Unsplash

Kerberos toleriert standardmäßig nur fünf Minuten Zeitunterschied zwischen Client und DC. Läuft eine Uhr weiter weg, scheitert jede Anmeldung mit einer Fehlermeldung, die auf den ersten Blick nichts mit der Zeit zu tun hat. In einer Windows-Domäne sind deshalb die DCs auch die Zeitserver: Windows-Clients holen sich die Zeit automatisch von dort.

Samba hat allerdings keinen eigenen NTP-Server. Die Zeit liefert chrony. Samba steuert nur etwas bei, das Windows zusätzlich verlangt: Domänenmitglieder akzeptieren die Zeit nur, wenn die Antwort mit dem Computerkonto signiert ist (MS-SNTP). Diese Signatur erzeugt Samba über einen Socket, und chrony fragt sie dort für jede Anfrage eines Windows-Clients ab.

Schritt 1: chrony einrichten (auf jedem DC)

Zusätzlich zu den bisherigen Ports muss UDP 123 offen sein.

apt install chrony          # ersetzt systemd-timesyncd

/etc/chrony/conf.d/samba-ad.conf, das Netz darf abfragen, Samba signiert die Antworten:

allow 192.168.1.0/24
ntpsigndsocket /var/lib/samba/ntp_signd

Als Zeitquelle für die DCs selbst bleibt der Debian-Pool aus der mitgelieferten chrony.conf eingetragen. Wer einen eigenen Zeitserver im Netz hat, setzt ihn dort ein.

Das Verzeichnis mit dem Socket gehört root und ist für andere gesperrt. chrony läuft aber als eigener Benutzer und braucht Zugriff:

chown root:_chrony /var/lib/samba/ntp_signd
chmod 750 /var/lib/samba/ntp_signd
systemctl restart chrony

Debian liefert das AppArmor-Profil von chrony bereits mit der passenden Freigabe für diesen Socket aus, dafür ist nichts weiter zu tun.

Schritt 2: Prüfen

chronyc tracking mit Leap status Normal, chronyc sources mit der aktiven Quelle und chronyc clients mit den ersten Clients im Netz

chronyc tracking            # Stratum und "Leap status: Normal"
chronyc -n sources          # ^* = aktive Quelle
chronyc clients             # wer holt sich die Zeit
ss -ulnp | grep ':123 '     # chronyd lauscht auf UDP 123

Auf einem Windows-Client in der Domäne:

w32tm /resync
w32tm /query /source

Der erste Befehl muss ohne Fehler durchlaufen, der zweite einen DC anzeigen. Bleibt die Quelle bei Local CMOS Clock oder schlägt /resync fehl, kommt die signierte Antwort nicht an. Dann zuerst die Rechte auf /var/lib/samba/ntp_signd und die Firewall prüfen.

Linux-Clients: zwei Stolperfallen

Linux-Clients holen sich die Zeit nicht automatisch vom DC, dort trägt man die DCs als NTP-Server ein. Zwei Fallen sind dabei typisch.

ntpsec braucht standardmäßig drei Quellen. Debian setzt in /etc/ntpsec/ntp.conf die Zeile tos minclock 4 minsane 3. Mit einem oder zwei DCs als einzigen Quellen kommen nie drei zusammen, ntpsec wird also nie synchron: ntpq -p zeigt die DCs als Kandidaten (+), aber nie als aktive Quelle (*), und ntpq -c rv meldet stratum=16, refid=INIT. Die Lösung: die pool-Zeilen auskommentieren und nach den Server-Einträgen die Mindestzahl senken:

server dc1.example.lan iburst
server dc2.example.lan iburst
tos minclock 1 minsane 1

systemd-timesyncd hängt Serverlisten aneinander. Mehrere Drop-ins unter /etc/systemd/timesyncd.conf.d/ mit je einer NTP=-Zeile ersetzen sich nicht, sie werden zusammengefügt. Bringt ein Hoster oder Image schon eine eigene Datei mit, steht dessen Server vorne in der Liste und bleibt die aktive Quelle. Ein leeres NTP= setzt die Liste zurück:

[Time]
NTP=
NTP=dc1.example.lan dc2.example.lan

Ob es greift, zeigt timedatectl show-timesync -p SystemNTPServers -p ServerName.

Fazit

Schon ein einzelner Samba-DC unter Debian nimmt einem Windows-Server die typischen Aufgaben ab: Anmeldung, Gruppenrichtlinien, DNS und Zeit. Ein zweiter DC sorgt für Ausfallsicherheit. Der größte Unterschied zu Windows ist dann die fehlende SYSVOL-Replikation, und die schließt ein eingeschränkter rsync-Schlüssel mit wenigen Zeilen Skript.

Kommentare

0

Noch keine Kommentare. Sei der Erste!

Kommentar schreiben

Kommentare werden vor der Veröffentlichung geprüft.