feat(bw): vaultwarden

This commit is contained in:
arcnmx 2024-05-26 14:04:19 -07:00
parent 0b0a91d506
commit 0947ca0532
15 changed files with 437 additions and 7 deletions

View file

@ -92,7 +92,10 @@ in {
prepKeyEnvironment = pkgs.writeShellScript "barcodebuddy-scanner-apikey.sh" ''
set -eu
printf "API_KEY=$(cat $API_KEY_PATH)\\n" > $RUNTIME_DIRECTORY/${apiKeyFile}
printf "" > $RUNTIME_DIRECTORY/${apiKeyFile}
chmod 0640 $RUNTIME_DIRECTORY/${apiKeyFile}
printf "API_KEY=$(cat $API_KEY_PATH)\\n" >> $RUNTIME_DIRECTORY/${apiKeyFile}
'';
in {
wantedBy = [

View file

@ -0,0 +1,86 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.modules) mkIf mkOptionDefault;
inherit (lib.attrsets) attrNames filterAttrs mapAttrs' nameValuePair;
inherit (lib.strings) concatMapStringsSep;
cfg = config.services.vaultwarden;
RuntimeDirectory = "bitwarden_rs";
secretsFile = "secrets.env";
in {
options.services.vaultwarden = with lib.types; {
port = mkOption {
type = port;
default = 8222;
};
websocketPort = mkOption {
type = nullOr port;
default = null;
};
databaseUrlPath = mkOption {
type = nullOr str;
default = null;
};
adminTokenPath = mkOption {
type = nullOr str;
default = null;
};
smtpPasswordPath = mkOption {
type = nullOr str;
default = null;
};
};
config.services.vaultwarden = {
config = {
DATA_FOLDER = mkOptionDefault "/var/lib/bitwarden_rs";
WEB_VAULT_ENABLED = mkOptionDefault true;
ROCKET_ENV = mkOptionDefault "production";
ROCKET_ADDRESS = mkOptionDefault "::1";
ROCKET_PORT = mkOptionDefault cfg.port;
WEBSOCKET_ENABLED = mkOptionDefault (cfg.websocketPort != null);
WEBSOCKET_ADDRESS = mkOptionDefault "::1";
WEBSOCKET_PORT = mkIf (cfg.websocketPort != null) cfg.websocketPort;
};
};
config.systemd.services.vaultwarden = let
filterNullAttrs = filterAttrs (_: v: v != null);
secretPaths' = {
DATABASE_URL = cfg.databaseUrlPath;
ADMIN_TOKEN = cfg.adminTokenPath;
SMTP_PASSWORD = cfg.smtpPasswordPath;
};
secretPaths = filterNullAttrs secretPaths';
hasSecrets = secretPaths != {};
mkPrintSecret = key: let
path = "${key}_PATH";
in ''
if [[ -n ''${${path}-} ]]; then
printf "${key}=$(cat ''${${path}})\\n" >> $RUNTIME_DIRECTORY/${secretsFile}
fi
'';
prepSecrets = pkgs.writeShellScript "vaultwarden-secrets.sh" ''
set -eu
printf "" > $RUNTIME_DIRECTORY/${secretsFile}
chmod 0640 $RUNTIME_DIRECTORY/${secretsFile}
${concatMapStringsSep "\n" mkPrintSecret (attrNames secretPaths')}
'';
in
mkIf cfg.enable {
environment = mkIf hasSecrets (mapAttrs' (key: nameValuePair "${key}_PATH") secretPaths);
serviceConfig = {
inherit RuntimeDirectory;
EnvironmentFile = mkIf hasSecrets [
"-/run/${RuntimeDirectory}/${secretsFile}"
];
ExecStartPre = mkIf hasSecrets [
"${prepSecrets}"
];
};
};
}

View file

@ -0,0 +1,41 @@
{
lib,
gensokyo-zone,
...
}: let
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
inherit (lib.modules) mkIf;
inherit (lib.attrsets) mapAttrs;
in {
config.exports.services.vaultwarden = {config, ...}: {
id = mkAlmostOptionDefault "bw";
defaults.port.listen = mkAlmostOptionDefault "lan";
nixos = {
serviceAttr = "vaultwarden";
assertions = mkIf config.enable [
(nixosConfig: {
assertion = config.ports.default.port == nixosConfig.services.vaultwarden.port;
message = "port mismatch";
})
(nixosConfig: {
assertion = nixosConfig.services.vaultwarden.websocketPort == null || config.ports.websocket.port == nixosConfig.services.vaultwarden.websocketPort;
message = "websocketPort mismatch";
})
(nixosConfig: {
assertion = config.ports.websocket.enable == (nixosConfig.services.vaultwarden.websocketPort != null);
message = "websocketPort enable mismatch";
})
];
};
ports = mapAttrs (_: mapAlmostOptionDefaults) {
default = {
port = 8222;
protocol = "http";
};
websocket = {
port = 8223;
protocol = "http";
};
};
};
}

View file

@ -0,0 +1,80 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault;
cfg = config.services.vaultwarden;
upstreamName = "vaultwarden'access";
upstreamName'websocket = "vaultwarden'websocket'access";
locations = {
"/".proxy.enable = true;
"/notifications/hub" = {
proxy = {
enable = true;
upstream = mkDefault upstreamName'websocket;
websocket.enable = true;
};
};
"/notifications/hub/negotiate" = {
proxy = {
enable = true;
websocket.enable = true;
};
};
};
name.shortServer = mkDefault "bw";
copyFromVhost = mkDefault "vaultwarden";
in {
config.services.nginx = {
upstreams' = {
${upstreamName}.servers = {
local = mkIf cfg.enable {
enable = mkDefault true;
addr = mkDefault "localhost";
port = mkDefault cfg.port;
};
access = {upstream, ...}: {
enable = mkDefault (!upstream.servers.local.enable or false);
accessService = {
name = "vaultwarden";
};
};
};
${upstreamName'websocket}.servers = {
local = mkIf cfg.enable {
enable = mkDefault (cfg.websocketPort != null);
addr = mkDefault "localhost";
port = mkIf (cfg.websocketPort != null) (mkDefault cfg.websocketPort);
};
access = {upstream, ...}: {
enable = mkDefault (!cfg.enable && !upstream.servers.local.enable or false);
accessService = {
name = "vaultwarden";
port = "websocket";
};
};
};
};
virtualHosts = {
vaultwarden = {
inherit name locations;
ssl.force = mkDefault true;
proxy.upstream = mkDefault upstreamName;
};
vaultwarden'local = {
inherit name locations;
ssl = {
force = mkDefault true;
cert = {
inherit copyFromVhost;
};
};
local.enable = true;
proxy = {
inherit copyFromVhost;
};
};
};
};
}

View file

@ -9,7 +9,7 @@
in {
services.postgresql = {
enable = mkDefault true;
ensureDatabases = ["hass" "invidious" "dex" "keycloak"];
ensureDatabases = ["hass" "invidious" "dex" "keycloak" "vaultwarden"];
ensureUsers = [
{
name = "hass";
@ -19,7 +19,7 @@ in {
{
name = "invidious";
ensureDBOwnership = true;
authentication.int.allow = true;
authentication.int.allow = !config.services.invidious.enable;
}
{
name = "dex";
@ -29,7 +29,12 @@ in {
{
name = "keycloak";
ensureDBOwnership = true;
authentication.int.allow = true;
authentication.int.allow = !config.services.keycloak.enable;
}
{
name = "vaultwarden";
ensureDBOwnership = true;
authentication.int.allow = !config.services.vaultwarden.enable;
}
];
};

View file

@ -1,4 +1,4 @@
postgresql-init: ENC[AES256_GCM,data:lbkeMv6PZgB7tEl4VbIYX9VUAgJ6Kcj0jLNyyqxJJcVJPjo1lF2d/i5bFnU1/6aJ2T7ftMW4hefYgrnIMdKXxPPfrHftaEMhl9bfJIsuX2I1CXAasZOhpsmg9Wf2cvXuVYIlqTVssg+3EKW0ejCMdX6OfGdAXvBlio1DQs7YrUc+BjDiEuAUAaaYbz67EYY3dpYQixQGl/8G2w7S897uCXpc1oOh6vbGY4Nl+GGQ7B5xrrbYcdATwfGyYlZYSlIv8feDsLv7Rt+w3o4tTAxcz+8qZ7KZ6sIsu/nUoYeqoT9MJ8uRpWccXKcBVAFSEooUIHUEBA/QsGizAXBgzCnyLDvuv3DOquo2xeMg0kWM8zsF1f9YRyUKqQ==,iv:RKIvggRZlPocygabF0iKNBThBRFG5rlzrIvGjjt7s0o=,tag:U/XUDJs5J8lHB9BJ5/0fFA==,type:str]
postgresql-init: ENC[AES256_GCM,data:hsSiYNQy9G/zw+XVGW2ewu9/5pz9QobrpOZ/3a00pjtbW03Yn7t2NlELMKsz1cLkkzSfvLQC7hVCONNrlxMYc0zOIhGNH4rpY8FzMa5q2oXmouO5zE2wYqBTjx/9KezXrRJv32g0s4wxP7RoBBC9fRqbOmYrXQJZQZDV7kze6NdXv0WtvAwp54/szG5TeQkXymNP+TKtI9qV8EMBcSXze5Gr2ia625TSYvY7/cbOTeMvOaQ9Y1SKm1G10dLwIxE2Wolc/qOs0kzUzT7ZLPAo8TSW3vBCojMv1xZahF7M7PGQih4gR8XMZLvAVRrUBfVuZpbWcvqijgTjqhn5wegBL8RI0ry/Dw07Cx/31+9Zcwtqt0l3LDM56XFYFBKY/oscsbhd1RAKcK2iPI9HXWB5Jipu6B0OLJd7CWWcuCrPP2YjKJVyDVR0Sgrnc0bcefXJs/5e+1yNzeorbvPtIvxItLeeoQ==,iv:sauPtv+SK7T/+T1gXO7RjAeLwH3nKJgf8d8tPBbVWgw=,tag:6ZtuRsPvL9+Y8CUNHqmrgg==,type:str]
sops:
shamir_threshold: 1
kms: []
@ -78,8 +78,8 @@ sops:
NVg3YVJ0eDFDZTZuSjIzdlVWZnI0OVUKMZ0vG0GIfyGtmNZQ6C94bABpI6Fb6VVJ
8vGv1rf2kxJXy9dktQs1pvgP6CD1ZQu9qCGvd+UjQgrgmqy0HABhKA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-03-13T21:46:56Z"
mac: ENC[AES256_GCM,data:rEtRHX3PH1B+uoR82lDH3ACKHPbhxy+y7B9YgR6TzPSU4yIaTSqSK51eLJZoUtW6UTl6QDcTrsKDA8lGu9M/Ohfx8ayp6rkX63H/hkl0h6YaQmWDAQoNAAEWqfJ9r8O8tKKpE6qF/rw4c4KpuA5ONufOl9qj1KSgFzz0WHaKtWk=,iv:TUBAe62dmF6FAjZOPaxwzQjWL21TdWQG0YyuXJGgtk8=,tag:dewWivfnZO30Np2gajwLIw==,type:str]
lastmodified: "2024-05-26T19:56:47Z"
mac: ENC[AES256_GCM,data:6GHSGv54tO4SH7fb1ud4Zrht+ncmEyaVVByppEFPbm4e0cUHr0/sM06dfaB8baoM0knA2VlJRJE1zpfANYmYHbtGBDqHW0yhmh9UhwQFUUah9LjNXdsiPzTLPUq3vuaadO1BnPiZEqk1lToVNr3LN+V4LaD3nLMVRSp1dGhgCNk=,iv:9IrRC1UlYZpY/K2kDiHXhIydR5qBo94p0odS/WnAZZA=,tag:0wVyXa06MWP6xFh6ebUb+w==,type:str]
pgp:
- created_at: "2024-03-21T17:42:39Z"
enc: |-

View file

@ -0,0 +1,139 @@
vaultwarden-database-url: ENC[AES256_GCM,data:S1VaNmBE1ZRvxxDOpRLS5K5bZ6YqzKD7Gw1fd8lzkv8iHfirdMb6fiJS37+z2yMmgGFktO7nLoy+y05yxTzpECAtlhfwQtuahKCS7g8HT27sVAB/oILmfVAYzm51uVQViII=,iv:2uvFAht47GSNQYyljqvJlGcN09vdJAEPKWsIPuYgIYE=,tag:CptCKjyBNv/eHd6kVhNbiQ==,type:str]
vaultwarden-admin-token: ENC[AES256_GCM,data:aGJpvhYKU/BnjH9QaSCuvpCEVWaCI39EXY7pN3BCmqmFhueze6XNodcmcNmtdrKJrGf8fibi01kO4zzBN1LSEw==,iv:tOpEn1ipuVMXV8PQ40jFtCbfVhLKcLK2wwfzJuK+7ic=,tag:ZRK/F2JijQgjof94bSu0CQ==,type:str]
sops:
shamir_threshold: 1
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age12ze362pu5mza6ef9akrptr7hfe4auaqul4rkta7kyy2tnrstqensgmujeq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArTkpmTzg2TVNkUzN1anhn
Tm9uVXlwTlJnTFdqNFMrODhRYW1lWnlFcEhBCnVrTjhWZWpFMUR6MDZXZUIwVXZB
L1JWZFRZcGt0cDBlU2ZVeXNjSEszSFEKLS0tIHZRSEJPamlsRTRjV05JWUFkcWZL
UmIwbU5yTkltYWRnbVlXcTR3RGFCajAKiwxNJsd9UNFBarTTGNQBz9tx6OKWLFO0
WCsMtiNwJcxOtBTcLL1GwalwOCnN2Cc9xy37V/4np5dQL8d22EegjQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age176uyyyk7veqnzmm8xzwfhf0u23m6hm02cldlfkldunqe6std0gcq6lg057
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvTDlhWDE3WGxybTNTQVZk
WE04VmI4MFJnMzdLRmdJcWlxOTVOa2pNL0VBCkFHS21UcDZ2VTUwdUNUK1NjQWdl
MFcySERHdGU4SjlkdUZ6VTg0QlNxdWcKLS0tIGFZYVYwelA2Q1JuTWVvdUpJR0pL
ZW9YakoxSGRBa3J2YUlaOEFFd25BSVEKyObsLBi3Jkyu8GIbuTFZQU7l2plH6zS0
TF1lBGu8dSgZicGUqhspC0BvXPd1GtIxBXpT3RCc4mK8HITirT2AjQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age15hmlkd9p5rladsjzpmvrh6u34xvggu9mzdsdxdj3ms43tltxeuhq4g7g9k
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrU0FWVDFwcUdFazByYjBM
YWVYTWZBVzM0T1NqbEpGZVVKR2pJVWxhVGtRCng2eXlWdmF3RzREQ2RTeTNVTWM2
cDFoYW9FdTBqcURjdmlZN3pHQ0ZxU2sKLS0tIDFxUHhSTlI4clZJcEE5a3kzSXo4
aVdXM1pQREFjcFJIR3FDdGcvVHQrbzgKu98WWiatWhlBvPNQsZMiI1NMXpwBlxlo
GhP85QXIUa4V1BWSvmnRw9ljYrpviFBFLmk7sZOLpJoJzcsjIRLMnA==
-----END AGE ENCRYPTED FILE-----
- recipient: age10t6kc5069cyky929vvxk8aznqyxpkx3k5h5rmlyz83xtjmr22ahqe8mzes
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuMSsrMHNXN3BGNlF2Zkd6
bTdNV2dNSDhmK1NtTDFkMklRVkhwY2dyQjE4CnNQd1NmT0sxUXZBeUlRQWVTQU5z
ZkVCbW5WYjB6RHpOU1NpWGtOSHAycE0KLS0tIHRVaUtFWW5CbS9ZRVRUeWVKVFRh
WHBJaTVENW9uUmNZTDE5L0NhZG5NL3MKqwcV1HZs21z895ujeLHNHHCgDMNztdTG
zQYhqgQ7P7S/ykT8a2Qc/Y2SLIo2ECX5wSV+a+vWkpTaJSf4hp0yLg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1a2quf2ekkj94ygu7wgvhrvh44fwn32c0l2cwvgvjh23wst90s54szdsvgr
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGcW9ualNLNjQrOTlGcjQr
UzNoYkp3a1JYSUpYZEdYNXdNOERRcVNqb0dVCndGSmtCNGdZdEpBcTI4NTduVUFk
NytqRnVUYXFadjhyUkdVbWtOOUwzb2sKLS0tIHVLNHl0dHdLRkFXa1phWkR2VFVY
SmNORjRlMHVzQm9nLy9TTURtcndQMlkKRn2ldZek0F8l+KiUvikcvi/oudO7byPK
xYhs9QrZS0CmE94k7cYrI2yE7TdwE03BcSY2Sv90F06uSdHdRnBFqQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age16klpkaut5759dut8mdm3jn0rnp8w6kxyvs9n6ntqrdsayjtd7upqlvw489
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJY1lhMWFsaXNUSFFWRHNK
WVVxeVB4VkVpTWFkVndZdSthVDAwY295Um1jCjdXa05uSFMwTXBacmYyZmZFeXNM
RnBjWjA0aUVQaVJIUTNIb3FmUERMR2sKLS0tIGRBZlRTekVrenIrZU5kKzVVOURi
ckcvRXdSbGMxUTRzb1ovNUI2R0JEc00K1NodlRscDSzyJvOvLLDQ/csQ9bNNIcrZ
LS3CegfUNASprO+k3/L+5laAm0WYpgZL5YFbgzh8zs+s0Q9R2e7Qqg==
-----END AGE ENCRYPTED FILE-----
- recipient: age13qgddr326g5je0fpq2r3k940vsr3fh9nlvl9xtcxk3xg2x0k3vsq7pvzaj
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxY2xSaW51dVpEOHcwbkli
dDNNQk1aVFM5Z0gvVHR1WVpaY0t6YWt0UXdnCkEyZ2Y5OThPZmRNK3I4eW1sc0RY
M3Z1OExkTnAwRzBmVndDMVZyYjJzbUUKLS0tIFZNWG1TdkVpZ1UzL2owQ0gvS1NM
c25Zb0xkUlZKNE9lRHdSekVjRWtUYVEK5A4L6xhv4OMrEXPJfcRO2BDuQ591DSb+
4AJ5Sy/dwecZ1O/j7HvPwb6i/euXtDDLMjh+5m0G5tx3TpUtmO4nEg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ktmx2szedfnpe5xumnzs8vkk0ffqgga6ved3drtksg9pye6ndsnsnqq488
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpajhMK1p2YU5iakUyYzVR
TkdFSWVFZ3VJRXI2Z1ljU0FvalIvU1M0TlVrCmNEVUJyV1ZURy9TUHJHMkc5cWZ0
YVhoMFl4U0NqdUl1V1lNdGh0K0RjalEKLS0tIDQyV2g1SkhuVHFMY0toWFg3NWVo
UDNIYnpKcncrYWNTRlIzbHZUVk9WOE0Kbko4KSTQSqIjET6iBnaYyRI749QfQGEk
/5IZGBQdhERaeU4WCm0UHxyyiEyUbfmCJYQrxdxaRzVVEX2lJQddtQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1fjcafp0j45sz03zq5srnxyq2mujndmn25vceg3wj2cgzymqm73ssmhdgku
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBycWJSbXZiK0VHTjRlMjJT
enUxRmM1QjVEVHFSYWM1Y1VPSEdsdXZBNFZBCjFWM2ZjdFV6TWhkZnZ3ZlVFT2Jm
SHRwTE05RFgyUGhwZVp6ODJiRXlSOGsKLS0tIDdnZTFNTGNFdnV3NGJKbG9Fb0lB
UXg2N0xKUml4dy9SOGN3NGRYa3JRN28K4+tqEeK+TuLuSFbC/Cu7K+jMK2tx96FG
RJ+Y3tOJTt4jd66jwrslcyyZmWHhDSajVnsYWBy6XQPBGqPd6RYkhQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1tkkau8vk5h9dh3kemash4eghn7lk84j0hhpmvvf7j6phgcsm9vmsphv0py
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaUDNvMGs2QUt1VE9uVjdH
OCtjbkxRTWpRTFhzY2gySjNzb1BmMFk1dXhJCjZpV1lTU1ltTFZlQitucGN2cGli
VW9IdnRFRnN5cDdoYXVjQUtFVlBFckEKLS0tIEhrdnp3blFyajN4OTRCZDVmeXJs
QTZ0Y2NrYi9WbGpCd0d1dHRqS1AzYk0K2TgpwYN+rcnoxURWJeQe3JlKXTRg2reR
6+DgdrZ/geJbKVmCQkeCxxbMU1zUqpbB9B8AxsunsiKhdZnohm5NYw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-05-26T20:29:52Z"
mac: ENC[AES256_GCM,data:5rt1+feYuDESuYd/MpD+Dcf0SPjgaetWFq3ZoH9Fb6tE+2I183wQzMLO/ToxGP+Ea2o8Z/FbPesZ9P6hmKzLpHQdEhSmfilpCU0LYr98ze+9xFzuHfUWJ5u4ZZZ8uqZ7U7wW3GKM0YBtihSNBN/LF+gKUazC9pLZ/IoQEmvTwxs=,iv:O6EAod7lCtwalVw2xOYDu8Ifnb99YsL6C+hO0zngOj4=,tag:uN5z7lighvrSyjHYDSW2Hg==,type:str]
pgp:
- created_at: "2024-05-26T20:06:39Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA82M54yws73UAQ/+Nfgm6hU+WiiRLwJdyPO8iWnPjB4ELWcmQw7I/QLg4jti
4vGMyGq+F6v4nZorvsmk/OVde2rTUvKmENCy6Bh1/TbfHxSCJkJJi1L8oxZiwA3M
oJoC5usQ5K0kWPiHZgsjHNiEGsPfSO8FBV+ipYYzPpXsBKNS+jg4Lv+kkRga1TUx
lky2ffJmjrjLp3In+EicnQIt7J43KZzE2hbJ45vGbr6IjspqvdTHfJ6upRXWu+Xy
acYr9uC/W6ZbsTkhcES9GS9ZqJZ/WTh1l5lrVWztcMgtG1SDZJee2GxAVTL85X+N
Y61s6D5gJJLWO0HF5tCRaCjs0MsaJkDIF9U3z5jwXX1BSoa6QA6qErPM6PQ4bVI3
dQ5zJ6dLKzRcP4vR4k9SSWE51FVU1zKzsrEHPAm15dCix3+TqnxPCERwlZgvsvWp
B+yp2jZfAL7C3sJqUIv92+DVszA5ZA5ZWLTAsyakFHzdNz4VNahIO/edGH57YXu3
whvpDUgscqNdXaADwwzBEzAsByB/G21PM+W20LT5vfyyb0Nkprin1T9ZBpGJIyuP
WSzfoOvxPuJVa/SIOwfYtEZUAUquMI4f9og+0YU+ZiQuMIXGCoHNZX4y5ivxiG22
vcvPgdvJNllb8ix2gGGGCGTVwqCdyAuN48UtqESclDiC9jJ7KdjXXs+AefRXSzPS
XgGyTVziTQQjenT+ZNH5rAtBzVGLqtRsU0mKquce22AxGy8jlsAJ0340VEth2Rnd
Qk8mlzZg14IYP2/qy3qvwozv9ygP02ROhfXMO0RjfqnRybRuSHCj1d9mmp/YUno=
=iYQp
-----END PGP MESSAGE-----
fp: CD8CE78CB0B3BDD4
- created_at: "2024-05-26T20:06:39Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQEMA2W9MER3HLb7AQf/V6GhWuzdF3iW+1O4m6FhONNfVbqvWsPcZrMXiyXTqxk4
G+tNh2ccIXDCDBdfGC5vhdOFv12tn6bTyuFwPmCf8r+2pKtRn3omn4mRlsGspgP8
kM8xIwsBgRwkbg+u4rQpNb/3RGcC5Sm8SY3bNgTLU8rWI/s1+ppyhn67Ep2E8IrQ
Foe8mKnbZihFFxzj3VhV4IyysJgPoIxG9Z/Mnc5DAUso1nK4mzC80INgnoSEhYAk
RIuENp2R45tE/p1h2ITZqsI9eT6QY/OjgDWp6kAWIH5jehUFep3tU9rkQRCfZLbT
SQARFuzXC5xAuQTOUCpGMedkgv6V/oCESkhl6dNbG9JeAShLF4YWeLyG7Ftrxqfz
iA+K0UA0qywo0mHZyl8K1bJwQJONbBb2RbjbJiAfkfOdWXQBH3AkkQdDTGUGjKQR
4lFDSo4cYk6CnB5XI3jDrJE4rX24oAg+KNPKu3GTpw==
=1ZB1
-----END PGP MESSAGE-----
fp: 65BD3044771CB6FB
unencrypted_suffix: _unencrypted
version: 3.8.1

48
nixos/vaultwarden.nix Normal file
View file

@ -0,0 +1,48 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault;
inherit (config.services) postgresql;
cfg = config.services.vaultwarden;
enableAdmin = false;
in {
config.services.vaultwarden = {
enable = mkDefault true;
dbBackend = mkDefault "postgresql";
websocketPort = mkDefault 8223;
databaseUrlPath = mkIf (!postgresql.enable) (mkDefault config.sops.secrets.vaultwarden-database-url.path);
adminTokenPath = mkIf enableAdmin (mkDefault config.sops.secrets.vaultwarden-admin-token.path);
config = {
SIGNUPS_ALLOWED = mkDefault false;
ROCKET_ADDRESS = mkDefault "::";
WEBSOCKET_ADDRESS = mkDefault "::";
DATABASE_URL = mkIf postgresql.enable (mkDefault "postgresql://vaultwarden@/vaultwarden");
};
};
config.systemd.services.vaultwarden = mkIf cfg.enable {
gensokyo-zone.sharedMounts.vaultwarden.path = mkDefault cfg.config.DATA_FOLDER;
};
config.users = mkIf cfg.enable {
users.vaultwarden.uid = 915;
groups.vaultwarden.gid = config.users.users.vaultwarden.uid;
};
config.networking.firewall = mkIf cfg.enable {
interfaces.lan.allowedTCPPorts = [
cfg.port
(mkIf (cfg.websocketPort != null) cfg.websocketPort)
];
};
config.sops.secrets = let
sopsFile = mkDefault ./secrets/vaultwarden.yaml;
owner = "vaultwarden";
in {
vaultwarden-database-url = mkIf (!postgresql.enable) {
inherit sopsFile owner;
};
vaultwarden-admin-token = mkIf enableAdmin {
inherit sopsFile owner;
};
};
}

View file

@ -32,6 +32,7 @@ in {
nixos.access.mosquitto
nixos.access.gensokyo
nixos.access.keycloak
nixos.access.vaultwarden
nixos.access.vouch
nixos.access.freeipa
nixos.access.freepbx
@ -112,6 +113,14 @@ in {
virtualHosts.keycloak'local.allServerNames
];
};
bw = {
inherit (nginx) group;
domain = virtualHosts.vaultwarden.serverName;
extraDomainNames = mkMerge [
virtualHosts.vaultwarden.otherServerNames
virtualHosts.vaultwarden'local.allServerNames
];
};
home = {
inherit (nginx) group;
domain = virtualHosts.home-assistant.serverName;
@ -266,6 +275,11 @@ in {
local.denyGlobal = true;
ssl.cert.enable = true;
};
vaultwarden = {
# we're not the real bw record-holder, so don't respond globally..
local.denyGlobal = true;
ssl.cert.enable = true;
};
vouch = {
ssl.cert.enable = true;
};

View file

@ -12,6 +12,7 @@ _: {
sshd.enable = true;
keycloak.enable = true;
vouch-proxy.enable = true;
vaultwarden.enable = true;
};
};
}

View file

@ -1,6 +1,7 @@
{
"lxc": {
"lxc.mount.entry": [
"/rpool/shared/vaultwarden mnt/shared/vaultwarden none bind,optional,create=dir",
"/dev/net/tun dev/net/tun none bind,optional,create=file"
],
"lxc.idmap": [

View file

@ -12,6 +12,7 @@
nixos.reisen-ct
nixos.ipa
nixos.keycloak
nixos.vaultwarden
nixos.cloudflared
nixos.vouch
];
@ -27,6 +28,8 @@
inherit (keycloak'system.exports.services) keycloak;
vouch'system = access.systemForServiceId "login";
inherit (vouch'system.exports.services) vouch-proxy;
vaultwarden'system = access.systemForServiceId "bw";
inherit (vaultwarden'system.exports.services) vaultwarden;
in {
"${keycloak.id}.${config.networking.domain}" = let
portName =
@ -52,6 +55,12 @@
service = vouch-proxy;
};
};
"${vaultwarden.id}.${config.networking.domain}" = {
service = access.proxyUrlFor {
system = vaultwarden'system;
service = vaultwarden;
};
};
};
};
};

View file

@ -160,6 +160,7 @@ mkshared plex 100193 100193 0750
mkshared postgresql 100071 100071 0750
mkshared unifi 100990 100990 0750
mkshared zigbee2mqtt 100317 100317 0700
mkshared vaultwarden 100915 100915 0750
mkshared minecraft 100913 100913 0750
mkshared minecraft/bedrock 100913 100913 0750

View file

@ -18,6 +18,7 @@ module "hakurei_system_records" {
"krb5",
"ipa",
"ipa-cock",
"bw",
"unifi",
"pbx",
"smb",

View file

@ -44,6 +44,7 @@ module "keycloak" {
subdomains = [
"sso",
"login",
"bw",
]
}