blob: c564d34f17832d784875ef60ea0950b9e23a4198 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
{ lib, pkgs, config, name, ... }:
{
options.myServices.certificates = {
enable = lib.mkEnableOption "enable certificates";
certConfig = lib.mkOption {
default = {
webroot = "/var/lib/acme/acme-challenges";
email = "ismael@bouya.org";
postRun = builtins.concatStringsSep "\n" [
(lib.optionalString config.services.httpd.Prod.enable "systemctl reload httpdProd.service")
(lib.optionalString config.services.httpd.Tools.enable "systemctl reload httpdTools.service")
(lib.optionalString config.services.httpd.Inte.enable "systemctl reload httpdInte.service")
(lib.optionalString config.services.nginx.enable "systemctl reload nginx.service")
];
};
description = "Default configuration for certificates";
};
};
config = lib.mkIf config.myServices.certificates.enable {
services.duplyBackup.profiles.system.excludeFile = ''
+ /var/lib/acme/acme-challenges
'';
services.nginx = {
recommendedTlsSettings = true;
virtualHosts = {
"${config.hostEnv.fqdn}" = {
acmeRoot = config.security.acme.certs."${name}".webroot;
useACMEHost = name;
forceSSL = true;
};
};
};
services.websites.certs = config.myServices.certificates.certConfig;
myServices.databasesCerts = config.myServices.certificates.certConfig;
myServices.ircCerts = config.myServices.certificates.certConfig;
security.acme.acceptTerms = true;
security.acme.preliminarySelfsigned = true;
security.acme.certs = {
"${name}" = config.myServices.certificates.certConfig // {
domain = config.hostEnv.fqdn;
};
};
systemd.services = lib.attrsets.mapAttrs' (k: v:
lib.attrsets.nameValuePair "acme-selfsigned-${k}" {
wantedBy = [ "acme-selfsigned-certificates.target" ];
script = lib.mkAfter ''
cp $workdir/server.crt ${config.security.acme.certs."${k}".directory}/cert.pem
chown '${v.user}:${v.group}' ${config.security.acme.certs."${k}".directory}/cert.pem
chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.certs."${k}".directory}/cert.pem
cp $workdir/ca.crt ${config.security.acme.certs."${k}".directory}/chain.pem
chown '${v.user}:${v.group}' ${config.security.acme.certs."${k}".directory}/chain.pem
chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.certs."${k}".directory}/chain.pem
'';
}
) config.security.acme.certs //
lib.attrsets.mapAttrs' (k: data:
lib.attrsets.nameValuePair "acme-${k}" {
after = lib.mkAfter [ "bind.service" ];
serviceConfig.ExecStartPre =
let
script = pkgs.writeScript "acme-pre-start" ''
#!${pkgs.runtimeShell} -e
mkdir -p '${data.webroot}/.well-known/acme-challenge'
chmod a+w '${data.webroot}/.well-known/acme-challenge'
#doesn't work for multiple concurrent runs
#chown -R '${data.user}:${data.group}' '${data.webroot}/.well-known/acme-challenge'
'';
in
"+${script}";
# This is a workaround to
# https://github.com/NixOS/nixpkgs/issues/84409
# https://github.com/NixOS/nixpkgs/issues/84633
serviceConfig.RemainAfterExit = lib.mkForce false;
serviceConfig.WorkingDirectory = lib.mkForce "/var/lib/acme/${k}/.lego";
serviceConfig.StateDirectory = lib.mkForce "acme/${k}/.lego acme/${k}";
serviceConfig.ExecStartPost =
let
keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
fileMode = if data.allowKeysForGroup then "640" else "600";
spath = "/var/lib/acme/${k}/.lego";
script = pkgs.writeScript "acme-post-start" ''
#!${pkgs.runtimeShell} -e
cd /var/lib/acme/${k}
# Test that existing cert is older than new cert
KEY=${spath}/certificates/${keyName}.key
if [ -e $KEY -a $KEY -nt key.pem ]; then
cp -p ${spath}/certificates/${keyName}.key key.pem
cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
ln -sf fullchain.pem cert.pem
cat key.pem fullchain.pem > full.pem
${data.postRun}
fi
chmod ${fileMode} *.pem
chown '${data.user}:${data.group}' *.pem
'';
in
lib.mkForce "+${script}";
}
) config.security.acme.certs //
{
httpdProd = lib.mkIf config.services.httpd.Prod.enable
{ after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
httpdTools = lib.mkIf config.services.httpd.Tools.enable
{ after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
httpdInte = lib.mkIf config.services.httpd.Inte.enable
{ after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
};
};
}
|