2017-06-27 16:54:25 +02:00
|
|
|
{ config, lib, pkgs, ... }:
|
2017-06-07 22:31:40 +02:00
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.services.vault;
|
2017-06-27 16:54:25 +02:00
|
|
|
|
2017-06-07 22:31:40 +02:00
|
|
|
configFile = pkgs.writeText "vault.hcl" ''
|
|
|
|
listener "tcp" {
|
2017-06-27 16:54:25 +02:00
|
|
|
address = "${cfg.address}"
|
|
|
|
tls_cert_file = "${cfg.tlsCertFile}"
|
|
|
|
tls_key_file = "${cfg.tlsKeyFile}"
|
|
|
|
${cfg.listenerExtraConfig}
|
2017-06-07 22:31:40 +02:00
|
|
|
}
|
2017-06-27 16:54:25 +02:00
|
|
|
storage "${cfg.storageBackend}" {
|
|
|
|
${cfg.storageConfig}
|
2017-06-07 22:31:40 +02:00
|
|
|
}
|
2017-06-27 16:54:25 +02:00
|
|
|
${optionalString (cfg.telemetryConfig != "") ''
|
|
|
|
telemetry {
|
|
|
|
${cfg.telemetryConfig}
|
|
|
|
}
|
|
|
|
''}
|
2017-06-07 22:31:40 +02:00
|
|
|
'';
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
|
|
|
|
services.vault = {
|
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
enable = mkEnableOption "Vault daemon";
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
address = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "127.0.0.1:8200";
|
|
|
|
description = "The name of the ip interface to listen to";
|
2017-06-07 22:31:40 +02:00
|
|
|
};
|
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
tlsCertFile = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "/etc/vault/cert.pem";
|
|
|
|
example = "/path/to/your/cert.pem";
|
|
|
|
description = "TLS certificate file. A self-signed certificate will be generated if file not exists";
|
2017-06-07 22:31:40 +02:00
|
|
|
};
|
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
tlsKeyFile = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "/etc/vault/key.pem";
|
|
|
|
example = "/path/to/your/key.pem";
|
|
|
|
description = "TLS private key file. A self-signed certificate will be generated if file not exists";
|
|
|
|
};
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
listenerExtraConfig = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
default = ''
|
|
|
|
tls_min_version = "tls12"
|
|
|
|
'';
|
|
|
|
description = "extra configuration";
|
|
|
|
};
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
storageBackend = mkOption {
|
2017-06-27 21:32:11 +02:00
|
|
|
type = types.enum ["inmem" "inmem_transactional" "inmem_ha" "inmem_transactional_ha" "file_transactional" "consul" "zookeeper" "file" "s3" "azure" "dynamodb" "etcd" "mssql" "mysql" "postgresql" "swift" "gcs"];
|
2017-06-27 16:54:25 +02:00
|
|
|
default = "inmem";
|
|
|
|
description = "The name of the type of storage backend";
|
|
|
|
};
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
storageConfig = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
description = "Storage configuration";
|
2017-06-27 21:32:11 +02:00
|
|
|
default = if (cfg.storageBackend == "file" || cfg.storageBackend == "file_transactional") then ''
|
|
|
|
path = "/var/lib/vault"
|
|
|
|
'' else ''
|
|
|
|
'';
|
2017-06-07 22:31:40 +02:00
|
|
|
};
|
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
telemetryConfig = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
default = "";
|
|
|
|
description = "Telemetry configuration";
|
|
|
|
};
|
2017-06-07 22:31:40 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2017-06-28 03:15:20 +02:00
|
|
|
config = let
|
|
|
|
localDir = if (cfg.storageBackend == "file" || cfg.storageBackend == "file_transactional") then
|
|
|
|
let
|
|
|
|
matched = builtins.match ''.*path[ ]*=[ ]*"([^"]+)".*'' (toString cfg.storageConfig);
|
|
|
|
in
|
|
|
|
if matched == null then
|
|
|
|
throw ''`storageBackend` "${cfg.storageBackend}" requires path in `storageConfig`''
|
|
|
|
else
|
|
|
|
head matched
|
|
|
|
else
|
|
|
|
null;
|
|
|
|
in mkIf cfg.enable {
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
users.extraUsers.vault = {
|
|
|
|
name = "vault";
|
|
|
|
group = "vault";
|
|
|
|
uid = config.ids.uids.vault;
|
|
|
|
description = "Vault daemon user";
|
|
|
|
};
|
|
|
|
users.extraGroups.vault.gid = config.ids.gids.vault;
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
systemd.services.vault = {
|
|
|
|
description = "Vault server daemon";
|
2017-06-07 22:31:40 +02:00
|
|
|
|
2017-06-27 16:54:25 +02:00
|
|
|
wantedBy = ["multi-user.target"];
|
2017-06-28 02:58:19 +02:00
|
|
|
after = [ "network.target" ]
|
|
|
|
++ optional (config.services.consul.enable && cfg.storageBackend == "consul") "consul.service";
|
2017-06-27 16:54:25 +02:00
|
|
|
|
2017-06-28 03:15:20 +02:00
|
|
|
preStart = optionalString (localDir != null) ''
|
|
|
|
install -d -m0700 -o vault -g vault "${localDir}"
|
|
|
|
'' + ''
|
2017-06-27 16:54:25 +02:00
|
|
|
# generate a self-signed certificate, you will have to set environment variable "VAULT_SKIP_VERIFY=1" in the client
|
|
|
|
if [ ! -s ${cfg.tlsCertFile} -o ! -s ${cfg.tlsKeyFile} ]; then
|
|
|
|
mkdir -p $(dirname ${cfg.tlsCertFile}) || true
|
|
|
|
mkdir -p $(dirname ${cfg.tlsKeyFile }) || true
|
|
|
|
${pkgs.openssl.bin}/bin/openssl req -x509 -newkey rsa:2048 -sha256 -nodes -days 99999 \
|
|
|
|
-subj /C=US/ST=NY/L=NYC/O=vault/CN=${cfg.address} \
|
|
|
|
-keyout ${cfg.tlsKeyFile} -out ${cfg.tlsCertFile}
|
|
|
|
|
|
|
|
chown root:vault ${cfg.tlsKeyFile} ${cfg.tlsCertFile}
|
|
|
|
chmod 440 ${cfg.tlsKeyFile} ${cfg.tlsCertFile}
|
|
|
|
fi
|
|
|
|
'';
|
|
|
|
|
|
|
|
serviceConfig = {
|
|
|
|
User = "vault";
|
|
|
|
Group = "vault";
|
|
|
|
PermissionsStartOnly = true;
|
|
|
|
ExecStart = "${pkgs.vault}/bin/vault server -config ${configFile}";
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
ProtectSystem = "full";
|
|
|
|
ProtectHome = "read-only";
|
|
|
|
AmbientCapabilities = "cap_ipc_lock";
|
|
|
|
NoNewPrivileges = true;
|
|
|
|
KillSignal = "SIGINT";
|
|
|
|
TimeoutStopSec = "30s";
|
|
|
|
Restart = "on-failure";
|
|
|
|
StartLimitInterval = "60s";
|
|
|
|
StartLimitBurst = 3;
|
|
|
|
};
|
2017-06-28 03:15:20 +02:00
|
|
|
|
|
|
|
unitConfig.RequiresMountsFor = optional (localDir != null) localDir;
|
2017-06-27 16:54:25 +02:00
|
|
|
};
|
2017-06-07 22:31:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|