FreeIPA Identity Management on AlmaLinux 9 on Azure User Guide
Overview
FreeIPA is an open source identity management suite for Linux environments. It combines four things that are usually run separately into one managed domain: an LDAP directory (389 Directory Server) holding users, groups, hosts and services; a Kerberos KDC (MIT Kerberos) issuing tickets for single sign-on; a certificate authority (Dogtag) that issues and renews certificates for every host and service in the domain; and a web interface and CLI for administering all of it, with host-based access control, sudo rules and two-factor authentication.
The cloudimg image delivers FreeIPA 4.13.1 on AlmaLinux 9, with your entire identity domain built on the first boot of your own VM. Backed by 24/7 cloudimg support.
Nothing is baked into this image, and that is the point. ipa-server-install writes the realm, the server hostname and a freshly generated certificate authority into installed state. If any of that shipped inside a shared marketplace image, every buyer would receive the same CA signing key — enough to mint certificates that every other customer's domain would trust — along with the same Kerberos master key and the same realm. So the image contains staged packages only: no directory instance, no CA, no Kerberos principals and no realm. All of it is created on your VM, once, at first boot.
What is included:
- FreeIPA 4.13.1 (
ipa-server) from the AlmaLinux 9 AppStream repository, with 389 Directory Server 2.8.0, MIT Kerberos 1.21.1 and Dogtag PKI 11.7.1 - A complete IdM domain provisioned at first boot: LDAP directory, Kerberos KDC, a certificate authority generated for your VM alone, and the FreeIPA web interface on port 443
- No default login: the IdM
adminpassword and the Directory Manager password are generated on your VM at first boot and written to a root-only file. They exist nowhere else, and they are never passed on a command line or written to the system journal - A certificate authority whose private key is unique to your VM
firewalldconfigured to the exact port set this appliance needs, with Dogtag's internal ports and the Kerberos administration port closed- SELinux enforcing, with no permissive mode and no custom policy module
- Unattended security updates via
dnf-automatic, proven at build time to actually install a pending update
FreeIPA is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them. This image packages the unmodified open source software, which is distributed under the GNU General Public License v3.0 or later.

Prerequisites
- An Azure subscription
- A VM size with at least 8 GiB of RAM. FreeIPA runs a directory server, a Kerberos KDC and a Java certificate authority together;
Standard_B2msis the recommended minimum and is what this image is tested on - An SSH key pair for the
azureuseraccount
Step 1: Deploy from the Azure Marketplace
Find FreeIPA Identity Management on AlmaLinux 9 in the Azure Marketplace, select Get It Now, and create a VM of size Standard_B2ms or larger. Allow inbound 22 for administration, plus 80, 443, 389, 636, 88 and 464 for the identity services described in Step 6.
Step 2: Deploy from the Azure CLI
az group create --name freeipa-rg --location eastus
az vm create \
--resource-group freeipa-rg \
--name my-idm \
--image cloudimg:freeipa-almalinux-9:default:latest \
--size Standard_B2ms \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
The VM name matters: by default your realm is derived from it. A VM named my-idm produces the domain my-idm.internal and the realm MY-IDM.INTERNAL. Step 5 explains how to use your own domain instead.
Step 3: Connect to your VM
ssh azureuser@<vm-ip>
Step 4: Wait for first boot to finish
First boot takes about ten minutes, and that is expected. Provisioning an IdM domain means generating a certificate authority from scratch, building a directory instance and creating every Kerberos principal. On a Standard_B2ms this measured 573 seconds end to end, 558 of which were ipa-server-install itself. Nothing times out; the work simply takes that long.
Watch it complete:
sudo systemctl is-active freeipa-firstboot.service
While it is still working this reports activating. When it is finished it reports active, and the record of what was built is written to a sentinel file:
sudo cat /var/lib/cloudimg/freeipa-firstboot.done
provisionedAt=2026-09-20T08:02:38Z
realm=ALMA9-FREEIPA-SMK2-09200650-F7A1C3.INTERNAL
serverFqdn=ipa.alma9-freeipa-smk2-09200650-f7a1c3.internal
ipaServerInstallSeconds=558
firstbootTotalSeconds=573

Confirm every component of the domain is running:
sudo ipactl status
Directory Service: RUNNING
krb5kdc Service: RUNNING
kadmin Service: RUNNING
httpd Service: RUNNING
ipa-custodia Service: RUNNING
pki-tomcatd Service: RUNNING
ipa-otpd Service: RUNNING
After a reboot the stack takes roughly 90 seconds to come back up fully.
Step 5: Understand your realm, and use your own domain
FreeIPA is unusually sensitive to host naming: the realm and the server's fully qualified name are written into the CA certificate and into every Kerberos principal, and they cannot be changed afterwards without rebuilding the domain.
By default, this image derives a private domain from the name you gave the VM:
| VM name | Domain | Realm | Server FQDN |
|---|---|---|---|
my-idm |
my-idm.internal |
MY-IDM.INTERNAL |
ipa.my-idm.internal |
.internal is reserved by ICANN for private use, so this can never collide with a registered name, and deriving it from your VM name keeps your realm distinct. The Azure-supplied <vm>.<id>.bx.internal.cloudapp.net name is deliberately not used as a realm: it lives in Microsoft's namespace and changes shape between virtual networks.
Check what your VM chose:
sudo ipa env realm domain server
domain: alma9-freeipa-smk2-09200650-f7a1c3.internal
realm: ALMA9-FREEIPA-SMK2-09200650-F7A1C3.INTERNAL
server: ipa.alma9-freeipa-smk2-09200650-f7a1c3.internal
To use your own domain, supply it before the VM's first boot by writing /etc/cloudimg/freeipa.conf with cloud-init custom-data at create time:
#cloud-config
write_files:
- path: /etc/cloudimg/freeipa.conf
permissions: '0644'
content: |
IPA_DOMAIN=idm.example.com
IPA_HOSTNAME=ipa.idm.example.com
IPA_REALM=IDM.EXAMPLE.COM
IPA_NETBIOS=EXAMPLE
Pass it with --custom-data cloud-init.yaml on az vm create. The first-boot script reads these values instead of deriving its own, sets the hostname to IPA_HOSTNAME, and builds the domain there. IPA_HOSTNAME must sit inside IPA_DOMAIN or provisioning stops with a clear error rather than half-building a domain.
If you only realise afterwards, the domain has to be rebuilt: sudo ipa-server-install --uninstall -U, then remove /var/lib/cloudimg/freeipa-firstboot.done and /var/lib/cloudimg/freeipa-domain.env, write the file above, and reboot. Deploying a fresh VM is usually quicker.
Step 6: Check what is listening
ss -lntu | awk 'NR==1 || $5 !~ /127\.0\.0\.1|\[::1\]/' | head -14
sudo firewall-cmd --zone=public --list-ports
22/tcp 80/tcp 88/tcp 389/tcp 443/tcp 464/tcp 636/tcp 88/udp 464/udp
Each open port earns its place:
| Port | Why it is open |
|---|---|
22/tcp |
SSH administration |
80/tcp |
CA certificate and CRL distribution. ipa-client-install fetches the CA certificate over plain HTTP before it has anything to trust, and issued certificates carry an HTTP CRL distribution point. Browsers are redirected to HTTPS |
443/tcp |
The web interface and the IdM API that the ipa command and every enrolled client use |
389/tcp |
LDAP with STARTTLS, for enrolled clients and LDAP-aware applications |
636/tcp |
LDAPS, for clients that require implicit TLS |
88/tcp, 88/udp |
The Kerberos KDC. UDP is the default transport; TCP is the fallback for large tickets |
464/tcp, 464/udp |
Kerberos password changes (kpasswd) by enrolled users |
Three ports are listening on the VM but deliberately closed by the firewall, and should never be opened in your network security group:
8080and8443belong to Dogtag, the certificate authority. The web server reaches Dogtag over a loopback-only AJP connection on127.0.0.1:8009, so these are purely internal749is the Kerberos administration port. FreeIPA administers principals through its own API on 443, and Red Hat's documented FreeIPA port list does not include it
The integrated DNS role is not enabled in this image. FreeIPA can run its own BIND server, but on a VM with a public address that means an internet-reachable recursive resolver, which is a denial-of-service amplification vector and not a safe default. Azure already provides DNS in every virtual network, and Azure Private DNS Zones are the natural place for the _kerberos._tcp and _ldap._tcp service records that clients use for automatic discovery. If you do want the integrated DNS role, add it with sudo ipa-dns-install and restrict recursion to your own network before opening port 53.

Step 7: Retrieve your credentials
Both passwords were generated on your VM at first boot and written to a root-only file:
sudo stat -c '%n %a %U:%G' /root/freeipa-credentials.txt
/root/freeipa-credentials.txt 600 root:root
sudo cat /root/freeipa-credentials.txt
# cloudimg FreeIPA on AlmaLinux 9 — per-VM credentials
# Generated on this VM at first boot. These values exist nowhere else.
IPA_REALM=ALMA9-FREEIPA-SMK2-09200650-F7A1C3.INTERNAL
IPA_DOMAIN=alma9-freeipa-smk2-09200650-f7a1c3.internal
IPA_SERVER_FQDN=ipa.alma9-freeipa-smk2-09200650-f7a1c3.internal
IPA_WEB_UI=https://ipa.alma9-freeipa-smk2-09200650-f7a1c3.internal/ipa/ui/
IPA_ADMIN_USER=admin
IPA_ADMIN_PASSWORD=<generated on your VM>
DIRECTORY_MANAGER_DN=cn=Directory Manager
DIRECTORY_MANAGER_PASSWORD=<generated on your VM>
admin is the IdM administrator, used for day-to-day identity management. Directory Manager is the LDAP superuser, used only for low-level directory operations and replica creation — you will rarely need it.
Step 8: Get a Kerberos ticket
Interactively, run sudo kinit admin and type the IPA_ADMIN_PASSWORD value at the prompt. To do it in one step, read the password straight out of the credentials file:
sudo bash -c 'grep ^IPA_ADMIN_PASSWORD= /root/freeipa-credentials.txt | cut -d= -f2- | kinit admin' && echo "ticket granted"
Then confirm you hold a ticket in your own realm:
sudo klist
sudo ipa ping

Step 9: Add a user
sudo ipa user-add awilson --first=Amara --last=Wilson --email=awilson@example.com || sudo ipa user-show awilson
Read it back:
sudo ipa user-find
Give the new account a password, which the user must change at their first login:
sudo ipa passwd awilson

Step 10: Sign in to the web interface
The web interface is served under the server's own fully qualified name, and FreeIPA redirects any other address there. This is normal for an identity server — the name is what the Kerberos service principal and the TLS certificate are issued for — so point your browser at the name rather than the IP.
The straightforward option is an entry in your workstation's hosts file, mapping your VM's public address to the FQDN from Step 7:
<vm-public-ip> ipa.my-idm.internal
For a shared deployment, create the equivalent record in an Azure Private DNS Zone linked to your virtual network, or in your own DNS.
Then browse to https://ipa.my-idm.internal/ipa/ui/ and sign in as admin. Your browser will warn that the certificate is not trusted, because it was issued by your VM's own certificate authority; install /etc/ipa/ca.crt as a trusted root to remove the warning.


Step 11: Enrol a client machine
On another AlmaLinux, Rocky, RHEL or Fedora machine that can resolve your server's name:
sudo dnf -y install ipa-client
sudo ipa-client-install \
--server=ipa.my-idm.internal \
--domain=my-idm.internal \
--realm=MY-IDM.INTERNAL \
--principal=admin \
--mkhomedir
Because the integrated DNS role is not enabled, pass --server, --domain and --realm explicitly rather than relying on SRV-record discovery. Once enrolled, users in your domain can log in to that machine and sudo rules and host-based access control apply.
Step 12: Inspect your certificate authority
Your VM generated its own CA at first boot. Its private key exists only on this VM:
sudo openssl x509 -in /etc/ipa/ca.crt -noout -subject -issuer -dates
subject=O=ALMA9-FREEIPA-SMK2-09200650-F7A1C3.INTERNAL, CN=Certificate Authority
issuer=O=ALMA9-FREEIPA-SMK2-09200650-F7A1C3.INTERNAL, CN=Certificate Authority
notBefore=Sep 20 07:56:46 2026 GMT
notAfter=Sep 20 07:56:46 2046 GMT
Every certificate the domain has issued is listed in the web interface under Authentication → Certificates, and sudo ipa cert-find shows the same from the CLI.

/root/cacert.p12 holds a backup of the CA signing key, encrypted with the Directory Manager password, and is readable only by root. Copy it somewhere safe: without it you cannot rebuild a replica of this CA.
Step 13: Back up the domain
FreeIPA ships its own backup tool, which captures the directory data, the CA and all configuration:
sudo ipa-backup
sudo ls -1 /var/lib/ipa/backup/
Restore with sudo ipa-restore <backup-directory>. Take a backup before any upgrade, and keep /root/cacert.p12 and /root/freeipa-credentials.txt with it.
Step 14: Keep the VM patched
Unattended security updates are enabled:
systemctl is-enabled dnf-automatic.timer
grep -E '^(upgrade_type|apply_updates)' /etc/dnf/automatic.conf
upgrade_type = default
apply_updates = yes
upgrade_type is deliberately default rather than security: security-only mode depends on repository metadata that not every EL-family repository publishes, and getting that judgement wrong produces an image whose automatic updates silently never update anything.
Apply updates by hand at any time:
sudo dnf -y upgrade --refresh
Reboot after a kernel update. The domain survives reboots: the hostname is pinned so that Kerberos principals stay valid.
Security notes
- No credential is shared between VMs. The IdM admin password, the Directory Manager password, the CA private key and certificate, the Kerberos master key, the LDAP TLS material, the SSH host keys and the machine ID are all generated on your VM at first boot. Two VMs deployed from this image were compared field by field and had nothing in common
- No credential is baked into the image. The captured image contains no directory instance, no CA and no realm at all, so there is nothing to leak
- Passwords never reach the process table or the journal.
ipa-server-installaccepts passwords only on the command line or at an interactive prompt; the command line is visible to every local user throughpsand is echoed into the journal, so the first-boot script drives the installer through a pseudo-terminal and supplies both passwords on standard input instead - The build account is removed before the image is captured,
rootis locked, and SSH accepts keys only —PermitRootLogin noandPasswordAuthentication no - SELinux is enforcing, with no custom policy module and no permissive domains
- The Dogtag administration ports (
8080,8443) and the Kerberos administration port (749) are closed by the host firewall - Rotate the IdM admin password with
sudo ipa passwd adminonce you have signed in
Support
cloudimg provides 24/7 support for this image. Contact support@cloudimg.co.uk.