repeated_keys
This commit is contained in:
62
flake.nix
62
flake.nix
@@ -158,38 +158,40 @@
|
|||||||
# Add a module to a specific host.
|
# Add a module to a specific host.
|
||||||
systems = {
|
systems = {
|
||||||
# common modules
|
# common modules
|
||||||
modules.nixos = with inputs; [
|
modules = {
|
||||||
authentik-nix.nixosModules.default
|
nixos = with inputs; [
|
||||||
disko.nixosModules.disko
|
authentik-nix.nixosModules.default
|
||||||
impermanence.nixosModules.impermanence
|
disko.nixosModules.disko
|
||||||
lanzaboote.nixosModules.lanzaboote
|
impermanence.nixosModules.impermanence
|
||||||
sops-nix.nixosModules.sops
|
lanzaboote.nixosModules.lanzaboote
|
||||||
home-manager.nixosModules.home-manager
|
sops-nix.nixosModules.sops
|
||||||
nix-index-database.nixosModules.nix-index
|
home-manager.nixosModules.home-manager
|
||||||
stylix.nixosModules.stylix
|
nix-index-database.nixosModules.nix-index
|
||||||
];
|
stylix.nixosModules.stylix
|
||||||
|
];
|
||||||
|
|
||||||
# External HM modules injected into ALL homes — both standalone
|
# External HM modules injected into ALL homes — both standalone
|
||||||
# homeConfigurations and homes embedded in nixosConfigurations.
|
# homeConfigurations and homes embedded in nixosConfigurations.
|
||||||
# The snowfall-lib fork patches create-systems to pass systems.modules.home
|
# The snowfall-lib fork patches create-systems to pass systems.modules.home
|
||||||
# into create-home-system-modules so both paths are covered from here.
|
# into create-home-system-modules so both paths are covered from here.
|
||||||
# The ARM guard for steam-rom-manager is handled by that module itself.
|
# The ARM guard for steam-rom-manager is handled by that module itself.
|
||||||
modules.home = with inputs; [
|
home = with inputs; [
|
||||||
nix-index-database.homeModules.nix-index
|
nix-index-database.homeModules.nix-index
|
||||||
steam-rom-manager.homeManagerModules.default
|
steam-rom-manager.homeManagerModules.default
|
||||||
sops-nix.homeManagerModules.sops
|
sops-nix.homeManagerModules.sops
|
||||||
stylix.homeModules.stylix
|
stylix.homeModules.stylix
|
||||||
plasma-manager.homeModules.plasma-manager
|
plasma-manager.homeModules.plasma-manager
|
||||||
];
|
];
|
||||||
|
|
||||||
modules.darwin = with inputs; [
|
darwin = with inputs; [
|
||||||
nix-homebrew.darwinModules.nix-homebrew
|
nix-homebrew.darwinModules.nix-homebrew
|
||||||
home-manager.darwinModules.home-manager
|
home-manager.darwinModules.home-manager
|
||||||
nix-plist-manager.darwinModules.default
|
nix-plist-manager.darwinModules.default
|
||||||
nix-rosetta-builder.darwinModules.default
|
nix-rosetta-builder.darwinModules.default
|
||||||
nix-index-database.darwinModules.nix-index
|
nix-index-database.darwinModules.nix-index
|
||||||
stylix.darwinModules.stylix
|
stylix.darwinModules.stylix
|
||||||
];
|
];
|
||||||
|
};
|
||||||
|
|
||||||
# Host config
|
# Host config
|
||||||
hosts = {
|
hosts = {
|
||||||
|
|||||||
@@ -15,9 +15,11 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
home.username = "matt";
|
home = {
|
||||||
home.homeDirectory = "/home/matt";
|
username = "matt";
|
||||||
home.stateVersion = "23.11";
|
homeDirectory = "/home/matt";
|
||||||
|
stateVersion = "23.11";
|
||||||
|
};
|
||||||
|
|
||||||
${namespace} = {
|
${namespace} = {
|
||||||
desktop.plasma = lib.mkForce enabled;
|
desktop.plasma = lib.mkForce enabled;
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ in
|
|||||||
|
|
||||||
coolercontrol.enable = mkBoolOpt false "Enable CoolerControl fan/cooling control";
|
coolercontrol.enable = mkBoolOpt false "Enable CoolerControl fan/cooling control";
|
||||||
|
|
||||||
corectrl.enable = mkBoolOpt false "Enable CoreCtrl GPU control";
|
corectrl = {
|
||||||
corectrl.enablePolkit = mkBoolOpt false "Enable CoreCtrl polkit rules";
|
enable = mkBoolOpt false "Enable CoreCtrl GPU control";
|
||||||
corectrl.polkitGroup = mkOpt types.str "wheel" "Group allowed to use CoreCtrl without password";
|
enablePolkit = mkBoolOpt false "Enable CoreCtrl polkit rules";
|
||||||
|
polkitGroup = mkOpt types.str "wheel" "Group allowed to use CoreCtrl without password";
|
||||||
|
};
|
||||||
|
|
||||||
lact.enable = mkBoolOpt false "Enable LACT daemon (AMD GPU control)";
|
lact.enable = mkBoolOpt false "Enable LACT daemon (AMD GPU control)";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -118,51 +118,55 @@ let
|
|||||||
];
|
];
|
||||||
|
|
||||||
# Systemd service for automatic model updates
|
# Systemd service for automatic model updates
|
||||||
systemd.services.update-qwen-model = {
|
systemd = {
|
||||||
description = "Update Qwen3-Coder-Next model from HuggingFace";
|
services = {
|
||||||
serviceConfig = {
|
update-qwen-model = {
|
||||||
Type = "oneshot";
|
description = "Update Qwen3-Coder-Next model from HuggingFace";
|
||||||
ExecStart = "${pkgs.writeShellScript "update-qwen-model" ''
|
serviceConfig = {
|
||||||
set -euo pipefail
|
Type = "oneshot";
|
||||||
|
ExecStart = "${pkgs.writeShellScript "update-qwen-model" ''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
MODEL_DIR="${cfg.configDir}/llama-cpp/models"
|
MODEL_DIR="${cfg.configDir}/llama-cpp/models"
|
||||||
MODEL_NAME="${cfg.llama-cpp.model}.gguf"
|
MODEL_NAME="${cfg.llama-cpp.model}.gguf"
|
||||||
REPO_ID="unsloth/Qwen3-Coder-Next-GGUF"
|
REPO_ID="unsloth/Qwen3-Coder-Next-GGUF"
|
||||||
|
|
||||||
# Create model directory if it doesn't exist
|
# Create model directory if it doesn't exist
|
||||||
mkdir -p "$MODEL_DIR"
|
mkdir -p "$MODEL_DIR"
|
||||||
|
|
||||||
# Download the latest version of the model
|
# Download the latest version of the model
|
||||||
echo "Updating $MODEL_NAME from HuggingFace..."
|
echo "Updating $MODEL_NAME from HuggingFace..."
|
||||||
${pkgs.python3Packages.huggingface-hub}/bin/hf download \
|
${pkgs.python3Packages.huggingface-hub}/bin/hf download \
|
||||||
"$REPO_ID" \
|
"$REPO_ID" \
|
||||||
"$MODEL_NAME" \
|
"$MODEL_NAME" \
|
||||||
--local-dir "$MODEL_DIR"
|
--local-dir "$MODEL_DIR"
|
||||||
|
|
||||||
echo "Model updated successfully"
|
echo "Model updated successfully"
|
||||||
''}";
|
''}";
|
||||||
User = "nix-apps";
|
User = "nix-apps";
|
||||||
Group = "jallen-nas";
|
Group = "jallen-nas";
|
||||||
EnvironmentFile = [ config.sops.templates."ntfy.env".path ];
|
EnvironmentFile = [ config.sops.templates."ntfy.env".path ];
|
||||||
|
};
|
||||||
|
unitConfig.OnFailure = "update-qwen-model-notify-failure.service";
|
||||||
|
# Run daily at 3 AM
|
||||||
|
startAt = "*-*-* 03:00:00";
|
||||||
|
};
|
||||||
|
|
||||||
|
update-qwen-model-notify-failure = {
|
||||||
|
description = "Notify ntfy on update-qwen-model failure";
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${ntfyModelFailScript}";
|
||||||
|
EnvironmentFile = [ config.sops.templates."ntfy.env".path ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Ensure model is available before llama-cpp starts
|
||||||
|
llama-cpp = {
|
||||||
|
after = [ "update-qwen-model.service" ];
|
||||||
|
wants = [ "update-qwen-model.service" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
unitConfig.OnFailure = "update-qwen-model-notify-failure.service";
|
|
||||||
# Run daily at 3 AM
|
|
||||||
startAt = "*-*-* 03:00:00";
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.update-qwen-model-notify-failure = {
|
|
||||||
description = "Notify ntfy on update-qwen-model failure";
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart = "${ntfyModelFailScript}";
|
|
||||||
EnvironmentFile = [ config.sops.templates."ntfy.env".path ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Ensure model is available before llama-cpp starts
|
|
||||||
systemd.services.llama-cpp = {
|
|
||||||
after = [ "update-qwen-model.service" ];
|
|
||||||
wants = [ "update-qwen-model.service" ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
namespace,
|
namespace,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
with lib;
|
|
||||||
let
|
let
|
||||||
name = "arrs";
|
name = "arrs";
|
||||||
cfg = config.${namespace}.services.${name};
|
cfg = config.${namespace}.services.${name};
|
||||||
@@ -55,141 +54,143 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
# Enable radarr service
|
# Enable radarr service
|
||||||
services.radarr = {
|
services = {
|
||||||
enable = true;
|
radarr = {
|
||||||
openFirewall = cfg.openFirewall;
|
enable = true;
|
||||||
user = "nix-apps";
|
openFirewall = cfg.openFirewall;
|
||||||
group = "jallen-nas";
|
user = "nix-apps";
|
||||||
dataDir = "${cfg.configDir}/radarr";
|
group = "jallen-nas";
|
||||||
};
|
dataDir = "${cfg.configDir}/radarr";
|
||||||
|
};
|
||||||
|
|
||||||
# Enable Sonarr service
|
# Enable Sonarr service
|
||||||
services.sonarr = {
|
sonarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = cfg.openFirewall;
|
openFirewall = cfg.openFirewall;
|
||||||
user = "nix-apps";
|
user = "nix-apps";
|
||||||
group = "jallen-nas";
|
group = "jallen-nas";
|
||||||
dataDir = "${cfg.configDir}/sonarr";
|
dataDir = "${cfg.configDir}/sonarr";
|
||||||
package = pkgs.sonarr;
|
package = pkgs.sonarr;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.lidarr = {
|
lidarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = cfg.openFirewall;
|
openFirewall = cfg.openFirewall;
|
||||||
user = "nix-apps";
|
user = "nix-apps";
|
||||||
group = "jallen-nas";
|
group = "jallen-nas";
|
||||||
dataDir = "${cfg.configDir}/lidarr";
|
dataDir = "${cfg.configDir}/lidarr";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Enable Sabnzbd service
|
# Enable Sabnzbd service
|
||||||
services.sabnzbd = {
|
sabnzbd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
user = "nix-apps";
|
user = "nix-apps";
|
||||||
group = "jallen-nas";
|
group = "jallen-nas";
|
||||||
secretFiles = [
|
secretFiles = [
|
||||||
config.sops.templates."sabnzbd.ini".path
|
config.sops.templates."sabnzbd.ini".path
|
||||||
];
|
];
|
||||||
configFile = null;
|
configFile = null;
|
||||||
settings = lib.mkForce {
|
settings = lib.mkForce {
|
||||||
misc = {
|
misc = {
|
||||||
host = "0.0.0.0";
|
host = "0.0.0.0";
|
||||||
port = 8280;
|
port = 8280;
|
||||||
cache_limit = "10G";
|
cache_limit = "10G";
|
||||||
download_dir = "${cfg.configDir}/downloads";
|
download_dir = "${cfg.configDir}/downloads";
|
||||||
complete_dir = "${cfg.configDir}/incomplete";
|
complete_dir = "${cfg.configDir}/incomplete";
|
||||||
username = "admin";
|
username = "admin";
|
||||||
};
|
|
||||||
servers = {
|
|
||||||
"news.newsgroupdirect.com" = {
|
|
||||||
name = "news.newsgroupdirect.com";
|
|
||||||
displayname = "news.newsgroupdirect.com";
|
|
||||||
host = "news.newsgroupdirect.com";
|
|
||||||
port = 563;
|
|
||||||
timeout = 60;
|
|
||||||
connections = 8;
|
|
||||||
ssl = true;
|
|
||||||
ssl_verify = 2;
|
|
||||||
ssl_ciphers = "";
|
|
||||||
enable = true;
|
|
||||||
required = false;
|
|
||||||
optional = false;
|
|
||||||
retention = 0;
|
|
||||||
expire_date = "";
|
|
||||||
quota = "";
|
|
||||||
usage_at_start = 0;
|
|
||||||
priority = 0;
|
|
||||||
notes = "";
|
|
||||||
};
|
};
|
||||||
};
|
servers = {
|
||||||
categories = {
|
"news.newsgroupdirect.com" = {
|
||||||
"*" = {
|
name = "news.newsgroupdirect.com";
|
||||||
name = "*";
|
displayname = "news.newsgroupdirect.com";
|
||||||
order = 0;
|
host = "news.newsgroupdirect.com";
|
||||||
pp = 3;
|
port = 563;
|
||||||
script = "None";
|
timeout = 60;
|
||||||
dir = "";
|
connections = 8;
|
||||||
newzbin = "";
|
ssl = true;
|
||||||
priority = 0;
|
ssl_verify = 2;
|
||||||
|
ssl_ciphers = "";
|
||||||
|
enable = true;
|
||||||
|
required = false;
|
||||||
|
optional = false;
|
||||||
|
retention = 0;
|
||||||
|
expire_date = "";
|
||||||
|
quota = "";
|
||||||
|
usage_at_start = 0;
|
||||||
|
priority = 0;
|
||||||
|
notes = "";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
audio = {
|
categories = {
|
||||||
name = "audio";
|
"*" = {
|
||||||
order = 3;
|
name = "*";
|
||||||
pp = "";
|
order = 0;
|
||||||
script = "Default";
|
pp = 3;
|
||||||
dir = "";
|
script = "None";
|
||||||
newzbin = "";
|
dir = "";
|
||||||
priority = -100;
|
newzbin = "";
|
||||||
};
|
priority = 0;
|
||||||
software = {
|
};
|
||||||
name = "software";
|
audio = {
|
||||||
order = 4;
|
name = "audio";
|
||||||
pp = "";
|
order = 3;
|
||||||
script = "Default";
|
pp = "";
|
||||||
dir = "";
|
script = "Default";
|
||||||
newzbin = "";
|
dir = "";
|
||||||
priority = -100;
|
newzbin = "";
|
||||||
};
|
priority = -100;
|
||||||
"movies" = {
|
};
|
||||||
name = "movies";
|
software = {
|
||||||
order = 5;
|
name = "software";
|
||||||
pp = "";
|
order = 4;
|
||||||
script = "Default";
|
pp = "";
|
||||||
dir = "";
|
script = "Default";
|
||||||
newzbin = "";
|
dir = "";
|
||||||
priority = -100;
|
newzbin = "";
|
||||||
};
|
priority = -100;
|
||||||
"tv" = {
|
};
|
||||||
name = "tv";
|
"movies" = {
|
||||||
order = 6;
|
name = "movies";
|
||||||
pp = "";
|
order = 5;
|
||||||
script = "Default";
|
pp = "";
|
||||||
dir = "";
|
script = "Default";
|
||||||
newzbin = "";
|
dir = "";
|
||||||
priority = -100;
|
newzbin = "";
|
||||||
|
priority = -100;
|
||||||
|
};
|
||||||
|
"tv" = {
|
||||||
|
name = "tv";
|
||||||
|
order = 6;
|
||||||
|
pp = "";
|
||||||
|
script = "Default";
|
||||||
|
dir = "";
|
||||||
|
newzbin = "";
|
||||||
|
priority = -100;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
services.deluge = {
|
deluge = {
|
||||||
enable = false;
|
enable = false;
|
||||||
user = "nix-apps";
|
user = "nix-apps";
|
||||||
group = "jallen-nas";
|
group = "jallen-nas";
|
||||||
openFirewall = cfg.openFirewall;
|
openFirewall = cfg.openFirewall;
|
||||||
dataDir = cfg.dataDir;
|
dataDir = cfg.dataDir;
|
||||||
web = {
|
web = {
|
||||||
enable = true;
|
enable = true;
|
||||||
port = 8112;
|
port = 8112;
|
||||||
|
openFirewall = cfg.openFirewall;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
jackett = {
|
||||||
|
enable = false;
|
||||||
|
user = "nix-apps";
|
||||||
|
group = "jallen-nas";
|
||||||
openFirewall = cfg.openFirewall;
|
openFirewall = cfg.openFirewall;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.jackett = {
|
|
||||||
enable = false;
|
|
||||||
user = "nix-apps";
|
|
||||||
group = "jallen-nas";
|
|
||||||
openFirewall = cfg.openFirewall;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -167,53 +167,74 @@ let
|
|||||||
# but /var/lib/crowdsec already exists as a real dir. Disabling DynamicUser on
|
# but /var/lib/crowdsec already exists as a real dir. Disabling DynamicUser on
|
||||||
# those two services lets them use the real crowdsec user/group instead, which is
|
# those two services lets them use the real crowdsec user/group instead, which is
|
||||||
# consistent with how crowdsec.service itself runs.
|
# consistent with how crowdsec.service itself runs.
|
||||||
systemd.services.crowdsec.serviceConfig = lib.mkMerge [
|
systemd = {
|
||||||
{ DynamicUser = lib.mkForce false; }
|
# The ntfy plugin config YAML (with credentials baked in) is managed as a
|
||||||
(lib.mkIf (cfg.ntfy.enable && cfg.ntfy.envFile != "") {
|
# SOPS template in sops.nix — it renders to /run/secrets/rendered/crowdsec/
|
||||||
EnvironmentFile = [ cfg.ntfy.envFile ];
|
# notifications/ntfy.yaml at runtime. We use a tmpfiles symlink to expose
|
||||||
})
|
# it at the path CrowdSec scans, since environment.etc can't reference
|
||||||
];
|
# /run paths as source.
|
||||||
systemd.services.crowdsec-firewall-bouncer.serviceConfig.DynamicUser = lib.mkForce false;
|
tmpfiles.rules = lib.mkIf cfg.ntfy.enable [
|
||||||
systemd.services.crowdsec-firewall-bouncer-register.serviceConfig.DynamicUser = lib.mkForce false;
|
"L /etc/crowdsec/notifications/ntfy.yaml - - - - ${
|
||||||
|
config.sops.templates."crowdsec/notifications/ntfy.yaml".path
|
||||||
|
}"
|
||||||
|
];
|
||||||
|
services = {
|
||||||
|
crowdsec = {
|
||||||
|
serviceConfig = lib.mkMerge [
|
||||||
|
{ DynamicUser = lib.mkForce false; }
|
||||||
|
(lib.mkIf (cfg.ntfy.enable && cfg.ntfy.envFile != "") {
|
||||||
|
EnvironmentFile = [ cfg.ntfy.envFile ];
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
# The upstream unit has Requires= but no After= for the register service, so
|
# The upstream unit has Requires= but no After= for the register service, so
|
||||||
# the bouncer starts in parallel and hits LoadCredential before the key file
|
# the bouncer starts in parallel and hits LoadCredential before the key file
|
||||||
# exists. Adding After= enforces that the register service completes first.
|
# exists. Adding After= enforces that the register service completes first.
|
||||||
systemd.services.crowdsec-firewall-bouncer.after = [ "crowdsec-firewall-bouncer-register.service" ];
|
crowdsec-firewall-bouncer = {
|
||||||
|
serviceConfig.DynamicUser = lib.mkForce false;
|
||||||
|
after = [ "crowdsec-firewall-bouncer-register.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
# The upstream register script exits with an error when the bouncer is already
|
crowdsec-firewall-bouncer-register = {
|
||||||
# registered in the LAPI but the local api-key.cred file is missing (e.g. after
|
serviceConfig.DynamicUser = lib.mkForce false;
|
||||||
# a system wipe or impermanence rotation). Override the script so that when the
|
|
||||||
# key file is absent it deletes the stale registration and re-registers, producing
|
# The upstream register script exits with an error when the bouncer is already
|
||||||
# a fresh key file.
|
# registered in the LAPI but the local api-key.cred file is missing (e.g. after
|
||||||
systemd.services.crowdsec-firewall-bouncer-register.script =
|
# a system wipe or impermanence rotation). Override the script so that when the
|
||||||
let
|
# key file is absent it deletes the stale registration and re-registers, producing
|
||||||
apiKeyFile = "/var/lib/crowdsec-firewall-bouncer-register/api-key.cred";
|
# a fresh key file.
|
||||||
bouncerName = "nas-bouncer";
|
script =
|
||||||
cscli = lib.getExe' config.services.crowdsec.package "cscli";
|
let
|
||||||
jq = lib.getExe pkgs.jq;
|
apiKeyFile = "/var/lib/crowdsec-firewall-bouncer-register/api-key.cred";
|
||||||
in
|
bouncerName = "nas-bouncer";
|
||||||
lib.mkForce ''
|
cscli = lib.getExe' config.services.crowdsec.package "cscli";
|
||||||
if ${cscli} bouncers list --output json | ${jq} -e -- 'any(.[]; .name == "${bouncerName}")' >/dev/null; then
|
jq = lib.getExe pkgs.jq;
|
||||||
# Bouncer already registered. Verify the API key is still present.
|
in
|
||||||
if [ ! -f ${apiKeyFile} ]; then
|
lib.mkForce ''
|
||||||
echo "Bouncer registered but API key file missing — deleting stale registration and re-registering"
|
if ${cscli} bouncers list --output json | ${jq} -e -- 'any(.[]; .name == "${bouncerName}")' >/dev/null; then
|
||||||
${cscli} bouncers delete -- ${bouncerName}
|
# Bouncer already registered. Verify the API key is still present.
|
||||||
rm -f '${apiKeyFile}'
|
if [ ! -f ${apiKeyFile} ]; then
|
||||||
if ! ${cscli} bouncers add --output raw -- ${bouncerName} >${apiKeyFile}; then
|
echo "Bouncer registered but API key file missing — deleting stale registration and re-registering"
|
||||||
rm -f '${apiKeyFile}'
|
${cscli} bouncers delete -- ${bouncerName}
|
||||||
exit 1
|
rm -f '${apiKeyFile}'
|
||||||
fi
|
if ! ${cscli} bouncers add --output raw -- ${bouncerName} >${apiKeyFile}; then
|
||||||
fi
|
rm -f '${apiKeyFile}'
|
||||||
else
|
exit 1
|
||||||
# Bouncer not registered — fresh registration.
|
fi
|
||||||
rm -f '${apiKeyFile}'
|
fi
|
||||||
if ! ${cscli} bouncers add --output raw -- ${bouncerName} >${apiKeyFile}; then
|
else
|
||||||
rm -f '${apiKeyFile}'
|
# Bouncer not registered — fresh registration.
|
||||||
exit 1
|
rm -f '${apiKeyFile}'
|
||||||
fi
|
if ! ${cscli} bouncers add --output raw -- ${bouncerName} >${apiKeyFile}; then
|
||||||
fi
|
rm -f '${apiKeyFile}'
|
||||||
'';
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# crowdsec-firewall-bouncer-register calls cscli without -c, so cscli
|
# crowdsec-firewall-bouncer-register calls cscli without -c, so cscli
|
||||||
# looks for /etc/crowdsec/config.yaml. The upstream crowdsec.service uses
|
# looks for /etc/crowdsec/config.yaml. The upstream crowdsec.service uses
|
||||||
@@ -277,17 +298,6 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# The ntfy plugin config YAML (with credentials baked in) is managed as a
|
|
||||||
# SOPS template in sops.nix — it renders to /run/secrets/rendered/crowdsec/
|
|
||||||
# notifications/ntfy.yaml at runtime. We use a tmpfiles symlink to expose
|
|
||||||
# it at the path CrowdSec scans, since environment.etc can't reference
|
|
||||||
# /run paths as source.
|
|
||||||
systemd.tmpfiles.rules = lib.mkIf cfg.ntfy.enable [
|
|
||||||
"L /etc/crowdsec/notifications/ntfy.yaml - - - - ${
|
|
||||||
config.sops.templates."crowdsec/notifications/ntfy.yaml".path
|
|
||||||
}"
|
|
||||||
];
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -31,83 +31,89 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
services.livekit = {
|
services = {
|
||||||
enable = true;
|
livekit = {
|
||||||
openFirewall = true;
|
enable = true;
|
||||||
settings.room.auto_create = false;
|
openFirewall = true;
|
||||||
inherit keyFile;
|
settings.room.auto_create = false;
|
||||||
};
|
inherit keyFile;
|
||||||
services.lk-jwt-service = {
|
};
|
||||||
enable = true;
|
lk-jwt-service = {
|
||||||
port = 8585;
|
enable = true;
|
||||||
# can be on the same virtualHost as synapse
|
port = 8585;
|
||||||
livekitUrl = "wss://mjallen.dev/livekit/sfu";
|
# can be on the same virtualHost as synapse
|
||||||
inherit keyFile;
|
livekitUrl = "wss://mjallen.dev/livekit/sfu";
|
||||||
};
|
inherit keyFile;
|
||||||
# generate the key when needed
|
};
|
||||||
systemd.services.livekit-key = {
|
nginx = {
|
||||||
before = [
|
enable = true;
|
||||||
"lk-jwt-service.service"
|
defaultHTTPListenPort = 8188;
|
||||||
"livekit.service"
|
virtualHosts = {
|
||||||
];
|
"matrix.mjallen.dev".locations = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
"= /.well-known/matrix/client" = {
|
||||||
path = with pkgs; [
|
alias = file;
|
||||||
livekit
|
extraConfig = ''
|
||||||
coreutils
|
default_type application/json;
|
||||||
gawk
|
add_header Access-Control-Allow-Origin "*";
|
||||||
];
|
'';
|
||||||
script = ''
|
};
|
||||||
echo "Key missing, generating key"
|
|
||||||
echo "lk-jwt-service: $(livekit-server generate-keys | tail -1 | awk '{print $3}')" > "${keyFile}"
|
|
||||||
'';
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
unitConfig.ConditionPathExists = "!${keyFile}";
|
|
||||||
};
|
|
||||||
# restrict access to livekit room creation to a homeserver
|
|
||||||
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = "mjallen.dev";
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
defaultHTTPListenPort = 8188;
|
|
||||||
virtualHosts = {
|
|
||||||
"matrix.mjallen.dev".locations = {
|
|
||||||
"= /.well-known/matrix/client" = {
|
|
||||||
alias = file;
|
|
||||||
extraConfig = ''
|
|
||||||
default_type application/json;
|
|
||||||
add_header Access-Control-Allow-Origin "*";
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"mjallen.dev".locations = {
|
|
||||||
"= /.well-known/matrix/client" = {
|
|
||||||
alias = file;
|
|
||||||
extraConfig = ''
|
|
||||||
default_type application/json;
|
|
||||||
add_header Access-Control-Allow-Origin "*";
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
"mjallen.dev".locations = {
|
||||||
|
"= /.well-known/matrix/client" = {
|
||||||
|
alias = file;
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/json;
|
||||||
|
add_header Access-Control-Allow-Origin "*";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
"^~ /livekit/jwt/" = {
|
"^~ /livekit/jwt/" = {
|
||||||
priority = 400;
|
priority = 400;
|
||||||
proxyPass = "http://[::1]:${toString config.services.lk-jwt-service.port}/";
|
proxyPass = "http://[::1]:${toString config.services.lk-jwt-service.port}/";
|
||||||
};
|
};
|
||||||
|
|
||||||
"^~ /livekit/sfu/" = {
|
"^~ /livekit/sfu/" = {
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
proxy_send_timeout 120;
|
proxy_send_timeout 120;
|
||||||
proxy_read_timeout 120;
|
proxy_read_timeout 120;
|
||||||
proxy_buffering off;
|
proxy_buffering off;
|
||||||
|
|
||||||
proxy_set_header Accept-Encoding gzip;
|
proxy_set_header Accept-Encoding gzip;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
'';
|
'';
|
||||||
priority = 400;
|
priority = 400;
|
||||||
proxyPass = "http://[::1]:${toString config.services.livekit.settings.port}/";
|
proxyPass = "http://[::1]:${toString config.services.livekit.settings.port}/";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
# generate the key when needed
|
||||||
|
systemd = {
|
||||||
|
services = {
|
||||||
|
livekit-key = {
|
||||||
|
before = [
|
||||||
|
"lk-jwt-service.service"
|
||||||
|
"livekit.service"
|
||||||
|
];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
path = with pkgs; [
|
||||||
|
livekit
|
||||||
|
coreutils
|
||||||
|
gawk
|
||||||
|
];
|
||||||
|
script = ''
|
||||||
|
echo "Key missing, generating key"
|
||||||
|
echo "lk-jwt-service: $(livekit-server generate-keys | tail -1 | awk '{print $3}')" > "${keyFile}"
|
||||||
|
'';
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
unitConfig.ConditionPathExists = "!${keyFile}";
|
||||||
|
};
|
||||||
|
# restrict access to livekit room creation to a homeserver
|
||||||
|
lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = "mjallen.dev";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
namespace,
|
namespace,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
with lib;
|
|
||||||
let
|
let
|
||||||
name = "nextcloud";
|
name = "nextcloud";
|
||||||
cfg = config.${namespace}.services.${name};
|
cfg = config.${namespace}.services.${name};
|
||||||
@@ -18,130 +17,143 @@ let
|
|||||||
options = { };
|
options = { };
|
||||||
|
|
||||||
moduleConfig = {
|
moduleConfig = {
|
||||||
# Override the empty systemd service created by mkModule.
|
|
||||||
# The native NixOS nextcloud module doesn't create a persistent "nextcloud.service"
|
|
||||||
# (it uses PHP-FPM pools and cron instead), so we clear this to avoid the error:
|
|
||||||
# "Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing."
|
|
||||||
systemd.services.nextcloud = lib.mkForce { };
|
|
||||||
# Setup the native NixOS Nextcloud service
|
# Setup the native NixOS Nextcloud service
|
||||||
services.nextcloud = {
|
services = {
|
||||||
enable = true;
|
nextcloud = {
|
||||||
package = pkgs.nextcloud33;
|
enable = true;
|
||||||
hostName = "cloud.mjallen.dev";
|
package = pkgs.nextcloud33;
|
||||||
home = "${cfg.configDir}/nextcloud";
|
hostName = "cloud.mjallen.dev";
|
||||||
datadir = "${cfg.dataDir}/nextcloud";
|
home = "${cfg.configDir}/nextcloud";
|
||||||
configureRedis = true;
|
datadir = "${cfg.dataDir}/nextcloud";
|
||||||
enableImagemagick = true;
|
configureRedis = true;
|
||||||
appstoreEnable = true;
|
enableImagemagick = true;
|
||||||
|
appstoreEnable = true;
|
||||||
|
|
||||||
# extraApps = with pkgs.${namespace}; {
|
# extraApps = with pkgs.${namespace}; {
|
||||||
# richdocumentscode = nextcloud-code-server;
|
# richdocumentscode = nextcloud-code-server;
|
||||||
# # richdocuments = nextcloud-richdocuments;
|
# # richdocuments = nextcloud-richdocuments;
|
||||||
# };
|
# };
|
||||||
|
|
||||||
# Use PostgreSQL for database
|
# Use PostgreSQL for database
|
||||||
config = {
|
config = {
|
||||||
dbtype = "pgsql";
|
dbtype = "pgsql";
|
||||||
dbname = "nextcloud";
|
dbname = "nextcloud";
|
||||||
dbuser = "nextcloud";
|
dbuser = "nextcloud";
|
||||||
dbhost = "/run/postgresql"; # Socket directory
|
dbhost = "/run/postgresql"; # Socket directory
|
||||||
# dbpassFile = config.sops.secrets."jallen-nas/nextcloud/dbpassword".path;
|
# dbpassFile = config.sops.secrets."jallen-nas/nextcloud/dbpassword".path;
|
||||||
adminuser = "mjallen";
|
adminuser = "mjallen";
|
||||||
adminpassFile = config.sops.secrets."matt_password".path;
|
adminpassFile = config.sops.secrets."matt_password".path;
|
||||||
};
|
};
|
||||||
|
|
||||||
# PHP settings
|
# PHP settings
|
||||||
phpOptions = lib.mkOverride 90 {
|
phpOptions = lib.mkOverride 90 {
|
||||||
memory_limit = "512M";
|
memory_limit = "512M";
|
||||||
upload_max_filesize = "10G";
|
upload_max_filesize = "10G";
|
||||||
post_max_size = "10G";
|
post_max_size = "10G";
|
||||||
output_buffering = "0";
|
output_buffering = "0";
|
||||||
"opcache.interned_strings_buffer" = "16";
|
"opcache.interned_strings_buffer" = "16";
|
||||||
"opcache.max_accelerated_files" = "10000";
|
"opcache.max_accelerated_files" = "10000";
|
||||||
"opcache.memory_consumption" = "128";
|
"opcache.memory_consumption" = "128";
|
||||||
"opcache.save_comments" = "1";
|
"opcache.save_comments" = "1";
|
||||||
"opcache.revalidate_freq" = "1";
|
"opcache.revalidate_freq" = "1";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Configure caching for better performance
|
# Configure caching for better performance
|
||||||
caching = {
|
caching = {
|
||||||
apcu = true;
|
apcu = true;
|
||||||
redis = true;
|
redis = true;
|
||||||
memcached = false;
|
memcached = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Auto-update apps
|
# Auto-update apps
|
||||||
autoUpdateApps = {
|
autoUpdateApps = {
|
||||||
enable = false;
|
enable = false;
|
||||||
startAt = "05:00:00";
|
startAt = "05:00:00";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Configure HTTPS if enabled
|
# Configure HTTPS if enabled
|
||||||
https = false;
|
https = false;
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
installed = true;
|
installed = true;
|
||||||
auth.bruteforce.protection.enabled = false;
|
auth.bruteforce.protection.enabled = false;
|
||||||
user_oidc = {
|
user_oidc = {
|
||||||
auto_provision = false;
|
auto_provision = false;
|
||||||
|
};
|
||||||
|
overwrite.cli.url = "https://cloud.mjallen.dev";
|
||||||
|
overwriteprotocol = "https";
|
||||||
|
overwritehost = "cloud.mjallen.dev";
|
||||||
|
log_type = "file";
|
||||||
|
default_phone_region = "US";
|
||||||
|
trusted_proxies = [
|
||||||
|
net.hosts.nas.lan
|
||||||
|
"127.0.0.1"
|
||||||
|
"::1"
|
||||||
|
];
|
||||||
|
trusted_domains = [
|
||||||
|
"cloud.mjallen.dev"
|
||||||
|
"${net.hosts.nas.lan}:${toString cfg.port}"
|
||||||
|
];
|
||||||
|
enabledPreviewProviders = [
|
||||||
|
"OC\\Preview\\PNG"
|
||||||
|
"OC\\Preview\\JPEG"
|
||||||
|
"OC\\Preview\\GIF"
|
||||||
|
"OC\\Preview\\BMP"
|
||||||
|
"OC\\Preview\\XBitmap"
|
||||||
|
"OC\\Preview\\Krita"
|
||||||
|
"OC\\Preview\\WebP"
|
||||||
|
"OC\\Preview\\MarkDown"
|
||||||
|
"OC\\Preview\\TXT"
|
||||||
|
"OC\\Preview\\OpenDocument"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nginx = {
|
||||||
|
enable = true;
|
||||||
|
group = "jallen-nas";
|
||||||
|
virtualHosts.${config.services.nextcloud.hostName} = {
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = cfg.port;
|
||||||
|
ssl = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
overwrite.cli.url = "https://cloud.mjallen.dev";
|
|
||||||
overwriteprotocol = "https";
|
|
||||||
overwritehost = "cloud.mjallen.dev";
|
|
||||||
log_type = "file";
|
|
||||||
default_phone_region = "US";
|
|
||||||
trusted_proxies = [
|
|
||||||
net.hosts.nas.lan
|
|
||||||
"127.0.0.1"
|
|
||||||
"::1"
|
|
||||||
];
|
|
||||||
trusted_domains = [
|
|
||||||
"cloud.mjallen.dev"
|
|
||||||
"${net.hosts.nas.lan}:${toString cfg.port}"
|
|
||||||
];
|
|
||||||
enabledPreviewProviders = [
|
|
||||||
"OC\\Preview\\PNG"
|
|
||||||
"OC\\Preview\\JPEG"
|
|
||||||
"OC\\Preview\\GIF"
|
|
||||||
"OC\\Preview\\BMP"
|
|
||||||
"OC\\Preview\\XBitmap"
|
|
||||||
"OC\\Preview\\Krita"
|
|
||||||
"OC\\Preview\\WebP"
|
|
||||||
"OC\\Preview\\MarkDown"
|
|
||||||
"OC\\Preview\\TXT"
|
|
||||||
"OC\\Preview\\OpenDocument"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.nextcloud.isSystemUser = lib.mkForce true;
|
users = {
|
||||||
users.users.nextcloud.isNormalUser = lib.mkForce false;
|
users = {
|
||||||
users.groups.nextcloud = { };
|
nextcloud = {
|
||||||
|
isSystemUser = lib.mkForce true;
|
||||||
|
isNormalUser = lib.mkForce false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
groups = {
|
||||||
|
nextcloud = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# Ensure nextcloud services start after PostgreSQL is ready.
|
# Ensure nextcloud services start after PostgreSQL is ready.
|
||||||
# The upstream NixOS module only adds this ordering when services.postgresql.enable
|
# The upstream NixOS module only adds this ordering when services.postgresql.enable
|
||||||
# is true in the same config, but here PostgreSQL is managed separately.
|
# is true in the same config, but here PostgreSQL is managed separately.
|
||||||
systemd.services.nextcloud-setup = {
|
systemd = {
|
||||||
after = [ "postgresql.service" ];
|
services = {
|
||||||
requires = [ "postgresql.service" ];
|
# Override the empty systemd service created by mkModule.
|
||||||
};
|
# The native NixOS nextcloud module doesn't create a persistent "nextcloud.service"
|
||||||
systemd.services.nextcloud-update-db = {
|
# (it uses PHP-FPM pools and cron instead), so we clear this to avoid the error:
|
||||||
after = [ "postgresql.service" ];
|
# "Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing."
|
||||||
requires = [ "postgresql.service" ];
|
nextcloud = lib.mkForce { };
|
||||||
};
|
nextcloud-setup = {
|
||||||
|
after = [ "postgresql.service" ];
|
||||||
# Configure web server
|
requires = [ "postgresql.service" ];
|
||||||
services.nginx = {
|
};
|
||||||
enable = true;
|
nextcloud-update-db = {
|
||||||
group = "jallen-nas";
|
after = [ "postgresql.service" ];
|
||||||
virtualHosts.${config.services.nextcloud.hostName} = {
|
requires = [ "postgresql.service" ];
|
||||||
listen = [
|
};
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
port = cfg.port;
|
|
||||||
ssl = false;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
# empty_pattern: { ... }: is a valid and readable no-arg pattern.
|
# empty_pattern: { ... }: is a valid and readable no-arg pattern.
|
||||||
# unquoted_uri: false-positives inside shell heredocs in Nix strings.
|
# unquoted_uri: false-positives inside shell heredocs in Nix strings.
|
||||||
# useless_has_attr: if/has-attr patterns are sometimes clearer.
|
# useless_has_attr: if/has-attr patterns are sometimes clearer.
|
||||||
# repeated_keys: intentionally split across sections for readability/context.
|
|
||||||
disabled = [
|
disabled = [
|
||||||
"manual_inherit",
|
"manual_inherit",
|
||||||
"manual_inherit_from",
|
"manual_inherit_from",
|
||||||
@@ -13,7 +12,6 @@ disabled = [
|
|||||||
"empty_pattern",
|
"empty_pattern",
|
||||||
"unquoted_uri",
|
"unquoted_uri",
|
||||||
"useless_has_attr",
|
"useless_has_attr",
|
||||||
"repeated_keys",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Exclude files where statix's parser fails on complex shell-in-Nix content.
|
# Exclude files where statix's parser fails on complex shell-in-Nix content.
|
||||||
|
|||||||
@@ -8,85 +8,89 @@
|
|||||||
(modulesPath + "/installer/scan/not-detected.nix")
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot = {
|
||||||
"usbhid"
|
initrd = {
|
||||||
"usb_storage"
|
luks.devices."cryptroot".device = "/dev/disk/by-uuid/6fc86225-2bd4-4d9f-ba51-c3bc6b1dc7f9";
|
||||||
"sdhci_pci"
|
availableKernelModules = [
|
||||||
];
|
"usbhid"
|
||||||
boot.initrd.kernelModules = [ ];
|
"usb_storage"
|
||||||
boot.kernelModules = [ ];
|
"sdhci_pci"
|
||||||
boot.extraModulePackages = [ ];
|
];
|
||||||
|
kernelModules = [ ];
|
||||||
fileSystems."/" = {
|
};
|
||||||
device = "none";
|
kernelModules = [ ];
|
||||||
fsType = "tmpfs";
|
extraModulePackages = [ ];
|
||||||
options = [ "mode=755" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
fileSystems = {
|
||||||
device = "/dev/disk/by-uuid/80CC-18FC";
|
"/" = {
|
||||||
fsType = "vfat";
|
device = "none";
|
||||||
options = [
|
fsType = "tmpfs";
|
||||||
"fmask=0022"
|
options = [ "mode=755" ];
|
||||||
"dmask=0022"
|
};
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/home" = {
|
"/boot" = {
|
||||||
device = "/dev/mapper/cryptroot";
|
device = "/dev/disk/by-uuid/80CC-18FC";
|
||||||
fsType = "btrfs";
|
fsType = "vfat";
|
||||||
options = [
|
options = [
|
||||||
"subvol=home"
|
"fmask=0022"
|
||||||
"compress=zstd"
|
"dmask=0022"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.initrd.luks.devices."cryptroot".device =
|
"/home" = {
|
||||||
"/dev/disk/by-uuid/6fc86225-2bd4-4d9f-ba51-c3bc6b1dc7f9";
|
device = "/dev/mapper/cryptroot";
|
||||||
|
fsType = "btrfs";
|
||||||
|
options = [
|
||||||
|
"subvol=home"
|
||||||
|
"compress=zstd"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
fileSystems."/persist" = {
|
"/persist" = {
|
||||||
device = "/dev/mapper/cryptroot";
|
device = "/dev/mapper/cryptroot";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [
|
||||||
"subvol=persist"
|
"subvol=persist"
|
||||||
"compress=zstd"
|
"compress=zstd"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/etc" = {
|
"/etc" = {
|
||||||
device = "/dev/mapper/cryptroot";
|
device = "/dev/mapper/cryptroot";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [
|
||||||
"subvol=etc"
|
"subvol=etc"
|
||||||
"compress=zstd"
|
"compress=zstd"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/root" = {
|
"/root" = {
|
||||||
device = "/dev/mapper/cryptroot";
|
device = "/dev/mapper/cryptroot";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [
|
||||||
"subvol=root"
|
"subvol=root"
|
||||||
"compress=zstd"
|
"compress=zstd"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/nix" = {
|
"/nix" = {
|
||||||
device = "/dev/mapper/cryptroot";
|
device = "/dev/mapper/cryptroot";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [
|
||||||
"subvol=nix"
|
"subvol=nix"
|
||||||
"compress=zstd"
|
"compress=zstd"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/var/log" = {
|
"/var/log" = {
|
||||||
device = "/dev/mapper/cryptroot";
|
device = "/dev/mapper/cryptroot";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [
|
||||||
"subvol=log"
|
"subvol=log"
|
||||||
"compress=zstd"
|
"compress=zstd"
|
||||||
];
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
swapDevices = [ ];
|
swapDevices = [ ];
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ in
|
|||||||
{
|
{
|
||||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
users = {
|
users = {
|
||||||
groups.nut.name = "nut";
|
|
||||||
groups."jallen-nas".name = "jallen-nas";
|
|
||||||
# Nix app account
|
# Nix app account
|
||||||
users = {
|
users = {
|
||||||
nix-apps = {
|
nix-apps = {
|
||||||
@@ -66,7 +64,11 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
groups.nextcloud-exporter = { };
|
groups = {
|
||||||
groups.crowdsec = { };
|
nextcloud-exporter = { };
|
||||||
|
crowdsec = { };
|
||||||
|
nut.name = "nut";
|
||||||
|
"jallen-nas".name = "jallen-nas";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user