Change:
I'm currently running web, IMAP, SMTP, and XMPP servers for a single domain on the same host. All of them should support SSL, and I'm using letsencrypt/ACME via the (amazingly simple) NixOS integration. Unfortunately, AFAICT, the current ACME infrastructure in NixOS only supports a single certificate per domain; the directory location and domain are tied to the same parameter (namely, the <namein the record). This would be suboptimal but reasonable, except that the services (rightfully) run as separate users, and all need to read the shared certificate. On 16.09, I could do this (hackily) by setting the user and group on the certificate; however, in 17.03 it appears that the nginx config sets the user to nginx's, thwarting my workaround. So I'm looking at implementing this properly, with a different certificate for each service. It seems to me that adding an option to override the domain passed to cert_le would be a good fix; something like the following would work then: It also seems plausible to me that something could be made to work by repeating in for other domains, but that presumably requires those other domains to work as well, and seems extremely fragile. N/A; this is a feature request System: 16.09.1914., though it also appears to apply to 17.03 and unstable) Nix version: 1.11.8 Nixpkgs version: 16.09.1914. (again, this also seems true in 17.03 and unstable)
I submitted a PR to add a domain option to resolve this. Unfortunately, there are still some a couple rough edges: all the certificates are sharing the same challenge directory, so all of the ACME configs are using root for the user, and using the group to read the key (see, e.g., ). letsencrypt has that should suffice for any reasonable use (if you don't re-generate keys a couple times to make sure that service restarts are working), but it might not be a bad idea to call that out somewhere. I don't think the latter is worth worrying about, but I'm curious if anyone has ideas for permissions on the challenge directory. My thought is that nginx can only reasonably serve a single directory for the challenge for a domain, and so the two options are share a user for all the acme configurations and use groups to control reading the keys (my current solution) make the challenge directory world writable The former is a bit icky, but the latter seems unsafe; then anyone with ssh access to the server could get certificates for any domain with ACME configured. With the first solution, at least you can only steal a certificate if you have access to the group, which means pretty much either root or else exploiting the service, and in either case there's no real defense against reading the certificate. Am I missing a better solution?
Thanks for your analysis and the PR. :+1: I've been sharing the main certificate between services by placing the service users in a new group. Regarding the challenge directory, I think your first suggestion makes a lot of sense. :+1: We have some more issues with our current ACME module. For instance, because we are using simple, we don't support dns-01 challenges yet. I've been thinking about replacing simple with dehydrated or Do you maybe have an opinion on that? This would mean a major refactoring of the module, though, and the certificates and keys will probably be placed in different files/directories.
Pretty much all I know about ACME is what's in Nix; I saw that it was supported, and figured that was (almost) good enough for me. I'm intrigued and might be interested in taking a look at alternative clients, but it's not something I expect to do in the near future.

Discussion:
''; }; <ins> domain = mkOption { type = types.nullOr types.str; default = null; description = "Domain to fetch certificate for (defaults to the entry name)"; }; </ins> email = mkOption { type = types.nullOr types.str; default = null;

servicesLists = mapAttrsToList certToServices cfg.certs; certToServices = cert: data: let <ins> domain = if data.domain != null then data.domain else cert; </ins> cpath = "${cfg.directory}/${cert}"; rights = if data.allowKeysForGroup then "750" else "700"; <del> cmdline = [ "-v" "-d" cert "--default_root" data.webroot "--valid_min" cfg.validMin ] </del> <ins> cmdline = [ "-v" "-d" domain "--default_root" data.webroot "--valid_min" cfg.validMin ] </ins> ++ optionals (data.email != null) [ "--email" data.email ] ++ concatMap (p: [ "-f" p ]) data.plugins ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains);