nix fmt
This commit is contained in:
@@ -4,14 +4,16 @@
|
||||
myData,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.borgstor = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable borg storage user";
|
||||
dataDir = lib.mkOption {type = path;};
|
||||
sshKeys = lib.mkOption {type = listOf str;};
|
||||
dataDir = lib.mkOption { type = path; };
|
||||
sshKeys = lib.mkOption { type = listOf str; };
|
||||
};
|
||||
|
||||
config = with config.mj.services.borgstor;
|
||||
config =
|
||||
with config.mj.services.borgstor;
|
||||
lib.mkIf enable {
|
||||
users.users.borgstor = {
|
||||
description = "Borg Storage";
|
||||
@@ -21,11 +23,9 @@
|
||||
isSystemUser = true;
|
||||
createHome = false;
|
||||
uid = myData.uidgid.borgstor;
|
||||
openssh.authorizedKeys.keys =
|
||||
map (
|
||||
k: "command=\"${pkgs.borgbackup}/bin/borg serve --restrict-to-path ${dataDir}\",restrict ${k}"
|
||||
)
|
||||
sshKeys;
|
||||
openssh.authorizedKeys.keys = map (
|
||||
k: ''command="${pkgs.borgbackup}/bin/borg serve --restrict-to-path ${dataDir}",restrict ${k}''
|
||||
) sshKeys;
|
||||
};
|
||||
|
||||
users.groups.borgstor.gid = myData.uidgid.borgstor;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{...}: {
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./borgstor
|
||||
./deployerbot
|
||||
|
||||
@@ -3,34 +3,36 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.deployerbot.main = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable system updater orchestrator";
|
||||
deployDerivations = lib.mkOption {type = listOf str;};
|
||||
deployDerivations = lib.mkOption { type = listOf str; };
|
||||
deployIfPresent = lib.mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
derivationTarget = lib.mkOption {type = str;};
|
||||
pingTarget = lib.mkOption {type = str;};
|
||||
derivationTarget = lib.mkOption { type = str; };
|
||||
pingTarget = lib.mkOption { type = str; };
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
uidgid = lib.mkOption {type = int;};
|
||||
repo = lib.mkOption {type = str;};
|
||||
uidgid = lib.mkOption { type = int; };
|
||||
repo = lib.mkOption { type = str; };
|
||||
};
|
||||
|
||||
options.mj.services.deployerbot.follower = with lib.types; {
|
||||
enable = lib.mkEnableOption "Allow system to be deployed with deployerbot";
|
||||
sshAllowSubnets = lib.mkOption {type = listOf str;};
|
||||
publicKeys = lib.mkOption {type = listOf str;};
|
||||
uidgid = lib.mkOption {type = int;};
|
||||
sshAllowSubnets = lib.mkOption { type = listOf str; };
|
||||
publicKeys = lib.mkOption { type = listOf str; };
|
||||
uidgid = lib.mkOption { type = int; };
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(let
|
||||
cfg = config.mj.services.deployerbot.main;
|
||||
in
|
||||
(
|
||||
let
|
||||
cfg = config.mj.services.deployerbot.main;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
# TODO: git config --global user.email bot@jakstys.lt
|
||||
users.users.deployerbot-main = {
|
||||
@@ -46,49 +48,57 @@
|
||||
|
||||
systemd.services.deployerbot = {
|
||||
description = "Update all known systems";
|
||||
environment = {TZ = "UTC";};
|
||||
path = [pkgs.git pkgs.openssh pkgs.nix];
|
||||
environment = {
|
||||
TZ = "UTC";
|
||||
};
|
||||
path = [
|
||||
pkgs.git
|
||||
pkgs.openssh
|
||||
pkgs.nix
|
||||
];
|
||||
restartIfChanged = false;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "deployerbot-main";
|
||||
WorkingDirectory = config.users.users.deployerbot-main.home;
|
||||
LoadCredential = ["ssh-key:/etc/ssh/ssh_host_ed25519_key"];
|
||||
LoadCredential = [ "ssh-key:/etc/ssh/ssh_host_ed25519_key" ];
|
||||
};
|
||||
script = let
|
||||
deployDerivationsStr = builtins.concatStringsSep " " cfg.deployDerivations;
|
||||
in ''
|
||||
set -xeuo pipefail
|
||||
script =
|
||||
let
|
||||
deployDerivationsStr = builtins.concatStringsSep " " cfg.deployDerivations;
|
||||
in
|
||||
''
|
||||
set -xeuo pipefail
|
||||
|
||||
export GIT_SSH_COMMAND="ssh -i ''${CREDENTIALS_DIRECTORY}/ssh-key"
|
||||
if [[ ! -d config ]]; then
|
||||
git clone ${cfg.repo} config
|
||||
cd config
|
||||
else
|
||||
cd config
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
fi
|
||||
export GIT_SSH_COMMAND="ssh -i ''${CREDENTIALS_DIRECTORY}/ssh-key"
|
||||
if [[ ! -d config ]]; then
|
||||
git clone ${cfg.repo} config
|
||||
cd config
|
||||
else
|
||||
cd config
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
fi
|
||||
|
||||
nix flake update --accept-flake-config --commit-lock-file
|
||||
# TODO --all-systems
|
||||
nix flake check --all-systems --accept-flake-config
|
||||
nix flake update --accept-flake-config --commit-lock-file
|
||||
# TODO --all-systems
|
||||
nix flake check --all-systems --accept-flake-config
|
||||
|
||||
EXITCODE=0
|
||||
${pkgs.deploy-rs.deploy-rs}/bin/deploy \
|
||||
--ssh-opts="-i ''${CREDENTIALS_DIRECTORY}/ssh-key" \
|
||||
--ssh-user=deployerbot-follower \
|
||||
--confirm-timeout 60 \
|
||||
--skip-checks \
|
||||
--targets ${deployDerivationsStr} -- \
|
||||
--accept-flake-config || EXITCODE=1
|
||||
EXITCODE=0
|
||||
${pkgs.deploy-rs.deploy-rs}/bin/deploy \
|
||||
--ssh-opts="-i ''${CREDENTIALS_DIRECTORY}/ssh-key" \
|
||||
--ssh-user=deployerbot-follower \
|
||||
--confirm-timeout 60 \
|
||||
--skip-checks \
|
||||
--targets ${deployDerivationsStr} -- \
|
||||
--accept-flake-config || EXITCODE=1
|
||||
|
||||
if [[ $EXITCODE == 0 ]]; then
|
||||
git push origin main
|
||||
fi
|
||||
if [[ $EXITCODE == 0 ]]; then
|
||||
git push origin main
|
||||
fi
|
||||
|
||||
# Optional deployments
|
||||
${lib.concatMapStringsSep "\n" (t: ''
|
||||
# Optional deployments
|
||||
${lib.concatMapStringsSep "\n" (t: ''
|
||||
if ${pkgs.inetutils}/bin/ping -c 1 ${t.pingTarget}; then
|
||||
${pkgs.deploy-rs.deploy-rs}/bin/deploy \
|
||||
--ssh-opts="-i ''${CREDENTIALS_DIRECTORY}/ssh-key" \
|
||||
@@ -98,43 +108,45 @@
|
||||
--targets ${t.derivationTarget} -- \
|
||||
--accept-flake-config || EXITCODE=1
|
||||
fi
|
||||
'')
|
||||
cfg.deployIfPresent}
|
||||
'') cfg.deployIfPresent}
|
||||
|
||||
exit $EXITCODE
|
||||
'';
|
||||
exit $EXITCODE
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.timers.deployerbot = {
|
||||
description = "deployerbot-main timer";
|
||||
wantedBy = ["timers.target"];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = "*-*-* 23:30:00 UTC";
|
||||
};
|
||||
|
||||
mj.base.unitstatus.units = ["deployerbot"];
|
||||
mj.base.unitstatus.units = [ "deployerbot" ];
|
||||
|
||||
nix.settings.trusted-users = ["deployerbot-main"];
|
||||
})
|
||||
nix.settings.trusted-users = [ "deployerbot-main" ];
|
||||
}
|
||||
)
|
||||
|
||||
(let
|
||||
cfg = config.mj.services.deployerbot.follower;
|
||||
in
|
||||
(
|
||||
let
|
||||
cfg = config.mj.services.deployerbot.follower;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
users.users.deployerbot-follower = {
|
||||
description = "Deployerbot Follower";
|
||||
home = "/var/lib/deployerbot-follower";
|
||||
shell = "/bin/sh";
|
||||
group = "deployerbot-follower";
|
||||
extraGroups = ["wheel"];
|
||||
extraGroups = [ "wheel" ];
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
uid = cfg.uidgid;
|
||||
openssh.authorizedKeys.keys =
|
||||
map (k: "from=\"${builtins.concatStringsSep "," cfg.sshAllowSubnets}\" " + k)
|
||||
cfg.publicKeys;
|
||||
openssh.authorizedKeys.keys = map (
|
||||
k: ''from="${builtins.concatStringsSep "," cfg.sshAllowSubnets}" '' + k
|
||||
) cfg.publicKeys;
|
||||
};
|
||||
users.groups.deployerbot-follower.gid = cfg.uidgid;
|
||||
nix.settings.trusted-users = ["deployerbot-follower"];
|
||||
})
|
||||
nix.settings.trusted-users = [ "deployerbot-follower" ];
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,54 +1,59 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options.mj.services.friendlyport = with lib.types; {
|
||||
ports = lib.mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
subnets = lib.mkOption {type = listOf str;};
|
||||
subnets = lib.mkOption { type = listOf str; };
|
||||
tcp = lib.mkOption {
|
||||
type = listOf int;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
udp = lib.mkOption {
|
||||
type = listOf int;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
inherit (config.mj.services.friendlyport) ports;
|
||||
config =
|
||||
let
|
||||
inherit (config.mj.services.friendlyport) ports;
|
||||
|
||||
mkAdd = proto: subnets: ints: let
|
||||
subnetsS = builtins.concatStringsSep "," subnets;
|
||||
intsS = builtins.concatStringsSep "," (map builtins.toString ints);
|
||||
mkAdd =
|
||||
proto: subnets: ints:
|
||||
let
|
||||
subnetsS = builtins.concatStringsSep "," subnets;
|
||||
intsS = builtins.concatStringsSep "," (map builtins.toString ints);
|
||||
in
|
||||
if builtins.length ints == 0 then
|
||||
""
|
||||
else
|
||||
"iptables -A INPUT -p ${proto} --match multiport --dports ${intsS} --source ${subnetsS} -j ACCEPT";
|
||||
|
||||
startTCP = map (attr: mkAdd "tcp" attr.subnets attr.tcp) ports;
|
||||
startUDP = map (attr: mkAdd "udp" attr.subnets attr.udp) ports;
|
||||
|
||||
# TODO: when stopping the firewall, systemd uses the old ports. So this is a two-phase process.
|
||||
# How to stop the old one and start the new one?
|
||||
mkDel =
|
||||
proto: subnets: ints:
|
||||
let
|
||||
subnetsS = builtins.concatStringsSep "," subnets;
|
||||
intsS = builtins.concatStringsSep "," (map builtins.toString ints);
|
||||
in
|
||||
if builtins.length ints == 0 then
|
||||
""
|
||||
else
|
||||
"iptables -D INPUT -p ${proto} --match multiport --dports ${intsS} --source ${subnetsS} -j ACCEPT || :";
|
||||
|
||||
stopTCP = map (attr: mkDel "tcp" attr.subnets attr.tcp) ports;
|
||||
stopUDP = map (attr: mkDel "udp" attr.subnets attr.udp) ports;
|
||||
in
|
||||
if builtins.length ints == 0
|
||||
then ""
|
||||
else "iptables -A INPUT -p ${proto} --match multiport --dports ${intsS} --source ${subnetsS} -j ACCEPT";
|
||||
|
||||
startTCP = map (attr: mkAdd "tcp" attr.subnets attr.tcp) ports;
|
||||
startUDP = map (attr: mkAdd "udp" attr.subnets attr.udp) ports;
|
||||
|
||||
# TODO: when stopping the firewall, systemd uses the old ports. So this is a two-phase process.
|
||||
# How to stop the old one and start the new one?
|
||||
mkDel = proto: subnets: ints: let
|
||||
subnetsS = builtins.concatStringsSep "," subnets;
|
||||
intsS = builtins.concatStringsSep "," (map builtins.toString ints);
|
||||
in
|
||||
if builtins.length ints == 0
|
||||
then ""
|
||||
else "iptables -D INPUT -p ${proto} --match multiport --dports ${intsS} --source ${subnetsS} -j ACCEPT || :";
|
||||
|
||||
stopTCP = map (attr: mkDel "tcp" attr.subnets attr.tcp) ports;
|
||||
stopUDP = map (attr: mkDel "udp" attr.subnets attr.udp) ports;
|
||||
in {
|
||||
networking.firewall.extraCommands = lib.concatLines (startTCP ++ startUDP);
|
||||
networking.firewall.extraStopCommands = lib.concatLines (stopTCP ++ stopUDP);
|
||||
};
|
||||
{
|
||||
networking.firewall.extraCommands = lib.concatLines (startTCP ++ startUDP);
|
||||
networking.firewall.extraStopCommands = lib.concatLines (stopTCP ++ stopUDP);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
pkgs,
|
||||
myData,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.gitea = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable gitea";
|
||||
};
|
||||
@@ -79,7 +80,7 @@
|
||||
route /static/assets/* {
|
||||
uri strip_prefix /static
|
||||
file_server * {
|
||||
root ${pkgs.compressDrvWeb pkgs.gitea.data {}}/public
|
||||
root ${pkgs.compressDrvWeb pkgs.gitea.data { }}/public
|
||||
precompressed br gzip
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
lib,
|
||||
myData,
|
||||
...
|
||||
}: let
|
||||
}:
|
||||
let
|
||||
cfg = config.mj.services.hass;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.mj.services.hass = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable home-assistant";
|
||||
};
|
||||
@@ -13,12 +15,12 @@ in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
mj.services.friendlyport.ports = [
|
||||
{
|
||||
subnets = [myData.subnets.tailscale.cidr];
|
||||
tcp = [myData.ports.hass];
|
||||
subnets = [ myData.subnets.tailscale.cidr ];
|
||||
tcp = [ myData.ports.hass ];
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [];
|
||||
environment.systemPackages = [ ];
|
||||
|
||||
services = {
|
||||
home-assistant = {
|
||||
@@ -36,11 +38,11 @@ in {
|
||||
"ipp"
|
||||
];
|
||||
config = {
|
||||
default_config = {};
|
||||
default_config = { };
|
||||
|
||||
http = {
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = ["127.0.0.1"];
|
||||
trusted_proxies = [ "127.0.0.1" ];
|
||||
};
|
||||
#homeassistant = {
|
||||
# auth_providers = [
|
||||
@@ -51,7 +53,7 @@ in {
|
||||
# ];
|
||||
#};
|
||||
|
||||
wake_on_lan = {};
|
||||
wake_on_lan = { };
|
||||
|
||||
# requires a restore from backup
|
||||
"automation ui" = "!include automations.yaml";
|
||||
@@ -67,7 +69,9 @@ in {
|
||||
action = [
|
||||
{
|
||||
service = "wake_on_lan.send_magic_packet";
|
||||
data = {mac = "74:e6:b8:4c:fb:b7";};
|
||||
data = {
|
||||
mac = "74:e6:b8:4c:fb:b7";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,28 +3,32 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.headscale = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable headscale";
|
||||
clientOidcPath = lib.mkOption {type = str;};
|
||||
subnetCIDR = lib.mkOption {type = str;};
|
||||
clientOidcPath = lib.mkOption { type = str; };
|
||||
subnetCIDR = lib.mkOption { type = str; };
|
||||
};
|
||||
|
||||
config = lib.mkIf config.mj.services.headscale.enable {
|
||||
environment.systemPackages = [pkgs.headscale];
|
||||
environment.systemPackages = [ pkgs.headscale ];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [3478];
|
||||
networking.firewall.allowedUDPPorts = [3478];
|
||||
networking.firewall.allowedTCPPorts = [ 3478 ];
|
||||
networking.firewall.allowedUDPPorts = [ 3478 ];
|
||||
|
||||
services = {
|
||||
headscale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server_url = "https://vpn.jakstys.lt";
|
||||
ip_prefixes = [config.mj.services.headscale.subnetCIDR];
|
||||
ip_prefixes = [ config.mj.services.headscale.subnetCIDR ];
|
||||
log.level = "warn";
|
||||
dns_config = {
|
||||
nameservers = ["1.1.1.1" "8.8.4.4"];
|
||||
nameservers = [
|
||||
"1.1.1.1"
|
||||
"8.8.4.4"
|
||||
];
|
||||
magic_dns = false;
|
||||
base_domain = "jakst";
|
||||
};
|
||||
|
||||
@@ -3,16 +3,18 @@
|
||||
lib,
|
||||
myData,
|
||||
...
|
||||
}: let
|
||||
}:
|
||||
let
|
||||
cfg = config.mj.services.jakstpub;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.mj.services.jakstpub = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable jakstpub";
|
||||
dataDir = lib.mkOption {type = path;};
|
||||
dataDir = lib.mkOption { type = path; };
|
||||
# RequiresMountsFor is used by upstream, hacking with the unit
|
||||
requires = lib.mkOption {type = listOf str;};
|
||||
uidgid = lib.mkOption {type = int;};
|
||||
hostname = lib.mkOption {type = str;};
|
||||
requires = lib.mkOption { type = listOf str; };
|
||||
uidgid = lib.mkOption { type = int; };
|
||||
hostname = lib.mkOption { type = str; };
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -40,32 +42,30 @@ in {
|
||||
guest account = jakstpub
|
||||
server role = standalone server
|
||||
'';
|
||||
shares = let
|
||||
defaults = {
|
||||
"public" = "yes";
|
||||
"mangled names" = "no";
|
||||
"guest ok" = "yes";
|
||||
"force user" = "jakstpub";
|
||||
"force group" = "jakstpub";
|
||||
};
|
||||
in {
|
||||
public =
|
||||
defaults
|
||||
// {
|
||||
shares =
|
||||
let
|
||||
defaults = {
|
||||
"public" = "yes";
|
||||
"mangled names" = "no";
|
||||
"guest ok" = "yes";
|
||||
"force user" = "jakstpub";
|
||||
"force group" = "jakstpub";
|
||||
};
|
||||
in
|
||||
{
|
||||
public = defaults // {
|
||||
"path" = cfg.dataDir;
|
||||
"writeable" = "yes";
|
||||
"read only" = "no";
|
||||
"create mask" = "0664";
|
||||
"directory mask" = "0775";
|
||||
};
|
||||
snapshots =
|
||||
defaults
|
||||
// {
|
||||
snapshots = defaults // {
|
||||
"path" = cfg.dataDir + "/.zfs/snapshot";
|
||||
"writeable" = "no";
|
||||
"read only" = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
samba-wsdd = {
|
||||
@@ -92,14 +92,18 @@ in {
|
||||
|
||||
mj.services.friendlyport.ports = [
|
||||
{
|
||||
subnets = with myData.subnets; [tailscale.cidr vno1.cidr vno3.cidr];
|
||||
subnets = with myData.subnets; [
|
||||
tailscale.cidr
|
||||
vno1.cidr
|
||||
vno3.cidr
|
||||
];
|
||||
tcp = [
|
||||
80 # caddy above
|
||||
139 # smbd
|
||||
445 # smbd
|
||||
5357 # wsdd
|
||||
];
|
||||
udp = [3702]; # wsdd
|
||||
udp = [ 3702 ]; # wsdd
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
@@ -3,18 +3,19 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.matrix-synapse = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable matrix-synapse";
|
||||
signingKeyPath = lib.mkOption {type = path;};
|
||||
registrationSharedSecretPath = lib.mkOption {type = path;};
|
||||
macaroonSecretKeyPath = lib.mkOption {type = path;};
|
||||
signingKeyPath = lib.mkOption { type = path; };
|
||||
registrationSharedSecretPath = lib.mkOption { type = path; };
|
||||
macaroonSecretKeyPath = lib.mkOption { type = path; };
|
||||
};
|
||||
|
||||
config = lib.mkIf config.mj.services.matrix-synapse.enable {
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
extraConfigFiles = ["/run/matrix-synapse/secrets.yaml"];
|
||||
extraConfigFiles = [ "/run/matrix-synapse/secrets.yaml" ];
|
||||
settings = {
|
||||
server_name = "jakstys.lt";
|
||||
admin_contact = "motiejus@jakstys.lt";
|
||||
@@ -95,31 +96,34 @@
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /run/matrix-synapse 0700 matrix-synapse matrix-synapse -"
|
||||
];
|
||||
systemd.tmpfiles.rules = [ "d /run/matrix-synapse 0700 matrix-synapse matrix-synapse -" ];
|
||||
|
||||
systemd.services = {
|
||||
matrix-synapse = let
|
||||
# I tried to move this to preStart, but it complains:
|
||||
# Config is missing macaroon_secret_key
|
||||
secretsScript = pkgs.writeShellScript "write-secrets" ''
|
||||
set -xeuo pipefail
|
||||
umask 077
|
||||
ln -sf ''${CREDENTIALS_DIRECTORY}/jakstys_lt_signing_key /run/matrix-synapse/jakstys_lt_signing_key
|
||||
cat > /run/matrix-synapse/secrets.yaml <<EOF
|
||||
registration_shared_secret: "$(cat ''${CREDENTIALS_DIRECTORY}/registration_shared_secret)"
|
||||
macaroon_secret_key: "$(cat ''${CREDENTIALS_DIRECTORY}/macaroon_secret_key)"
|
||||
EOF
|
||||
'';
|
||||
in {
|
||||
serviceConfig.ExecStartPre = ["" secretsScript];
|
||||
serviceConfig.LoadCredential = with config.mj.services.matrix-synapse; [
|
||||
"jakstys_lt_signing_key:${signingKeyPath}"
|
||||
"registration_shared_secret:${registrationSharedSecretPath}"
|
||||
"macaroon_secret_key:${macaroonSecretKeyPath}"
|
||||
];
|
||||
};
|
||||
matrix-synapse =
|
||||
let
|
||||
# I tried to move this to preStart, but it complains:
|
||||
# Config is missing macaroon_secret_key
|
||||
secretsScript = pkgs.writeShellScript "write-secrets" ''
|
||||
set -xeuo pipefail
|
||||
umask 077
|
||||
ln -sf ''${CREDENTIALS_DIRECTORY}/jakstys_lt_signing_key /run/matrix-synapse/jakstys_lt_signing_key
|
||||
cat > /run/matrix-synapse/secrets.yaml <<EOF
|
||||
registration_shared_secret: "$(cat ''${CREDENTIALS_DIRECTORY}/registration_shared_secret)"
|
||||
macaroon_secret_key: "$(cat ''${CREDENTIALS_DIRECTORY}/macaroon_secret_key)"
|
||||
EOF
|
||||
'';
|
||||
in
|
||||
{
|
||||
serviceConfig.ExecStartPre = [
|
||||
""
|
||||
secretsScript
|
||||
];
|
||||
serviceConfig.LoadCredential = with config.mj.services.matrix-synapse; [
|
||||
"jakstys_lt_signing_key:${signingKeyPath}"
|
||||
"registration_shared_secret:${registrationSharedSecretPath}"
|
||||
"macaroon_secret_key:${macaroonSecretKeyPath}"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,21 +3,26 @@
|
||||
lib,
|
||||
myData,
|
||||
...
|
||||
}: let
|
||||
}:
|
||||
let
|
||||
cfg = config.mj.services.node_exporter;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.mj.services.node_exporter = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable node_exporter";
|
||||
extraSubnets = lib.mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
enabledCollectors = ["systemd" "processes"];
|
||||
enabledCollectors = [
|
||||
"systemd"
|
||||
"processes"
|
||||
];
|
||||
port = myData.ports.exporters.node;
|
||||
user = "node_exporter";
|
||||
group = "node_exporter";
|
||||
@@ -35,8 +40,8 @@ in {
|
||||
|
||||
mj.services.friendlyport.ports = [
|
||||
{
|
||||
subnets = [myData.subnets.tailscale.cidr] ++ cfg.extraSubnets;
|
||||
tcp = [myData.ports.exporters.node];
|
||||
subnets = [ myData.subnets.tailscale.cidr ] ++ cfg.extraSubnets;
|
||||
tcp = [ myData.ports.exporters.node ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
}:
|
||||
let
|
||||
cfg = config.mj.services.nsd-acme;
|
||||
mkHook = zone: let
|
||||
fullZone = "_acme-endpoint.${zone}";
|
||||
in
|
||||
mkHook =
|
||||
zone:
|
||||
let
|
||||
fullZone = "_acme-endpoint.${zone}";
|
||||
in
|
||||
pkgs.writeShellScript "nsd-acme-hook" ''
|
||||
set -euo pipefail
|
||||
METHOD=$1
|
||||
@@ -48,38 +51,42 @@
|
||||
;;
|
||||
esac
|
||||
'';
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.mj.services.nsd-acme = with lib.types; {
|
||||
enable = lib.mkEnableOption "enable acme certs via nsd";
|
||||
|
||||
zones = lib.mkOption {
|
||||
default = {};
|
||||
type = attrsOf (submodule (
|
||||
{name, ...}: {
|
||||
options = {
|
||||
accountKey = lib.mkOption {type = path;};
|
||||
days = lib.mkOption {
|
||||
type = int;
|
||||
default = 30;
|
||||
};
|
||||
staging = lib.mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
default = { };
|
||||
type = attrsOf (
|
||||
submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
accountKey = lib.mkOption { type = path; };
|
||||
days = lib.mkOption {
|
||||
type = int;
|
||||
default = 30;
|
||||
};
|
||||
staging = lib.mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
# Warning: paths here are here to be read from. Changing them will
|
||||
# not place the files somewhere else.
|
||||
certFile = lib.mkOption {
|
||||
type = str;
|
||||
default = "/var/lib/nsd-acme/${name}/${name}/cert.pem";
|
||||
# Warning: paths here are here to be read from. Changing them will
|
||||
# not place the files somewhere else.
|
||||
certFile = lib.mkOption {
|
||||
type = str;
|
||||
default = "/var/lib/nsd-acme/${name}/${name}/cert.pem";
|
||||
};
|
||||
keyFile = lib.mkOption {
|
||||
type = str;
|
||||
default = "/var/lib/nsd-acme/${name}/private/${name}/key.pem";
|
||||
};
|
||||
};
|
||||
keyFile = lib.mkOption {
|
||||
type = str;
|
||||
default = "/var/lib/nsd-acme/${name}/private/${name}/key.pem";
|
||||
};
|
||||
};
|
||||
}
|
||||
));
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -93,121 +100,122 @@ in {
|
||||
'';
|
||||
|
||||
systemd = {
|
||||
tmpfiles.rules = ["d /var/lib/nsd/acmezones 0755 nsd nsd -"];
|
||||
tmpfiles.rules = [ "d /var/lib/nsd/acmezones 0755 nsd nsd -" ];
|
||||
|
||||
services =
|
||||
{
|
||||
nsd-control-setup = {
|
||||
requiredBy = ["nsd.service"];
|
||||
before = ["nsd.service"];
|
||||
unitConfig.ConditionPathExists = let
|
||||
rc = config.services.nsd.remoteControl;
|
||||
in [
|
||||
"|!${rc.controlKeyFile}"
|
||||
"|!${rc.controlCertFile}"
|
||||
"|!${rc.serverKeyFile}"
|
||||
"|!${rc.serverCertFile}"
|
||||
];
|
||||
requiredBy = [ "nsd.service" ];
|
||||
before = [ "nsd.service" ];
|
||||
unitConfig.ConditionPathExists =
|
||||
let
|
||||
rc = config.services.nsd.remoteControl;
|
||||
in
|
||||
[
|
||||
"|!${rc.controlKeyFile}"
|
||||
"|!${rc.controlCertFile}"
|
||||
"|!${rc.serverKeyFile}"
|
||||
"|!${rc.serverCertFile}"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
UMask = 0077;
|
||||
UMask = 77;
|
||||
};
|
||||
script = ''
|
||||
${pkgs.nsd}/bin/nsd-control-setup
|
||||
chown nsd:nsd /etc/nsd/nsd_{control,server}.{key,pem}
|
||||
'';
|
||||
path = [pkgs.openssl];
|
||||
path = [ pkgs.openssl ];
|
||||
};
|
||||
}
|
||||
// lib.mapAttrs'
|
||||
(
|
||||
// lib.mapAttrs' (
|
||||
zone: cfg:
|
||||
lib.nameValuePair "nsd-acme-${zone}" {
|
||||
description = "dns-01 acme update for ${zone}";
|
||||
path = [pkgs.openssh pkgs.nsd];
|
||||
preStart = ''
|
||||
mkdir -p "$STATE_DIRECTORY/private"
|
||||
ln -sf "$CREDENTIALS_DIRECTORY/letsencrypt-account-key" \
|
||||
"$STATE_DIRECTORY/private/key.pem"
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = let
|
||||
lib.nameValuePair "nsd-acme-${zone}" {
|
||||
description = "dns-01 acme update for ${zone}";
|
||||
path = [
|
||||
pkgs.openssh
|
||||
pkgs.nsd
|
||||
];
|
||||
preStart = ''
|
||||
mkdir -p "$STATE_DIRECTORY/private"
|
||||
ln -sf "$CREDENTIALS_DIRECTORY/letsencrypt-account-key" \
|
||||
"$STATE_DIRECTORY/private/key.pem"
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
let
|
||||
hook = mkHook zone;
|
||||
days = builtins.toString cfg.days;
|
||||
in "${pkgs.uacme}/bin/uacme -c \${STATE_DIRECTORY} --verbose --days ${days} --hook ${hook} ${lib.optionalString cfg.staging "--staging"} issue ${zone}";
|
||||
in
|
||||
"${pkgs.uacme}/bin/uacme -c \${STATE_DIRECTORY} --verbose --days ${days} --hook ${hook} ${lib.optionalString cfg.staging "--staging"} issue ${zone}";
|
||||
|
||||
UMask = "0022";
|
||||
User = "nsd";
|
||||
Group = "nsd";
|
||||
StateDirectory = "nsd-acme/${zone}";
|
||||
LoadCredential = ["letsencrypt-account-key:${cfg.accountKey}"];
|
||||
ReadWritePaths = ["/var/lib/nsd/acmezones"];
|
||||
SuccessExitStatus = [0 1];
|
||||
UMask = "0022";
|
||||
User = "nsd";
|
||||
Group = "nsd";
|
||||
StateDirectory = "nsd-acme/${zone}";
|
||||
LoadCredential = [ "letsencrypt-account-key:${cfg.accountKey}" ];
|
||||
ReadWritePaths = [ "/var/lib/nsd/acmezones" ];
|
||||
SuccessExitStatus = [
|
||||
0
|
||||
1
|
||||
];
|
||||
|
||||
# from nixos/modules/security/acme/default.nix
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
CapabilityBoundingSet = [""];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
ProtectClock = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
RemoveIPC = true;
|
||||
# "cannot get devices"
|
||||
#RestrictAddressFamilies = [
|
||||
# "AF_INET"
|
||||
# "AF_INET6"
|
||||
#];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
# 1. allow a reasonable set of syscalls
|
||||
"@system-service @resources"
|
||||
# 2. and deny unreasonable ones
|
||||
"~@privileged"
|
||||
# 3. then allow the required subset within denied groups
|
||||
"@chown"
|
||||
];
|
||||
};
|
||||
}
|
||||
)
|
||||
cfg.zones;
|
||||
# from nixos/modules/security/acme/default.nix
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
ProtectClock = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
RemoveIPC = true;
|
||||
# "cannot get devices"
|
||||
#RestrictAddressFamilies = [
|
||||
# "AF_INET"
|
||||
# "AF_INET6"
|
||||
#];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
# 1. allow a reasonable set of syscalls
|
||||
"@system-service @resources"
|
||||
# 2. and deny unreasonable ones
|
||||
"~@privileged"
|
||||
# 3. then allow the required subset within denied groups
|
||||
"@chown"
|
||||
];
|
||||
};
|
||||
}
|
||||
) cfg.zones;
|
||||
|
||||
timers =
|
||||
lib.mapAttrs'
|
||||
(
|
||||
zone: _:
|
||||
lib.nameValuePair "nsd-acme-${zone}" {
|
||||
description = "nsd-acme for zone ${zone}";
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 01:30";
|
||||
};
|
||||
after = ["network-online.target"];
|
||||
wants = ["network-online.target"];
|
||||
}
|
||||
)
|
||||
cfg.zones;
|
||||
timers = lib.mapAttrs' (
|
||||
zone: _:
|
||||
lib.nameValuePair "nsd-acme-${zone}" {
|
||||
description = "nsd-acme for zone ${zone}";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 01:30";
|
||||
};
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
}
|
||||
) cfg.zones;
|
||||
};
|
||||
|
||||
mj.base.unitstatus.units =
|
||||
lib.mkIf config.mj.base.unitstatus.enable
|
||||
(
|
||||
["nsd-control-setup"]
|
||||
++ map (z: "nsd-acme-${z}")
|
||||
(lib.attrNames cfg.zones)
|
||||
);
|
||||
mj.base.unitstatus.units = lib.mkIf config.mj.base.unitstatus.enable (
|
||||
[ "nsd-control-setup" ] ++ map (z: "nsd-acme-${z}") (lib.attrNames cfg.zones)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
myData,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.postfix = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable postfix";
|
||||
saslPasswdPath = lib.mkOption {type = path;};
|
||||
saslPasswdPath = lib.mkOption { type = path; };
|
||||
};
|
||||
|
||||
config = lib.mkIf config.mj.services.postfix.enable {
|
||||
environment.systemPackages = [pkgs.mailutils];
|
||||
environment.systemPackages = [ pkgs.mailutils ];
|
||||
|
||||
services.postfix = {
|
||||
enable = true;
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options.mj.services.remote-builder = with lib.types; {
|
||||
server = {
|
||||
enable = lib.mkEnableOption "Enable remote builder server";
|
||||
uidgid = lib.mkOption {type = int;};
|
||||
sshAllowSubnet = lib.mkOption {type = str;};
|
||||
publicKeys = lib.mkOption {type = listOf str;};
|
||||
uidgid = lib.mkOption { type = int; };
|
||||
sshAllowSubnet = lib.mkOption { type = str; };
|
||||
publicKeys = lib.mkOption { type = listOf str; };
|
||||
};
|
||||
client = {
|
||||
enable = lib.mkEnableOption "Enable remote builder client";
|
||||
system = lib.mkOption {type = enum ["aarch64-linux" "x86_64-linux"];};
|
||||
hostName = lib.mkOption {type = str;};
|
||||
sshKey = lib.mkOption {type = path;};
|
||||
supportedFeatures = lib.mkOption {type = listOf str;};
|
||||
system = lib.mkOption {
|
||||
type = enum [
|
||||
"aarch64-linux"
|
||||
"x86_64-linux"
|
||||
];
|
||||
};
|
||||
hostName = lib.mkOption { type = str; };
|
||||
sshKey = lib.mkOption { type = path; };
|
||||
supportedFeatures = lib.mkOption { type = listOf str; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,42 +26,43 @@
|
||||
let
|
||||
cfg = config.mj.services.remote-builder.server;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
users.users.remote-builder = {
|
||||
description = "Remote Builder";
|
||||
home = "/var/lib/remote-builder";
|
||||
shell = "/bin/sh";
|
||||
group = "remote-builder";
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
uid = cfg.uidgid;
|
||||
openssh.authorizedKeys.keys =
|
||||
map (
|
||||
k: "from=\"${cfg.sshAllowSubnet}\" ${k}"
|
||||
)
|
||||
cfg.publicKeys;
|
||||
};
|
||||
users.groups.remote-builder.gid = cfg.uidgid;
|
||||
nix.settings.trusted-users = ["remote-builder"];
|
||||
}
|
||||
lib.mkIf cfg.enable {
|
||||
users.users.remote-builder = {
|
||||
description = "Remote Builder";
|
||||
home = "/var/lib/remote-builder";
|
||||
shell = "/bin/sh";
|
||||
group = "remote-builder";
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
uid = cfg.uidgid;
|
||||
openssh.authorizedKeys.keys = map (k: ''from="${cfg.sshAllowSubnet}" ${k}'') cfg.publicKeys;
|
||||
};
|
||||
users.groups.remote-builder.gid = cfg.uidgid;
|
||||
nix.settings.trusted-users = [ "remote-builder" ];
|
||||
}
|
||||
)
|
||||
(
|
||||
let
|
||||
cfg = config.mj.services.remote-builder.client;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
nix = {
|
||||
buildMachines = [
|
||||
{
|
||||
inherit (cfg) hostName system sshKey supportedFeatures;
|
||||
protocol = "ssh-ng";
|
||||
sshUser = "remote-builder";
|
||||
}
|
||||
];
|
||||
distributedBuilds = true;
|
||||
extraOptions = ''builders-use-substitutes = true'';
|
||||
};
|
||||
}
|
||||
lib.mkIf cfg.enable {
|
||||
nix = {
|
||||
buildMachines = [
|
||||
{
|
||||
inherit (cfg)
|
||||
hostName
|
||||
system
|
||||
sshKey
|
||||
supportedFeatures
|
||||
;
|
||||
protocol = "ssh-ng";
|
||||
sshUser = "remote-builder";
|
||||
}
|
||||
];
|
||||
distributedBuilds = true;
|
||||
extraOptions = "builders-use-substitutes = true";
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
lib,
|
||||
myData,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.sshguard = with lib.types; {
|
||||
enable = lib.mkOption {
|
||||
type = bool;
|
||||
@@ -15,9 +16,10 @@
|
||||
services.sshguard = {
|
||||
enable = true;
|
||||
blocktime = 900;
|
||||
whitelist =
|
||||
["192.168.0.0/16" myData.subnets.tailscale.cidr]
|
||||
++ (lib.catAttrs "publicIP" (lib.attrValues myData.hosts));
|
||||
whitelist = [
|
||||
"192.168.0.0/16"
|
||||
myData.subnets.tailscale.cidr
|
||||
] ++ (lib.catAttrs "publicIP" (lib.attrValues myData.hosts));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
lib,
|
||||
myData,
|
||||
...
|
||||
}: let
|
||||
}:
|
||||
let
|
||||
cfg = config.mj.services.syncthing;
|
||||
|
||||
devices = {
|
||||
@@ -20,17 +21,29 @@
|
||||
};
|
||||
folders = {
|
||||
Books = {
|
||||
devices = ["fwminex" "vno1-oh2" "mxp10"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
"mxp10"
|
||||
];
|
||||
id = "8lk0n-mm63y";
|
||||
label = "Books";
|
||||
};
|
||||
Mail = {
|
||||
devices = ["fwminex" "vno1-oh2"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "66fmz-x6f1a";
|
||||
label = "Mail";
|
||||
};
|
||||
M-Active = {
|
||||
devices = ["mxp10" "fwminex" "mtworx" "vno1-oh2"];
|
||||
devices = [
|
||||
"mxp10"
|
||||
"fwminex"
|
||||
"mtworx"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "f6fma-unkxq";
|
||||
label = "M-Active";
|
||||
versioning = {
|
||||
@@ -42,99 +55,157 @@
|
||||
};
|
||||
};
|
||||
M-Documents = {
|
||||
devices = ["fwminex" "vno1-oh2"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "4fu7z-z6es2";
|
||||
label = "M-Documents";
|
||||
};
|
||||
Vaikai = {
|
||||
devices = ["vno1-vinc" "sqq1-desk" "fwminex" "mtworx" "vno1-oh2" "v-kfire" "rzj-744P2PE" "mxp10" "a-kfire"];
|
||||
devices = [
|
||||
"vno1-vinc"
|
||||
"sqq1-desk"
|
||||
"fwminex"
|
||||
"mtworx"
|
||||
"vno1-oh2"
|
||||
"v-kfire"
|
||||
"rzj-744P2PE"
|
||||
"mxp10"
|
||||
"a-kfire"
|
||||
];
|
||||
id = "xbrfr-mhszm";
|
||||
label = "Vaikai";
|
||||
};
|
||||
M-Camera = {
|
||||
devices = ["mxp10" "fwminex" "mtworx" "vno1-oh2"];
|
||||
devices = [
|
||||
"mxp10"
|
||||
"fwminex"
|
||||
"mtworx"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "pixel_xl_dtm3-photos";
|
||||
label = "M-Camera";
|
||||
};
|
||||
R-Documents = {
|
||||
devices = ["rzj-744P2PE" "vno1-oh2"];
|
||||
devices = [
|
||||
"rzj-744P2PE"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "nm23h-aog6k";
|
||||
label = "R-Documents";
|
||||
};
|
||||
Pictures = {
|
||||
devices = ["fwminex" "vno1-oh2"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "d3hur-cbzyw";
|
||||
label = "Pictures";
|
||||
};
|
||||
Music = {
|
||||
devices = ["fwminex" "mtworx" "mxp10" "vno1-oh2"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"mtworx"
|
||||
"mxp10"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "tg94v-cqcwr";
|
||||
label = "music";
|
||||
};
|
||||
video-shared = {
|
||||
devices = ["mxp10" "mtworx" "fwminex" "vno1-oh2"];
|
||||
devices = [
|
||||
"mxp10"
|
||||
"mtworx"
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "byzmw-f6zhg";
|
||||
label = "video-shared";
|
||||
};
|
||||
stud-cache = {
|
||||
devices = ["fwminex" "vno1-oh2"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "2kq7n-jqzxj";
|
||||
label = "stud-cache";
|
||||
};
|
||||
M-R = {
|
||||
devices = ["fwminex" "rzj-744P2PE" "mxp10" "vno1-oh2" "mtworx"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"rzj-744P2PE"
|
||||
"mxp10"
|
||||
"vno1-oh2"
|
||||
"mtworx"
|
||||
];
|
||||
id = "evgn9-ahngz";
|
||||
label = "M-R";
|
||||
};
|
||||
Irenos = {
|
||||
devices = ["sqq1-desk" "vno1-oh2" "vno2-irena"];
|
||||
devices = [
|
||||
"sqq1-desk"
|
||||
"vno1-oh2"
|
||||
"vno2-irena"
|
||||
];
|
||||
id = "wuwai-qkcqj";
|
||||
label = "Irenos";
|
||||
};
|
||||
www-fwminex = {
|
||||
devices = ["fwminex" "vno1-oh2"];
|
||||
devices = [
|
||||
"fwminex"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "7z9sw-2nubh";
|
||||
label = "www-fwminex";
|
||||
};
|
||||
www-mxp10 = {
|
||||
devices = ["mxp10" "vno1-oh2"];
|
||||
devices = [
|
||||
"mxp10"
|
||||
"vno1-oh2"
|
||||
];
|
||||
id = "gqrtz-prx9h";
|
||||
label = "www-mxp10";
|
||||
};
|
||||
mykolo = {
|
||||
devices = ["mxp10"];
|
||||
devices = [ "mxp10" ];
|
||||
id = "wslmq-fyw4w";
|
||||
label = "mykolo";
|
||||
};
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.mj.services.syncthing = with lib.types; {
|
||||
enable = lib.mkEnableOption "Enable services syncthing settings";
|
||||
user = lib.mkOption {type = str;};
|
||||
group = lib.mkOption {type = str;};
|
||||
dataDir = lib.mkOption {type = path;};
|
||||
user = lib.mkOption { type = str; };
|
||||
group = lib.mkOption { type = str; };
|
||||
dataDir = lib.mkOption { type = path; };
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
mj.services.friendlyport.ports = [
|
||||
{
|
||||
subnets = myData.subnets.motiejus.cidrs;
|
||||
tcp = [8384];
|
||||
tcp = [ 8384 ];
|
||||
}
|
||||
];
|
||||
|
||||
services.syncthing = {
|
||||
inherit (cfg) enable user group dataDir;
|
||||
inherit (cfg)
|
||||
enable
|
||||
user
|
||||
group
|
||||
dataDir
|
||||
;
|
||||
openDefaultPorts = true;
|
||||
key = config.age.secrets.syncthing-key.path;
|
||||
cert = config.age.secrets.syncthing-cert.path;
|
||||
|
||||
settings = {
|
||||
devices =
|
||||
{}
|
||||
{ }
|
||||
// (lib.optionalAttrs (config.networking.hostName == "vno1-oh2") {
|
||||
inherit
|
||||
(devices)
|
||||
inherit (devices)
|
||||
fwminex
|
||||
mtworx
|
||||
vno1-oh2
|
||||
@@ -148,8 +219,7 @@ in {
|
||||
;
|
||||
})
|
||||
// (lib.optionalAttrs (config.networking.hostName == "fwminex") {
|
||||
inherit
|
||||
(devices)
|
||||
inherit (devices)
|
||||
fwminex
|
||||
mtworx
|
||||
vno1-oh2
|
||||
@@ -162,8 +232,7 @@ in {
|
||||
;
|
||||
})
|
||||
// (lib.optionalAttrs (config.networking.hostName == "mtworx") {
|
||||
inherit
|
||||
(devices)
|
||||
inherit (devices)
|
||||
mtworx
|
||||
fwminex
|
||||
vno1-oh2
|
||||
@@ -175,55 +244,50 @@ in {
|
||||
v-kfire
|
||||
;
|
||||
})
|
||||
// {};
|
||||
folders = with folders;
|
||||
{}
|
||||
// (
|
||||
lib.optionalAttrs (config.networking.hostName == "vno1-oh2") {
|
||||
"/var/www/dl/tel" = www-mxp10;
|
||||
"/var/www/dl/fwminex" = www-fwminex;
|
||||
"/var/www/dl/mykolo" = mykolo;
|
||||
"${cfg.dataDir}/annex2/Books" = Books;
|
||||
"${cfg.dataDir}/annex2/Mail" = Mail;
|
||||
"${cfg.dataDir}/annex2/M-Active" = M-Active;
|
||||
"${cfg.dataDir}/annex2/M-Camera" = M-Camera;
|
||||
"${cfg.dataDir}/annex2/M-Documents" = M-Documents;
|
||||
"${cfg.dataDir}/annex2/R-Documents" = R-Documents;
|
||||
"${cfg.dataDir}/annex2/Pictures" = Pictures;
|
||||
"${cfg.dataDir}/annex2/M-R" = M-R;
|
||||
"${cfg.dataDir}/stud-cache" = stud-cache;
|
||||
"${cfg.dataDir}/video/shared" = video-shared;
|
||||
"${cfg.dataDir}/video/Vaikai" = Vaikai;
|
||||
"${cfg.dataDir}/music" = Music;
|
||||
"${cfg.dataDir}/irenos" = Irenos;
|
||||
}
|
||||
)
|
||||
// (
|
||||
lib.optionalAttrs (config.networking.hostName == "mtworx") {
|
||||
"${cfg.dataDir}/M-Active" = M-Active;
|
||||
"${cfg.dataDir}/M-Camera" = M-Camera;
|
||||
"${cfg.dataDir}/M-R" = M-R;
|
||||
"${cfg.dataDir}/Vaikai" = Vaikai;
|
||||
"${cfg.dataDir}/Video" = video-shared;
|
||||
"${cfg.dataDir}/music" = Music;
|
||||
}
|
||||
)
|
||||
// (
|
||||
lib.optionalAttrs (config.networking.hostName == "fwminex") {
|
||||
"${cfg.dataDir}/.cache/evolution" = Mail;
|
||||
"${cfg.dataDir}/Books" = Books;
|
||||
"${cfg.dataDir}/M-Active" = M-Active;
|
||||
"${cfg.dataDir}/M-Documents" = M-Documents;
|
||||
"${cfg.dataDir}/M-Camera" = M-Camera;
|
||||
"${cfg.dataDir}/Pictures" = Pictures;
|
||||
"${cfg.dataDir}/Music" = Music;
|
||||
"${cfg.dataDir}/M-R" = M-R;
|
||||
"${cfg.dataDir}/Vaikai" = Vaikai;
|
||||
"${cfg.dataDir}/Video" = video-shared;
|
||||
"${cfg.dataDir}/stud-cache" = stud-cache;
|
||||
"${cfg.dataDir}/www" = www-fwminex;
|
||||
}
|
||||
);
|
||||
// { };
|
||||
folders =
|
||||
with folders;
|
||||
{ }
|
||||
// (lib.optionalAttrs (config.networking.hostName == "vno1-oh2") {
|
||||
"/var/www/dl/tel" = www-mxp10;
|
||||
"/var/www/dl/fwminex" = www-fwminex;
|
||||
"/var/www/dl/mykolo" = mykolo;
|
||||
"${cfg.dataDir}/annex2/Books" = Books;
|
||||
"${cfg.dataDir}/annex2/Mail" = Mail;
|
||||
"${cfg.dataDir}/annex2/M-Active" = M-Active;
|
||||
"${cfg.dataDir}/annex2/M-Camera" = M-Camera;
|
||||
"${cfg.dataDir}/annex2/M-Documents" = M-Documents;
|
||||
"${cfg.dataDir}/annex2/R-Documents" = R-Documents;
|
||||
"${cfg.dataDir}/annex2/Pictures" = Pictures;
|
||||
"${cfg.dataDir}/annex2/M-R" = M-R;
|
||||
"${cfg.dataDir}/stud-cache" = stud-cache;
|
||||
"${cfg.dataDir}/video/shared" = video-shared;
|
||||
"${cfg.dataDir}/video/Vaikai" = Vaikai;
|
||||
"${cfg.dataDir}/music" = Music;
|
||||
"${cfg.dataDir}/irenos" = Irenos;
|
||||
})
|
||||
// (lib.optionalAttrs (config.networking.hostName == "mtworx") {
|
||||
"${cfg.dataDir}/M-Active" = M-Active;
|
||||
"${cfg.dataDir}/M-Camera" = M-Camera;
|
||||
"${cfg.dataDir}/M-R" = M-R;
|
||||
"${cfg.dataDir}/Vaikai" = Vaikai;
|
||||
"${cfg.dataDir}/Video" = video-shared;
|
||||
"${cfg.dataDir}/music" = Music;
|
||||
})
|
||||
// (lib.optionalAttrs (config.networking.hostName == "fwminex") {
|
||||
"${cfg.dataDir}/.cache/evolution" = Mail;
|
||||
"${cfg.dataDir}/Books" = Books;
|
||||
"${cfg.dataDir}/M-Active" = M-Active;
|
||||
"${cfg.dataDir}/M-Documents" = M-Documents;
|
||||
"${cfg.dataDir}/M-Camera" = M-Camera;
|
||||
"${cfg.dataDir}/Pictures" = Pictures;
|
||||
"${cfg.dataDir}/Music" = Music;
|
||||
"${cfg.dataDir}/M-R" = M-R;
|
||||
"${cfg.dataDir}/Vaikai" = Vaikai;
|
||||
"${cfg.dataDir}/Video" = video-shared;
|
||||
"${cfg.dataDir}/stud-cache" = stud-cache;
|
||||
"${cfg.dataDir}/www" = www-fwminex;
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,10 +3,18 @@
|
||||
lib,
|
||||
myData,
|
||||
...
|
||||
}: let
|
||||
}:
|
||||
let
|
||||
cfg = config.mj.services.tailscale;
|
||||
inherit (lib) mkMerge types mkEnableOption mkOption mkIf;
|
||||
in {
|
||||
inherit (lib)
|
||||
mkMerge
|
||||
types
|
||||
mkEnableOption
|
||||
mkOption
|
||||
mkIf
|
||||
;
|
||||
in
|
||||
{
|
||||
options.mj.services.tailscale = with types; {
|
||||
enable = mkEnableOption "Enable tailscale";
|
||||
# https://github.com/tailscale/tailscale/issues/1548
|
||||
@@ -20,13 +28,11 @@ in {
|
||||
{
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
extraUpFlags = ["--operator=${config.mj.username}"];
|
||||
extraUpFlags = [ "--operator=${config.mj.username}" ];
|
||||
};
|
||||
networking.firewall.checkReversePath = "loose";
|
||||
networking.firewall.allowedUDPPorts = [myData.ports.tailscale];
|
||||
networking.firewall.allowedUDPPorts = [ myData.ports.tailscale ];
|
||||
}
|
||||
(mkIf (!cfg.verboseLogs) {
|
||||
systemd.services.tailscaled.serviceConfig.StandardOutput = "null";
|
||||
})
|
||||
(mkIf (!cfg.verboseLogs) { systemd.services.tailscaled.serviceConfig.StandardOutput = "null"; })
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}:
|
||||
{
|
||||
options.mj.services.wifibackup = with lib.types; {
|
||||
enable = lib.mkEnableOption "enable wifi code backups to M-Active";
|
||||
fromPath = lib.mkOption {
|
||||
@@ -20,11 +21,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
config = with config.mj.services.wifibackup;
|
||||
config =
|
||||
with config.mj.services.wifibackup;
|
||||
lib.mkIf enable {
|
||||
systemd.timers.wifibackup = {
|
||||
description = "wifibackup to M-Active";
|
||||
wantedBy = ["timers.target"];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = "*-*-* 22:00:00 UTC";
|
||||
};
|
||||
systemd.services.wifibackup = {
|
||||
@@ -32,25 +34,30 @@
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
SuccessExitStatus = [0 1];
|
||||
SuccessExitStatus = [
|
||||
0
|
||||
1
|
||||
];
|
||||
};
|
||||
script = let
|
||||
knownHostsCmd = pkgs.writeShellScript "known-hosts-localhost" ''
|
||||
echo -n "localhost "
|
||||
exec ${pkgs.coreutils}/bin/cat /etc/ssh/ssh_host_ed25519_key.pub
|
||||
'';
|
||||
in ''
|
||||
sed -i -E '/^(uuid|interface-name)=/d' ${fromPath}/*.nmconnection
|
||||
script =
|
||||
let
|
||||
knownHostsCmd = pkgs.writeShellScript "known-hosts-localhost" ''
|
||||
echo -n "localhost "
|
||||
exec ${pkgs.coreutils}/bin/cat /etc/ssh/ssh_host_ed25519_key.pub
|
||||
'';
|
||||
in
|
||||
''
|
||||
sed -i -E '/^(uuid|interface-name)=/d' ${fromPath}/*.nmconnection
|
||||
|
||||
exec ${pkgs.unison}/bin/unison \
|
||||
-sshcmd ${pkgs.openssh}/bin/ssh \
|
||||
-sshargs "-i /etc/ssh/ssh_host_ed25519_key -o KnownHostsCommand=${knownHostsCmd} -o UserKnownHostsFile=none -o GlobalKnownHostsFile=/dev/null" \
|
||||
-batch \
|
||||
-backuploc local \
|
||||
-backup "Name *" \
|
||||
${fromPath} \
|
||||
ssh://${toUser}@localhost/${toPath}/
|
||||
'';
|
||||
exec ${pkgs.unison}/bin/unison \
|
||||
-sshcmd ${pkgs.openssh}/bin/ssh \
|
||||
-sshargs "-i /etc/ssh/ssh_host_ed25519_key -o KnownHostsCommand=${knownHostsCmd} -o UserKnownHostsFile=none -o GlobalKnownHostsFile=/dev/null" \
|
||||
-batch \
|
||||
-backuploc local \
|
||||
-backup "Name *" \
|
||||
${fromPath} \
|
||||
ssh://${toUser}@localhost/${toPath}/
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,85 +3,84 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
mkUnlock = {
|
||||
sshEndpoint,
|
||||
pingEndpoint,
|
||||
remotePubkey,
|
||||
pwFile,
|
||||
pingTimeoutSec,
|
||||
}: let
|
||||
timeoutStr = builtins.toString pingTimeoutSec;
|
||||
in ''
|
||||
set -x
|
||||
# if host is reachable via "pingEndpoint", which, we presume is
|
||||
# VPN (which implies the rootfs has been unlocked for VPN to work),
|
||||
# exit successfully.
|
||||
${pkgs.iputils}/bin/ping -q -W ${timeoutStr} -c 1 ${pingEndpoint} && exit 0
|
||||
}:
|
||||
let
|
||||
mkUnlock =
|
||||
{
|
||||
sshEndpoint,
|
||||
pingEndpoint,
|
||||
remotePubkey,
|
||||
pwFile,
|
||||
pingTimeoutSec,
|
||||
}:
|
||||
let
|
||||
timeoutStr = builtins.toString pingTimeoutSec;
|
||||
in
|
||||
''
|
||||
set -x
|
||||
# if host is reachable via "pingEndpoint", which, we presume is
|
||||
# VPN (which implies the rootfs has been unlocked for VPN to work),
|
||||
# exit successfully.
|
||||
${pkgs.iputils}/bin/ping -q -W ${timeoutStr} -c 1 ${pingEndpoint} && exit 0
|
||||
|
||||
exec ${pkgs.openssh}/bin/ssh \
|
||||
-i /etc/ssh/ssh_host_ed25519_key \
|
||||
-o UserKnownHostsFile=none \
|
||||
-o GlobalKnownHostsFile=/dev/null \
|
||||
-o KnownHostsCommand="${pkgs.coreutils}/bin/echo ${sshEndpoint} ${remotePubkey}" \
|
||||
root@${sshEndpoint} < "${pwFile}"
|
||||
'';
|
||||
in {
|
||||
exec ${pkgs.openssh}/bin/ssh \
|
||||
-i /etc/ssh/ssh_host_ed25519_key \
|
||||
-o UserKnownHostsFile=none \
|
||||
-o GlobalKnownHostsFile=/dev/null \
|
||||
-o KnownHostsCommand="${pkgs.coreutils}/bin/echo ${sshEndpoint} ${remotePubkey}" \
|
||||
root@${sshEndpoint} < "${pwFile}"
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.mj.services.zfsunlock = with lib.types; {
|
||||
enable = lib.mkEnableOption "remotely unlock zfs-encrypted root volumes";
|
||||
|
||||
targets = lib.mkOption {
|
||||
default = {};
|
||||
default = { };
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
sshEndpoint = lib.mkOption {type = str;};
|
||||
pingEndpoint = lib.mkOption {type = str;};
|
||||
sshEndpoint = lib.mkOption { type = str; };
|
||||
pingEndpoint = lib.mkOption { type = str; };
|
||||
pingTimeoutSec = lib.mkOption {
|
||||
type = int;
|
||||
default = 20;
|
||||
};
|
||||
remotePubkey = lib.mkOption {type = str;};
|
||||
pwFile = lib.mkOption {type = path;};
|
||||
startAt = lib.mkOption {type = either str (listOf str);};
|
||||
remotePubkey = lib.mkOption { type = str; };
|
||||
pwFile = lib.mkOption { type = path; };
|
||||
startAt = lib.mkOption { type = either str (listOf str); };
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.mj.services.zfsunlock.enable {
|
||||
systemd.services =
|
||||
lib.mapAttrs'
|
||||
(
|
||||
name: cfg:
|
||||
lib.nameValuePair "zfsunlock-${name}" {
|
||||
description = "zfsunlock service for ${name}";
|
||||
script = mkUnlock (builtins.removeAttrs cfg ["startAt"]);
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
ProtectSystem = "strict";
|
||||
};
|
||||
}
|
||||
)
|
||||
config.mj.services.zfsunlock.targets;
|
||||
systemd.services = lib.mapAttrs' (
|
||||
name: cfg:
|
||||
lib.nameValuePair "zfsunlock-${name}" {
|
||||
description = "zfsunlock service for ${name}";
|
||||
script = mkUnlock (builtins.removeAttrs cfg [ "startAt" ]);
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
ProtectSystem = "strict";
|
||||
};
|
||||
}
|
||||
) config.mj.services.zfsunlock.targets;
|
||||
|
||||
systemd.timers =
|
||||
lib.mapAttrs'
|
||||
(
|
||||
name: cfg:
|
||||
lib.nameValuePair "zfsunlock-${name}" {
|
||||
description = "zfsunlock timer for ${name}";
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
OnCalendar = cfg.startAt;
|
||||
};
|
||||
after = ["network-online.target"];
|
||||
wants = ["network-online.target"];
|
||||
}
|
||||
)
|
||||
config.mj.services.zfsunlock.targets;
|
||||
systemd.timers = lib.mapAttrs' (
|
||||
name: cfg:
|
||||
lib.nameValuePair "zfsunlock-${name}" {
|
||||
description = "zfsunlock timer for ${name}";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = cfg.startAt;
|
||||
};
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
}
|
||||
) config.mj.services.zfsunlock.targets;
|
||||
|
||||
mj.base.unitstatus.units =
|
||||
map (name: "zfsunlock-${name}")
|
||||
(builtins.attrNames config.mj.services.zfsunlock.targets);
|
||||
mj.base.unitstatus.units = map (name: "zfsunlock-${name}") (
|
||||
builtins.attrNames config.mj.services.zfsunlock.targets
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user