@ -62,24 +62,30 @@ let
# Ensures that directories which are shared across all certs
# exist and have the correct user and group, since group
# is configurable on a per-cert basis.
userMigrationService = {
description = " F i x o w n e r a n d g r o u p o f a l l A C M E c e r t i f i c a t e s " ;
userMigrationService = let
script = with builtins ; concatStringsSep " \n " ( mapAttrsToList ( cert : data : ''
for fixpath in /var/lib/acme / $ { escapeShellArg cert } /var/lib/acme/.lego / $ { escapeShellArg cert } ; do
chown - R acme .lego/accounts
for fixpath in $ { escapeShellArg cert } . lego / $ { escapeShellArg cert } ; do
if [ - d " $ f i x p a t h " ] ; then
chmod - R u = rwX , g = rX , o = " $ f i x p a t h "
chown - R acme:$ { data . group } " $ f i x p a t h "
fi
done
'' ) c e r t C o n f i g s ) ;
in {
description = " F i x o w n e r a n d g r o u p o f a l l A C M E c e r t i f i c a t e s " ;
serviceConfig = {
serviceConfig = commonServiceConfig // {
# We don't want this to run every time a renewal happens
RemainAfterExit = true ;
# These StateDirectory entries negate the need for tmpfiles
StateDirectory = " a c m e a c m e / . l e g o a c m e / . l e g o / a c c o u n t s " ;
StateDirectory = [ " a c m e " " a c m e / . l e g o " " a c m e / . l e g o / a c c o u n t s " ] ;
StateDirectoryMode = 755 ;
WorkingDirectory = " / v a r / l i b / a c m e " ;
# Run the start script as root
ExecStart = " + " + ( pkgs . writeShellScript " a c m e - f i x p e r m s " script ) ;
} ;
} ;
@ -153,7 +159,6 @@ let
in {
inherit accountHash cert selfsignedDeps ;
webroot = data . webroot ;
group = data . group ;
renewTimer = {
@ -193,7 +198,10 @@ let
StateDirectory = " a c m e / ${ cert } " ;
BindPaths = " / v a r / l i b / a c m e / . m i n i c a : / t m p / c a / v a r / l i b / a c m e / ${ cert } : / t m p / ${ keyName } " ;
BindPaths = [
" / v a r / l i b / a c m e / . m i n i c a : / t m p / c a "
" / v a r / l i b / a c m e / ${ cert } : / t m p / ${ keyName } "
] ;
} ;
# Working directory will be /tmp
@ -234,17 +242,19 @@ let
# Keep in mind that these directories will be deleted if the user runs
# systemctl clean --what=state
# acme/.lego/${cert} is listed for this reason.
StateDirectory =
" a c m e / ${ cert } " +
" a c m e / . l e g o / ${ cert } " +
" a c m e / . l e g o / ${ cert } / ${ certDir } " +
" a c m e / . l e g o / a c c o u n t s / ${ accountHash } " ;
StateDirectory = [
" a c m e / ${ cert } "
" a c m e / . l e g o / ${ cert } "
" a c m e / . l e g o / ${ cert } / ${ certDir } "
" a c m e / . l e g o / a c c o u n t s / ${ accountHash } "
] ;
# Needs to be space separated, but can't use a multiline string because that'll include newlines
BindPaths =
" ${ accountDir } : / t m p / a c c o u n t s " +
" / v a r / l i b / a c m e / ${ cert } : / t m p / o u t " +
" / v a r / l i b / a c m e / . l e g o / ${ cert } / ${ certDir } : / t m p / c e r t i f i c a t e s " ;
BindPaths = [
" ${ accountDir } : / t m p / a c c o u n t s "
" / v a r / l i b / a c m e / ${ cert } : / t m p / o u t "
" / v a r / l i b / a c m e / . l e g o / ${ cert } / ${ certDir } : / t m p / c e r t i f i c a t e s "
] ;
# Only try loading the credentialsFile if the dns challenge is enabled
EnvironmentFile = mkIf useDns data . credentialsFile ;
@ -257,7 +267,16 @@ let
$ { data . postRun }
fi
'' ) ;
} ;
} // ( optionalAttrs ( data . webroot != null ) {
# Lego always tries to create .well-known/acme-challenge, but if webroot is owned
# by the wrong user then it will crash and break cert renewal.
ExecStartPre = " + " + pkgs . writeShellScript " a c m e - ${ cert } - m a k e - w e b r o o t " ''
mkdir - p ' $ { data . webroot } /.well-known/acme-challenge '
cd ' $ { data . webroot } '
chown ' acme:$ { data . group } ' . . well-known .well-known/acme-challenge
'' ;
} ) ;
# Working directory will be /tmp
script = ''
@ -676,15 +695,6 @@ in {
systemd . timers = mapAttrs' ( cert : conf : nameValuePair " a c m e - ${ cert } " conf . renewTimer ) certConfigs ;
systemd . tmpfiles . rules = unique (
flatten (
mapAttrsToList (
cert : conf :
optional ( conf . webroot != null ) " d ${ conf . webroot } / . w e l l - k n o w n / a c m e - c h a l l e n g e - a c m e ${ conf . group } "
) certConfigs
)
) ;
systemd . targets = let
# Create some targets which can be depended on to be "active" after cert renewals
finishedTargets = mapAttrs' ( cert : conf : nameValuePair " a c m e - f i n i s h e d - ${ cert } " {