Giving passwordless identity to services: understanding the service principal naming pattern, creating them with kadmin, storing them in a keytab file, and managing keytab entries with ktutil and klist.

In episode 6 you authenticated humans — users whose passwords are turned into TGTs. But in the enterprise world, the entities that most often talk to the KDC aren't humans, they're services: SSH, web servers, NFS, databases. Services can't type a password when asked. Episode 7 covers how services get a Kerberos identity — through a service principal — and how that identity is securely stored in a keytab so the service can authenticate without a password.
The key concept to hold onto: a service principal is a long-term key pair shared between the service and the KDC. A keytab is just the file container for that key pair. As long as the KDC and the keytab hold the same key, the service can get in "without saying a word."
Every service principal takes the form:
service/hostname@REALMThe service part is the service name, hostname is the FQDN of the machine where the service runs, and REALM is the Kerberos realm. Some of the most common service components:
| Component | Used for |
|---|---|
host/ | Host-based authentication: SSH, login, and system tools |
HTTP/ | Web servers with SPNEGO or Negotiate (episode 15) |
nfs/ | Kerberized NFS mounts (episode 14) |
cifs/ | SMB or CIFS share access |
postgres/, mysql/ | Databases with GSSAPI (episode 16) |
One important rule: service principals must be unique. You must not have two HTTP/web1.example.com@EXAMPLE.COM principals on two different machines — the KDC will reject it, or one of them will always fail. The hostname in the principal must be exactly the FQDN clients use to reach the service, because the service ticket is encrypted for that hostname. If clients access web1.example.com but the principal was only created for web1, authentication fails with a server not found in Kerberos database error.
Warning
Use the full FQDN, not a short hostname — host/web1.example.com, not host/web1 — and never use an alias different from what clients use. This tiny mistake is the number one cause of service authentication failures in production.
Unlike user principals, service principals don't need a password a human can type — they're simply given a random key. That's why the command uses the -randkey option:
$ sudo kadmin.local
kadmin.local: addprinc -randkey host/web1.example.com
WARNING: no policy specified for "host/web1.example.com@EXAMPLE.COM";
assigning "default" policy.
Principal "host/web1.example.com@EXAMPLE.COM" created.
kadmin.local: addprinc -randkey HTTP/web1.example.com
Principal "HTTP/web1.example.com@EXAMPLE.COM" created.-randkey asks the KDC to generate a random key instead of prompting for a password. Every key in the database gets a version number — KVNO (Key Version Number). When a key is reset or rotated, the KVNO goes up. The service uses this KVNO to make sure its keytab is still in sync with the KDC; if the keytab holds an old KVNO, a Key version number mismatch error appears.
A keytab (key table) is a file storing a service principal's keys. Because this file contains cryptographic material equivalent to a password, it must be treated as strictly as a credential file:
/etc/krb5.keytab for host-based services.root, permission 600 — chmod 600 /etc/krb5.keytab.Keys are written to a keytab from inside kadmin with ktadd:
kadmin.local: ktadd -k /etc/krb5.keytab HTTP/web1.example.com
Entry for principal "HTTP/web1.example.com" with kvno 3, encryption type
aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/krb5.keytab.After this, the web server can read the HTTP/web1.example.com key from /etc/krb5.keytab whenever a client requests authentication — without ever storing or typing a password. This is the essence of "passwordless authentication" for services.
To verify a keytab's contents, use klist with the -k (keytab), -t (show modification times), and -e (enctype) options:
sudo klist -kte /etc/krb5.keytabKeytab name: FILE:/etc/krb5.keytab
KVNO Timestamp Principal
---- ----------------- --------------------------------------------------------
3 08/03/2026 09:00 host/web1.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
3 08/03/2026 09:00 HTTP/web1.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)Note the KVNO and enctype columns on each line. When troubleshooting, compare the KVNO in the keytab against the KVNO in the KDC database (getprinc) — if they don't match, the service key has been rotated and the keytab needs updating.
ktutil is an interactive utility for keytab manipulation: viewing, deleting, or merging entries.
$ sudo ktutil
ktutil: read_kt /etc/krb5.keytab
ktutil: list
ktutil: delete_entry 1
ktutil: write_kt /etc/krb5.keytab
ktutil: quitThe typical flow: read_kt loads the keytab contents into memory, list displays entries indexed 0, 1, 2, and so on, delete_entry removes an entry by index, then write_kt writes the result back. This is useful for cleaning out old principals from a keytab — for example when a service is renamed or a machine is decommissioned. On some systems, the ktab command provides similar, simpler functionality: ktab -l to list and ktab -d to delete.
For separate keytabs (for example, one file per service), create one with -k pointing to another path, then distribute it securely to the machine that needs it. Merge multiple keytab files if needed via ktutil — the KDC will match whichever principal is inside.
Once the keytab is in place, test whether the service can get a ticket without a password:
kinit -kt /etc/krb5.keytab HTTP/web1.example.com
klistkinit -kt reads the key from the keytab without showing a password prompt, then obtains a TGT for that service principal. If successful, klist shows the HTTP/web1.example.com@EXAMPLE.COM ticket — proof that the KDC recognizes the keytab's key.
Important
A keytab is a secret file: whoever reads it can act as that service. Disk encryption, permission 600, and periodic key rotation are mandatory practices. Never copy a keytab into a public directory or upload it to a repository.
In episode 7, you learned how services get identity without a password: a service principal named service/hostname@REALM is created with addprinc -randkey, its key is stored in a keytab via ktadd, and the service authenticates with kinit -kt.
Key takeaways:
service/hostname@REALM naming pattern must be unique, and its FQDN must exactly match what clients use.klist -kte for inspection, ktutil for managing entries, kinit -kt for testing.In the next episode, episode 8, we move up to full admin level: principal management and administration — managing principals at scale, password policies, admin ACLs in kadm5.acl, and auditing kadmin activity. Keep the keytab from this episode ready, because we'll build identity management tooling on top of it.