1
0
Fork 0
selfhostblocks/vaultwarden/default.nix

268 lines
8 KiB
Nix
Raw Normal View History

{ customPkgs
, pkgs
, utils
2023-04-04 09:18:25 +02:00
, secret
}:
{ serviceName ? "Vaultwarden"
, subdomain ? "vaultwarden"
, ingress ? 18005
, signupsAllowed ? true # signups allowed since we're behind SSO
, signupsVerify ? false
, user ? "vaultwarden"
, group ? "vaultwarden"
, dataFolder ? "/var/lib/vaultwarden"
, postgresDatabase ? "vaultwarden"
, postgresUser ? "vaultwarden"
, postgresPasswordLocation ? "vaultwarden"
, webvaultEnabled ? true
, webvaultPath ? "/usr/share/webapps/vaultwarden"
2023-01-30 05:22:57 +01:00
, cookieSecretName ? "cookiesecret"
, clientSecretName ? "clientsecret"
, smtp ? {}
, sso ? {}
, distribution ? {}
2023-02-12 06:28:00 +01:00
, KeycloakService ? null
, KeycloakCliService ? null
, HaproxyService ? null
}:
let
mkVaultwardenWeb = pkgs.callPackage ./web.nix {inherit utils;};
2023-01-30 05:22:57 +01:00
ssoIngress = if sso != {} then ingress else null;
serviceIngress = if sso != {} then ingress+1 else ingress;
2023-02-12 06:28:00 +01:00
metricsPort = if sso != {} then ingress+2 else ingress+1;
2023-01-30 05:22:57 +01:00
smtpConfig = smtp;
in
rec {
inherit user group;
2023-02-19 22:36:18 +01:00
inherit subdomain;
db = customPkgs.mkPostgresDB {
name = "${serviceName}PostgresDB";
database = postgresDatabase;
username = postgresUser;
# TODO: use passwordFile
password = postgresPasswordLocation;
};
web = mkVaultwardenWeb {
name = "${serviceName}Web";
path = webvaultPath;
};
service = let
name = "${serviceName}Service";
domain = utils.getDomain distribution name;
pkgsVaultwarden-1_27_0 =
let pkg = builtins.fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/988cc958c57ce4350ec248d2d53087777f9e1949/pkgs/tools/security/vaultwarden/default.nix";
sha256 = "0hwjbq5qb8y5frb2ca3m501x84zaibzyn088zzaf7zcwkxvqb0im";
};
in pkgs.callPackage pkg {
inherit (pkgs.darwin.apple_sdk.frameworks) Security CoreServices;
dbBackend = "postgresql";
};
in {
inherit name;
2023-01-22 18:02:46 +01:00
pkg =
{ db
, web
2023-01-22 18:02:46 +01:00
}: let
postgresHost = db.target.properties.hostname;
in utils.systemd.mkService rec {
name = "vaultwarden";
content = ''
[Unit]
Description=Vaultwarden Server
Documentation=https://github.com/dani-garcia/vaultwarden
After=network.target
2023-01-30 05:22:57 +01:00
After=${utils.keyServiceDependencies smtpConfig.keys}
Wants=${utils.keyServiceDependencies smtpConfig.keys}
2023-01-22 18:02:46 +01:00
[Service]
Environment=DATA_FOLDER=${dataFolder}
Environment=DATABASE_URL=postgresql://${postgresUser}:${postgresPasswordLocation}@${postgresHost}/${postgresDatabase}
Environment=IP_HEADER=X-Real-IP
Environment=WEB_VAULT_FOLDER=${web.path}
Environment=WEB_VAULT_ENABLED=${if webvaultEnabled then "true" else "false"}
Environment=SIGNUPS_ALLOWED=${if signupsAllowed then "true" else "false"}
Environment=SIGNUPS_VERIFY=${if signupsVerify then "true" else "false"}
# Disabled because the /admin path is protected by SSO
Environment=DISABLE_ADMIN_TOKEN=true
Environment=INVITATIONS_ALLOWED=true
Environment=DOMAIN=https://${subdomain}.${domain}
# Assumes we're behind a reverse proxy
Environment=ROCKET_ADDRESS=127.0.0.1
2023-01-30 05:22:57 +01:00
Environment=ROCKET_PORT=${builtins.toString serviceIngress}
2023-01-22 18:02:46 +01:00
Environment=USE_SYSLOG=true
Environment=EXTENDED_LOGGING=true
Environment=LOG_FILE=
Environment=LOG_LEVEL=trace
2023-01-30 05:22:57 +01:00
${utils.keyEnvironmentFiles smtpConfig.keys}
Environment=SMTP_FROM=${smtpConfig.from}
Environment=SMTP_FROM_NAME=${smtpConfig.fromName}
Environment=SMTP_PORT=${builtins.toString smtpConfig.port}
Environment=SMTP_AUTH_MECHANISM=${smtpConfig.authMechanism}
2023-01-22 18:02:46 +01:00
ExecStart=${pkgsVaultwarden-1_27_0}/bin/vaultwarden
2023-01-22 18:02:46 +01:00
WorkingDirectory=${dataFolder}
StateDirectory=${name}
User=${user}
Group=${group}
# Allow vaultwarden to bind ports in the range of 0-1024 and restrict it to
# that capability
2023-01-30 05:22:57 +01:00
CapabilityBoundingSet=${if serviceIngress <= 1024 then "CAP_NET_BIND_SERVICE" else ""}
AmbientCapabilities=${if serviceIngress <= 1024 then "CAP_NET_BIND_SERVICE" else ""}
2023-01-22 18:02:46 +01:00
PrivateUsers=yes
NoNewPrivileges=yes
LimitNOFILE=1048576
UMask=0077
ProtectSystem=strict
ProtectHome=yes
# ReadWritePaths=${dataFolder}
PrivateTmp=yes
PrivateDevices=yes
ProtectHostname=yes
ProtectClock=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RemoveIPC=yes
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.target
'';
};
dependsOn = {
inherit db;
inherit web;
};
type = "systemd-unit";
};
haproxy = service: {
frontend = {
acl = {
acl_vaultwarden = "hdr_beg(host) vaultwarden.";
};
use_backend = "if acl_vaultwarden";
};
backend = {
2023-01-01 00:18:51 +01:00
# TODO: instead, we should generate target specific service https://hydra.nixos.org/build/203347995/download/2/manual/#idm140737322273072
servers = map (dist: {
2023-01-22 18:02:46 +01:00
name = "vaultwarden_${dist.properties.hostname}_1";
# TODO: should use the hostname
# address = "${dist.properties.hostname}:${builtins.toString ingress}";
address = "127.0.0.1:${builtins.toString ingress}";
resolvers = "default";
2023-01-01 00:18:51 +01:00
}) service;
};
};
2023-02-12 06:28:00 +01:00
oauth2Proxy =
let
name = "${serviceName}Oauth2Proxy";
in customPkgs.mkOauth2Proxy {
inherit name;
serviceName = subdomain;
domain = utils.getDomain distribution name;
2023-02-19 22:36:18 +01:00
keycloakSubdomain = KeycloakService.subdomain;
keycloakDomain = utils.getDomain distribution "KeycloakService";
2023-02-12 06:28:00 +01:00
ingress = "127.0.0.1:${toString ssoIngress}";
egress = [ "http://127.0.0.1:${toString serviceIngress}" ];
realm = sso.realm;
allowed_roles = [ "user" "/admin|admin" ];
skip_auth_routes = [
"^/api"
"^/identity/connect/token"
"^/identity/accounts/prelogin"
];
2023-02-12 06:28:00 +01:00
inherit metricsPort;
keys = {
cookieSecret = "${serviceName}_oauth2proxy_cookiesecret";
clientSecret = "${serviceName}_oauth2proxy_clientsecret";
};
inherit distribution HaproxyService KeycloakService KeycloakCliService;
2023-01-30 05:22:57 +01:00
};
keycloakCliConfig = {
clients = {
vaultwarden = {
2023-02-12 06:28:00 +01:00
resourcesUris = {
adminPath = ["/admin/*"];
userPath = ["/*"];
};
access = {
admin = {
roles = [ "admin" ];
resources = [ "adminPath" ];
};
user = {
roles = [ "user" ];
resources = [ "userPath" ];
};
};
};
};
};
2023-01-29 01:01:04 +01:00
2023-02-05 09:27:09 +01:00
deployKeys = domain: {
2023-01-30 05:22:57 +01:00
"${serviceName}_oauth2proxy_cookiesecret".text = ''
2023-04-04 09:18:25 +02:00
OAUTH2_PROXY_COOKIE_SECRET="${secret "${domain}/${subdomain}/${cookieSecretName}"}"
2023-01-30 05:22:57 +01:00
'';
"${serviceName}_oauth2proxy_clientsecret".text = ''
2023-04-04 09:18:25 +02:00
OAUTH2_PROXY_CLIENT_SECRET="${secret "${domain}/${subdomain}/${clientSecretName}"}"
2023-01-30 05:22:57 +01:00
'';
"${serviceName}_smtp_all".text = ''
2023-04-04 09:18:25 +02:00
SMTP_HOST="${secret "${domain}/mailgun.com/smtp_hostname"}"
SMTP_USERNAME="${secret "${domain}/mailgun.com/smtp_login"}"
SMTP_PASSWORD="${secret "${domain}/mailgun.com/password"}"
2023-01-30 05:22:57 +01:00
'';
};
smtp.keys.setup = "${serviceName}_smtp_all";
2023-01-29 01:01:04 +01:00
services = {
${db.name} = db;
${web.name} = web;
${service.name} = service;
2023-02-12 06:28:00 +01:00
${oauth2Proxy.name} = oauth2Proxy;
2023-01-29 01:01:04 +01:00
};
distribute = on: {
${db.name} = on;
${web.name} = on;
${service.name} = on;
2023-02-12 06:28:00 +01:00
${oauth2Proxy.name} = on;
2023-01-29 01:01:04 +01:00
};
}