Enrolling FreeIPA clients at scale with one-time passwords

Enroll hundreds of hosts into FreeIPA without sharing admin credentials by pre-creating host entries with random one-time passwords and driving enrollment from kickstart or Ansible.

On this page

How one-time passwords make bulk FreeIPA enrollment safe at scale

One-time passwords let a large fleet enroll into FreeIPA without anyone sharing an administrator password. An administrator creates a host entry on the IPA server ahead of time and sets a random one-time password on it. The machine then runs ipa-client-install with that password once, during its first boot or provisioning run. The password is only valid for that single enrollment, so no reusable secret has to sit in a kickstart file, a playbook variable or a ticket. Enrollment is still a per-host action: each machine must present its own entry and password, and the server issues that host its keytab and certificate. The approach works best when the host list is known in advance, when the team that builds machines differs from the team that holds IPA administrator rights, and when provisioning can be scripted so that each one-time password reaches only the host it belongs to.

Choose a different method when the hosts cannot be named ahead of time or when a stronger identity already exists. Cloud autoscaling groups that create short-lived instances are a poor fit for pre-created entries, because stale host records accumulate unless something removes them. Machines that already hold host certificates from another trusted authority may enroll with PKINIT instead, which removes the password step entirely (see the sibling topic on PKINIT and host certificates). Before rollout, confirm with your own build pipeline how one-time passwords will be generated, stored only as long as needed and delivered to each host, and confirm how your IPA version handles host entries that were created but never enrolled. Test the full path on a small group of hosts first, including a failed enrollment and a rebuild, so that the cleanup steps are known before the number of hosts grows.

Which enrollment method fits which estate

This table compares four ways to enroll FreeIPA clients: pre-created hosts with one-time passwords, enrollment with a privileged user's credentials, PKINIT with existing host certificates, and kickstart or Ansible-driven enrollment. Read each row against your estate's build pipeline, how many hosts you add at once, and who may hold admin credentials. The main takeaway is that the method is mostly a choice about where secrets are created and who can see them.

MethodCredential exposureAutomation fitWhen to choose itMain trade-off
Pre-created host with one-time passwordShort-lived random password per host, generated by an admin and handed to the install stepGood with scripts that can pass one value per hostMixed estates where hosts are built by different teams and no admin password should leave the IdM teamEach host needs a password handoff, and unused passwords must be cleaned up
Enrollment with a privileged user's credentialsAn admin or enrollment user password is placed on each build or in automationEasy to script, but the secret is reused across every hostSmall labs or one-off enrollments where the team accepts shared admin exposureReusing a privileged secret widens the blast radius if a build host is compromised
PKINIT with existing host certificatesNo password is shared; trust rests on a certificate the host already holdsFits automated provisioning that already issues host certificatesEstates with a working certificate pipeline and a need to avoid passwords or OTPs entirelyDepends on certificate issuance and renewal being in place before enrollment
Kickstart-driven enrollmentDepends on the method passed into the kickstart file, so secrets sit in build templatesStrong fit for bare-metal and VM builds that already run kickstartLarge numbers of RHEL-family hosts built from a single templateTemplates become sensitive files that need the same access control as the secrets they carry
Ansible-driven enrollment with ansible-freeipaSecrets come from an Ansible vault or the controller, not from the hostStrong fit for playbook-managed fleets and repeatable rerunsEstates already managed with Ansible that want host records and enrollment kept in one reviewed workflowRequires a controlled automation host and disciplined vault handling
Interactive enrollment by an operatorOperator types a password or OTP at the consolePoor fit for hundreds of hostsRebuilds of a few hosts or recovery workSlow and error-prone at scale, and hard to audit

Setting up bulk enrollment with one-time passwords

This sequence takes a host from a DNS check to a verified FreeIPA login without anyone sharing administrator credentials. Each host gets its own one-time password, and each step closes with a check you can run before moving on.

  1. Confirm DNS resolution for every client

    Before any host is enrolled, check that each client resolves the IdM domain and the server names through DNS. Confirm that the resolv.conf on each client lists at least two DNS servers, as the FreeIPA deployment recommendations advise, and that those servers can answer for the IPA domain. Your network or platform team owns this step, and the DNS settings should be part of the image or kickstart template rather than hand-edited afterward. You know it is done when a forward lookup and a reverse lookup of a sample client return the expected names from every subnet where enrollment will run. Confirm these settings with your own network team, since resolver configuration varies by environment.

  2. Create an enrollment role with narrow rights

    Create a dedicated FreeIPA user or role whose only purpose is host enrollment, instead of using the admin account. Grant it the host management permissions needed to add host entries and set one-time passwords, and nothing broader. Your IdM administrator performs this step, and the automation identity should be a separate account with its own audit trail. You know it is done when a test run using this identity can create a sample host entry, but the same identity is refused when it tries to change an unrelated user or group. Check the exact privilege names in your FreeIPA version's documentation before you grant them.

  3. Pre-create host entries with random passwords

    For each host in the batch, create the host entry in FreeIPA ahead of time and set a random one-time password on it. Generate each password with a cryptographically secure generator and never reuse one across hosts. The enrollment role does this work, so no human needs to see the passwords. You know it is done when the host list in FreeIPA matches your inventory exactly, and each entry shows a pending enrollment state with a password set. Keep the batch small enough that a failed host is easy to find and reissue.

  4. Store one-time passwords in a secrets vault

    Write each generated password into a secrets store your automation can read at provisioning time, such as a vault service your organization already operates. Restrict read access to the provisioning pipeline, and set a retention rule so passwords are removed once enrollment succeeds. Passwords should not appear in tickets, chat, shell history or plain text files in a repository. You know it is done when the provisioning pipeline can read the password for one test host, a reviewer without that access cannot, and the store records each read for audit.

  5. Enroll clients from kickstart or ansible-freeipa

    Run the enrollment during provisioning, either from a kickstart post-install script or from an ansible-freeipa client role, passing the host's one-time password from the vault. The role or script should call the client installer with the explicit server, domain and realm, so nothing depends on discovery. Enroll a small pilot group first and watch the installer output for errors. You know the host is enrolled when the installer exits cleanly and the host appears in FreeIPA with its enrollment state changed from pending. Confirm the exact installer options against your client version.

  6. Verify identity with id and getent

    On each enrolled host, confirm that SSSD resolves directory identities. Run id on a test user and getent passwd and getent group for the same user and a known group. The output should show the user's UID, primary group and group memberships from FreeIPA, not local files. Your platform team owns this check, and it should be scripted so every host in the batch is covered. You know it is done when each host returns the same expected identity data for the test user. If results differ between hosts, check DNS and time synchronization first.

  7. Test a login and remove the used password

    Sign in as a test user over SSH or the console, using a Kerberos ticket or the method your access policy allows, and confirm that host access rules admit the user and deny an account without permission. Once the host passes the login test, remove or expire its one-time password in the vault so it cannot be reused. You know it is done when the test login succeeds, the denied account is refused, the vault no longer holds a usable enrollment password for the host, and the enrollment record is saved with the batch for audit.

Kickstart or Ansible: choosing the driver

Kickstart runs at install time, so a host can enroll before anyone logs in to it. The build runs ipa-client-install once the base system is in place, and the one-time password is the only enrollment secret the build needs. Plan the build so the password is consumed during enrollment and never stored in a golden image or template.

  • Explicit install arguments: pass the domain, server, realm and one-time password directly and run unattended, so the build does not depend on discovery succeeding during install.
  • Password delivery: fetch the secret over an authenticated channel at build time, not from a file baked into the image.
  • Log review: check the %post section and installer logs for echoed command lines or the password, and confirm where each log is written.
  • Template hygiene: a template carrying leftover enrollment state can cause failures on every clone, so clear it before templating.
  • Host object timing: the host entry must exist before the build starts, so pre-create it with a random password.

Test one build end to end and confirm that the password appears in no file the pipeline writes before you scale the template.

Security risks in bulk enrollment and how to contain them

Bulk enrollment moves a lot of trust through one process, so a leaked password, a forgotten host entry or an over-privileged automation account can affect many machines at once. The cards below name the risks that recur in these rollouts and the containment step for each. Check every one against your own automation and your own FreeIPA topology before you start.

Passwords left in logs and history

A one-time password printed by a provisioning script, echoed in a kickstart log or typed on a command line can end up in shell history, CI job output or /var/log on the target host. Anyone who reads those logs before the host enrolls can use the password to join the host under the name it was reserved for. Containment: pass the OTP through a secrets store or a file with restricted permissions, disable command echo in provisioning scripts, and confirm that your CI system masks the value. Then check the logs of a test host for the string.

Unused host entries stay enrollable

A host entry created with a one-time password remains enrollable until someone uses it or removes it. Hosts that were planned but never built, or that were rebuilt under a different name, can therefore be claimed by any party who holds the password. Containment: run a regular report of host entries that have a pending OTP, compare it with your inventory, and delete entries for machines that are not coming. Treat each stale entry as a credential to revoke.

Over-broad automation accounts

The account that creates host entries and generates OTPs often has rights well beyond that task, such as managing users, groups or certificates. If its credentials leak from a pipeline, the attacker gets far more than enrollment. Containment: create a dedicated role with only the host-add and OTP-set privileges the playbook needs, use a service principal with a keytab restricted to the automation host, and review its privileges after each change to the playbook.

Stale keytabs on rebuilt hosts

When a host is rebuilt under the same name without first removing its old principal and keytab, the old keys can still be valid and the new machine may reuse or conflict with them. This blurs which system authenticated and complicates incident response. Containment: remove the host's keytab and certificates on the old machine or delete the host entry before rebuilding, and make the rebuild workflow include a re-enrollment step that replaces credentials rather than keeping them. Confirm the procedure in the re-enrollment guidance for your version.

First server during certificate renewal

During a large rollout the first FreeIPA server often handles certificate renewal and CRL publication by default, and enrollment traffic can concentrate on it. Heavy load or a failed server at that point can stall enrollments and certificate work, and restoring an outdated backup into an active topology can break replication. Containment: confirm which server holds the renewal role before you start, schedule the rollout around it, avoid restoring backups during enrollment waves, and monitor that server's health and replication status throughout.

Questions teams ask before enrolling hosts at scale

How much effort does bulk FreeIPA client enrollment take?

Effort depends mostly on how many distinct host builds you have, how much of the enrollment already runs through your provisioning tooling, and how many hosts sit outside your standard images. A single kickstart or image path with one enrollment step is a small change. Several build paths, hosts that are rebuilt often, and hosts with unusual DNS or time settings add design and testing work. Ask any partner to split the estimate into the enrollment design, the automation build, the pilot on representative hosts and the rollout itself, and to state which of these recur after go-live.

Can our own team run bulk enrollment without outside help?

Yes, if your engineers already automate builds and are comfortable with the FreeIPA admin tools. The core pattern is to pre-create each host record with a random one-time password, pass that password to the new machine during kickstart or configuration management, and let the client complete enrollment once. The parts that usually need experience are the role and host-group design, the kickstart and Ansible wiring, and the failure handling. An outside team is most useful when deadlines are fixed or the estate spans several build pipelines that nobody on staff owns end to end.

What access and inputs does bulk enrollment require from us?

You need an account with rights to create host entries and generate one-time passwords on the FreeIPA servers, a way to deliver each password to the target host without writing it into shared repositories, and working DNS for the realm. Keep the admin credentials for the enrollment run out of the automation itself. Confirm with your identity team which account and role will create hosts, how the Ansible control node authenticates, and whether your DNS servers resolve the client names. Also confirm that every target can reach the FreeIPA servers and the time source they use.

How long does a rollout to hundreds of hosts take, and what sets that?

The schedule is set by the number of build paths, how many hosts you can reboot or rebuild in each change window, and how long your pilot takes to show clean results. Enrollment itself is quick per host, so the bottleneck is usually change control and validation. Ask for a schedule that shows a pilot group, a staged rollout by site or host role, and a defined point to stop if failures rise. Any duration you are quoted should be traced back to these inputs and to your own maintenance calendar.

What happens to hosts that fail enrollment, and how do we find them?

Plan for failures before the first batch runs. The usual causes are a one-time password that was never delivered or was used already, DNS names that do not resolve, clock skew, blocked ports, and hosts that were enrolled before under a different realm. Record each host's enrollment result in your automation output and compare the list of pre-created host entries with the list of enrolled clients. Decide in advance who re-issues a password, who rebuilds a host, and when a host is removed from the batch, so failed machines do not sit half-enrolled.

Do one-time passwords replace PKINIT for enrolling clients?

Not in every case. One-time passwords suit hosts that are built from images or kickstart files where you can pass a single-use secret at install time. PKINIT uses an existing host certificate instead of a password, which fits hosts that already have certificates from your provisioning process. Each method has its own trust and rotation model, so the choice should follow how your hosts are built and who controls the certificate source. Confirm with your security team which method they accept before you standardize on one for the whole estate.

What a scoped enrollment engagement covers

A scoped enrollment engagement starts with a host inventory that the client and DeployOpen reconcile in writing: which machines enroll, their operating systems and distribution versions, which network segment each sits in, which DNS servers their resolv.conf points to, and which IPA domain and realm they will join. From that inventory the design sets the one-time password flow. Hosts are pre-created on the FreeIPA server with random one-time passwords, so no administrator credential is shared with the people or automation that run enrollment. The design also records how those passwords move from the server to each host, how long they stay valid, and who may read them. Automation design covers the kickstart or provisioning template, the playbooks that call the ansible-freeipa roles, and the order in which hosts are enrolled, so a failed batch can be rerun without creating duplicate host entries.

The vault and role model is where most of the access risk sits. Passwords and any credentials the automation needs are kept in an Ansible Vault or another secret store the client already operates, with separate vault IDs for production and non-production inventories. Each automation identity gets only the FreeIPA permissions it needs to create hosts and read their one-time passwords, and nothing broader. The engagement also sets a test enrollment on a pilot group of hosts, chosen to cover each distribution and network zone in the inventory, and checks login, SSSD status, DNS registration and host group membership before any batch runs. Handover documentation then covers the playbooks, variable files, role versions, the pilot results, the rollback path for a failed batch and the owner for each secret. Confirm with your FreeIPA team which ansible-freeipa release you will pin, because the role interfaces change between releases.

Engagements are fixed-scope: DeployOpen agrees the scope, deliverables and timeline in writing before work starts, and quotes from that written scope rather than from a standard price list. Ask the quote to show each deliverable separately, the testing effort on the pilot group, and whether any work is recurring, such as a retainer for later batches. The client supplies access to the FreeIPA servers, the target hosts or their provisioning system, the host lists, a named approver for secrets, and change windows for each batch. Confirm early whether the change windows allow the pilot to run during business hours, and whether the enrollment must be re-run for hosts rebuilt later.

How DeployOpen scopes and supports FreeIPA enrollment

DeployOpen plans and delivers FreeIPA client enrollment at scale inside your own infrastructure, from the enrollment method and automation to the documentation your operations team keeps. Engagements are fixed-scope, with the scope, deliverables and timeline agreed in writing before any work starts.

How we scope

  • Inventory the host groups, operating systems and networks that need enrollment, and confirm which hosts stay out of scope.
  • Agree the one-time password method, host naming rules and who may create host entries in your FreeIPA realm.
  • Record the written scope, deliverables and timeline before a quote is issued, so the boundaries of the work are explicit.

How we build

  • Build the host pre-creation and one-time password workflow, then test it against a small pilot group of representative machines.
  • Write kickstart or automation templates and ansible-freeipa client roles that match your distributions and provisioning tooling.
  • Test enrollment, failure handling and re-runs in a non-production realm before any change reaches your production estate.

How we hand over

  • Document the enrollment runbook, including how one-time passwords are generated, stored, expired and audited.
  • Provide the automation code, role variables and configuration as versioned artifacts in your own repositories.
  • Walk your operations team through the workflow and record open items, so your staff can run enrollment without us.

How we support

  • Offer ongoing support, upgrades and testing as a retainer after handover, scoped separately from the original build.
  • Review enrollment automation when FreeIPA server or client versions change, and confirm compatibility before rollout.
  • Ask your team to confirm the supported client distributions and the security review requirements for your environment before work starts.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.