move to new secrets module
This commit is contained in:
parent
1ef2fc61c7
commit
363203d9ae
@ -24,4 +24,5 @@
|
|||||||
deviceSpecific.isShared = false;
|
deviceSpecific.isShared = false;
|
||||||
deviceSpecific.isGaming = true;
|
deviceSpecific.isGaming = true;
|
||||||
deviceSpecific.enableVirtualisation = true;
|
deviceSpecific.enableVirtualisation = true;
|
||||||
|
deviceSpecific.wireguard.enable = true;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
deviceSpecific.isShared = false;
|
deviceSpecific.isShared = false;
|
||||||
deviceSpecific.isGaming = true;
|
deviceSpecific.isGaming = true;
|
||||||
deviceSpecific.enableVirtualisation = false;
|
deviceSpecific.enableVirtualisation = false;
|
||||||
|
deviceSpecific.wireguard.enable = true;
|
||||||
|
|
||||||
boot.blacklistedKernelModules = [
|
boot.blacklistedKernelModules = [
|
||||||
"psmouse"
|
"psmouse"
|
||||||
|
@ -25,4 +25,5 @@
|
|||||||
deviceSpecific.isShared = false;
|
deviceSpecific.isShared = false;
|
||||||
deviceSpecific.isGaming = false;
|
deviceSpecific.isGaming = false;
|
||||||
deviceSpecific.enableVirtualisation = false;
|
deviceSpecific.enableVirtualisation = false;
|
||||||
|
deviceSpecific.wireguard.enable = false;
|
||||||
}
|
}
|
||||||
|
@ -54,13 +54,18 @@ in {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
secrets.spotify = {
|
||||||
|
owner = "alukard";
|
||||||
|
services = [ "spotifyd" ];
|
||||||
|
};
|
||||||
|
|
||||||
services.spotifyd-user = {
|
services.spotifyd-user = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = (pkgs.spotifyd.override { withALSA = false; withPulseAudio = true; withPortAudio = false; });
|
package = (pkgs.spotifyd.override { withALSA = false; withPulseAudio = true; withPortAudio = false; });
|
||||||
settings = {
|
settings = {
|
||||||
global = {
|
global = {
|
||||||
username = "${config.secrets.spotify.user}";
|
username = "alukard.files@gmail.com";
|
||||||
password = "${config.secrets.spotify.password}";
|
password_cmd = "${pkgs.coreutils}/bin/cat ${config.secrets.spotify.decrypted}";
|
||||||
backend = "pulseaudio";
|
backend = "pulseaudio";
|
||||||
volume_controller = "softvol";
|
volume_controller = "softvol";
|
||||||
device_name = "nix";
|
device_name = "nix";
|
||||||
|
@ -61,6 +61,16 @@ with types; {
|
|||||||
type = bool;
|
type = bool;
|
||||||
default = config.deviceSpecific.devInfo.drive.type == "ssd";
|
default = config.deviceSpecific.devInfo.drive.type == "ssd";
|
||||||
};
|
};
|
||||||
|
wireguard = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
killswitch = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ with deviceSpecific;
|
|||||||
# monthly = 2;
|
# monthly = 2;
|
||||||
# };
|
# };
|
||||||
# };
|
# };
|
||||||
|
secrets.samba-windows = {
|
||||||
|
encrypted = "${config.home-manager.users.alukard.xdg.dataHome}/password-store/samba/windows.gpg";
|
||||||
|
services = [ ];
|
||||||
|
};
|
||||||
|
secrets.samba-linux = {
|
||||||
|
encrypted = "${config.home-manager.users.alukard.xdg.dataHome}/password-store/samba/linux.gpg";
|
||||||
|
services = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
fileSystems = {
|
fileSystems = {
|
||||||
"/shared/nixos" = lib.mkIf isVM {
|
"/shared/nixos" = lib.mkIf isVM {
|
||||||
@ -53,8 +61,7 @@ with deviceSpecific;
|
|||||||
fsType = "cifs";
|
fsType = "cifs";
|
||||||
device = "//192.168.0.100/data";
|
device = "//192.168.0.100/data";
|
||||||
options = [
|
options = [
|
||||||
"user=${secrets.linux-samba.user}"
|
"credentials=${secrets.samba-linux.decrypted}"
|
||||||
"password=${secrets.linux-samba.password}"
|
|
||||||
"uid=${toString config.users.users.alukard.uid}"
|
"uid=${toString config.users.users.alukard.uid}"
|
||||||
"gid=${toString config.users.groups.users.gid}"
|
"gid=${toString config.users.groups.users.gid}"
|
||||||
"vers=3.0"
|
"vers=3.0"
|
||||||
@ -84,8 +91,7 @@ with deviceSpecific;
|
|||||||
fsType = "cifs";
|
fsType = "cifs";
|
||||||
device = "//192.168.0.100/files";
|
device = "//192.168.0.100/files";
|
||||||
options = [
|
options = [
|
||||||
"user=${secrets.linux-samba.user}"
|
"credentials=${secrets.samba-linux.decrypted}"
|
||||||
"password=${secrets.linux-samba.password}"
|
|
||||||
"uid=${toString config.users.users.alukard.uid}"
|
"uid=${toString config.users.users.alukard.uid}"
|
||||||
"gid=${toString config.users.groups.users.gid}"
|
"gid=${toString config.users.groups.users.gid}"
|
||||||
"vers=3.0"
|
"vers=3.0"
|
||||||
@ -104,8 +110,7 @@ with deviceSpecific;
|
|||||||
fsType = "cifs";
|
fsType = "cifs";
|
||||||
device = "//192.168.0.100/Files";
|
device = "//192.168.0.100/Files";
|
||||||
options = [
|
options = [
|
||||||
"user=${secrets.windows-samba.user}"
|
"credentials=${secrets.samba-windows.decrypted}"
|
||||||
"password=${secrets.windows-samba.password}"
|
|
||||||
"uid=${toString config.users.users.alukard.uid}"
|
"uid=${toString config.users.users.alukard.uid}"
|
||||||
"gid=${toString config.users.groups.users.gid}"
|
"gid=${toString config.users.groups.users.gid}"
|
||||||
"vers=3.0"
|
"vers=3.0"
|
||||||
@ -123,8 +128,7 @@ with deviceSpecific;
|
|||||||
fsType = "cifs";
|
fsType = "cifs";
|
||||||
device = "//192.168.0.100/Data";
|
device = "//192.168.0.100/Data";
|
||||||
options = [
|
options = [
|
||||||
"user=${secrets.windows-samba.user}"
|
"credentials=${secrets.samba-windows.decrypted}"
|
||||||
"password=${secrets.windows-samba.password}"
|
|
||||||
"uid=${toString config.users.users.alukard.uid}"
|
"uid=${toString config.users.users.alukard.uid}"
|
||||||
"gid=${toString config.users.groups.users.gid}"
|
"gid=${toString config.users.groups.users.gid}"
|
||||||
"vers=3.0"
|
"vers=3.0"
|
||||||
|
115
modules/secrets-envsubst.nix
Normal file
115
modules/secrets-envsubst.nix
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
{ pkgs, config, lib, inputs, ... }:
|
||||||
|
with lib;
|
||||||
|
with types;
|
||||||
|
let
|
||||||
|
envsubstSecrets = { name, ... }: {
|
||||||
|
options = {
|
||||||
|
directory = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
secrets = mkOption { type = listOf str; };
|
||||||
|
template = mkOption { type = str; };
|
||||||
|
prefix = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
substituted = mkOption {
|
||||||
|
type = path;
|
||||||
|
default = "/var/secrets/${name}-envsubst";
|
||||||
|
};
|
||||||
|
envsubst = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "${pkgs.envsubst}/bin/envsubst -no-unset -no-empty";
|
||||||
|
};
|
||||||
|
owner = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "root:root";
|
||||||
|
};
|
||||||
|
permissions = mkOption {
|
||||||
|
type = lib.types.addCheck lib.types.str
|
||||||
|
(perm: !isNull (builtins.match "[0-7]{3}" perm));
|
||||||
|
default = "400";
|
||||||
|
};
|
||||||
|
services = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [ "${name}.service" ];
|
||||||
|
};
|
||||||
|
__toString = mkOption {
|
||||||
|
readOnly = true;
|
||||||
|
default = s: s.substituted;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exportSecrets = name: cfg:
|
||||||
|
let prefix = lib.optionalString (!isNull cfg.prefix) "${cfg.prefix}_";
|
||||||
|
in map (secret:
|
||||||
|
''
|
||||||
|
export ${prefix}${secret}="$(cat ${
|
||||||
|
config.secrets."${name}-envsubst-${secret}".decrypted
|
||||||
|
})"'') cfg.secrets;
|
||||||
|
|
||||||
|
envsubst = name: cfg:
|
||||||
|
with cfg; {
|
||||||
|
"${name}-envsubst" = rec {
|
||||||
|
|
||||||
|
requires = [ "user@1000.service" ]
|
||||||
|
++ map (secret: "${name}-envsubst-${secret}-secrets.service")
|
||||||
|
cfg.secrets;
|
||||||
|
after = requires;
|
||||||
|
bindsTo = requires;
|
||||||
|
|
||||||
|
preStart = "mkdir -p '${builtins.dirOf substituted}'";
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
${builtins.concatStringsSep "\n" (exportSecrets name cfg)}
|
||||||
|
|
||||||
|
if cat '${
|
||||||
|
builtins.toFile "template" template
|
||||||
|
}' | ${cfg.envsubst} > '${substituted}.tmp'; then
|
||||||
|
mv -f '${substituted}.tmp' '${substituted}'
|
||||||
|
chown '${owner}' '${substituted}'
|
||||||
|
chmod '${permissions}' '${substituted}'
|
||||||
|
else
|
||||||
|
echo "Failed to run the substition"
|
||||||
|
rm '${substituted}.tmp'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
addDependencies = name: cfg:
|
||||||
|
with cfg;
|
||||||
|
genAttrs services (service: rec {
|
||||||
|
requires = [ "${name}-envsubst" ];
|
||||||
|
after = requires;
|
||||||
|
bindsTo = requires;
|
||||||
|
});
|
||||||
|
mkServices = name: cfg: [ (envsubst name cfg) (addDependencies name cfg) ];
|
||||||
|
|
||||||
|
mkIndividualSecrets = name: cfg:
|
||||||
|
map (x: {
|
||||||
|
"${name}-envsubst-${x}" = {
|
||||||
|
encrypted = "${config.home-manager.users.alukard.xdg.dataHome}/password-store/${
|
||||||
|
lib.optionalString (!isNull cfg.directory) "${cfg.directory}/"
|
||||||
|
}${x}.gpg";
|
||||||
|
services = [ ];
|
||||||
|
};
|
||||||
|
}) cfg.secrets;
|
||||||
|
in {
|
||||||
|
options.secrets-envsubst = lib.mkOption {
|
||||||
|
type = attrsOf (submodule envsubstSecrets);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
config.systemd.services =
|
||||||
|
mkMerge (concatLists (mapAttrsToList mkServices config.secrets-envsubst));
|
||||||
|
config.secrets = mkMerge
|
||||||
|
(concatLists (mapAttrsToList mkIndividualSecrets config.secrets-envsubst));
|
||||||
|
}
|
@ -1,46 +1,146 @@
|
|||||||
{ pkgs, config, lib, ... }:
|
{ pkgs, config, lib, inputs, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
with types;
|
with types;
|
||||||
let
|
let
|
||||||
secret = description:
|
password-store = "${config.home-manager.users.alukard.xdg.dataHome}/password-store";
|
||||||
mkOption {
|
secret = { name, ... }: {
|
||||||
inherit description;
|
options = {
|
||||||
type = nullOr str;
|
encrypted = mkOption {
|
||||||
|
type = path;
|
||||||
|
default = "${password-store}/${name}.gpg";
|
||||||
|
};
|
||||||
|
decrypted = mkOption {
|
||||||
|
type = path;
|
||||||
|
default = "/var/secrets/${name}";
|
||||||
|
};
|
||||||
|
decrypt = mkOption {
|
||||||
|
default = pkgs.writeShellScript "gpg-decrypt" ''
|
||||||
|
set -euo pipefail
|
||||||
|
export GPG_TTY="$(tty)"
|
||||||
|
${pkgs.gnupg}/bin/gpg-connect-agent updatestartuptty /bye 1>&2
|
||||||
|
${pkgs.gnupg}/bin/gpg --batch --no-tty --decrypt
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
user = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "alukard";
|
||||||
|
};
|
||||||
|
owner = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "root:root";
|
||||||
|
};
|
||||||
|
permissions = mkOption {
|
||||||
|
type = lib.types.addCheck lib.types.str
|
||||||
|
(perm: !isNull (builtins.match "[0-7]{3}" perm));
|
||||||
|
default = "400";
|
||||||
|
};
|
||||||
|
services = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [ "${name}" ];
|
||||||
|
};
|
||||||
|
__toString = mkOption {
|
||||||
|
readOnly = true;
|
||||||
|
default = s: s.decrypted;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
decrypt = name: cfg:
|
||||||
|
with cfg; {
|
||||||
|
"${name}-secrets" = rec {
|
||||||
|
|
||||||
|
requires = [ "user@1000.service" ];
|
||||||
|
after = requires;
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
stat '${encrypted}'
|
||||||
|
mkdir -p '${builtins.dirOf decrypted}'
|
||||||
|
'';
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
if cat '${encrypted}' | /run/wrappers/bin/sudo -u ${user} ${cfg.decrypt} > '${decrypted}.tmp'; then
|
||||||
|
mv -f '${decrypted}.tmp' '${decrypted}'
|
||||||
|
chown '${owner}' '${decrypted}'
|
||||||
|
chmod '${permissions}' '${decrypted}'
|
||||||
|
else
|
||||||
|
echo "Failed to decrypt the secret"
|
||||||
|
rm '${decrypted}.tmp'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
addDependencies = name: cfg:
|
||||||
|
with cfg;
|
||||||
|
genAttrs services (service: rec {
|
||||||
|
requires = [ "${name}-secrets.service" ];
|
||||||
|
after = requires;
|
||||||
|
bindsTo = requires;
|
||||||
|
});
|
||||||
|
|
||||||
|
mkServices = name: cfg: [ (decrypt name cfg) (addDependencies name cfg) ];
|
||||||
|
|
||||||
|
allServices = toString (map (name: "${name}-envsubst.service")
|
||||||
|
(builtins.attrNames config.secrets-envsubst)
|
||||||
|
++ map (name: "${name}-secrets.service")
|
||||||
|
(builtins.attrNames config.secrets));
|
||||||
|
in {
|
||||||
|
options.secrets = lib.mkOption {
|
||||||
|
type = attrsOf (submodule secret);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
options.secretsConfig = {
|
||||||
|
repo = lib.mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "ssh://git@github.com/AlukardBF/pass";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.systemd.services =
|
||||||
|
mkMerge (concatLists (mapAttrsToList mkServices config.secrets));
|
||||||
|
|
||||||
|
config.environment.systemPackages = [
|
||||||
|
(pkgs.writeShellScriptBin "activate-secrets" ''
|
||||||
|
set -euo pipefail
|
||||||
|
# Make sure card is available and unlocked
|
||||||
|
# echo fetch | gpg --card-edit --no-tty --command-fd=0
|
||||||
|
# ${pkgs.gnupg}/bin/gpg --card-status
|
||||||
|
if [ -d "${password-store}/.git" ]; then
|
||||||
|
cd "${password-store}"; ${pkgs.git}/bin/git pull
|
||||||
|
else
|
||||||
|
${pkgs.git}/bin/git clone ${lib.escapeShellArg config.secretsConfig.repo} "${password-store}"
|
||||||
|
fi
|
||||||
|
ln -sf ${
|
||||||
|
pkgs.writeShellScript "push" "${pkgs.git}/bin/git push origin master"
|
||||||
|
} "${password-store}/.git/hooks/post-commit"
|
||||||
|
cat ${password-store}/spotify.gpg | ${pkgs.gnupg}/bin/gpg --decrypt > /dev/null
|
||||||
|
sudo systemctl restart ${allServices}
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
config.security.sudo.extraRules = [{
|
||||||
|
users = [ "alukard" ];
|
||||||
|
commands = [{
|
||||||
|
command = "/run/current-system/sw/bin/systemctl restart ${allServices}";
|
||||||
|
options = [ "NOPASSWD" ];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
|
||||||
|
config.home-manager.users.alukard = {
|
||||||
|
xsession.windowManager.i3 = {
|
||||||
|
config.startup = [{ command = "activate-secrets"; }];
|
||||||
|
};
|
||||||
|
programs.password-store = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.pass-nodmenu;
|
||||||
|
settings.PASSWORD_STORE_DIR = password-store;
|
||||||
};
|
};
|
||||||
mkCredOption = service: extra:
|
|
||||||
mkOption {
|
|
||||||
description = "Credentials for ${service}";
|
|
||||||
type = nullOr (submodule {
|
|
||||||
options = {
|
|
||||||
user = mkOption {
|
|
||||||
type = str;
|
|
||||||
description = "Username for ${service}";
|
|
||||||
};
|
|
||||||
password = mkOption {
|
|
||||||
type = str;
|
|
||||||
description = "Password for ${service}";
|
|
||||||
};
|
|
||||||
} // extra;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
in rec {
|
|
||||||
options.secrets = {
|
|
||||||
wireguard = mkOption {
|
|
||||||
description = "Wireguard conf";
|
|
||||||
type = attrs;
|
|
||||||
};
|
|
||||||
windows-samba = mkCredOption "samba on windows" { };
|
|
||||||
linux-samba = mkCredOption "samba on linux" { };
|
|
||||||
spotify = mkCredOption "Spotify" { };
|
|
||||||
};
|
};
|
||||||
config = let
|
|
||||||
unlocked = import (pkgs.runCommand "check-secret" { }
|
|
||||||
"set +e; grep -qI . ${../secret.nix}; echo $? > $out") == 0;
|
|
||||||
secretnix = import ../secret.nix;
|
|
||||||
secrets = if !unlocked || isNull secretnix then
|
|
||||||
builtins.trace "secret.nix locked, building without any secrets"
|
|
||||||
(mapAttrs (n: v: null) options.secrets)
|
|
||||||
else
|
|
||||||
secretnix;
|
|
||||||
in { inherit secrets; };
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.secrets.wireguard.${config.device};
|
cfg = config.deviceSpecific.wireguard;
|
||||||
kernel = config.boot.kernelPackages;
|
kernel = config.boot.kernelPackages;
|
||||||
in {
|
in {
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -9,7 +9,10 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
enableSshSupport = true;
|
enableSshSupport = true;
|
||||||
pinentryFlavor = "gnome3";
|
pinentryFlavor = "gnome3";
|
||||||
sshKeys = [ "E6A6377C3D0827C36428A290199FDB3B91414AFE" ];
|
sshKeys = [
|
||||||
|
# "E6A6377C3D0827C36428A290199FDB3B91414AFE"
|
||||||
|
"7A7130ABF128CC2C32B3D6AD27515056B0193CE1"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -14,6 +14,7 @@
|
|||||||
nix
|
nix
|
||||||
overlay
|
overlay
|
||||||
secrets
|
secrets
|
||||||
|
secrets-envsubst
|
||||||
security
|
security
|
||||||
ssh
|
ssh
|
||||||
xdg
|
xdg
|
||||||
|
Loading…
x
Reference in New Issue
Block a user