8.4 KiB
Kerberos Server
MIT Kerberos V KDC + admin server container running on Ubuntu 26.04.
Prerequisites
DNS setup
Kerberos is sensitive to hostname resolution. The following DNS records must be in place before starting the container.
Forward record — resolves the KDC hostname to its IP address:
krb5.example.org. IN A 192.168.1.10
_kerberos._tcp.example.org. IN SRV 1 0 88 krb5.example.org.
_kerberos._udp.example.org. IN SRV 1 0 88 krb5.example.org.
_kerberos-adm._tcp.example.org. IN SRV 1 0 749 krb5.example.org.
_kpasswd._udp.example.org. IN SRV 1 0 464 krb5.example.org.
Reverse record — resolves the IP back to the hostname (required by some Kerberos operations):
10.1.168.192.in-addr.arpa. IN PTR krb5.example.org.
The container's hostname must match KRB5_KDC_HOST exactly — it is set via the hostname: field in the compose file.
Note: DNS-based KDC discovery (SRV records) is disabled for the server container in the generated configuration (dns_lookup_kdc = false), however it is required for clients to locate the KDC. The KDC hostname must be resolvable by clients via DNS or a local hosts file entry.
Environment variables
| Variable | Default | Description |
|---|---|---|
KRB5_REALM |
EXAMPLE.ORG |
Kerberos realm (uppercase) |
KRB5_DOMAIN |
example.org |
DNS domain mapped to the realm |
KRB5_KDC_HOST |
(required) | FQDN of this KDC, used by clients and in service ticket names |
KRB5_MASTER_PASSWORD |
(required on first start) | Database master key — set once, cannot be changed without destroying the database |
KRB5_ADMIN_PRINCIPAL |
admin |
Name of the bootstrap admin principal |
KRB5_ADMIN_PASSWORD |
(required on first start) | Password for <admin>@<REALM> |
Copy env.example to ~/app-data/kerberos/kerberos.env and fill in real values before first run.
Admin principal naming
By default the bootstrap principal is created as admin@REALM — a flat, UPN-style name. This is the value of KRB5_ADMIN_PRINCIPAL used verbatim.
MIT Kerberos also supports the traditional primary/instance convention, where the /admin instance signals administrative intent. If you prefer that style, set the full name in the variable:
KRB5_ADMIN_PRINCIPAL=slawek/admin
This creates slawek/admin@REALM and grants it full kadmin rights via the ACL. Either form works — it is purely a naming preference.
Important:
KRB5_MASTER_PASSWORDandKRB5_ADMIN_PASSWORDare only required on first start. Once the realm is initialised (the database file exists in the volume), these variables are not read and can be removed from the env file for enhanced security. The master password cannot be changed without wiping thekerberos_datavolume and reinitialising the realm, which invalidates all issued tickets and keytabs.
Build
./scripts/build.sh
Run
./scripts/run-container.sh
The kerberos_data volume (/var/lib/krb5kdc) holds the realm database, configuration, and keytab. All files are written once on first start. On subsequent starts the container requires no environment variables — the persisted configuration is used as-is. Sensitive variables (KRB5_MASTER_PASSWORD, KRB5_ADMIN_PASSWORD) can be removed from the env file after the realm is initialised.
Ports
| Port | Protocol | Service |
|---|---|---|
| 88 | TCP/UDP | KDC (ticket granting) |
| 464 | TCP/UDP | kpasswd (password changes) |
| 749 | TCP | kadmin (remote administration) |
Client configuration
Pre-authentication is required (+preauth is set by default), so clients must supply a password or keytab — anonymous TGT requests are rejected.
The KDC hostname (KRB5_KDC_HOST) must be resolvable from every client machine via DNS or a local hosts file entry.
Linux
Install the MIT Kerberos client tools:
sudo apt install krb5-user # Debian / Ubuntu
sudo dnf install krb5-workstation # Fedora / RHEL
Create /etc/krb5.conf:
[libdefaults]
default_realm = EXAMPLE.ORG
[realms]
EXAMPLE.ORG = {
kdc = kerberos.example.org
admin_server = kerberos.example.org
}
[domain_realm]
.example.org = EXAMPLE.ORG
example.org = EXAMPLE.ORG
kinit user@EXAMPLE.ORG # obtain a ticket
klist # verify
kdestroy # release
macOS
Kerberos (Heimdal) is built into macOS — no installation required. It is interoperable with MIT KDCs.
Create /etc/krb5.conf with the same content as the Linux example above.
kinit user@EXAMPLE.ORG
klist
kdestroy
Acquired tickets are also visible in Ticket Viewer (/System/Library/CoreServices/Ticket Viewer.app).
For SSH with GSSAPI, add to ~/.ssh/config:
Host *.example.org
GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes
Windows (standalone, not domain-joined)
Install MIT Kerberos for Windows (KfW) from web.mit.edu/kerberos/dist. The built-in Windows Kerberos provider (SSPI) is designed for Active Directory domain membership and is not suitable for standalone use against a custom KDC.
Create the configuration file at %ProgramData%\MIT\Kerberos5\krb5.ini (system-wide) or set the KRB5_CONFIG environment variable to point to a file of your choice:
[libdefaults]
default_realm = EXAMPLE.ORG
[realms]
EXAMPLE.ORG = {
kdc = kerberos.example.org
admin_server = kerberos.example.org
}
[domain_realm]
.example.org = EXAMPLE.ORG
example.org = EXAMPLE.ORG
Use the KfW Network Identity Manager GUI or the bundled command-line tools from a Command Prompt:
kinit user@EXAMPLE.ORG
klist
kdestroy
Managing principals
Remote (kadmin)
kadmin connects to kadmind on port 749 from any machine with a valid krb5.conf. Authenticate as a principal with rights in kadm5.acl:
kadmin -p admin@REALM
With a keytab instead of a password prompt:
kadmin -p admin@REALM -k -t /path/to/admin.keytab
All commands below work identically in kadmin — replace kadmin.local with kadmin -p admin@REALM.
Local (kadmin.local)
Exec into the running container — no authentication required, bypasses kadmind entirely:
container exec -it kerberos bash
Principals
# List all principals (supports glob: "user*")
kadmin.local -q "listprincs"
# Inspect a principal
kadmin.local -q "getprinc user@REALM"
# Add a user principal
kadmin.local -q "addprinc user@REALM"
# Add a service principal (random key, no password)
kadmin.local -q "addprinc -randkey service/host.example.org@REALM"
# Change password
kadmin.local -q "cpw -pw newpassword user@REALM"
# Randomise key (invalidates existing tickets and keytabs)
kadmin.local -q "cpw -randkey service/host.example.org@REALM"
# Set expiry
kadmin.local -q "modprinc -expire '2027-01-01' user@REALM"
# Unlock after failed authentication lockout
kadmin.local -q "modprinc -unlock user@REALM"
# Delete a principal
kadmin.local -q "delprinc user@REALM"
Keytabs
# Extract keytab (randomises the principal's key)
kadmin.local -q "ktadd -k /tmp/service.keytab service/host.example.org@REALM"
# Extract without randomising key (-norandkey, preserves existing tickets)
kadmin.local -q "ktadd -k /tmp/service.keytab -norandkey service/host.example.org@REALM"
# Remove keytab entries for a principal
kadmin.local -q "ktremove -k /tmp/service.keytab service/host.example.org@REALM all"
Password policies
# Create a policy
kadmin.local -q "addpol -minlength 12 -minclasses 3 -maxlife '90 days' -maxfailure 5 default"
# Assign policy to a principal
kadmin.local -q "modprinc -policy default user@REALM"
# Inspect a policy
kadmin.local -q "getpol default"
# List policies
kadmin.local -q "listpols"
# Delete a policy (fails if any principal uses it)
kadmin.local -q "delpol default"
OpenLDAP SASL/GSSAPI integration
- Create the LDAP service principal and extract a keytab:
kadmin.local -q "addprinc -randkey ldap/ldap.example.org@REALM" kadmin.local -q "ktadd -k /tmp/ldap.keytab ldap/ldap.example.org@REALM" - Copy the keytab into the OpenLDAP container at
/etc/ldap/ldap.keytab. - Set
KRB5_KTNAME=/etc/ldap/ldap.keytabin the OpenLDAP container environment. - Install
libsasl2-modules-gssapi-mitin the OpenLDAP image and enable theGSSAPISASL mechanism.