Skip to content

Instantly share code, notes, and snippets.

@liarokapisv
Created November 23, 2025 23:24
Show Gist options
  • Select an option

  • Save liarokapisv/6be7f475ad29de9b6ac11796e90e0e69 to your computer and use it in GitHub Desktop.

Select an option

Save liarokapisv/6be7f475ad29de9b6ac11796e90e0e69 to your computer and use it in GitHub Desktop.
BWS fetch module
{
lib,
pkgs,
config,
...
}:
let
cfg = config.services.bws;
baseDir = "/var/lib/bws";
secretsDir = "${baseDir}/secrets";
fetchScript = pkgs.writeShellScript "bws-fetch.sh" ''
set -euo pipefail
${lib.concatMapStringsSep "\n" (
name:
let
secret = cfg.secrets.${name};
in
''
json=$(${lib.getExe cfg.package} secret get ${lib.escapeShellArg secret.id})
value=$(echo "$json" | ${lib.getExe pkgs.jq} -r '.value')
printf '%s' "$value" > ${lib.escapeShellArg secret.path}
chmod ${secret.mode} ${lib.escapeShellArg secret.path}
chown ${secret.owner}:${secret.group} ${lib.escapeShellArg secret.path} || true
''
) (builtins.attrNames cfg.secrets)}
${lib.optionalString (cfg.secrets != { }) ''
for file in "${secretsDir}"/*; do
[ -e "$file" ] || continue
case "$(basename "$file")" in
${lib.concatMapStringsSep "|" (name: cfg.secrets.${name}.name) (builtins.attrNames cfg.secrets)})
;;
*)
rm -f "$file"
;;
esac
done
''}
'';
in
{
options.services.bws = {
enable = lib.mkEnableOption "Bitwarden Secrets Manager";
secrets = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, config, ... }:
{
options = {
id = lib.mkOption {
type = lib.types.str;
description = "Secret ID.";
};
name = lib.mkOption {
type = lib.types.str;
default = name;
description = "Secret filename.";
};
path = lib.mkOption {
type = lib.types.path;
default = "${secretsDir}/${config.name}";
defaultText = lib.literalExpression ''"''${secretsDir}/''${config.name}"'';
description = "Path where the secret is written.";
};
mode = lib.mkOption {
type = lib.types.str;
default = "0400";
description = "File mode.";
};
owner = lib.mkOption {
type = lib.types.str;
default = "root";
description = "File owner.";
};
group = lib.mkOption {
type = lib.types.str;
default = "root";
description = "File group.";
};
};
}
)
);
default = { };
description = "Secrets to fetch.";
};
package = lib.mkOption {
type = lib.types.package;
default = pkgs.bws;
description = "The bws package to use.";
};
auth.envFile = lib.mkOption {
type = lib.types.path;
default = "/var/lib/bws/auth/auth.env";
description = "Path to environment file containing BWS_ACCESS_TOKEN.";
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
systemd.services.bws-fetch = {
description = "Fetch Bitwarden Secrets";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = fetchScript;
EnvironmentFile = "-${cfg.auth.envFile}";
StateDirectory = "bws bws/secrets bws/auth";
StateDirectoryMode = "0700";
WorkingDirectory = baseDir;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
NoNewPrivileges = true;
};
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment