Allow using existing ACME certificates
Add a certificate scheme for using an existing ACME certificate without setting up Nginx. Also use names instead of magic numbers for certificate schemes.
This commit is contained in:
parent
42c5564791
commit
a948c49ca7
7 changed files with 49 additions and 35 deletions
50
default.nix
50
default.nix
|
@ -48,7 +48,11 @@ in
|
|||
type = types.listOf types.str;
|
||||
example = [ "imap.example.com" "pop3.example.com" ];
|
||||
default = [];
|
||||
description = "Secondary domains and subdomains for which it is necessary to generate a certificate.";
|
||||
description = ''
|
||||
({option}`mailserver.certificateScheme` == `acme-nginx`)
|
||||
|
||||
Secondary domains and subdomains for which it is necessary to generate a certificate.
|
||||
'';
|
||||
};
|
||||
|
||||
messageSizeLimit = mkOption {
|
||||
|
@ -448,19 +452,26 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
certificateScheme = mkOption {
|
||||
type = types.enum [ 1 2 3 ];
|
||||
default = 2;
|
||||
certificateScheme = let
|
||||
schemes = [ "manual" "selfsigned" "acme-nginx" "acme" ];
|
||||
translate = i: warn "setting mailserver.certificateScheme by number is deprecated, please use names instead"
|
||||
(builtins.elemAt schemes (i - 1));
|
||||
in mkOption {
|
||||
type = with types; coercedTo (enum [ 1 2 3 ]) translate (enum schemes);
|
||||
default = "selfsigned";
|
||||
description = ''
|
||||
Certificate Files. There are three options for these.
|
||||
The scheme to use for managing TLS certificates:
|
||||
|
||||
1) You specify locations and manually copy certificates there.
|
||||
2) You let the server create new (self signed) certificates on the fly.
|
||||
3) You let the server create a certificate via `Let's Encrypt`. Note that
|
||||
this implies that a stripped down webserver has to be started. This also
|
||||
implies that the FQDN must be set as an `A` record to point to the IP of
|
||||
the server. In particular port 80 on the server will be opened. For details
|
||||
on how to set up the domain records, see the guide in the readme.
|
||||
1. `manual`: you specify locations via {option}`mailserver.certificateFile` and
|
||||
{option}`mailserver.keyFile` and manually copy certificates there.
|
||||
2. `selfsigned`: you let the server create new (self-signed) certificates on the fly.
|
||||
3. `acme-nginx`: you let the server request certificates from [Let's Encrypt](https://letsencrypt.org)
|
||||
via NixOS' ACME module. By default, this will set up a stripped-down Nginx server for
|
||||
{option}`mailserver.fqdn` and open port 80. For this to work, the FQDN must be properly
|
||||
configured to point to your server (see the [setup guide](setup-guide.rst) for more information).
|
||||
4. `acme`: you already have an ACME certificate set up (for example, you're already running a TLS-enabled
|
||||
Nginx server on the FQDN). This is better than `manual` because the appropriate services will be reloaded
|
||||
when the certificate is renewed.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -468,8 +479,9 @@ in
|
|||
type = types.path;
|
||||
example = "/root/mail-server.crt";
|
||||
description = ''
|
||||
Scheme 1)
|
||||
Location of the certificate
|
||||
({option}`mailserver.certificateScheme` == `manual`)
|
||||
|
||||
Location of the certificate.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -477,8 +489,9 @@ in
|
|||
type = types.path;
|
||||
example = "/root/mail-server.key";
|
||||
description = ''
|
||||
Scheme 1)
|
||||
Location of the key file
|
||||
({option}`mailserver.certificateScheme` == `manual`)
|
||||
|
||||
Location of the key file.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -486,8 +499,9 @@ in
|
|||
type = types.path;
|
||||
default = "/var/certs";
|
||||
description = ''
|
||||
Scheme 2)
|
||||
This is the folder where the certificate will be created. The name is
|
||||
({option}`mailserver.certificateScheme` == `selfsigned`)
|
||||
|
||||
This is the folder where the self-signed certificate will be created. The name is
|
||||
hardcoded to "cert-DOMAIN.pem" and "key-DOMAIN.pem" and the
|
||||
certificate is valid for 10 years.
|
||||
'';
|
||||
|
|
|
@ -81,7 +81,7 @@ these should be the most common ones.
|
|||
|
||||
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
|
||||
# down nginx and opens port 80.
|
||||
certificateScheme = 3;
|
||||
certificateScheme = "acme-nginx";
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -21,22 +21,22 @@ let
|
|||
in
|
||||
{
|
||||
# cert :: PATH
|
||||
certificatePath = if cfg.certificateScheme == 1
|
||||
certificatePath = if cfg.certificateScheme == "manual"
|
||||
then cfg.certificateFile
|
||||
else if cfg.certificateScheme == 2
|
||||
else if cfg.certificateScheme == "selfsigned"
|
||||
then "${cfg.certificateDirectory}/cert-${cfg.fqdn}.pem"
|
||||
else if cfg.certificateScheme == 3
|
||||
else if cfg.certificateScheme == "acme" || cfg.certificateScheme == "acme-nginx"
|
||||
then "${config.security.acme.certs.${cfg.fqdn}.directory}/fullchain.pem"
|
||||
else throw "Error: Certificate Scheme must be in { 1, 2, 3 }";
|
||||
else throw "unknown certificate scheme";
|
||||
|
||||
# key :: PATH
|
||||
keyPath = if cfg.certificateScheme == 1
|
||||
keyPath = if cfg.certificateScheme == "manual"
|
||||
then cfg.keyFile
|
||||
else if cfg.certificateScheme == 2
|
||||
else if cfg.certificateScheme == "selfsigned"
|
||||
then "${cfg.certificateDirectory}/key-${cfg.fqdn}.pem"
|
||||
else if cfg.certificateScheme == 3
|
||||
else if cfg.certificateScheme == "acme" || cfg.certificateScheme == "acme-nginx"
|
||||
then "${config.security.acme.certs.${cfg.fqdn}.directory}/key.pem"
|
||||
else throw "Error: Certificate Scheme must be in { 1, 2, 3 }";
|
||||
else throw "unknown certificate scheme";
|
||||
|
||||
passwordFiles = let
|
||||
mkHashFile = name: hash: pkgs.writeText "${builtins.hashString "sha256" name}-password-hash" hash;
|
||||
|
|
|
@ -23,6 +23,6 @@ in
|
|||
config = with cfg; lib.mkIf enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
dovecot opendkim openssh postfix rspamd
|
||||
] ++ (if certificateScheme == 2 then [ openssl ] else []);
|
||||
] ++ (if certificateScheme == "selfsigned" then [ openssl ] else []);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
{ config, pkgs, lib, ... }:
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.mailserver;
|
||||
|
@ -31,7 +31,7 @@ in
|
|||
++ lib.optional enablePop3 110
|
||||
++ lib.optional enablePop3Ssl 995
|
||||
++ lib.optional enableManageSieve 4190
|
||||
++ lib.optional (certificateScheme == 3) 80;
|
||||
++ lib.optional (certificateScheme == "acme-nginx") 80;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ let
|
|||
acmeRoot = "/var/lib/acme/acme-challenge";
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (cfg.enable && cfg.certificateScheme == 3) {
|
||||
services.nginx = {
|
||||
config = lib.mkIf (cfg.enable && (cfg.certificateScheme == "acme" || cfg.certificateScheme == "acme-nginx")) {
|
||||
services.nginx = lib.mkIf (cfg.certificateScheme == "acme-nginx") {
|
||||
enable = true;
|
||||
virtualHosts."${cfg.fqdn}" = {
|
||||
serverName = cfg.fqdn;
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
let
|
||||
cfg = config.mailserver;
|
||||
certificatesDeps =
|
||||
if cfg.certificateScheme == 1 then
|
||||
if cfg.certificateScheme == "manual" then
|
||||
[]
|
||||
else if cfg.certificateScheme == 2 then
|
||||
else if cfg.certificateScheme == "selfsigned" then
|
||||
[ "mailserver-selfsigned-certificate.service" ]
|
||||
else
|
||||
[ "acme-finished-${cfg.fqdn}.target" ];
|
||||
|
@ -29,7 +29,7 @@ in
|
|||
{
|
||||
config = with cfg; lib.mkIf enable {
|
||||
# Create self signed certificate
|
||||
systemd.services.mailserver-selfsigned-certificate = lib.mkIf (cfg.certificateScheme == 2) {
|
||||
systemd.services.mailserver-selfsigned-certificate = lib.mkIf (cfg.certificateScheme == "selfsigned") {
|
||||
after = [ "local-fs.target" ];
|
||||
script = ''
|
||||
# Create certificates if they do not exist yet
|
||||
|
|
Loading…
Reference in a new issue