1{ pkgs ? import <nixpkgs> {}
2, lib ? pkgs.lib
3
4, domains ? [ "acme-v01.api.letsencrypt.org" "letsencrypt.org" ]
5}:
6
7pkgs.runCommand "letsencrypt-snakeoil-ca" {
8 nativeBuildInputs = [ pkgs.openssl ];
9} ''
10 addpem() {
11 local file="$1"; shift
12 local storeFileName="$(IFS=.; echo "$*")"
13
14 echo -n " " >> "$out"
15
16 # Every following argument is an attribute, so let's recurse and check
17 # every attribute whether it must be quoted and write it into $out.
18 while [ -n "$1" ]; do
19 if expr match "$1" '^[a-zA-Z][a-zA-Z0-9]*$' > /dev/null; then
20 echo -n "$1" >> "$out"
21 else
22 echo -n '"' >> "$out"
23 echo -n "$1" | sed -e 's/["$]/\\&/g' >> "$out"
24 echo -n '"' >> "$out"
25 fi
26 shift
27 [ -z "$1" ] || echo -n . >> "$out"
28 done
29
30 echo " = builtins.toFile \"$storeFileName\" '''" >> "$out"
31 sed -e 's/^/ /' "$file" >> "$out"
32
33 echo " ''';" >> "$out"
34 }
35
36 echo '# Generated via mkcert.sh in the same directory.' > "$out"
37 echo '{' >> "$out"
38
39 openssl req -newkey rsa:4096 -x509 -sha256 -days 36500 \
40 -subj '/CN=Snakeoil CA' -nodes -out ca.pem -keyout ca.key
41
42 addpem ca.key ca key
43 addpem ca.pem ca cert
44
45 ${lib.concatMapStrings (fqdn: let
46 opensslConfig = pkgs.writeText "snakeoil.cnf" ''
47 [req]
48 default_bits = 4096
49 prompt = no
50 default_md = sha256
51 req_extensions = req_ext
52 distinguished_name = dn
53 [dn]
54 CN = ${fqdn}
55 [req_ext]
56 subjectAltName = DNS:${fqdn}
57 '';
58 in ''
59 export OPENSSL_CONF=${lib.escapeShellArg opensslConfig}
60 openssl genrsa -out snakeoil.key 4096
61 openssl req -new -key snakeoil.key -out snakeoil.csr
62 openssl x509 -req -in snakeoil.csr -sha256 -set_serial 666 \
63 -CA ca.pem -CAkey ca.key -out snakeoil.pem -days 36500
64 addpem snakeoil.key ${lib.escapeShellArg fqdn} key
65 addpem snakeoil.pem ${lib.escapeShellArg fqdn} cert
66 '') domains}
67
68 echo '}' >> "$out"
69''