8 cfg = config.security.ipa;
14 ldapConf = pkgs.writeText "ldap.conf" ''
15 # Turning this off breaks GSSAPI used with krb5 when rdns = false
18 URI ldaps://${cfg.server}
20 TLS_CACERT /etc/ipa/ca.crt
23 pkgs.runCommand "ipa-nssdb"
25 nativeBuildInputs = [pkgs.nss.tools];
28 certutil -d $out -N --empty-password
29 certutil -d $out -A --empty-password -n "${cfg.realm} IPA CA" -t CT,C,C -i ${cfg.certificate}
34 enable = mkEnableOption "FreeIPA domain integration";
36 certificate = mkOption {
39 IPA server CA certificate.
41 Use `nix-prefetch-url http://$server/ipa/config/ca.crt` to
42 obtain the file and the hash.
44 example = literalExpression ''
46 url = http://ipa.example.com/ipa/config/ca.crt;
47 sha256 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
54 example = "example.com";
55 description = "Domain of the IPA server.";
60 example = "EXAMPLE.COM";
61 description = "Kerberos realm.";
66 example = "ipa.example.com";
67 description = "IPA Server hostname.";
72 example = "dc=example,dc=com";
73 description = "Base DN to use when performing LDAP operations.";
76 offlinePasswords = mkOption {
79 description = "Whether to store offline passwords when the server is down.";
82 cacheCredentials = mkOption {
85 description = "Whether to cache credentials.";
88 ipaHostname = mkOption {
90 example = "myworkstation.example.com";
91 default = if config.networking.domain != null then config.networking.fqdn
92 else "${config.networking.hostName}.${cfg.domain}";
93 defaultText = literalExpression ''
94 if config.networking.domain != null then config.networking.fqdn
95 else "''${networking.hostName}.''${security.ipa.domain}"
97 description = "Fully-qualified hostname used to identify this host in the IPA domain.";
100 ifpAllowedUids = mkOption {
101 type = types.listOf types.str;
103 description = "A list of users allowed to access the ifp dbus interface.";
110 description = "Whether to enable FreeIPA automatic hostname updates.";
113 interface = mkOption {
117 description = "Network interface to perform hostname updates through.";
121 chromiumSupport = mkOption {
124 description = "Whether to whitelist the FreeIPA domain in Chromium.";
129 config = mkIf cfg.enable {
132 assertion = !config.security.krb5.enable;
133 message = "krb5 must be disabled through `security.krb5.enable` for FreeIPA integration to work.";
136 assertion = !config.users.ldap.enable;
137 message = "ldap must be disabled through `users.ldap.enable` for FreeIPA integration to work.";
141 environment.systemPackages = with pkgs; [krb5Full freeipa];
144 "ipa/default.conf".text = ''
146 basedn = ${cfg.basedn}
148 domain = ${cfg.domain}
149 server = ${cfg.server}
150 host = ${config.networking.hostName}
151 xmlrpc_uri = https://${cfg.server}/ipa/xml
155 "ipa/nssdb".source = nssDb;
157 "krb5.conf".text = ''
159 default_realm = ${cfg.realm}
160 dns_lookup_realm = false
161 dns_lookup_kdc = true
163 ticket_lifetime = 24h
165 udp_preference_limit = 0
169 kdc = ${cfg.server}:88
170 master_kdc = ${cfg.server}:88
171 admin_server = ${cfg.server}:749
172 default_domain = ${cfg.domain}
173 pkinit_anchors = FILE:/etc/ipa/ca.crt
177 .${cfg.domain} = ${cfg.realm}
178 ${cfg.domain} = ${cfg.realm}
179 ${cfg.server} = ${cfg.realm}
183 db_library = ${pkgs.freeipa}/lib/krb5/plugins/kdb/ipadb.so
187 "openldap/ldap.conf".source = ldapConf;
190 environment.etc."chromium/policies/managed/freeipa.json" = mkIf cfg.chromiumSupport {
192 { "AuthServerWhitelist": "*.${cfg.domain}" }
196 systemd.services."ipa-activation" = {
197 wantedBy = [ "sysinit.target" ];
198 before = [ "sysinit.target" "shutdown.target" ];
199 conflicts = [ "shutdown.target" ];
200 unitConfig.DefaultDependencies = false;
201 serviceConfig.Type = "oneshot";
202 serviceConfig.RemainAfterExit = true;
204 # libcurl requires a hard copy of the certificate
205 if ! ${pkgs.diffutils}/bin/diff ${cfg.certificate} /etc/ipa/ca.crt > /dev/null 2>&1; then
206 rm -f /etc/ipa/ca.crt
207 cp ${cfg.certificate} /etc/ipa/ca.crt
210 if [ ! -f /etc/krb5.keytab ]; then
213 In order to complete FreeIPA integration, please join the domain by completing the following steps:
214 1. Authenticate as an IPA user authorized to join new hosts, e.g. kinit admin@${cfg.realm}
215 2. Join the domain and obtain the keytab file: ipa-join
216 3. Install the keytab file: sudo install -m 600 krb5.keytab /etc/
217 4. Restart sssd systemd service: sudo systemctl restart sssd
224 services.sssd.config = ''
225 [domain/${cfg.domain}]
228 access_provider = ipa
229 chpass_provider = ipa
231 ipa_domain = ${cfg.domain}
232 ipa_server = _srv_, ${cfg.server}
233 ipa_hostname = ${cfg.ipaHostname}
235 cache_credentials = ${pyBool cfg.cacheCredentials}
236 krb5_store_password_if_offline = ${pyBool cfg.offlinePasswords}
237 ${optionalString ((toLower cfg.domain) != (toLower cfg.realm))
238 "krb5_realm = ${cfg.realm}"}
240 dyndns_update = ${pyBool cfg.dyndns.enable}
241 dyndns_iface = ${cfg.dyndns.interface}
243 ldap_tls_cacert = /etc/ipa/ca.crt
244 ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock
247 services = nss, sudo, pam, ssh, ifp
248 domains = ${cfg.domain}
251 homedir_substring = /home
254 pam_pwd_expiration_warning = 3
266 user_attributes = +mail, +telephoneNumber, +givenname, +sn, +lock
267 allowed_uids = ${concatStringsSep ", " cfg.ifpAllowedUids}
270 services.ntp.servers = singleton cfg.server;
271 services.sssd.enable = true;
272 services.ntp.enable = true;
274 security.pki.certificateFiles = singleton cfg.certificate;