blob: ee163ab6b72e8ad458a27719618af967ff7d75a0 [file] [log] [blame]
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +00001{ base, pkgs, drive_paths, lib, config, ... }:
2lib.recursiveUpdate {
TheCodedProfb6184602023-06-13 17:04:59 -04003 environment.systemPackages = with pkgs; [ vaultwarden ];
TheCodedProfaec8c452023-06-12 18:26:46 -04004
TheCodedProfb6184602023-06-13 17:04:59 -04005 services.vaultwarden.enable = true;
6 services.vaultwarden.dbBackend = "postgresql";
TheCodedProfaec8c452023-06-12 18:26:46 -04007
Skyler Grey87a11552023-06-14 23:02:25 +02008 sops.secrets = lib.pipe [ "ADMIN_TOKEN" "SMTP_PASSWORD" "YUBICO_SECRET_KEY" "HIBP_API_KEY" ] [
9 (map (name: {
TheCodedProfb6184602023-06-13 17:04:59 -040010 inherit name; value = {
11 mode = "0400";
12 owner = config.users.users.root.name;
13 group = config.users.users.nobody.group;
14 sopsFile = ../secrets/vaultwarden.json;
15 format = "json";
16 };
Skyler Grey87a11552023-06-14 23:02:25 +020017 }))
TheCodedProfb6184602023-06-13 17:04:59 -040018 builtins.listToAttrs
19 ];
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000020} (
TheCodedProfb6184602023-06-13 17:04:59 -040021 let
22 isDerived = base != null;
23 in
24 if isDerived
25 # We cannot use mkIf as both sides are evaluated no matter the condition value
26 # Given we use base as an attrset, mkIf will error if base is null in here
27 then
28 with lib;
29 let
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000030 cfg = config.services.vaultwarden;
TheCodedProfb6184602023-06-13 17:04:59 -040031
32 vaultwarden_config = {
TheCodedProfaec8c452023-06-12 18:26:46 -040033 # Server Settings
34 DOMAIN = "https://passwords.clicks.codes";
35 ROCKET_ADDRESS = "127.0.0.1";
36 ROCKET_PORT = 8452;
37
38
39 # General Settings
TheCodedProfb6184602023-06-13 17:04:59 -040040 SIGNUPS_ALLOWED = false;
41 INVITATIONS_ALLOWED = true;
42 SIGNUPS_DOMAINS_WHITELIST = "clicks.codes,coded.codes,thecoded.prof,starrysky.fyi,hopescaramels.com,pinea.dev";
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000043 SIGNUPS_VERIFY = true;
TheCodedProfaec8c452023-06-12 18:26:46 -040044
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000045 RSA_KEY_FILENAME = "${drive_paths.External1000SSD.path}/bitwarden/rsa_key";
46 ICON_CACHE_FOLDER = "${drive_paths.External1000SSD.path}/bitwarden/icon_cache";
47 ATTACHMENTS_FOLDER = "${drive_paths.External4000HDD.path}/bitwarden/attachments";
48 SENDS_FOLDER = "${drive_paths.External4000HDD.path}/bitwarden/sends";
49 TMP_FOLDER = "${drive_paths.External4000HDD.path}/bitwarden/tmp";
TheCodedProfaec8c452023-06-12 18:26:46 -040050
TheCodedProfb6184602023-06-13 17:04:59 -040051 DISABLE_2FA_REMEMBER = true;
TheCodedProfaec8c452023-06-12 18:26:46 -040052
53 # Admin Account
TheCodedProfb6184602023-06-13 17:04:59 -040054 ADMIN_TOKEN = "!!ADMIN_TOKEN!!";
TheCodedProfaec8c452023-06-12 18:26:46 -040055
56
57 # Database Settings
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000058 DATABASE_URL =
59 "postgresql://vaultwarden:!!clicks_bitwarden_db_secret!!@127.0.0.1:${toString config.services.postgresql.port}/vaultwarden";
TheCodedProfaec8c452023-06-12 18:26:46 -040060
61
62 # Mail Settings
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000063 SMTP_HOST = "mail.clicks.codes";
TheCodedProfaec8c452023-06-12 18:26:46 -040064 SMTP_FROM = "bitwarden@clicks.codes";
65 SMTP_FROM_NAME = "Clicks Bitwarden";
66 SMTP_SECURITY = "starttls";
67 SMTP_PORT = 587;
68
Skyler Grey (Minion3665)e430df32023-06-23 18:22:19 +000069 SMTP_USERNAME = "bitwarden@clicks.codes";
TheCodedProfbdc23452023-06-14 13:39:10 -040070 SMTP_PASSWORD = "!!SMTP_PASSWORD!!";
TheCodedProfaec8c452023-06-12 18:26:46 -040071
TheCodedProfbdc23452023-06-14 13:39:10 -040072 REQUIRE_DEVICE_EMAIL = true;
TheCodedProfaec8c452023-06-12 18:26:46 -040073
Skyler Greyeb1e0fc2023-07-19 20:11:03 +000074 IP_HEADER = "X-Forwarded-For";
TheCodedProfaec8c452023-06-12 18:26:46 -040075
76 # YubiKey Settings
TheCodedProfbdc23452023-06-14 13:39:10 -040077 YUBICO_CLIENT_ID = "89788";
78 YUBICO_SECRET_KEY = "!!YUBICO_SECRET_KEY!!";
TheCodedProfaec8c452023-06-12 18:26:46 -040079
80
81 # TODO: Buy a license
82 # HIBP Settings
TheCodedProfd23784c2023-06-13 14:28:23 -040083 # HIBP_API_KEY="!!HIBP_API_KEY!!";
TheCodedProfb6184602023-06-13 17:04:59 -040084 };
85
86 nameToEnvVar = name:
87 let
88 parts = builtins.split "([A-Z0-9]+)" name;
89 partsToEnvVar = parts: foldl'
90 (key: x:
91 let last = stringLength key - 1; in
92 if isList x then key + optionalString (key != "" && substring last 1 key != "_") "_" + head x
93 else if key != "" && elem (substring 0 1 x) lowerChars then # to handle e.g. [ "disable" [ "2FAR" ] "emember" ]
94 substring 0 last key + optionalString (substring (last - 1) 1 key != "_") "_" + substring last 1 key + toUpper x
95 else key + toUpper x) ""
96 parts;
97 in
98 if builtins.match "[A-Z0-9_]+" name != null then name else partsToEnvVar parts;
99
100 # Due to the different naming schemes allowed for config keys,
101 # we can only check for values consistently after converting them to their corresponding environment variable name.
102 configEnv =
103 let
104 configEnv = concatMapAttrs
105 (name: value: optionalAttrs (value != null) {
106 ${nameToEnvVar name} = if isBool value then boolToString value else toString value;
107 })
108 vaultwarden_config;
109 in
110 { DATA_FOLDER = "/var/lib/bitwarden_rs"; } // optionalAttrs (!(configEnv ? WEB_VAULT_ENABLED) || configEnv.WEB_VAULT_ENABLED == "true") {
111 WEB_VAULT_FOLDER = "${cfg.webVaultPackage}/share/vaultwarden/vault";
TheCodedProfbdc23452023-06-14 13:39:10 -0400112 } // configEnv;
TheCodedProfb6184602023-06-13 17:04:59 -0400113
114 configFile = pkgs.writeText "vaultwarden.env" (concatStrings (mapAttrsToList (name: value: "${name}=${value}\n") configEnv));
115 in
116 {
117 scalpel.trafos."vaultwarden.env" = {
118 source = toString configFile;
119 matchers."ADMIN_TOKEN".secret =
120 config.sops.secrets.ADMIN_TOKEN.path;
121 matchers."SMTP_PASSWORD".secret =
122 config.sops.secrets.SMTP_PASSWORD.path;
123 matchers."YUBICO_SECRET_KEY".secret =
124 config.sops.secrets.YUBICO_SECRET_KEY.path;
125 matchers."HIBP_API_KEY".secret =
126 config.sops.secrets.HIBP_API_KEY.path;
127 matchers."clicks_bitwarden_db_secret".secret =
128 config.sops.secrets.clicks_bitwarden_db_password.path;
129 owner = config.users.users.vaultwarden.name;
130 group = config.users.groups.vaultwarden.name;
131 mode = "0400";
132 };
133
134 services.vaultwarden.environmentFile = config.scalpel.trafos."vaultwarden.env".destination;
135 } else { }
136)