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_PASSWORD and KRB5_ADMIN_PASSWORD are 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 the kerberos_data volume 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

Exec into the running container — no authentication required, bypasses kadmind entirely

Principals

Run kadmin.local inside the container to launch the kadmin administration shell. Type ? for help. You can also run one-off commands directly from the shell using kadmin.local -q "command".

Useful commands:

  • listprincs - List all principals (supports glob: "user*")
  • getprinc user@REALM - Inspect a principal
  • addprinc user@REALM - Add a user principal
  • addprinc -randkey service/host.example.org@REALM - Add a service principal (random key, no password)
  • cpw -pw newpassword user@REALM - Change password
  • cpw -randkey service/host.example.org@REALM - Randomise key (invalidates existing tickets and keytabs)
  • modprinc -expire '2027-01-01' user@REALM - Set expiry
  • modprinc -unlock user@REALM - Unlock after failed authentication lockout
  • delprinc user@REALM - Delete a principal

Keytabs

  • ktadd -k /tmp/service.keytab service/host.example.org@REALM - Extract keytab (randomises the principal's key)
  • ktadd -k /tmp/service.keytab -norandkey service/host.example.org@REALM - Extract without randomising key (preserves existing tickets)
  • ktremove -k /tmp/service.keytab service/host.example.org@REALM all - Remove keytab entries for a principal

Password policies

  • addpol -minlength 12 -minclasses 3 -maxlife '90 days' -maxfailure 5 default - Create a policy
  • modprinc -policy default user@REALM - Assign policy to a principal
  • getpol default - Inspect a policy
  • listpols - List policies
  • delpol default - Delete a policy (fails if any principal uses it)

SSH server configuration

SSH uses the host/ service principal. The FQDN must match the result of forward DNS resolution of the server's hostname, and the IP must reverse-resolve to the same FQDN.

Linux

Create the host principal and extract the keytab to the default location (run as root on the SSH server — the keytab is written to /etc/krb5.keytab, mode 0600):

Authenticate as Kerberos admin principal and run the following kadmin commands:

  • addprinc -randkey host/ssh-server.example.org@REALM - creates the principal with a random key (no password)
  • ktadd -k /tmp/krb5.keytab host/ssh-server.example.org@REALM - extracts the keytab

Add to /etc/ssh/sshd_config:

GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
GSSAPIStrictAcceptorCheck yes

GSSAPIStrictAcceptorCheck verifies the server's identity against the keytab — keep it enabled. Reload sshd:

[libdefaults]
    k5login_authoritative = false

Client connection

SSH will prefer public key authentication by default even when GSSAPI is available. To enforce Kerberos:

ssh -o GSSAPIAuthentication=yes -o GSSAPIDelegateCredentials=yes user@ssh-server.example.org

To make this permanent for a host in ~/.ssh/config:

Host ssh-server.example.org
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials yes

On Windows (KfW) and macOS the same ssh flags apply. macOS additionally accepts -K as a shorthand for GSSAPIAuthentication=yes.

Windows

GSSAPIAuthentication is available on Windows Server 2022, 2025, Windows 10 (May 2021 Update), and Windows 11 only. Windows Server 2019 does not support it.

Install MIT Kerberos for Windows (KfW) on the SSH server — Windows OpenSSH uses it for GSSAPI when the machine is not domain-joined. Create the host principal and extract a keytab:

kadmin -p admin@REALM -q "addprinc -randkey host/win-server.example.org@REALM"
kadmin -p admin@REALM -q "ktadd -k /tmp/win-server.keytab host/win-server.example.org@REALM"

Copy the keytab to the Windows server and set KRB5_KTNAME in the system environment to its path, or place it at the KfW default (%ProgramData%\MIT\Kerberos5\krb5.keytab).

Add to %ProgramData%\ssh\sshd_config:

GSSAPIAuthentication yes

The following directives are not available on Windows OpenSSH and must not be added: GSSAPICleanupCredentials, GSSAPIStrictAcceptorCheck, KerberosAuthentication, KerberosTicketCleanup.

Restart the sshd service after the change (requires an elevated PowerShell prompt):

Restart-Service sshd

OpenLDAP SASL/GSSAPI integration

  1. 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"
    
  2. Copy the keytab into the OpenLDAP container at /etc/krb5.keytab.
  3. Set KRB5_KTNAME if you have chosen to use a non-default keytab location in the OpenLDAP container environment.
  4. Install libsasl2-modules-gssapi-mit in the OpenLDAP image and enable the GSSAPI SASL mechanism.
S
Description
No description provided
Readme 76 KiB
Languages
Shell 85.7%
Dockerfile 10.9%
HCL 3.4%