A step-by-step implementation guide for deploying FreeIPA as the identity,
authentication, and directory backbone of the open-source office estate
defined in the Open-Source Office Environment — Reference Architecture Series.
FreeIPA combines 389 Directory Server (LDAP), MIT Kerberos, Bind DNS,
an integrated Certificate Authority (Dogtag / certmonger), NIS/SSSD and
HBAC + sudo policies into one managed domain. It is the Linux-native
equivalent of Microsoft Active Directory.
Scope. This document covers a two-server, highly-available FreeIPA
realm for a single office (office.local), with Debian 12 (bookworm)
clients joined viarealmd/sssd. It lists every input decision you must
make up front, all dependencies, and the concrete commands to install and
verify the domain.
1. Document Control
| Field | Value |
|---|---|
| Document | FreeIPA Implementation Document |
| Version | 1.0 |
| Status | Draft for implementation |
| Owner | IT / Systems Administration |
| Audience | System administrators, network engineers, security officer |
| Related | Open-Source Office Environment — Reference Architecture |
| Target realm | OFFICE.LOCAL (Kerberos), office.local (DNS) |
| Target OS (server) | Debian 12 (bookworm) or Rocky/Alma 9 |
| Target OS (client) | Debian 12 (bookworm) |
2. Key Inputs
These are the decisions and values that must be agreed before
installation. Every command downstream references them.
2.1 Naming & realm
| Input | Example value | Notes |
|---|---|---|
| Kerberos realm name | OFFICE.LOCAL | Conventionally uppercase FQDN. Must match across all replicas and clients. Cannot be renamed later without rebuilding. |
| DNS domain | office.local | FreeIPA will host this zone. Use a subdomain of a real domain if you need external trust, e.g. corp.example.com. |
| Directory Manager (root DN) password | strong, stored in Vaultwarden | Root password for LDAP (cn=Directory Manager). Rotate yearly. |
| FreeIPA admin password | strong, stored in Vaultwarden | Initial admin superuser. Create named admins after install; disable the generic admin for daily use. |
| NTP / time source | ntp1.office.local (or pool.ntp.org) | Kerberos dies without synchronized clocks. Max skew 5 min. |
2.2 Network topology
| Input | Example value | Notes |
|---|---|---|
| Primary server FQDN | ipa1.office.local | First FreeIPA server (the “initial master”). |
| Primary server IP | 10.10.10.10 | Must be static. This IP is the LDAP/Kerberos/DNS endpoint. |
| Replica server FQDN | ipa2.office.local | Second FreeIPA server for HA. |
| Replica server IP | 10.10.10.11 | Static. |
| Client subnet | 10.10.10.0/24 | Workstations, laptops, thin clients. |
| Client DNS server | FreeIPA server IPs | Clients resolve via FreeIPA DNS so SRV records work. |
| Reverse DNS zone | 10.10.10.in-addr.arpa. | Optional but recommended for Kerberos/GSSAPI sanity. |
2.3 Certificate authority
| Input | Example value | Notes |
|---|---|---|
| CA type | Integrated Dogtag CA | Self-signed root, internal to the realm. Trusted on all joined clients. |
| CA subject DN | CN=Certificate Authority,O=OFFICE.LOCAL | Customize to org name if desired. |
| Certificate validity | 20 years (root), 2 years (service) | Defaults; tune per policy. |
| External trust needed? | No (standalone realm) | If you later need a forest trust with AD, plan the CA cross-signing now. |
2.4 DNS policy
| Input | Example value | Notes |
|---|---|---|
FreeIPA manages office.local? | Yes (bind integrated) | Lets FreeIPA publish _ldap._tcp, _kerberos._tcp, _kpasswd SRV records automatically. |
| Forwarders | 1.1.1.1, 9.9.9.9 | Upstream recursive resolvers for everything outside office.local. |
| DNSSEC validation | On (via forwarders) | Recommended. |
| Reverse zone managed? | Yes | Enables PTR records for Kerberos sanity. |
2.5 Host / account policy
| Input | Example value | Notes |
|---|---|---|
| Default login shell | /bin/bash | Set in FreeIPA config. |
| Home directory pattern | /home/%u | Auto-created on first login via pam_mkhomedir. |
| UID/GID range | 10000–999999 (POSIX), SIDs auto-allocated | Avoid collision with local /etc/passwd ranges. |
| User naming scheme | firstname.lastname | Enforced via a helper script, not native policy. |
| Password policy | Min 14 chars, 90-day max, 5 history, lockout after 5 | Set in ipa pwpolicy. |
| HBAC default | deny_all + named allow_<role> rules | Start from deny-all, open explicitly. |
| sudo rule default | Named role-based rules, no broad ALL=(ALL) ALL | Centralized via ipa sudorule. |
3. Dependencies
3.1 Platform / OS dependencies
| Dependency | Purpose | Installed by |
|---|---|---|
| Debian 12 (bookworm) or RHEL-family 9 | Supported server OS | Manual |
freeipa-server package | Server binaries (389 DS, MIT Kerberos, bind, Dogtag) | apt install |
freeipa-server-dns | Integrated bind + DNS SRV automation | apt install |
freeipa-server-trust-ad | AD trust support (only if needed later) | optional |
sssd, krb5, oddjob, certmonger | Client-side services | client install |
chrony (or systemd-timesyncd) | Time sync — mandatory for Kerberos | base OS |
softhsm2 | PKCS#11 store for CA keys (newer FreeIPA) | pulled in |
3.2 Infrastructure dependencies
| Dependency | Why | Notes |
|---|---|---|
| Static IPs for both IPA servers | DNS + SRV records point at fixed addresses | Configure before install. |
| Working NTP on all hosts | Kerberos tickets require <5 min clock skew | Configure before ipa-server-install. |
| Forward/reverse DNS resolvable | FreeIPA validates the host FQDN matches PTR during install | Pre-create A + PTR, or let FreeIPA create them. |
| Firewall open: 53/udp+tcp (DNS), 80/tcp (HTTP), 88/udp+tcp (Kerberos), 123/udp (NTP), 389/tcp (LDAP), 443/tcp (HTTPS), 464/udp+tcp (Kadmin), 636/tcp (LDAPS) | FreeIPA service ports | Configure on OPNsense/OpenWrt and host firewalls. |
| Sufficient RAM/CPU | 389 DS + Dogtag + bind are memory-hungry | Min 4 GB RAM, 2 vCPU; 8 GB recommended. |
| Fast, redundant disk | LDAP DB and CA store | SSD-backed; LVM for easy growth. |
| Proxmox VE cluster (per reference arch) | VMs for ipa1, ipa2 | Snapshot before each change. |
3.3 Soft / organizational dependencies
| Dependency | Why |
|---|---|
| Signed-off naming convention | Realm name, DNS domain, OU layout can’t be renamed cheaply. |
| Privileged-credential store (Vaultwarden) | Directory Manager + admin passwords must not be in plaintext scripts. |
| Ansible control node (per reference arch) | Reproducible client joins, HBAC/sudo policy rollout. |
| Backup target (Proxmox Backup Server) | VM-level snapshots of ipa1/ipa2 before every change. |
| Maintenance window | First install and replica promotion require brief DNS/Kerberos disruption. |
3.4 Dependency map
chrony / NTP
(mandatory)FreeIPA Server
ipa1 + ipa2Forward+reverse DNS
(static A/PTR)Firewall ports
53/80/88/123/389/443/464/636SSD LVM
4GB+ RAMVaultwarden
for secretsProxmox cluster + PBS
VM + backupKeycloak SSOClient joins via realmd/sssdPostfix/Dovecot LDAP authSamba (optional AD-like shares)HBAC + sudo rules
4. Pre-Installation Checklist
Run through this before ipa-server-install. Each item blocks install if false.
- Two static IPs reserved (
ipa1=10.10.10.10,ipa2=10.10.10.11) with matching A and PTR records (or agreement to let FreeIPA create them). /etc/hostson both servers contains only their own FQDN mapped to their primary IP — no stale127.0.1.1hostname entries.hostnamectl set-hostname ipa1.office.localset on both hosts.chronyrunning and clocks within 1 second of an external source.- Firewall opened on ports listed in §3.2 on both the host firewall and the network edge.
- Debian 12 fully updated:
apt update && apt full-upgrade. - Directory Manager and admin passwords generated and stored in Vaultwarden.
- DNS domain
office.localchosen and not overlapping any external domain you use. - Proxmox snapshot of both VMs taken.
- Maintenance window booked (30 min for primary, 15 min for replica).
5. Installation: Primary Server (ipa1)
5.1 Install packages
apt update
apt install -y freeipa-server freeipa-server-dns chrony
5.2 Run the installer
ipa-server-install \
--realm=OFFICE.LOCAL \
--domain=office.local \
--ds-password='<DIRECTORY_MANAGER_PASSWORD>' \
--admin-password='<ADMIN_PASSWORD>' \
--hostname=ipa1.office.local \
--ip-address=10.10.10.10 \
--setup-dns \
--forwarder=1.1.1.1 \
--forwarder=9.9.9.9 \
--reverse-zone=10.10.10.in-addr.arpa. \
--mkhomedir \
--no-ntp \
--unattended
Key flags explained:
| Flag | Meaning |
|---|---|
--realm / --domain | Kerberos realm + DNS zone from §2.1. |
--ds-password | Root LDAP (Directory Manager) password. |
--admin-password | Initial admin superuser. |
--setup-dns | Install + configure integrated bind. |
--forwarder | Upstream resolvers for non-office.local names. |
--reverse-zone | Manage PTR records; needed for clean Kerberos. |
--mkhomedir | Auto-create /home/<user> on first login (clients). |
--no-ntp | We use chrony already running; prevents conflicts. |
--unattended | Non-interactive; all values from flags. |
5.3 Verify the primary
kinit admin # get a Kerberos ticket
ipa ping # should return IPA server version
ipa-replica-manage list # (empty until replica added)
host ipa1.office.local # resolves via FreeIPA DNS
dig _ldap._tcp.office.local SRV # SRV record published
5.4 Harden the primary
# Create a named super-admin and disable generic admin for daily use
ipa user-add sysadmin --first=Sys --last=Admin --password
ipa group-add-member admins --users=sysadmin
# Optionally disable generic admin after first named admin verified
ipa user-mod admin --nsaccountlock=TRUE
6. Installation: Replica (ipa2)
A replica provides LDAP/Kerberos/DNS/CA redundancy. Clients configured with
both server IPs keep authenticating if ipa1 fails.
6.1 Prepare the replica host
On ipa1, generate a replica promotion file:
kinit admin
ipa-replica-prepare ipa2.office.local --ip-address=10.10.10.11
# Produces /var/lib/ipa/replica-info-ipa2.office.local.tar.gz
# Copy it to ipa2 (e.g. via scp behind WireGuard).
6.2 Install on the replica
On ipa2:
apt update
apt install -y freeipa-server freeipa-server-dns chrony
# (host name, NTP, firewall per §4 already done)
ipa-replica-install \
--setup-dns \
--forwarder=1.1.1.1 \
--forwarder=9.9.9.9 \
/root/replica-info-ipa2.office.local.tar.gz \
--unattended
6.3 Verify replication
ipa-replica-manage list # shows ipa1 <-> ipa2 agreement
ipa-csreplica-manage list # CA replication
ipa host-find # both servers listed
Delete the replica-info tarball after success:
rm /root/replica-info-ipa2.office.local.tar.gz.
7. Client Join (Debian 12 workstation)
7.1 One-time inputs
| Input | Value |
|---|---|
| Realm | OFFICE.LOCAL |
| Domain | office.local |
| FreeIPA servers | ipa1.office.local, ipa2.office.local |
| Client DNS | pointed at FreeIPA server IPs (DHCP option 6) |
| Join principal | admin (or a delegated “join” service account) |
7.2 Join a client
apt install -y realmd sssd sssd-tools libnss-sss libpam-sss adcli \
krb5-user oddjob oddjob-mkhomedir packagekit
# Tell realmd where the IPA servers are (via DNS SRV, or explicit):
realm discover office.local
# Join
realm join -v --computer-ou="CN=Computers,DC=office,DC=local" \
--user=admin office.local
7.3 Post-join configuration
# Use FreeIPA for all lookups
realm permit --all # or realm permit --groups <group>
# Enable mkhomedir so first login creates /home/<user>
pam-auth-update --enable mkhomedir
# Confirm
id <someuser>@office.local # should resolve UID/GID
kinit <someuser> # should get a TGT
7.4 SSSD tuning (recommended /etc/sssd/sssd.conf highlights)
[domain/office.local]
ipa_domain = office.local
ipa_server = _srv_, ipa1.office.local, ipa2.office.local
ldap_tls_cacert = /etc/ipa/ca.crt
krb5_store_password_if_offline = true
cache_credentials = true
enumerate = false # do not list all users (perf)
8. Policy Configuration
8.1 Password policy
ipa pwpolicy-mod --minlength=14 --maxlife=90 --minlife=1 \
--history=5 --maxfail=5 --failinterval=60 --lockouttime=600
8.2 HBAC rules (host-based access control)
# Deny all by default
ipa hbacrule-disable allow_all
# Create role rules
ipa hbacrule-add --hostcat=host --usercat=user allow_finance
ipa hbacrule-add-member --hosts=erp1.office.local allow_finance
ipa hbacrule-add-member --groups=finance allow_finance
ipa hbacrule-add --hostcat=host --usercat=user allow_devops
ipa hbacrule-add-member --hosts=git1.office.local allow_devops
ipa hbacrule-add-member --groups=devops allow_devops
8.3 Sudo rules
ipa sudorule-add sysadmin-sudo
ipa sudorule-add-allow-command --commands=ALL sysadmin-sudo
ipa sudorule-add-host --hostcat=all sysadmin-sudo
ipa sudorule-add-user --group=sysadmin sysadmin-sudo
8.4 User lifecycle
| Action | Command |
|---|---|
| Create user | ipa user-add jane.doe --first=Jane --last=Doe --password |
| Add to group | ipa group-add-member finance --users=jane.doe |
| Disable | ipa user-disable jane.doe |
| Stage (pre-hire) | ipa stageuser-add ... then ipa stageuser-activate |
| Delete | ipa user-del jane.doe (preserves UID for audit) |
9. Backup & Recovery
| What | How | Cadence |
|---|---|---|
| Full VM snapshot | Proxmox Backup Server | Nightly + before each change |
| Online LDAP backup | ipa-backup --data --online on ipa1 | Nightly, keep 14 days |
| Full IPA backup (with CA) | ipa-backup (offline) | Weekly |
| Replica rebuild | Promote a fresh VM via ipa-replica-install from ipa1 | On-demand |
| Disaster recovery | Restore ipa1 VM from PBS, then re-add replicas | Tested quarterly |
Keep at least one
ipa-backuparchive offsite (Borgmatic) — it contains the CA private material; without it the realm cannot be fully recovered.
10. Validation & Acceptance Tests
Run all of these to sign off the implementation.
kinit adminsucceeds onipa1andipa2.ipa pingreturns from both servers.- A joined client can
kinita normal user andsshinto another joined host without a password (GSSAPI). - Disabling
ipa1leaves clients still authenticating viaipa2(kill the VM, confirm logins). - HBAC
deny_all+ a role rule blocks a user from a host they should not reach. - Sudo rule grants
sysadmingroup elevated rights only where defined. ipa user-disableinstantly revokes login across all clients (SSSD cache honored).- Certificates issued by FreeIPA CA are trusted on a freshly joined client (
openssl s_client -connect ipa1:443validates). - DNS SRV records
_ldap._tcp,_kerberos._tcp,_kpasswd._tcp.office.localresolve. ipa-backupruns cleanly and the archive can be restored to a test VM.- Clock-drift test: stop
chronyon a client, skew 6 min, confirm Kerberos login fails (proves NTP dependency).
11. Operational Runbook (excerpt)
| Event | Action |
|---|---|
| Add a user | ipa user-add → assign group → user changes password at first login. |
| Add a host | realm join from the host; it auto-creates a host principal + keytab. |
| Promote a new replica | ipa-replica-prepare → ipa-replica-install. |
| Rotate Directory Manager password | ipa user-mod for admin; for DM use dsconf / re-run ipa-server-install password tooling; update Vaultwarden. |
| Renew certs | FreeIPA auto-renews via certmonger; monitor getcert list. |
| Decommission a host | ipa host-del <fqdn> (revokes keytab). |
| Certificate expires/CA issues | ipa-cacert-manage + ipa-certupdate on all clients. |
| Replica failed | ipa-replica-manage del <fqdn> on a healthy master, rebuild. |
12. Rollover to the Rest of the Estate
Once FreeIPA is validated, downstream services consume it:
- Keycloak — LDAP user federation + Kerberos; all web apps inherit identities.
- Postfix/Dovecot — LDAP recipient maps + Dovecot
auth_ldap. - Nextcloud — LDAP/SCIM user backend.
- Samba (optional) — join as an AD-trust peer if Windows guests need shares.
- Ansible — inventory reads FreeIPA host groups; playbooks enforce HBAC/sudo state.
This closes the loop: one directory of truth, one login, one CA, fully open-source.
Leave a Reply