Containers

Run FreeIPA Server in Docker or Podman Containers

Most FreeIPA guides walk you through a bare-metal install that takes over DNS, Kerberos, and LDAP on the host. Running FreeIPA in a container keeps all that contained (literally) while giving you the same identity management stack. If you need centralized authentication for your Linux infrastructure without dedicating an entire VM to it, this is the fastest path.

Original content from computingforgeeks.com - post 102105

This guide covers deploying FreeIPA Server 4.12 in Podman containers on Rocky Linux 10, complete with SSL/TLS via Let’s Encrypt, user and group management, password policies, HBAC rules, and sudo integration. The same steps work on AlmaLinux 10, RHEL 10, and Fedora 42 with minor package name differences. Docker commands are included where they differ from Podman.

Tested March 2026 on Rocky Linux 10.1 (kernel 6.12, SELinux enforcing) with Podman 5.6.0, FreeIPA 4.12.2 (AlmaLinux 10 container image), Nginx 1.26.3

What FreeIPA Gives You

FreeIPA bundles several identity and access management components into a single integrated solution:

  • 389 Directory Server – LDAP directory for storing users, groups, hosts, and policies
  • MIT Kerberos KDC – Single sign-on and strong authentication across your Linux infrastructure
  • Dogtag Certificate System – Built-in PKI for issuing and managing certificates
  • SSSD integration – Client-side authentication that works even when the server is temporarily unreachable
  • Web UI and CLI – Manage everything from a browser or the ipa command line tool
  • Host-Based Access Control (HBAC) – Control which users can access which servers
  • Sudo rules – Centrally manage sudo privileges across all enrolled hosts

The container approach gives you all of this without touching the host’s DNS, NTP, or Kerberos configuration. Everything runs inside Podman with persistent storage on a bind-mounted volume.

Prerequisites

  • Rocky Linux 10, AlmaLinux 10, or RHEL 10 (also works on Fedora 42)
  • Minimum 6 GB RAM (8 GB recommended, the Dogtag CA is memory-hungry during initial setup)
  • 4 vCPUs
  • 30 GB disk space
  • A fully qualified hostname set on the host (e.g., ipa.example.com)
  • Tested on: Rocky Linux 10.1, Podman 5.6.0, FreeIPA 4.12.2 (AlmaLinux 10 container)

Install Podman

Podman is available in the default Rocky Linux 10 repositories. Install it along with podman-docker which provides Docker CLI compatibility:

sudo dnf install -y podman podman-docker

Verify the installation:

podman --version

You should see the Podman version confirmed:

podman version 5.6.0

If you prefer Docker, install it from the official Docker repository. See our guide on installing Podman on CentOS/Fedora or Podman on Rocky/AlmaLinux for detailed setup instructions.

Configure the Host

Set the hostname to a fully qualified domain name. The hostname must be different from the IPA domain name, otherwise the installer rejects it.

sudo hostnamectl set-hostname ipa.example.com

Add the hostname to /etc/hosts:

echo "$(hostname -I | awk '{print $1}') ipa.example.com ipa" | sudo tee -a /etc/hosts

FreeIPA containers run systemd internally, which requires the container_manage_cgroup SELinux boolean:

sudo setsebool -P container_manage_cgroup 1

The -P flag makes this persistent across reboots.

Pull the FreeIPA Container Image

Pre-built FreeIPA server images are published to both Docker Hub and Quay.io. Available tags include almalinux-10, almalinux-9, rocky-9, fedora-42, and centos-9-stream.

sudo podman pull docker.io/freeipa/freeipa-server:almalinux-10

The image is approximately 900 MB. For Docker, replace podman with docker in all commands.

Verify the image was pulled:

sudo podman images

The output lists the FreeIPA server image:

REPOSITORY                        TAG           IMAGE ID      CREATED     SIZE
docker.io/freeipa/freeipa-server  almalinux-10  37c495f8f6f0  2 days ago  899 MB

You can also build the image from source by cloning the freeipa-container repository and running podman build -t freeipa-server -f Dockerfile.almalinux-10 . but the pre-built images are updated frequently and work well for most deployments.

Deploy FreeIPA Server Container

Create the persistent data directory. FreeIPA stores all configuration, certificates, LDAP data, and Kerberos databases here:

sudo mkdir -p /var/lib/ipa-data

Launch the container with an unattended installation. Replace the passwords and domain name with your own values:

sudo podman run --name freeipa-server -d \
  -h ipa.example.com \
  --read-only \
  -v /var/lib/ipa-data:/data:Z \
  -p 8443:443 -p 8080:80 \
  -p 389:389 -p 636:636 \
  -p 88:88 -p 464:464 \
  -p 88:88/udp -p 464:464/udp \
  -e DEBUG_NO_EXIT=1 \
  freeipa/freeipa-server:almalinux-10 \
  ipa-server-install -U \
  --realm EXAMPLE.COM \
  --domain example.com \
  --ds-password=YourDirManagerPass \
  --admin-password=YourAdminPass \
  --no-ntp \
  --no-host-dns

Here is what the key flags do:

  • --read-only – Runs the container filesystem as read-only (recommended by the FreeIPA container project)
  • -v /var/lib/ipa-data:/data:Z – Bind-mounts persistent storage with proper SELinux label (:Z)
  • -p 8443:443 -p 8080:80 – Maps HTTPS/HTTP to non-standard host ports so Nginx can use 443/80 for SSL termination
  • -e DEBUG_NO_EXIT=1 – Prevents the container from shutting down on installation failure, making troubleshooting easier
  • --no-ntp – Skips NTP configuration (the container uses the host’s clock)
  • --no-host-dns – Skips DNS resolution checks for the hostname

The installation takes 5 to 10 minutes depending on your hardware. The Dogtag CA component takes the longest. Monitor progress with:

sudo podman logs -f freeipa-server

When the install completes, you’ll see this output:

The IPA Master Server will be configured with:
Hostname:       ipa.computingforgeeks.com
IP address(es): 192.168.1.136
Domain name:    computingforgeeks.com
Realm name:     COMPUTINGFORGEEKS.COM

Configuring directory server (dirsrv). Estimated time: 30 seconds
  [1/42]: creating directory server instance
  ...
  [42/42]: restarting directory server
Done configuring directory server (dirsrv).
Configuring Kerberos KDC (krb5kdc)
  ...
Done configuring Kerberos KDC (krb5kdc).
Configuring certificate server (pki-tomcatd). Estimated time: 3 minutes
  [1/33]: configuring certificate server instance
  ...
  [33/33]: restarting certificate server
Done configuring certificate server (pki-tomcatd).
  ...
Setup complete

Next steps:
	1. You must make sure these network ports are open:
		TCP Ports:
		  * 80, 443: HTTP/HTTPS
		  * 389, 636: LDAP/LDAPS
		  * 88, 464: kerberos
	2. You can now obtain a kerberos ticket using the command: 'kinit admin'

FreeIPA server configured.

Verify the container is running:

sudo podman ps

Test that FreeIPA is functional by getting a Kerberos ticket:

sudo podman exec freeipa-server bash -c 'echo YourAdminPass | kinit admin && ipa user-find'

A successful response confirms the admin user exists and FreeIPA is operational:

--------------
1 user matched
--------------
  User login: admin
  Last name: Administrator
  Home directory: /home/admin
  Login shell: /bin/bash
  Principal name: [email protected]
  UID: 334400000
  GID: 334400000
  Account disabled: False
----------------------------
Number of entries returned 1
----------------------------

Docker equivalent: Replace sudo podman with sudo docker in all the commands above. Docker handles the cgroup and systemd setup slightly differently, but the FreeIPA container image supports both runtimes.

Configure SSL with Let’s Encrypt

FreeIPA generates its own self-signed CA during installation. For production use, you’ll want a trusted certificate from Let’s Encrypt so browsers don’t show certificate warnings. The cleanest approach is running Nginx on the host as a reverse proxy with SSL termination.

Install Certbot and Nginx

Enable the EPEL repository (certbot lives there on RHEL-family systems) and install everything needed:

sudo dnf install -y epel-release
sudo dnf install -y certbot python3-certbot-dns-cloudflare nginx

If your server has a public IP, you can use the simpler HTTP-01 challenge with certbot certonly --standalone. For private networks, the DNS challenge works without inbound HTTP access.

Obtain the Certificate

Create a Cloudflare API credentials file (if using DNS validation):

sudo mkdir -p /etc/letsencrypt
echo "dns_cloudflare_api_token = YOUR_CF_API_TOKEN" | sudo tee /etc/letsencrypt/cloudflare.ini
sudo chmod 600 /etc/letsencrypt/cloudflare.ini

Request the certificate:

sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d ipa.example.com \
  --non-interactive --agree-tos -m [email protected]

Certbot stores the certificate at /etc/letsencrypt/live/ipa.example.com/. For servers with public IP addresses, use the standalone method instead:

sudo certbot certonly --standalone -d ipa.example.com \
  --non-interactive --agree-tos -m [email protected]

Configure Nginx Reverse Proxy

Create the Nginx configuration for FreeIPA. Nginx terminates SSL on port 443 and proxies requests to the container’s HTTPS port (8443):

sudo vi /etc/nginx/conf.d/freeipa.conf

Add this configuration:

server {
    listen 443 ssl;
    http2 on;
    server_name ipa.example.com;

    ssl_certificate /etc/letsencrypt/live/ipa.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ipa.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass https://127.0.0.1:8443;
        proxy_ssl_verify off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Referer $http_referer;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }
}

server {
    listen 80;
    server_name ipa.example.com;
    return 301 https://$host$request_uri;
}

The proxy_ssl_verify off directive tells Nginx to accept the FreeIPA container’s self-signed certificate on the backend connection. The frontend connection to users is secured with the Let’s Encrypt certificate.

SELinux blocks Nginx from making network connections by default. Enable it:

sudo setsebool -P httpd_can_network_connect 1

Test the configuration and start Nginx:

sudo nginx -t
sudo systemctl enable --now nginx

Verify Nginx is running and certificate auto-renewal works:

sudo systemctl status nginx
sudo certbot renew --dry-run

Open firewall ports for HTTPS and the FreeIPA services:

sudo firewall-cmd --permanent --add-service={http,https,ldap,ldaps,kerberos,kpasswd}
sudo firewall-cmd --reload

Access the FreeIPA Web UI

Open https://ipa.example.com in your browser. With the Let’s Encrypt certificate in place, you’ll see a valid padlock icon instead of a certificate warning.

Log in with username admin and the admin password you set during installation.

FreeIPA Web UI Login Page
FreeIPA login page served over HTTPS with a valid Let’s Encrypt certificate

After logging in, FreeIPA lands on the Active Users view where you can see all user accounts:

FreeIPA Users List showing created users
Active users list in FreeIPA 4.12.2 showing the admin account and created users

Manage Users

FreeIPA provides both a web interface and CLI for user management. The CLI is generally faster for batch operations, while the web UI is better for exploring user details and settings.

Create Users from the CLI

All ipa commands run inside the container. Get a Kerberos ticket first, then create users:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa user-add jdoe --first=John --last=Doe [email protected] --password
'

The --password flag prompts for an initial password. The user must change it on first login.

Create multiple users at once:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa user-add ssmith --first=Sarah --last=Smith [email protected]
ipa user-add mjones --first=Mike --last=Jones [email protected]
'

Create Users from the Web UI

Navigate to Identity > Users > Active users and click Add. Fill in the user details:

FreeIPA Add User form in Web UI
Adding a new user through the FreeIPA web interface

Click on any user to see their full profile, group memberships, and account settings:

FreeIPA User Details page
User details page showing identity, account, and group membership information

See our detailed guide on managing users and groups in FreeIPA using CLI for bulk operations and advanced user attributes.

Manage Groups

Groups in FreeIPA control access to services, hosts, and sudo privileges. Create groups and add members:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa group-add developers --desc="Development team"
ipa group-add sysadmins --desc="System Administrators"
ipa group-add-member developers --users=jdoe,ssmith
ipa group-add-member sysadmins --users=mjones
'

Verify the group membership:

sudo podman exec freeipa-server bash -c 'echo YourAdminPass | kinit admin && ipa group-show developers'

The groups show up in the web UI under Identity > User Groups:

FreeIPA Groups List in Web UI
User groups including custom developers and sysadmins groups alongside the built-in groups

Click on a group to see its members and settings:

FreeIPA Group Details page
Developers group details showing member users

Configure Password Policies

FreeIPA ships with a default global password policy. Tighten it for production use:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa pwpolicy-mod global_policy \
  --maxlife=90 \
  --minlife=1 \
  --history=5 \
  --minlength=12 \
  --minclasses=3
'

This sets passwords to expire after 90 days, require at least 12 characters with 3 different character classes (uppercase, lowercase, digits, special), and remember the last 5 passwords to prevent reuse.

You can also create group-specific password policies. A group policy with a higher priority number takes precedence over the global policy:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa pwpolicy-add sysadmins --maxlife=60 --minlength=16 --minclasses=4 --priority=1
'

The password policy configuration in the web UI under Policy > Password Policies:

FreeIPA Password Policy configuration
Password policies in FreeIPA showing the global policy configuration

For more on password management, see managing FreeIPA users and groups.

Set Up Host-Based Access Control (HBAC)

HBAC rules let you control which users or groups can access which hosts via specific services. FreeIPA comes with a default allow_all rule that grants everyone access everywhere. In production, you’ll want to disable that and create targeted rules.

Create a rule that allows the developers group to SSH into development servers:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa hbacrule-add allow_developers --desc="Allow developers to access dev servers"
ipa hbacrule-add-user allow_developers --groups=developers
ipa hbacrule-add-service allow_developers --hbacsvcs=sshd
'

HBAC rules appear under Policy > Host Based Access Control > HBAC Rules:

FreeIPA HBAC Rules list
HBAC rules showing the custom allow_developers rule alongside defaults

The rule details page shows who the rule applies to, which services, and which hosts:

FreeIPA HBAC Rule Details page
HBAC rule details for the allow_developers rule

Test an HBAC rule before enforcing it:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa hbactest --user=jdoe --host=ipa.computingforgeeks.com --service=sshd
'

Configure Centralized Sudo Rules

Instead of editing /etc/sudoers on every server individually, FreeIPA lets you define sudo rules centrally. All enrolled clients pick them up automatically.

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa sudorule-add dev_sudo --desc="Sudo access for developers"
ipa sudorule-add-user dev_sudo --groups=developers
ipa sudorule-mod dev_sudo --cmdcat=all --hostcat=all
ipa sudorule-add-option dev_sudo --sudooption="!authenticate"
'

This grants all developers passwordless sudo on all hosts. In practice, you’d scope the commands and hosts more tightly.

FreeIPA Sudo Rules list
Sudo rules in FreeIPA showing the dev_sudo rule

The rule details show the full configuration including user groups, command categories, and sudo options:

FreeIPA Sudo Rule Details page
Sudo rule configuration with command categories, host categories, and options

Enroll Client Machines

The real value of FreeIPA comes when you enroll client machines. Any Linux system can join the FreeIPA domain and get centralized authentication, HBAC, and sudo policies automatically.

On the client machine (Rocky/AlmaLinux 10):

sudo dnf install -y freeipa-client

Run the enrollment:

sudo ipa-client-install \
  --server=ipa.example.com \
  --domain=example.com \
  --realm=EXAMPLE.COM \
  --principal=admin \
  --password=YourAdminPass \
  --mkhomedir \
  --unattended

After enrollment, verify that FreeIPA users can authenticate on the client:

id jdoe

If the user exists in FreeIPA, you’ll see their UID, GID, and group memberships:

uid=334400003(jdoe) gid=334400003(jdoe) groups=334400003(jdoe),334400007(developers)

The enrolled host appears in the FreeIPA web UI under Identity > Hosts:

FreeIPA Enrolled Hosts list
Enrolled hosts in FreeIPA showing the server itself

For a complete client setup walkthrough, see our guide on installing FreeIPA Server on Rocky/AlmaLinux/RHEL 10 which includes client enrollment steps.

Certificate Management

FreeIPA includes a full PKI (Dogtag Certificate System) that issues certificates for enrolled hosts and services. The certificates page in the web UI under Authentication > Certificates shows all issued certificates:

FreeIPA Certificates management page
Certificate management in FreeIPA showing certificates issued by the internal CA

You can request certificates for services, manage revocation, and configure certificate profiles from the CLI:

sudo podman exec freeipa-server bash -c '
echo YourAdminPass | kinit admin
ipa cert-find
'

For SSL certificate management on the FreeIPA server itself, see securing FreeIPA Server with Let’s Encrypt SSL.

Container Management and Persistence

After the initial install, the container starts much faster on subsequent runs. All FreeIPA data persists in the /var/lib/ipa-data volume.

Start the Container on Boot

Generate a systemd service unit to auto-start the FreeIPA container:

sudo podman generate systemd --name freeipa-server --new --files
sudo mv container-freeipa-server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable container-freeipa-server.service

Backup and Restore

Backing up a containerized FreeIPA is simpler than a bare-metal install. The entire state lives in one directory:

sudo podman stop freeipa-server
sudo tar czf /backup/ipa-data-$(date +%Y%m%d).tar.gz /var/lib/ipa-data
sudo podman start freeipa-server

To restore, stop the container, extract the backup to /var/lib/ipa-data, and start the container again.

View Logs

Container logs show the FreeIPA server output:

sudo podman logs --tail 100 freeipa-server

For detailed LDAP or Kerberos logs, check the log files inside the data volume:

sudo ls /var/lib/ipa-data/var/log/
sudo cat /var/lib/ipa-data/var/log/ipaserver-install.log

Troubleshooting

Error: “hostname cannot be the same as the domain name”

FreeIPA requires the hostname and domain name to be different. If your hostname is ipa.example.com, your domain must be example.com (not ipa.example.com). The hostname must be a subdomain of the IPA domain.

Error: “CA configuration failed” or Container Exits During Install

The Dogtag CA component needs significant memory. If the container exits during the “Configuring certificate server” step, increase the VM’s RAM to at least 8 GB. The PKI Tomcat server times out after 90 seconds if it can’t start, and with insufficient memory it won’t make it in time.

Use -e DEBUG_NO_EXIT=1 when starting the container to prevent it from shutting down on failure, then check /var/lib/ipa-data/var/log/ipaserver-install.log for the root cause.

Error: “Failed to set RLIMIT_CORE: Operation not permitted”

This is a harmless warning from systemd inside the container. It appears because containers typically can’t change resource limits. It does not affect FreeIPA operation.

Container Exits Immediately with Code 123

Exit code 123 means systemd inside the container shut down due to a service failure. The FreeIPA install service is configured to power off the container if installation fails. Add -e DEBUG_NO_EXIT=1 to the run command and check the install log to find the actual error.

FreeIPA Container vs Bare-Metal Installation

AspectContainer (Podman/Docker)Bare-Metal
Installation time5 to 10 minutes10 to 15 minutes
Host impactMinimal (only port bindings)Takes over DNS, NTP, Kerberos on the host
Backuptar the /data volumeipa-backup + config files
Upgrade pathPull new image, restartdnf update + ipa-server-upgrade
OS isolationContainer OS can differ from hostMust match host OS
DNS serverNot included by defaultOptional integrated BIND DNS
Multi-replicaSupported via ipa-replica-installSame procedure
SELinuxHost SELinux enforcing + container labelsHost SELinux enforcing

For a traditional bare-metal installation, see our guides for Rocky/AlmaLinux/RHEL 10 or Rocky/AlmaLinux 9. To set up a FreeIPA replica for high availability, follow our replica configuration guide.

Available Container Image Tags

TagFreeIPA VersionArchitecture
almalinux-104.12.2amd64, arm64
almalinux-94.12.2amd64, arm64
rocky-94.12.2amd64, arm64
fedora-424.12.5amd64
fedora-434.13.1amd64
centos-9-stream4.13.1amd64

All images are published to both docker.io/freeipa/freeipa-server and quay.io/freeipa/freeipa-server. Check Docker Hub for the latest tags and build dates.

Related guides you might find useful:

Related Articles

Containers Install Kubernetes with Rancher RKE (Step-by-Step) AlmaLinux Install XAMPP on Rocky Linux 8 | AlmaLinux 8 | Oracle Linux 8 Kubernetes Install Kubernetes Dashboard on Any K8s Cluster AlmaLinux Install Elasticsearch 8.x on Rocky Linux 9 / AlmaLinux 9

5 thoughts on “Run FreeIPA Server in Docker or Podman Containers”

  1. NOT SUITABLE FOR PRODUCTION

    This is a terrible guide for anyone outside those wanting to test the latest source which doesn’t follow best practice in pretty much everything it does. It disables security and involves additional unnecessary configuration which long term makes docker and the container itself harder to patch and manage.

    Docker/podman:
    Just install from the repositories. It’s not some cutting edge container that needs the latest and greatest. Maintainability and security is more important. If this was originally written when docker didn’t allow for userspace containers except in source than ignore this – but that reasoning should have been included.

    Container:
    FreeIPA’s container is available from multiple registries. Again, those should be used so the container is patched/maintained

    SELinux:
    Telling people to disable SELinux or make it permissive instead of taking 5 seconds to include how to configure it is absolutely terrible practice. Additionally setenforce only works til next boot which is not mentioned. As there was no further config here, any new user would just disable it.

    Why recommend disabling SELinux by omission and then say to setsebool? This makes no sense.

    Networking:
    … why not mention port mapping in the first instance?

    It seems like an incredibly inefficient route was taken just to allow for more ads.

    I have no doubt the author is very knowledgeable and this might be useful if retitled as being for installation from source alongside mentioning it shouldn’t be used in production without scripts to automate the extra steps needed for patching.

    Reply
  2. Hello,
    I have yet to attempt this tutorial, but since Podman 2.0 setting the container_manage_cgroup boolean to true is **no longer required** (and is not desirable from a security standpoint), see the troubleshooting.md on Podman’s github repo.

    Reply
  3. dosn’t work in 2023. I use freeipa-centos7:latest Dockerfile and get this error:
    Failed to mount cgroup at /sys/fs/cgroup/systemd: Operation not permitted
    [!!!!!!] Failed to mount API filesystems, freezing.

    Reply

Leave a Comment

Press ESC to close