12 KiB
ansipa Administration Guide
Day-to-day operation of the ansipa management plane: the full policy catalogue and how to apply, target, and revert each policy. For the deployment/ports/ reverse-proxy story see the ansipa Setup Guide; for the architecture and container internals see FreeIPA & Ansible.
How administration works
Everything is driven by FreeIPA group membership. You never log into a client to change its policy — you add or remove a host or user from a group on the FreeIPA server, and the fleet converges on the next timer tick.
Two independent client-side mechanisms consume that membership, both installed by the Ansible playbooks and both idempotent and reversible (leaving a group undoes the change on the next run):
| Mechanism | Timer | Reads | Applies |
|---|---|---|---|
Policy enforcer (ansipa-enforce-policies.sh) |
ansipa-enforce-policies.timer, every 30 min |
host + user groups | daemon/sudo/ssh/monitoring/scan/SMB/block policies |
Installer timers (ansipa-install-*.sh) |
ansipa-install*.timer, every 30 min |
dev_pkg_*, dev_mod_*, dev_fp_* host groups |
packages, setup modules, Flatpaks |
Because it is all client-pull, everything works across NAT (the server never initiates a connection to a client). To apply a change immediately instead of waiting for the timer, run the relevant script on the client as root:
sudo /usr/local/bin/ansipa-enforce-policies.sh # policies
sudo /usr/local/bin/ansipa-install-packages.sh # dev_pkg_*
sudo /usr/local/bin/ansipa-install-modules.sh # dev_mod_*
sudo /usr/local/bin/ansipa-install-flatpaks.sh # dev_fp_*
The two group scopes
- Host groups (
dev_*) — a device policy. Applies to the machine(s) you add to the group. Managed withipa hostgroup-*. - User groups (
usr_*) — a user policy that follows the user to every enrolled machine they log into. Applies while the group exists; managed withipa group-*. Several user policies key off the group merely existing (not the specific host), because the enforcer runs on every host.
The two ways to bind a target
Most policies encode their target in the group name suffix
(dev_local-sudo-alice, dev_pkg_htop, usr_block-binary-nano). A few need
extra data (a printer URI, an SMB credential) which lives in the group
description, set with ipa group-mod <grp> --desc='…' — noted per-policy below.
Everyday commands
# Create + populate a host group (device policy)
ipa hostgroup-add dev_mon_base --desc "CheckMK monitored hosts"
ipa hostgroup-add-member dev_mon_base --hosts=client01.corp.example.com
ipa hostgroup-remove-member dev_mon_base --hosts=client01.corp.example.com
# Create + populate a user group (user policy)
ipa group-add usr_admin --desc "Fleet-wide sudoers"
ipa group-add-member usr_admin --users=alice
ipa group-remove-member usr_admin --users=alice
# Inspect
ipa host-show client01.corp.example.com | grep -A3 'Member of host-groups'
ipa hostgroup-show dev_pkg_htop
Everything below can equally be done from the FreeIPA web UI (Identity → Host Groups / User Groups).
Device policies (dev_* host groups)
dev_daemon-enable-<unit> / dev_daemon-disable-<unit>
Force a systemd unit on or off fleet-wide.
- Apply: enable →
systemctl enable --now <unit>; disable →disable --now. - Revert (leave group): the opposite action.
- The
.servicesuffix is optional (appended automatically for a bare name); any unit type works. A unit in both enable and disable groups is skipped with a warning. - Example:
ipa hostgroup-add dev_daemon-disable-bluetooththen add hosts →bluetooth.serviceis stopped and masked-off on them.
⚠️ Enabling
sshdthis way and later reverting will stop sshd — don't lock yourself out of a headless box you only reach over SSH.
dev_timeshift-backup
Enforce a daily Timeshift snapshot at 03:00 (requires timeshift; add the host
to dev_mod_timeshift to install it). Leaving the group removes the cron.
dev_no-local-users
Lock the password of every local account — root (UID 0) and all regular
users (UID ≥ 1000) — with passwd -l, so only FreeIPA accounts can authenticate.
Accounts already locked are left untouched and not tracked; revert unlocks only
what this policy locked. State: /var/lib/ansipa-policies/no-local-users.
dev_local-sudo-<username>
Grant <username> full sudo on this specific device via a sudoers drop-in.
Device-scoped (unlike usr_admin). Leaving the group removes the drop-in.
- Example:
ipa hostgroup-add dev_local-sudo-alice+ addlab-pc-3→ alice gets sudo onlab-pc-3only.
dev_ssh_<userid>
Distribute <userid>'s SSH public keys from their IPA profile to
/home/<userid>/.ssh/authorized_keys on hosts in the group (in an
ansipa-managed section; hand-added keys are preserved). Store the keys in IPA:
ipa user-mod alice --sshpubkey='ssh-ed25519 AAAA...'
ipa hostgroup-add dev_ssh_alice && ipa hostgroup-add-member dev_ssh_alice --hosts=…
Leaving the group removes only the ansipa-managed section.
Monitoring policies (dev_mon_*, usr_mon_*)
All CheckMK monitoring requires the CheckMK stack to be up and
ansipa-checkmk-setup.sh to have run on the FreeIPA container (seeds the
dev_mon_base credentials + the monitoring groups in IPA). All checks are
collected by the agent, so every monitored host must also be in
dev_mon_base.
dev_mon_base (required for all monitoring)
Installs the CheckMK agent, registers the host in CheckMK (under /ansipa), and
opens the agent for collection: pull mode on check_mk.socket (port 6556) where
the server can reach the client, or push mode (cmk-agent-ctl → server
:8000) for NAT clients. Built-in CPU/RAM/disk/uptime plus an installed-package
count check (Ansipa_Packages). Leaving the group deregisters the host and
disables the agent.
Credentials are auto-discovered from the
dev_mon_basegroup description (cmk://<host>:<port>/<site>:automation:<secret>), which the server populates. SetCMK_ADVERTISED_URLin.envto a client-routable address.
dev_mon_clamscan
Run a daily ClamAV + rkhunter + chkrootkit scan at 02:00 and report the result
to CheckMK as the Ansipa_ClamScan service (OK = clean, WARN = stale DB or
rkhunter warnings, CRIT = infected). Self-contained — it runs the scan and
writes the local check; results no longer go over SMB.
- Prerequisites:
dev_mod_anti-malware(tools) +dev_mon_base(agent). - Revert: removes the cron, scan script, log, and local check.
dev_mon_timeshift
Ansipa_Timeshift check on the newest Timeshift snapshot age: WARN > 5 days,
CRIT > 10 days or none found. Pair with dev_timeshift-backup (which creates
them) and dev_mon_base.
dev_mon_power
Ansipa_Power check on CPU-package power via Intel RAPL (preferred) or
lm-sensors: WARN ≥ 65 W, CRIT ≥ 95 W. Add the host to dev_mod_* that installs
lm_sensors if RAPL is unavailable.
usr_mon_logins (user group)
Ansipa_Logins check reporting SSH login attempts in the last 24 h (successful +
failed + invalid-user), with thresholds. Installed fleet-wide when the group
exists; needs dev_mon_base on the hosts.
Software-installer policies (dev_pkg_*, dev_mod_*, dev_fp_*)
These are the GPO-like software-deployment groups, applied by the
ansipa-install-* timers (not the policy enforcer). Join → installed; leave →
removed. Install state is tracked so revert only touches what ansipa installed.
dev_pkg_<package>
Install a single distro package (via pacman/dnf/apt — auto-detected).
ipa hostgroup-add dev_pkg_htop && ipa hostgroup-add-member dev_pkg_htop --hosts=…
dev_mod_<name>
Apply a whole setup module from setup/modules/optional-Modules/apps/ —
e.g. dev_mod_docker, dev_mod_anti-malware, dev_mod_timeshift,
dev_mod_ollama. This is how you install the tools other policies need
(dev_mod_anti-malware before dev_mon_clamscan, dev_mod_timeshift before
dev_timeshift-backup).
dev_fp_<app>
Install a Flathub Flatpak. Encode the app ID with __ in place of .:
# org.gimp.Gimp
ipa hostgroup-add dev_fp_org__gimp__Gimp
ipa hostgroup-add-member dev_fp_org__gimp__Gimp --hosts=…
User policies (usr_* user groups)
usr_admin
Full sudo on every enrolled host for members, via a %usr_admin sudoers
drop-in resolved through SSSD. Active while the group exists; the drop-in is
removed when the group is deleted (not merely when a member leaves — removing
a member just drops that user's sudo, since it is group-based).
usr_block-binary-<name>
Prevent members from running <name> on any enrolled host via a PATH-priority
wrapper that checks group membership at runtime. Use __ for . to block a
Flatpak (usr_block-binary-org__gimp__Gimp). Non-members are unaffected
(the wrapper transparently execs the real binary). Deleting the IPA group removes
the wrapper.
usr_prt_<printer>
Auto-add <printer> to CUPS on any host where a member is logged in. Store the
printer URI in the group description:
ipa group-add usr_prt_frontdesk --desc='ipps://printserver/printers/frontdesk'
ipa group-add-member usr_prt_frontdesk --users=alice
Requires cups (installed by the policy deploy). Leaving/deleting removes the
printer.
usr_smb_r_<name> / usr_smb_rw_<name>
Auto-mount a Samba share at ~/<name> for logged-in members (rw wins if a user
is in both). Store the credential in the group description (written by
ansipa-smb-setup.sh for the built-in shares):
cifs://<ipa-host>:<samba-user>:<password>
Requires cifs-utils (installed by the policy deploy). Leaving unmounts on the
next run.
usr_smb_adm_policystore
Mount the policy store at ~/policystore (rw) for admin members, so you can edit
the live policies.d/*.sh files directly on the share — changes take effect
fleet-wide on the next 30-min enforcer tick, no redeploy needed. Credential in
the group description (auto-set by ansipa-smb-setup.sh).
BaseUser sync (BaseUser group)
Not a policy script — a systemd.path unit (deployed by
deploy-baseuser-sync.yml) that, on login, adds any member of the FreeIPA
BaseUser group to the local baseusers group. Use it to grant a baseline local
group to all standard users.
Common recipes
Onboard a new workstation (identity + monitoring + a couple of apps):
H=ws-42.corp.example.com
ipa hostgroup-add-member dev_mon_base --hosts=$H
ipa hostgroup-add-member dev_mon_clamscan --hosts=$H
ipa hostgroup-add-member dev_mod_anti-malware --hosts=$H # installs clamav/rkhunter
ipa hostgroup-add-member dev_mod_docker --hosts=$H
ipa hostgroup-add-member dev_pkg_htop --hosts=$H
# then, on the box (or wait 30 min):
sudo /usr/local/bin/ansipa-enforce-policies.sh
sudo /usr/local/bin/ansipa-install-modules.sh
Give a helpdesk user sudo everywhere, block a risky tool:
ipa group-add-member usr_admin --users=bob
ipa group-add usr_block-binary-tcpdump && ipa group-add-member usr_block-binary-tcpdump --users=intern
Edit policy logic live (as an admin in usr_smb_adm_policystore):
$EDITOR ~/policystore/dev_mon_clamscan.sh # applied fleet-wide next enforcer tick
Troubleshooting
| Symptom | Check |
|---|---|
| Policy not applying | sudo /usr/local/bin/ansipa-enforce-policies.sh on the client; read the [ansipa-policies] discovery line — is the group listed? |
| Host not in CheckMK | Is it in dev_mon_base? Is CMK_ADVERTISED_URL client-routable? ipa hostgroup-show dev_mon_base description present? |
| ClamAV shows "no scan yet" | Scans run 02:00; trigger once with sudo /usr/local/bin/ansipa-clamscan.sh. Tools installed via dev_mod_anti-malware? |
| Package group ignored | dev_pkg_* uses the installer timer, not the enforcer — run sudo /usr/local/bin/ansipa-install-packages.sh. |
Enforcer error ipa: command not found |
The host is not enrolled — run freeipa-enroll.sh first. |
| Changes take up to 30 min | That's the timer cadence; run the script manually to apply now. |
State for all policies lives under /var/lib/ansipa-policies/; logs go to the
journal under the ansipa-policies tag (journalctl -t ansipa-policies).