added stuff
This commit is contained in:
parent
e8d9044d2b
commit
9d0ebdfbd0
907 changed files with 70990 additions and 0 deletions
7
nyx/modules/core/common/default.nix
Normal file
7
nyx/modules/core/common/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./docs # generated system documentation of my nested module system
|
||||
./system # system configurations, from bootloader to desktop environment
|
||||
./secrets # secrets management
|
||||
];
|
||||
}
|
16
nyx/modules/core/common/docs/default.nix
Normal file
16
nyx/modules/core/common/docs/default.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
|
||||
cfg = config.modules.documentation;
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
environment.etc = {
|
||||
"nyxos/options.md".source = cfg.markdownPackage;
|
||||
"nyxos/options.html".source = cfg.htmlPackage;
|
||||
};
|
||||
};
|
||||
}
|
180
nyx/modules/core/common/secrets/default.nix
Normal file
180
nyx/modules/core/common/secrets/default.nix
Normal file
|
@ -0,0 +1,180 @@
|
|||
{
|
||||
self,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf optionalString;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
|
||||
# mkSecret is an abstraction over agenix secrets
|
||||
# it allows for secrets to be written conditionally and with
|
||||
# relatively secure defaults without having to set each one of them
|
||||
# manually.
|
||||
mkSecret = enableCondition: {
|
||||
file,
|
||||
owner ? "root",
|
||||
group ? "root",
|
||||
mode ? "400",
|
||||
}:
|
||||
mkIf enableCondition {
|
||||
file = "${self}/secrets/${file}";
|
||||
inherit group owner mode;
|
||||
};
|
||||
in {
|
||||
age.identityPaths = [
|
||||
"${optionalString sys.impermanence.root.enable "/persist"}/etc/ssh/ssh_host_ed25519_key"
|
||||
"${optionalString sys.impermanence.home.enable "/persist"}/home/notashelf/.ssh/id_ed25519"
|
||||
];
|
||||
|
||||
age.secrets = {
|
||||
# TODO: system option for declaring host as a potential builder
|
||||
nix-builderKey = mkSecret true {
|
||||
file = "common-nix-builder.age";
|
||||
};
|
||||
|
||||
tailscale-client = mkSecret true {
|
||||
file = "client-tailscale.age";
|
||||
owner = "notashelf";
|
||||
group = "users";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
# secrets needed for peers
|
||||
spotify-secret = mkSecret config.modules.system.programs.spotify.enable {
|
||||
file = "client-spotify.age";
|
||||
owner = "notashelf";
|
||||
group = "users";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
wg-client = mkSecret true {
|
||||
file = "client-wg.age";
|
||||
owner = "notashelf";
|
||||
group = "users";
|
||||
mode = "700";
|
||||
};
|
||||
|
||||
client-email = mkSecret true {
|
||||
file = "client-email.age";
|
||||
owner = "notashelf";
|
||||
group = "users";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
# database secrets
|
||||
mongodb-secret = mkSecret cfg.database.mongodb.enable {
|
||||
file = "db-mongodb.age";
|
||||
};
|
||||
|
||||
garage-env = mkSecret cfg.database.garage.enable {
|
||||
file = "db-garage.age";
|
||||
mode = "400";
|
||||
owner = "garage";
|
||||
group = "garage";
|
||||
};
|
||||
|
||||
# service secrets
|
||||
wg-server = mkSecret cfg.networking.wireguard.enable {
|
||||
file = "service-wg.age";
|
||||
};
|
||||
|
||||
mkm-web = mkSecret cfg.mkm.enable {
|
||||
file = "service-mkm-web.age";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
matrix-secret = mkSecret cfg.social.matrix.enable {
|
||||
file = "service-matrix.age";
|
||||
owner = "matrix-synapse";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
vaultwarden-env = mkSecret cfg.vaultwarden.enable {
|
||||
file = "service-vaultwarden.age";
|
||||
owner = "vaultwarden";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
searx-secretkey = mkSecret cfg.searxng.enable {
|
||||
file = "service-searx.age";
|
||||
mode = "400";
|
||||
owner = "searx";
|
||||
group = "searx";
|
||||
};
|
||||
|
||||
nextcloud-secret = mkSecret cfg.nextcloud.enable {
|
||||
file = "service-nextcloud.age";
|
||||
mode = "400";
|
||||
owner = "nextcloud";
|
||||
group = "nextcloud";
|
||||
};
|
||||
|
||||
attic-env = mkSecret cfg.bincache.atticd.enable {
|
||||
file = "service-attic.age";
|
||||
mode = "400";
|
||||
owner = "atticd";
|
||||
group = "atticd";
|
||||
};
|
||||
|
||||
harmonia-privateKey = mkSecret cfg.bincache.harmonia.enable {
|
||||
file = "service-harmonia.age";
|
||||
mode = "770";
|
||||
owner = "harmonia";
|
||||
group = "harmonia";
|
||||
};
|
||||
|
||||
forgejo-runner-token = mkSecret cfg.forgejo.enable {
|
||||
file = "service-forgejo-runner-token.age";
|
||||
mode = "400";
|
||||
owner = "gitea-runner";
|
||||
group = "gitea-runner";
|
||||
};
|
||||
|
||||
forgejo-runner-config = mkSecret cfg.forgejo.enable {
|
||||
file = "service-forgejo-runner-config.age";
|
||||
mode = "400";
|
||||
owner = "gitea-runner";
|
||||
group = "gitea-runner";
|
||||
};
|
||||
|
||||
# mailserver secrets
|
||||
mailserver-secret = mkSecret cfg.mailserver.enable {
|
||||
file = "mailserver-postmaster.age";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
mailserver-forgejo-secret = mkSecret cfg.forgejo.enable {
|
||||
file = "mailserver-forgejo.age";
|
||||
owner = "forgejo";
|
||||
group = "forgejo";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
mailserver-vaultwarden-secret = mkSecret cfg.vaultwarden.enable {
|
||||
file = "mailserver-vaultwarden.age";
|
||||
owner = "vaultwarden";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
mailserver-cloud-secret = mkSecret cfg.nextcloud.enable {
|
||||
file = "mailserver-cloud.age";
|
||||
owner = "nextcloud";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
mailserver-matrix-secret = mkSecret cfg.social.matrix.enable {
|
||||
file = "mailserver-matrix.age";
|
||||
owner = "matrix-synapse";
|
||||
mode = "400";
|
||||
};
|
||||
|
||||
mailserver-noreply-secret = mkSecret cfg.social.mastodon.enable {
|
||||
file = "mailserver-noreply.age";
|
||||
owner = "mastodon";
|
||||
mode = "400";
|
||||
};
|
||||
};
|
||||
}
|
86
nyx/modules/core/common/system/containers/alpha/default.nix
Normal file
86
nyx/modules/core/common/system/containers/alpha/default.nix
Normal file
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
hostConfig = config;
|
||||
in {
|
||||
config = mkIf (builtins.elem "alpha" config.modules.system.containers.enabledContainers) {
|
||||
systemd = {
|
||||
services."container@alpha".after = ["container@firewall.service"];
|
||||
tmpfiles.rules = [
|
||||
"D /srv/containers/home 755 root root"
|
||||
];
|
||||
};
|
||||
|
||||
containers."alpha" = {
|
||||
autoStart = false;
|
||||
enableTun = true;
|
||||
ephemeral = true;
|
||||
privateNetwork = true;
|
||||
localAddress = "10.1.0.1";
|
||||
hostAddress = "10.1.0.2";
|
||||
config = _: {
|
||||
_module.args = {inherit lib;};
|
||||
nixpkgs.pkgs = pkgs;
|
||||
|
||||
system.stateVersion = "23.05";
|
||||
|
||||
users = {
|
||||
groups.alpha = {};
|
||||
users.alpha = {
|
||||
isNormalUser = true;
|
||||
extraGroups = ["alpha"];
|
||||
home = "/home/alpha";
|
||||
createHome = true;
|
||||
initialPassword = "alpha";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
gcc
|
||||
openjdk17_headless
|
||||
gitMinimal
|
||||
];
|
||||
|
||||
networking.interfaces.ve-alpha = {
|
||||
useDHCP = true;
|
||||
ipv4 = {
|
||||
addresses = [
|
||||
{
|
||||
address = "10.1.0.1";
|
||||
prefixLength = 32;
|
||||
}
|
||||
];
|
||||
routes = [
|
||||
{
|
||||
address = "10.1.0.2";
|
||||
prefixLength = 32;
|
||||
options = {src = "10.1.0.1";};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
bindMounts = {
|
||||
"/home" = {
|
||||
hostPath = "/srv/containers/home";
|
||||
isReadOnly = false;
|
||||
};
|
||||
|
||||
"/run/systemd/ask-password" = {
|
||||
hostPath = "/run/systemd/ask-password";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/run/systemd/ask-password-block" = {
|
||||
hostPath = "/run/systemd/ask-password-block";
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
99
nyx/modules/core/common/system/containers/beta/default.nix
Normal file
99
nyx/modules/core/common/system/containers/beta/default.nix
Normal file
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
in {
|
||||
config = mkIf (builtins.elem "beta" config.modules.system.containers.enabledContainers) {
|
||||
containers."beta" = {
|
||||
autoStart = false;
|
||||
enableTun = true;
|
||||
ephemeral = true;
|
||||
privateNetwork = true;
|
||||
localAddress = "10.2.0.1";
|
||||
hostAddress = "10.2.0.2";
|
||||
config = _: let
|
||||
backup_path = "/var/backup/postgresql";
|
||||
in {
|
||||
system.stateVersion = "23.05";
|
||||
|
||||
services.openssh.enable = true;
|
||||
|
||||
users = {
|
||||
groups.beta = {};
|
||||
users = {
|
||||
root.hashedPassword = "!"; # disable root login
|
||||
beta = {
|
||||
isNormalUser = true;
|
||||
createHome = true;
|
||||
group = "beta";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
time.timeZone = "Europe/Berlin";
|
||||
|
||||
networking.interfaces = {
|
||||
eth0 = {
|
||||
useDHCP = false;
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.6.1";
|
||||
prefixLength = 23;
|
||||
}
|
||||
];
|
||||
ipv6.addresses = [];
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowPing = true;
|
||||
allowedTCPPorts = [5432];
|
||||
};
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
enableTCPIP = true;
|
||||
package = pkgs.postgresql;
|
||||
dataDir = "/var/db/postgresql";
|
||||
authentication = ''
|
||||
host selfoss selfoss 192.168.6.2/32 trust
|
||||
'';
|
||||
initialScript = builtins.toFile "pg_initial_script" ''
|
||||
CREATE ROLE selfoss LOGIN CREATEDB;
|
||||
CREATE DATABASE selfoss OWNER selfoss;
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.postgresql.preStart = ''
|
||||
if [ ! -d ${backup_path} ]; then
|
||||
mkdir -p ${backup_path}
|
||||
chown postgres ${backup_path}
|
||||
fi
|
||||
'';
|
||||
|
||||
systemd.services.postgresql-dump = {
|
||||
path = with pkgs; [postgresql gzip];
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
};
|
||||
script = let
|
||||
db_list_command = "psql -l -t -A |cut -d'|' -f 1 |grep -v -e template0 -e template1 -e 'root=CT'";
|
||||
in ''
|
||||
${db_list_command}
|
||||
for db in `${db_list_command}`; do
|
||||
echo "Dumping $db"
|
||||
pg_dump --format directory --file ${backup_path}/$db $db
|
||||
done
|
||||
echo "Dumping all in one gzip"
|
||||
pg_dumpall |gzip > ${backup_path}/complete_dump.sql.gz
|
||||
'';
|
||||
startAt = "daily";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
11
nyx/modules/core/common/system/containers/default.nix
Normal file
11
nyx/modules/core/common/system/containers/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
_: {
|
||||
# this imports all container directories unconditionally, regardless of whether or not
|
||||
# they are included in containers.enabledContainers option definition
|
||||
# however, as a safeguard, we are required to check if a container is actually meant to be enabled
|
||||
# so each container does it's own "builtins.elem ..." bullshit before evaluating the container
|
||||
# configuration - hacky? yes. working? also yes.
|
||||
imports = [
|
||||
./alpha # sandbox
|
||||
./beta # postgresql
|
||||
];
|
||||
}
|
14
nyx/modules/core/common/system/default.nix
Normal file
14
nyx/modules/core/common/system/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
imports = [
|
||||
./containers # hotpluggable systemd-nspawn containers
|
||||
./emulation # emulation via binfmt for cross-building
|
||||
./encryption # LUKS encryption
|
||||
./gaming # available games and gaming utilities such as steam and mangohud
|
||||
./hardware # hardware capabilities - i.e bluetooth, sound, tpm etc.
|
||||
./impermanence # impermanence configuration
|
||||
./nix # configuration for the nix package manager and build tool
|
||||
./os # configurations for how the system should operate
|
||||
./security # anything from kernel hardening to audit daemeons
|
||||
./virtualization # hypervisor and virtualisation related options - docker, QEMU, waydroid etc.
|
||||
];
|
||||
}
|
25
nyx/modules/core/common/system/emulation/default.nix
Normal file
25
nyx/modules/core/common/system/emulation/default.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
in {
|
||||
config = mkIf sys.emulation.enable {
|
||||
nix.settings.extra-sandbox-paths = ["/run/binfmt" "${pkgs.qemu}"];
|
||||
|
||||
boot.binfmt = {
|
||||
emulatedSystems = sys.emulation.systems;
|
||||
registrations = {
|
||||
# aarch64 interpreter
|
||||
aarch64-linux.interpreter = "${pkgs.qemu}/bin/qemu-aarch64";
|
||||
|
||||
# i686 interpreter
|
||||
i686-linux.interpreter = "${pkgs.qemu}/bin/qemu-i686";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
47
nyx/modules/core/common/system/encryption/default.nix
Normal file
47
nyx/modules/core/common/system/encryption/default.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.modules.system.encryption;
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
boot = {
|
||||
# mildly improves performance for the disk encryption
|
||||
initrd.availableKernelModules = [
|
||||
"aesni_intel"
|
||||
"cryptd"
|
||||
"usb_storage"
|
||||
];
|
||||
|
||||
kernelParams = [
|
||||
# Disable password timeout
|
||||
"luks.options=timeout=0"
|
||||
"rd.luks.options=timeout=0"
|
||||
"rootflags=x-systemd.device-timeout=0"
|
||||
];
|
||||
};
|
||||
|
||||
services.lvm.enable = true;
|
||||
|
||||
# TODO: account for multiple encrypted devices
|
||||
boot.initrd.luks.devices."${cfg.device}" = {
|
||||
# improve performance on ssds
|
||||
bypassWorkqueues = true;
|
||||
|
||||
# handle LUKS decryption before LVM
|
||||
preLVM = true;
|
||||
|
||||
# the device with the maching id will be searched for the key file
|
||||
keyFile = mkIf (cfg.keyFile != null) "${cfg.keyFile}";
|
||||
|
||||
# the size of the key file in bytes
|
||||
keyFileSize = cfg.keySize;
|
||||
|
||||
# if keyfile is not there, fall back to cryptsetup password
|
||||
fallbackToPassword = cfg.fallbackToPassword; # IMPLIED BY config.boot.initrd.systemd.enable
|
||||
};
|
||||
};
|
||||
}
|
7
nyx/modules/core/common/system/gaming/default.nix
Normal file
7
nyx/modules/core/common/system/gaming/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./gamescope.nix
|
||||
./gamemode.nix
|
||||
./steam.nix
|
||||
];
|
||||
}
|
75
nyx/modules/core/common/system/gaming/gamemode.nix
Normal file
75
nyx/modules/core/common/system/gaming/gamemode.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf makeBinPath optionalString;
|
||||
inherit (config) modules;
|
||||
|
||||
env = modules.usrEnv;
|
||||
sys = modules.system;
|
||||
prg = sys.programs;
|
||||
|
||||
programs = makeBinPath (with pkgs; [
|
||||
inputs.hyprland.packages.${stdenv.system}.default
|
||||
coreutils
|
||||
power-profiles-daemon
|
||||
systemd
|
||||
libnotify
|
||||
]);
|
||||
|
||||
startscript = pkgs.writeShellScript "gamemode-start" ''
|
||||
${optionalString (env.desktop == "Hyprland") ''
|
||||
export PATH=$PATH:${programs}
|
||||
export HYPRLAND_INSTANCE_SIGNATURE=$(ls -w1 /tmp/hypr | tail -1)
|
||||
hyprctl --batch 'keyword decoration:blur 0 ; keyword animations:enabled 0 ; keyword misc:vfr 0'
|
||||
''}
|
||||
|
||||
powerprofilesctl set performance
|
||||
notify-send -a 'Gamemode' 'Optimizations activated' -u 'low'
|
||||
'';
|
||||
|
||||
endscript = pkgs.writeShellScript "gamemode-end" ''
|
||||
${optionalString (env.desktop == "Hyprland") ''
|
||||
export PATH=$PATH:${programs}
|
||||
export HYPRLAND_INSTANCE_SIGNATURE=$(ls -w1 /tmp/hypr | tail -1)
|
||||
hyprctl --batch 'keyword decoration:blur 1 ; keyword animations:enabled 1 ; keyword misc:vfr 1'
|
||||
''}
|
||||
|
||||
powerprofilesctl set balanced
|
||||
notify-send -a 'Gamemode' 'Optimizations deactivated' -u 'low'
|
||||
'';
|
||||
in {
|
||||
config = mkIf prg.gaming.gamemode.enable {
|
||||
programs.gamemode = {
|
||||
enable = true;
|
||||
enableRenice = true;
|
||||
settings = {
|
||||
general = {
|
||||
softrealtime = "auto";
|
||||
renice = 15;
|
||||
};
|
||||
|
||||
custom = {
|
||||
start = startscript.outPath;
|
||||
end = endscript.outPath;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
security.wrappers.gamemode = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
source = "${pkgs.gamemode}/bin/gamemoderun";
|
||||
capabilities = "cap_sys_ptrace,cap_sys_nice+pie";
|
||||
};
|
||||
|
||||
boot.kernel.sysctl = {
|
||||
# default on some gaming (SteamOS) and desktop (Fedora) distributions
|
||||
# might help with gaming performance
|
||||
"vm.max_map_count" = 2147483642;
|
||||
};
|
||||
};
|
||||
}
|
28
nyx/modules/core/common/system/gaming/gamescope.nix
Normal file
28
nyx/modules/core/common/system/gaming/gamescope.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (config) modules;
|
||||
|
||||
sys = modules.system;
|
||||
prg = sys.programs;
|
||||
in {
|
||||
config = mkIf prg.gaming.gamescope.enable {
|
||||
programs.gamescope = {
|
||||
enable = true;
|
||||
package = pkgs.gamescope; # the default, here in case I want to override it
|
||||
};
|
||||
|
||||
# workaround attempt for letting gamescope bypass YAMA LSM
|
||||
# doesn't work, but doesn't hurt to keep this here
|
||||
security.wrappers.gamescope = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
source = "${config.programs.gamescope.package}/bin/gamescope";
|
||||
capabilities = "cap_sys_ptrace,cap_sys_nice+pie";
|
||||
};
|
||||
};
|
||||
}
|
83
nyx/modules/core/common/system/gaming/steam.nix
Normal file
83
nyx/modules/core/common/system/gaming/steam.nix
Normal file
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
|
||||
prg = config.modules.system.programs;
|
||||
in {
|
||||
config = mkIf prg.gaming.steam.enable {
|
||||
nixpkgs = {
|
||||
config = {
|
||||
allowUnfreePredicate = pkg:
|
||||
builtins.elem (lib.getName pkg) [
|
||||
"steam"
|
||||
"steam-original"
|
||||
"steam-runtime"
|
||||
];
|
||||
};
|
||||
|
||||
overlays = [
|
||||
(_: prev: {
|
||||
steam = prev.steam.override ({extraPkgs ? _: [], ...}: {
|
||||
extraPkgs = pkgs':
|
||||
(extraPkgs pkgs')
|
||||
# Add missing dependencies
|
||||
++ (with pkgs'; [
|
||||
# Generic dependencies
|
||||
libgdiplus
|
||||
keyutils
|
||||
libkrb5
|
||||
libpng
|
||||
libpulseaudio
|
||||
libvorbis
|
||||
stdenv.cc.cc.lib
|
||||
xorg.libXcursor
|
||||
xorg.libXi
|
||||
xorg.libXinerama
|
||||
xorg.libXScrnSaver
|
||||
at-spi2-atk
|
||||
fmodex
|
||||
gtk3
|
||||
gtk3-x11
|
||||
harfbuzz
|
||||
icu
|
||||
glxinfo
|
||||
inetutils
|
||||
libthai
|
||||
mono5
|
||||
pango
|
||||
stdenv.cc.cc.lib
|
||||
strace
|
||||
zlib
|
||||
|
||||
# for Titanfall 2 Northstar launcher
|
||||
libunwind
|
||||
]);
|
||||
});
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
programs.steam = {
|
||||
# Enable steam
|
||||
enable = true;
|
||||
|
||||
# Whether to open ports in the firewall for Steam Remote Play
|
||||
remotePlay.openFirewall = false;
|
||||
|
||||
# Whether to open ports in the firewall for Source Dedicated Server
|
||||
dedicatedServer.openFirewall = false;
|
||||
|
||||
# Compatibility tools to install
|
||||
# For the accepted format (and the reason behind)
|
||||
# the "compattool" attribute, see:
|
||||
# <https://github.com/NixOS/nixpkgs/pull/296009>
|
||||
extraCompatPackages = [
|
||||
pkgs.proton-ge-bin.steamcompattool
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
32
nyx/modules/core/common/system/hardware/bluetooth.nix
Normal file
32
nyx/modules/core/common/system/hardware/bluetooth.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system.bluetooth;
|
||||
in {
|
||||
config = mkIf sys.enable {
|
||||
modules.system.boot.extraKernelParams = ["btusb"];
|
||||
|
||||
hardware.bluetooth = {
|
||||
enable = true;
|
||||
package = pkgs.bluez5-experimental;
|
||||
#hsphfpd.enable = true;
|
||||
powerOnBoot = true;
|
||||
disabledPlugins = ["sap"];
|
||||
settings = {
|
||||
General = {
|
||||
JustWorksRepairing = "always";
|
||||
MultiProfile = "multiple";
|
||||
Experimental = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# https://nixos.wiki/wiki/Bluetooth
|
||||
services.blueman.enable = true;
|
||||
};
|
||||
}
|
60
nyx/modules/core/common/system/hardware/cpu/amd/default.nix
Normal file
60
nyx/modules/core/common/system/hardware/cpu/amd/default.nix
Normal file
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkMerge versionOlder versionAtLeast;
|
||||
dev = config.modules.device;
|
||||
|
||||
kver = config.boot.kernelPackages.kernel.version;
|
||||
inherit (dev.cpu.amd) pstate zenpower;
|
||||
in {
|
||||
config = mkIf (builtins.elem dev.cpu.type ["amd" "vm-amd"]) {
|
||||
environment.systemPackages = [pkgs.amdctl];
|
||||
|
||||
hardware.cpu.amd.updateMicrocode = true;
|
||||
boot = mkMerge [
|
||||
{
|
||||
kernelModules = [
|
||||
"kvm-amd" # amd virtualization
|
||||
"amd-pstate" # load pstate module in case the device has a newer gpu
|
||||
"zenpower" # zenpower is for reading cpu info, i.e voltage
|
||||
"msr" # x86 CPU MSR access device
|
||||
];
|
||||
extraModulePackages = [config.boot.kernelPackages.zenpower];
|
||||
}
|
||||
|
||||
(mkIf (pstate.enable && (versionAtLeast kver "5.17") && (versionOlder kver "6.1")) {
|
||||
kernelParams = ["initcall_blacklist=acpi_cpufreq_init"];
|
||||
kernelModules = ["amd-pstate"];
|
||||
})
|
||||
|
||||
(mkIf (pstate.enable && (versionAtLeast kver "6.1") && (versionOlder kver "6.3")) {
|
||||
kernelParams = ["amd_pstate=passive"];
|
||||
})
|
||||
|
||||
# for older kernels
|
||||
# see <https://github.com/NixOS/nixos-hardware/blob/c256df331235ce369fdd49c00989fdaa95942934/common/cpu/amd/pstate.nix>
|
||||
(mkIf (pstate.enable && (versionAtLeast kver "6.3")) {
|
||||
kernelParams = ["amd_pstate=active"];
|
||||
})
|
||||
];
|
||||
|
||||
# Ryzen cpu control
|
||||
systemd.services.zenstates = mkIf zenpower.enable {
|
||||
enable = true;
|
||||
description = "Undervolt via Zenstates";
|
||||
after = ["syslog.target" "systemd-modules-load.service"];
|
||||
|
||||
unitConfig = {ConditionPathExists = "${pkgs.zenstates}/bin/zenstates";};
|
||||
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
ExecStart = "${pkgs.zenstates}/bin/zenstates ${zenpower.args}";
|
||||
};
|
||||
|
||||
wantedBy = ["multi-user.target"];
|
||||
};
|
||||
};
|
||||
}
|
6
nyx/modules/core/common/system/hardware/cpu/default.nix
Normal file
6
nyx/modules/core/common/system/hardware/cpu/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
_: {
|
||||
imports = [
|
||||
./amd
|
||||
./intel
|
||||
];
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
config = mkIf (builtins.elem dev.cpu.type ["intel" "vm-intel"]) {
|
||||
hardware.cpu.intel.updateMicrocode = true;
|
||||
boot = {
|
||||
kernelModules = ["kvm-intel"];
|
||||
kernelParams = ["i915.fastboot=1" "enable_gvt=1"];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [intel-gpu-tools];
|
||||
};
|
||||
}
|
12
nyx/modules/core/common/system/hardware/default.nix
Normal file
12
nyx/modules/core/common/system/hardware/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
imports = [
|
||||
./cpu # cpu specific options
|
||||
./gpu # gpu specific options
|
||||
./multimedia # enable multimedia: e.g. sound and video
|
||||
|
||||
./bluetooth.nix # bluetooth and device management
|
||||
./generic.nix # host-agnostic options and settings
|
||||
./tpm.nix # trusted platform module
|
||||
./yubikey.nix # yubikey device support and management tools
|
||||
];
|
||||
}
|
8
nyx/modules/core/common/system/hardware/generic.nix
Normal file
8
nyx/modules/core/common/system/hardware/generic.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{lib, ...}: {
|
||||
# This enables non-free firmware on devices not recognized by `nixos-generate-config`.
|
||||
# Disabling this option will make the system unbootable if such devices are critical
|
||||
# in your boot chain - therefore this should remain true until you are running a device
|
||||
# with mostly libre firmware. Which there is not many of.
|
||||
# on 2021-06-14: disabled this by accident and nuked my GPU drivers
|
||||
hardware.enableRedistributableFirmware = lib.mkDefault true;
|
||||
}
|
49
nyx/modules/core/common/system/hardware/gpu/amd/default.nix
Normal file
49
nyx/modules/core/common/system/hardware/gpu/amd/default.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
config = mkIf (builtins.elem dev.gpu.type ["amd" "hybrid-amd"]) {
|
||||
# enable amdgpu xorg drivers in case Hyprland breaks again
|
||||
services.xserver.videoDrivers = lib.mkDefault ["modesetting" "amdgpu"];
|
||||
|
||||
# enable amdgpu kernel module
|
||||
boot = {
|
||||
initrd.kernelModules = ["amdgpu"]; # load amdgpu kernel module as early as initrd
|
||||
kernelModules = ["amdgpu"]; # if loading somehow fails during initrd but the boot continues, try again later
|
||||
};
|
||||
|
||||
environment.systemPackages = [pkgs.nvtopPackages.amd];
|
||||
|
||||
# enables AMDVLK & OpenCL support
|
||||
hardware.opengl = {
|
||||
extraPackages = with pkgs;
|
||||
[
|
||||
amdvlk
|
||||
|
||||
# mesa
|
||||
mesa
|
||||
|
||||
# vulkan
|
||||
vulkan-tools
|
||||
vulkan-loader
|
||||
vulkan-validation-layers
|
||||
vulkan-extension-layer
|
||||
]
|
||||
++ (
|
||||
# this is a backwards-compatible way of loading appropriate opencl packages
|
||||
# in case the host runs an older revision of nixpkgs
|
||||
if pkgs ? rocmPackages.clr
|
||||
then with pkgs.rocmPackages; [clr clr.icd]
|
||||
else with pkgs; [rocm-opencl-icd rocm-opencl-runtime]
|
||||
);
|
||||
|
||||
extraPackages32 = [pkgs.driversi686Linux.amdvlk];
|
||||
};
|
||||
};
|
||||
}
|
7
nyx/modules/core/common/system/hardware/gpu/default.nix
Normal file
7
nyx/modules/core/common/system/hardware/gpu/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
_: {
|
||||
imports = [
|
||||
./intel
|
||||
./nvidia
|
||||
./amd
|
||||
];
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
dev = config.modules.device;
|
||||
|
||||
# let me play youtube videos without h.264, please and thank you
|
||||
vaapiIntel = pkgs.vaapiIntel.override {enableHybridCodec = true;};
|
||||
in {
|
||||
config = mkIf (builtins.elem dev.gpu.type ["intel" "hybrid-intel"]) {
|
||||
# enable the i915 kernel module
|
||||
boot.initrd.kernelModules = ["i915"];
|
||||
# better performance than the actual Intel driver
|
||||
services.xserver.videoDrivers = ["modesetting"];
|
||||
|
||||
# OpenCL support and VAAPI
|
||||
hardware.opengl = {
|
||||
extraPackages = with pkgs; [
|
||||
intel-compute-runtime
|
||||
intel-media-driver
|
||||
vaapiIntel
|
||||
vaapiVdpau
|
||||
libvdpau-va-gl
|
||||
];
|
||||
|
||||
extraPackages32 = with pkgs.pkgsi686Linux; [
|
||||
# intel-compute-runtime # FIXME does not build due to unsupported system
|
||||
intel-media-driver
|
||||
vaapiIntel
|
||||
vaapiVdpau
|
||||
libvdpau-va-gl
|
||||
];
|
||||
};
|
||||
|
||||
environment.variables = mkIf (config.hardware.opengl.enable && dev.gpu != "hybrid-nv") {
|
||||
VDPAU_DRIVER = "va_gl";
|
||||
};
|
||||
};
|
||||
}
|
117
nyx/modules/core/common/system/hardware/gpu/nvidia/default.nix
Normal file
117
nyx/modules/core/common/system/hardware/gpu/nvidia/default.nix
Normal file
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkDefault mkMerge versionOlder;
|
||||
|
||||
# use the latest possible nvidia package
|
||||
nvStable = config.boot.kernelPackages.nvidiaPackages.stable.version;
|
||||
nvBeta = config.boot.kernelPackages.nvidiaPackages.beta.version;
|
||||
|
||||
nvidiaPackage =
|
||||
if (versionOlder nvBeta nvStable)
|
||||
then config.boot.kernelPackages.nvidiaPackages.stable
|
||||
else config.boot.kernelPackages.nvidiaPackages.beta;
|
||||
|
||||
dev = config.modules.device;
|
||||
env = config.modules.usrEnv;
|
||||
in {
|
||||
config = mkIf (builtins.elem dev.gpu.type ["nvidia" "hybrid-nv"]) {
|
||||
# nvidia drivers are unfree software
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
services.xserver = mkMerge [
|
||||
{
|
||||
videoDrivers = ["nvidia"];
|
||||
}
|
||||
|
||||
# xorg settings
|
||||
(mkIf (!env.isWayland) {
|
||||
# disable DPMS
|
||||
monitorSection = ''
|
||||
Option "DPMS" "false"
|
||||
'';
|
||||
|
||||
# disable screen blanking in general
|
||||
serverFlagsSection = ''
|
||||
Option "StandbyTime" "0"
|
||||
Option "SuspendTime" "0"
|
||||
Option "OffTime" "0"
|
||||
Option "BlankTime" "0"
|
||||
'';
|
||||
})
|
||||
];
|
||||
|
||||
# blacklist nouveau module so that it does not conflict with nvidia drm stuff
|
||||
# also the nouveau performance is godawful, I'd rather run linux on a piece of paper than use nouveau
|
||||
# no offense to nouveau devs, I'm sure they're doing their best and they have my respect for that
|
||||
# but their best does not constitute a usable driver for me
|
||||
boot.blacklistedKernelModules = ["nouveau"];
|
||||
|
||||
environment = {
|
||||
sessionVariables = mkMerge [
|
||||
{LIBVA_DRIVER_NAME = "nvidia";}
|
||||
|
||||
(mkIf env.isWayland {
|
||||
WLR_NO_HARDWARE_CURSORS = "1";
|
||||
#__GLX_VENDOR_LIBRARY_NAME = "nvidia";
|
||||
#GBM_BACKEND = "nvidia-drm"; # breaks firefox apparently
|
||||
})
|
||||
|
||||
(mkIf (env.isWayland && (dev.gpu == "hybrid-nv")) {
|
||||
#__NV_PRIME_RENDER_OFFLOAD = "1";
|
||||
#WLR_DRM_DEVICES = mkDefault "/dev/dri/card1:/dev/dri/card0";
|
||||
})
|
||||
];
|
||||
systemPackages = with pkgs; [
|
||||
nvtopPackages.nvidia
|
||||
|
||||
# mesa
|
||||
mesa
|
||||
|
||||
# vulkan
|
||||
vulkan-tools
|
||||
vulkan-loader
|
||||
vulkan-validation-layers
|
||||
vulkan-extension-layer
|
||||
|
||||
# libva
|
||||
libva
|
||||
libva-utils
|
||||
];
|
||||
};
|
||||
|
||||
hardware = {
|
||||
nvidia = {
|
||||
package = mkDefault nvidiaPackage;
|
||||
modesetting.enable = mkDefault true;
|
||||
|
||||
prime.offload = let
|
||||
isHybrid = dev.gpu == "hybrid-nv";
|
||||
in {
|
||||
enable = isHybrid;
|
||||
enableOffloadCmd = isHybrid;
|
||||
};
|
||||
|
||||
powerManagement = {
|
||||
enable = mkDefault true;
|
||||
finegrained = mkDefault false;
|
||||
};
|
||||
|
||||
# use open source drivers by default, hosts may override this option if their gpu is
|
||||
# not supported by the open source drivers
|
||||
open = mkDefault true;
|
||||
nvidiaSettings = false; # add nvidia-settings to pkgs, useless on nixos
|
||||
nvidiaPersistenced = true;
|
||||
forceFullCompositionPipeline = true;
|
||||
};
|
||||
|
||||
opengl = {
|
||||
extraPackages = with pkgs; [nvidia-vaapi-driver];
|
||||
extraPackages32 = with pkgs.pkgsi686Linux; [nvidia-vaapi-driver];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./video
|
||||
./sound
|
||||
];
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkDefault;
|
||||
cfg = config.modules.system.sound;
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
imports = [./pipewire.nix];
|
||||
config = mkIf (cfg.enable && dev.hasSound) {
|
||||
sound = {
|
||||
enable = mkDefault false; # this just enables ALSA, which we don't really care abouyt
|
||||
mediaKeys.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) isx86Linux;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.lists) optionals;
|
||||
inherit (lib.generators) toLua;
|
||||
|
||||
cfg = config.modules.system.sound;
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
config = mkIf (cfg.enable && dev.hasSound) {
|
||||
# if the device advertises sound enabled, and pipewire is disabled
|
||||
# for whatever reason, we may fall back to PulseAudio to ensure
|
||||
# that we still have audio. I do not like PA, but bad audio
|
||||
# is better than no audio. Though we should always use
|
||||
# PipeWire where available
|
||||
hardware.pulseaudio.enable = !config.services.pipewire.enable;
|
||||
|
||||
# able to change scheduling policies, e.g. to SCHED_RR
|
||||
# sounds server use RealtimeKit (rtkti) to acquire
|
||||
# realtime priority
|
||||
security.rtkit.enable = config.services.pipewire.enable;
|
||||
|
||||
# enable pipewire and configure it for low latency
|
||||
# the below configuration may not fit every use case
|
||||
# and you are recommended to experiment with the values
|
||||
# in order to find the perfect configuration
|
||||
services = {
|
||||
pipewire = let
|
||||
quantum = 64;
|
||||
rate = 48000;
|
||||
qr = "${toString quantum}/${toString rate}";
|
||||
in {
|
||||
enable = true;
|
||||
|
||||
# emulation layers
|
||||
audio.enable = true;
|
||||
pulse.enable = true; # PA server emulation
|
||||
jack.enable = true; # JACK audio emulation
|
||||
alsa = {
|
||||
enable = true;
|
||||
support32Bit = isx86Linux pkgs; # if we're on x86 linux, we can support 32 bit
|
||||
};
|
||||
|
||||
extraConfig.pipewire."99-lowlatency" = {
|
||||
context = {
|
||||
properties.default.clock.min-quantum = quantum;
|
||||
modules = [
|
||||
{
|
||||
name = "libpipewire-module-rtkit";
|
||||
flags = ["ifexists" "nofail"];
|
||||
args = {
|
||||
nice.level = -15;
|
||||
rt = {
|
||||
prio = 88;
|
||||
time.soft = 200000;
|
||||
time.hard = 200000;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "libpipewire-module-protocol-pulse";
|
||||
args = {
|
||||
server.address = ["unix:native"];
|
||||
pulse.min = {
|
||||
req = qr;
|
||||
quantum = qr;
|
||||
frag = qr;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
stream.properties = {
|
||||
node.latency = qr;
|
||||
resample.quality = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
wireplumber = {
|
||||
enable = true;
|
||||
configPackages = let
|
||||
# generate "matches" section of the rules
|
||||
matches = toLua {
|
||||
multiline = false; # looks better while inline
|
||||
indent = false;
|
||||
} [[["node.name" "matches" "alsa_output.*"]]]; # nested lists are to produce `{{{ }}}` in the output
|
||||
|
||||
# generate "apply_properties" section of the rules
|
||||
apply_properties = toLua {} {
|
||||
"audio.format" = "S32LE";
|
||||
"audio.rate" = rate * 2;
|
||||
"api.alsa.period-size" = 2;
|
||||
};
|
||||
in
|
||||
[
|
||||
(pkgs.writeTextDir "share/lowlatency.lua.d/99-alsa-lowlatency.lua" ''
|
||||
alsa_monitor.rules = {
|
||||
{
|
||||
matches = ${matches};
|
||||
apply_properties = ${apply_properties};
|
||||
}
|
||||
}
|
||||
'')
|
||||
]
|
||||
++ optionals dev.hasBluetooth [
|
||||
(pkgs.writeTextDir "share/bluetooth.lua.d/51-bluez-config.lua" ''
|
||||
bluez_monitor.properties = {
|
||||
["bluez5.enable-sbc-xq"] = true,
|
||||
["bluez5.enable-msbc"] = true,
|
||||
["bluez5.enable-hw-volume"] = true,
|
||||
["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]"
|
||||
}
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.user.services = {
|
||||
pipewire.wantedBy = ["default.target"];
|
||||
pipewire-pulse.wantedBy = ["default.target"];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf isx86Linux;
|
||||
|
||||
sys = config.modules.system;
|
||||
in {
|
||||
config = mkIf sys.video.enable {
|
||||
hardware = {
|
||||
opengl = {
|
||||
enable = true;
|
||||
driSupport = true;
|
||||
driSupport32Bit = isx86Linux pkgs;
|
||||
};
|
||||
};
|
||||
|
||||
# benchmarking tools
|
||||
environment.systemPackages = with pkgs; [
|
||||
glxinfo
|
||||
glmark2
|
||||
];
|
||||
};
|
||||
}
|
28
nyx/modules/core/common/system/hardware/tpm.nix
Normal file
28
nyx/modules/core/common/system/hardware/tpm.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkDefault;
|
||||
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
config = mkIf dev.hasTPM {
|
||||
security.tpm2 = {
|
||||
# enable Trusted Platform Module 2 support
|
||||
enable = true;
|
||||
|
||||
# enable Trusted Platform 2 userspace resource manager daemon
|
||||
abrmd.enable = mkDefault false;
|
||||
|
||||
# The TCTI is the "Transmission Interface" that is used to communicate with a
|
||||
# TPM. this option sets TCTI environment variables to the specified values if enabled
|
||||
# - TPM2TOOLS_TCTI
|
||||
# - TPM2_PKCS11_TCTI
|
||||
tctiEnvironment.enable = mkDefault true;
|
||||
|
||||
# enable TPM2 PKCS#11 tool and shared library in system path
|
||||
pkcs11.enable = mkDefault false;
|
||||
};
|
||||
};
|
||||
}
|
33
nyx/modules/core/common/system/hardware/yubikey.nix
Normal file
33
nyx/modules/core/common/system/hardware/yubikey.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
config = lib.mkIf config.modules.system.yubikeySupport.enable {
|
||||
hardware.gpgSmartcards.enable = true;
|
||||
|
||||
services = {
|
||||
pcscd.enable = true;
|
||||
udev.packages = [pkgs.yubikey-personalization];
|
||||
};
|
||||
|
||||
programs = {
|
||||
ssh.startAgent = false;
|
||||
gnupg.agent = {
|
||||
enable = true;
|
||||
enableSSHSupport = true;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Yubico's official tools
|
||||
yubikey-manager # cli
|
||||
yubikey-manager-qt # gui
|
||||
yubikey-personalization # cli
|
||||
yubikey-personalization-gui # gui
|
||||
yubico-piv-tool # cli
|
||||
#yubioath-flutter # gui
|
||||
];
|
||||
};
|
||||
}
|
169
nyx/modules/core/common/system/impermanence/default.nix
Normal file
169
nyx/modules/core/common/system/impermanence/default.nix
Normal file
|
@ -0,0 +1,169 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) optionalString mkIf mkForce;
|
||||
|
||||
cfg = config.modules.system.impermanence;
|
||||
in {
|
||||
imports = [
|
||||
inputs.impermanence.nixosModules.impermanence
|
||||
];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users = {
|
||||
# this option makes it that users are not mutable outside our configurations
|
||||
# if you are on nixos, you are probably smart enough to not try and edit users
|
||||
# manually outside your configuration.nix or whatever
|
||||
# P.S: This option requires you to define a password file for your users
|
||||
# inside your configuration.nix - you can generate this password with
|
||||
# mkpasswd -m sha-512 > /persist/passwords/notashelf after you confirm /persist/passwords exists
|
||||
mutableUsers = false;
|
||||
|
||||
# each existing user needs to have a passwordFile defined here
|
||||
# otherwise, they will not be available for a login
|
||||
users = {
|
||||
root = {
|
||||
# passwordFile needs to be in a volume marked with `neededForBoot = true`
|
||||
hashedPasswordFile = "/persist/passwords/root";
|
||||
};
|
||||
notashelf = {
|
||||
hashedPasswordFile = "/persist/passwords/notashelf";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# home.persistence."/persist/home/notashelf" = {};
|
||||
environment.persistence."/persist" = {
|
||||
directories =
|
||||
[
|
||||
"/etc/nixos"
|
||||
"/etc/nix"
|
||||
"/etc/NetworkManager/system-connections"
|
||||
"/etc/secureboot"
|
||||
"/var/db/sudo"
|
||||
"/var/lib/flatpak"
|
||||
"/var/lib/libvirt"
|
||||
"/var/lib/bluetooth"
|
||||
"/var/lib/nixos"
|
||||
"/var/lib/pipewire"
|
||||
"/var/lib/systemd/coredump"
|
||||
"/var/cache/tailscale"
|
||||
"/var/lib/tailscale"
|
||||
]
|
||||
++ [config.programs.ccache.cacheDir];
|
||||
|
||||
files = [
|
||||
# important state
|
||||
"/etc/machine-id"
|
||||
# ssh stuff
|
||||
/*
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
"/etc/ssh/ssh_host_rsa_key"
|
||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
||||
*/
|
||||
# other
|
||||
# TODO: optionalstring for /var/lib/${lxd, docker}
|
||||
];
|
||||
|
||||
# builtins.concatMap (key: [key.path (key.path + ".pub")]) config.services.openssh.hostKeys
|
||||
};
|
||||
|
||||
# for some reason *this* is what makes networkmanager not get screwed completely instead of the impermanence module
|
||||
systemd.tmpfiles.rules = [
|
||||
"L /var/lib/NetworkManager/secret_key - - - - /persist/var/lib/NetworkManager/secret_key"
|
||||
"L /var/lib/NetworkManager/seen-bssids - - - - /persist/var/lib/NetworkManager/seen-bssids"
|
||||
"L /var/lib/NetworkManager/timestamps - - - - /persist/var/lib/NetworkManager/timestamps"
|
||||
];
|
||||
|
||||
services.openssh.hostKeys = mkForce [
|
||||
{
|
||||
bits = 4096;
|
||||
path = "/persist/etc/ssh/ssh_host_rsa_key";
|
||||
type = "rsa";
|
||||
}
|
||||
{
|
||||
bits = 4096;
|
||||
path = "/persist/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}
|
||||
];
|
||||
|
||||
boot.initrd.systemd.services.rollback = {
|
||||
description = "Rollback BTRFS root subvolume to a pristine state";
|
||||
wantedBy = ["initrd.target"];
|
||||
# make sure it's done after encryption
|
||||
# i.e. LUKS/TPM process
|
||||
after = ["systemd-cryptsetup@enc.service"];
|
||||
# mount the root fs before clearing
|
||||
before = ["sysroot.mount"];
|
||||
unitConfig.DefaultDependencies = "no";
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
mkdir -p /mnt
|
||||
|
||||
# We first mount the btrfs root to /mnt
|
||||
# so we can manipulate btrfs subvolumes.
|
||||
mount -o subvol=/ /dev/mapper/enc /mnt
|
||||
|
||||
# If home is meant to be impermanent, also mount the home subvolume to be deleted later
|
||||
${optionalString cfg.home.enable "mount -o subvol=/home /dev/mapper/enc /mnt/home"}
|
||||
|
||||
# While we're tempted to just delete /root and create
|
||||
# a new snapshot from /root-blank, /root is already
|
||||
# populated at this point with a number of subvolumes,
|
||||
# which makes `btrfs subvolume delete` fail.
|
||||
# So, we remove them first.
|
||||
#
|
||||
# /root contains subvolumes:
|
||||
# - /root/var/lib/portables
|
||||
# - /root/var/lib/machines
|
||||
|
||||
btrfs subvolume list -o /mnt/root |
|
||||
cut -f9 -d' ' |
|
||||
while read subvolume; do
|
||||
echo "deleting /$subvolume subvolume..."
|
||||
btrfs subvolume delete "/mnt/$subvolume"
|
||||
done &&
|
||||
echo "deleting /root subvolume..." &&
|
||||
btrfs subvolume delete /mnt/root
|
||||
|
||||
echo "restoring blank /root subvolume..."
|
||||
btrfs subvolume snapshot /mnt/root-blank /mnt/root
|
||||
|
||||
${optionalString cfg.home.enable ''
|
||||
echo "restoring blank /home subvolume..."
|
||||
mount -o subvol=/home /dev/mapper/enc /mnt/home
|
||||
''}
|
||||
|
||||
# Once we're done rolling back to a blank snapshot,
|
||||
# we can unmount /mnt and continue on the boot process.
|
||||
umount /mnt
|
||||
'';
|
||||
};
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.home.enable -> !cfg.root.enable;
|
||||
message = ''
|
||||
You have enabled home impermanence without root impermanence. This
|
||||
is not supported due to the fact that we handle all all impermanence
|
||||
related deletions and creations in a single service. Please enable
|
||||
`modules.system.impermanence.root.enable` if you wish to proceed.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# home impermanence is not very safe, and chances are I don't want it. Warn any potential
|
||||
# users (which may or may not be me) when it is enabled just to be safe.
|
||||
# p.s. I really don't like nix's warnings syntax. why can't it be the same
|
||||
# as the assertions format? /rant
|
||||
warnings =
|
||||
if cfg.home.enable
|
||||
then ["Home impermanence is enabled. This is experimental, beware."]
|
||||
else [];
|
||||
};
|
||||
}
|
52
nyx/modules/core/common/system/nix/builders.nix
Normal file
52
nyx/modules/core/common/system/nix/builders.nix
Normal file
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.attrsets) recursiveUpdate;
|
||||
inherit (lib.lists) filter;
|
||||
# a generic builder configuration
|
||||
builder = {
|
||||
systems = ["x86_64-linux"];
|
||||
speedFactor = 4;
|
||||
maxJobs = 4;
|
||||
supportedFeatures = ["benchmark" "nixos-test"];
|
||||
sshKey = "/home/notashelf/.ssh/builder";
|
||||
protocol = "ssh-ng";
|
||||
};
|
||||
|
||||
# override generic config builder with the assumption that more
|
||||
# resources and features are available to us
|
||||
bigBuilder = recursiveUpdate builder {
|
||||
maxJobs = 16;
|
||||
speedFactor = 16;
|
||||
supportedFeatures = builder.supportedFeatures ++ ["kvm" "big-parallel"];
|
||||
systems = builder.systems ++ ["aarch64-linux" "i686-linux"];
|
||||
};
|
||||
|
||||
mkBuilder = {
|
||||
builderBase ? builder,
|
||||
sshProtocol ? "ssh-ng",
|
||||
user ? "root",
|
||||
host,
|
||||
...
|
||||
}:
|
||||
recursiveUpdate builderBase {
|
||||
hostName = host;
|
||||
sshUser = user;
|
||||
protocol = sshProtocol;
|
||||
};
|
||||
in {
|
||||
nix = {
|
||||
distributedBuilds = true;
|
||||
buildMachines = filter (builder: builder.hostName != config.networking.hostName) [
|
||||
# large build machine
|
||||
(mkBuilder {
|
||||
builderBase = bigBuilder;
|
||||
user = "builder";
|
||||
host = "build.neushore.dev";
|
||||
sshProtocol = "ssh"; # ssh-ng is not supported by this device
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
222
nyx/modules/core/common/system/nix/default.nix
Normal file
222
nyx/modules/core/common/system/nix/default.nix
Normal file
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
inputs,
|
||||
self,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.trivial) pipe;
|
||||
inherit (lib.types) isType;
|
||||
inherit (lib.attrsets) mapAttrsToList optionalAttrs filterAttrs mapAttrs;
|
||||
inherit (lib.modules) mkDefault;
|
||||
in {
|
||||
imports = [
|
||||
./transcend # module that merges trees outside central nixpkgs with our system's
|
||||
./builders.nix # import builders config
|
||||
./overlays.nix
|
||||
];
|
||||
|
||||
system = {
|
||||
autoUpgrade.enable = false;
|
||||
stateVersion = mkDefault "23.05";
|
||||
};
|
||||
|
||||
environment = {
|
||||
etc = with inputs; {
|
||||
# set channels (backwards compatibility)
|
||||
"nix/flake-channels/system".source = self;
|
||||
"nix/flake-channels/nixpkgs".source = nixpkgs;
|
||||
"nix/flake-channels/home-manager".source = home-manager;
|
||||
|
||||
# preserve current flake in /etc
|
||||
"nixos/flake".source = self;
|
||||
};
|
||||
|
||||
# we need git for flakes, don't we
|
||||
systemPackages = [pkgs.git];
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
# https://github.com/NixOS/nixpkgs/commit/eb8ce7930d14dafcc7eff56c2f9efca6a3b2f622
|
||||
# pkgs = self.legacyPackages.${config.nixpkgs.system};
|
||||
|
||||
config = {
|
||||
allowUnfree = true; # really a pain in the ass to deal with when disabled
|
||||
allowBroken = false;
|
||||
allowUnsupportedSystem = true;
|
||||
|
||||
# default to none, add more as necessary
|
||||
permittedInsecurePackages = [
|
||||
"electron-24.8.6"
|
||||
"electron-25.9.0"
|
||||
"freeimage-unstable-2021-11-01"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# faster rebuilding
|
||||
documentation = {
|
||||
doc.enable = false;
|
||||
nixos.enable = true;
|
||||
info.enable = false;
|
||||
man = {
|
||||
enable = mkDefault true;
|
||||
generateCaches = mkDefault true;
|
||||
};
|
||||
};
|
||||
|
||||
nix = let
|
||||
# mappedRegistry = mapAttrs (_: v: {flake = v;}) inputs;
|
||||
mappedRegistry = pipe inputs [
|
||||
(filterAttrs (_: isType "flake"))
|
||||
(mapAttrs (_: flake: {inherit flake;}))
|
||||
(x: x // {nixpkgs.flake = inputs.nixpkgs;})
|
||||
];
|
||||
in {
|
||||
package = pkgs.nixSuper; # pkgs.nixVersions.unstable;
|
||||
|
||||
# pin the registry to avoid downloading and evaluating a new nixpkgs version every time
|
||||
# this will add each flake input as a registry to make nix3 commands consistent with your flake
|
||||
# additionally we also set `registry.default`, which was added by nix-super
|
||||
registry = mappedRegistry // optionalAttrs (config.nix.package == pkgs.nixSuper) {default = mappedRegistry.nixpkgs;};
|
||||
|
||||
# This will additionally add your inputs to the system's legacy channels
|
||||
# Making legacy nix commands consistent as well
|
||||
nixPath = mapAttrsToList (key: _: "${key}=flake:${key}") config.nix.registry;
|
||||
|
||||
# make builds run with low priority so my system stays responsive
|
||||
# this is especially helpful if you have auto-upgrade on
|
||||
daemonCPUSchedPolicy = "batch";
|
||||
daemonIOSchedClass = "idle";
|
||||
daemonIOSchedPriority = 7;
|
||||
|
||||
# set up garbage collection to run weekly,
|
||||
# removing unused packages that are older than 7 days
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "Mon *-*-* 03:00";
|
||||
options = "--delete-older-than 7d";
|
||||
};
|
||||
|
||||
# automatically optimize nix store my removing hard links
|
||||
# do it after the gc
|
||||
optimise = {
|
||||
automatic = true;
|
||||
dates = ["04:00"];
|
||||
};
|
||||
|
||||
settings = {
|
||||
# tell nix to use the xdg spec for base directories
|
||||
# while transitioning, any state must be carried over
|
||||
# manually, as Nix won't do it for us
|
||||
use-xdg-base-directories = true;
|
||||
|
||||
# specify the path to the nix registry
|
||||
flake-registry = "/etc/nix/registry.json";
|
||||
|
||||
# Free up to 10GiB whenever there is less than 5GB left.
|
||||
# this setting is in bytes, so we multiply with 1024 thrice
|
||||
min-free = "${toString (5 * 1024 * 1024 * 1024)}";
|
||||
max-free = "${toString (10 * 1024 * 1024 * 1024)}";
|
||||
|
||||
# automatically optimise symlinks
|
||||
auto-optimise-store = true;
|
||||
|
||||
# allow sudo users to mark the following values as trusted
|
||||
allowed-users = ["root" "@wheel" "nix-builder"];
|
||||
|
||||
# only allow sudo users to manage the nix store
|
||||
trusted-users = ["root" "@wheel" "nix-builder"];
|
||||
|
||||
# let the system decide the number of max jobs
|
||||
max-jobs = "auto";
|
||||
|
||||
# build inside sandboxed environments
|
||||
sandbox = true;
|
||||
sandbox-fallback = false;
|
||||
|
||||
# supported system features
|
||||
system-features = ["nixos-test" "kvm" "recursive-nix" "big-parallel"];
|
||||
|
||||
# extra architectures supported by my builders
|
||||
extra-platforms = config.boot.binfmt.emulatedSystems;
|
||||
|
||||
# continue building derivations if one fails
|
||||
keep-going = true;
|
||||
|
||||
# show more log lines for failed builds
|
||||
log-lines = 30;
|
||||
|
||||
# enable new nix command and flakes
|
||||
# and also "unintended" recursion as well as content addresssed nix
|
||||
extra-experimental-features = [
|
||||
"flakes" # flakes
|
||||
"nix-command" # experimental nix commands
|
||||
"recursive-nix" # let nix invoke itself
|
||||
"ca-derivations" # content addressed nix
|
||||
"auto-allocate-uids" # allow nix to automatically pick UIDs, rather than creating nixbld* user accounts
|
||||
"configurable-impure-env" # allow impure environments
|
||||
"cgroups" # allow nix to execute builds inside cgroups
|
||||
"git-hashing" # allow store objects which are hashed via Git's hashing algorithm
|
||||
"verified-fetches" # enable verification of git commit signatures for fetchGit
|
||||
];
|
||||
|
||||
# don't warn me that my git tree is dirty, I know
|
||||
warn-dirty = false;
|
||||
|
||||
# maximum number of parallel TCP connections used to fetch imports and binary caches, 0 means no limit
|
||||
http-connections = 50;
|
||||
|
||||
# whether to accept nix configuration from a flake without prompting
|
||||
accept-flake-config = false;
|
||||
|
||||
# execute builds inside cgroups
|
||||
use-cgroups = true;
|
||||
|
||||
# for direnv GC roots
|
||||
keep-derivations = true;
|
||||
keep-outputs = true;
|
||||
|
||||
# use binary cache, this is not gentoo
|
||||
# external builders can also pick up those substituters
|
||||
builders-use-substitutes = true;
|
||||
|
||||
# substituters to use
|
||||
substituters = [
|
||||
"https://cache.ngi0.nixos.org" # content addressed nix cache (TODO)
|
||||
"https://cache.nixos.org" # funny binary cache
|
||||
"https://cache.privatevoid.net" # for nix-super
|
||||
"https://nixpkgs-wayland.cachix.org" # automated builds of *some* wayland packages
|
||||
"https://nix-community.cachix.org" # nix-community cache
|
||||
"https://hyprland.cachix.org" # hyprland
|
||||
"https://nixpkgs-unfree.cachix.org" # unfree-package cache
|
||||
"https://numtide.cachix.org" # another unfree package cache
|
||||
"https://anyrun.cachix.org" # anyrun program launcher
|
||||
"https://nyx.cachix.org" # cached stuff from my flake outputs
|
||||
"https://neovim-flake.cachix.org" # a cache for my neovim flake
|
||||
"https://cache.garnix.io" # garnix binary cache, hosts prismlauncher
|
||||
"https://cache.notashelf.dev" # my own binary cache, served over https
|
||||
"https://ags.cachix.org" # ags
|
||||
];
|
||||
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA="
|
||||
"cache.privatevoid.net:SErQ8bvNWANeAvtsOESUwVYr2VJynfuc9JRwlzTTkVg="
|
||||
"nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
"hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
|
||||
"nixpkgs-unfree.cachix.org-1:hqvoInulhbV4nJ9yJOEr+4wxhDV4xq2d1DK7S6Nj6rs="
|
||||
"numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE="
|
||||
"anyrun.cachix.org-1:pqBobmOjI7nKlsUMV25u9QHa9btJK65/C8vnO3p346s="
|
||||
"notashelf.cachix.org-1:VTTBFNQWbfyLuRzgm2I7AWSDJdqAa11ytLXHBhrprZk="
|
||||
"neovim-flake.cachix.org-1:iyQ6lHFhnB5UkVpxhQqLJbneWBTzM8LBYOFPLNH4qZw="
|
||||
"nyx.cachix.org-1:xH6G0MO9PrpeGe7mHBtj1WbNzmnXr7jId2mCiq6hipE="
|
||||
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
|
||||
"cache.notashelf.dev-1:DhlmJBtURj+XS3j4F8SFFukT8dYgSjtFcd3egH8rE6U="
|
||||
"ags.cachix.org-1:naAvMrz0CuYqeyGNyLgE010iUiuf/qx6kYrUv3NwAJ8="
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
52
nyx/modules/core/common/system/nix/overlays.nix
Normal file
52
nyx/modules/core/common/system/nix/overlays.nix
Normal file
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
inputs',
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (builtins) concatStringsSep length;
|
||||
inherit (lib.lists) zipListsWith;
|
||||
inherit (lib.strings) escapeShellArg;
|
||||
in {
|
||||
nixpkgs.overlays = [
|
||||
(_: prev: let
|
||||
oldIcons = [
|
||||
"↑"
|
||||
"↓"
|
||||
"⏱"
|
||||
"⏵"
|
||||
"✔"
|
||||
"⏸"
|
||||
"⚠"
|
||||
"∅"
|
||||
"∑"
|
||||
];
|
||||
newIcons = [
|
||||
"f062" #
|
||||
"f063" #
|
||||
"f520" #
|
||||
"f04b" #
|
||||
"f00c" #
|
||||
"f04c" #
|
||||
"f071" #
|
||||
"f1da" #
|
||||
"f04a0" #
|
||||
];
|
||||
in {
|
||||
nixSuper = inputs'.nix-super.packages.default;
|
||||
nixSchemas = inputs'.nixSchemas.packages.default;
|
||||
|
||||
nix-output-monitor = assert length oldIcons == length newIcons;
|
||||
prev.nix-output-monitor.overrideAttrs (o: {
|
||||
postPatch =
|
||||
(o.postPatch or "")
|
||||
+ ''
|
||||
sed -i ${escapeShellArg (
|
||||
concatStringsSep "\n" (zipListsWith (a: b: "s/${a}/\\\\x${b}/") oldIcons newIcons)
|
||||
)} lib/NOM/Print.hs
|
||||
|
||||
sed -i 's/┌/╭/' lib/NOM/Print/Tree.hs
|
||||
'';
|
||||
});
|
||||
})
|
||||
];
|
||||
}
|
37
nyx/modules/core/common/system/nix/transcend/default.nix
Normal file
37
nyx/modules/core/common/system/nix/transcend/default.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
# credits go to @eclairevoyant on this one
|
||||
# lets us import modules from PRs that are not yet merged
|
||||
# and handles disabling of the relevant module locally
|
||||
# I've extracted the modules section to make this system more robust and explicit
|
||||
{
|
||||
lib,
|
||||
modulesPath,
|
||||
...
|
||||
}: let
|
||||
inherit (builtins) fetchTree getAttr map;
|
||||
inherit (lib.attrsets) attrValues;
|
||||
|
||||
modules = import ./modules.nix;
|
||||
|
||||
transcendModules =
|
||||
map ({
|
||||
# repo details
|
||||
owner,
|
||||
repo,
|
||||
rev,
|
||||
narHash,
|
||||
# module path
|
||||
module,
|
||||
}: {
|
||||
disabledModules = modulesPath + module;
|
||||
importedModules =
|
||||
(fetchTree {
|
||||
type = "github";
|
||||
inherit owner repo rev narHash;
|
||||
})
|
||||
+ "/nixos/modules/${module}";
|
||||
})
|
||||
(attrValues modules);
|
||||
in {
|
||||
disabledModules = map (getAttr "disabledModules") transcendModules;
|
||||
imports = map (getAttr "importedModules") transcendModules;
|
||||
}
|
12
nyx/modules/core/common/system/nix/transcend/modules.nix
Normal file
12
nyx/modules/core/common/system/nix/transcend/modules.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
# the name here is arbitrary, and is used as an identifier
|
||||
# what matters is the presence of owner, module and rev
|
||||
"nix-gc" = {
|
||||
# https://github.com/NixOS/nixpkgs/pull/260620
|
||||
owner = "nobbz";
|
||||
repo = "nixpkgs";
|
||||
module = "/services/misc/nix-gc.nix";
|
||||
rev = "10ec045f1dc82c72630c85906e1ae1d54340a7e0";
|
||||
narHash = "sha256-AV3TXXWp0AxM98wCbEa3iThUQ5AbTMC/3fZAa50lfKI=";
|
||||
};
|
||||
}
|
39
nyx/modules/core/common/system/os/activation/default.nix
Normal file
39
nyx/modules/core/common/system/os/activation/default.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
system.activationScripts = {
|
||||
# if system declares that it wants closure diffs, then run the diff script on activation
|
||||
# this is useless if you are using nh, which does this for you in a different way
|
||||
diff = lib.mkIf config.modules.system.activation.diffGenerations {
|
||||
supportsDryActivation = true;
|
||||
text = ''
|
||||
if [[ -e /run/current-system ]]; then
|
||||
echo "=== diff to current-system ==="
|
||||
${pkgs.nvd}/bin/nvd --nix-bin-dir='${config.nix.package}/bin' diff /run/current-system "$systemConfig"
|
||||
echo "=== end of the system diff ==="
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# <https://github.com/colemickens/nixcfg/blob/main/mixins/ssh.nix>
|
||||
# symlink root's ssh config to ours
|
||||
# to fix nix-daemon's ability to remote build since it sshs from the root account
|
||||
root_ssh_config = let
|
||||
sshDir = "/home/notashelf/.ssh";
|
||||
in {
|
||||
text = ''
|
||||
(
|
||||
# symlink root ssh config to ours so daemon can use our agent/keys/etc...
|
||||
mkdir -p /root/.ssh
|
||||
ln -sf ${sshDir}/config /root/.ssh/config
|
||||
ln -sf ${sshDir}/known_hosts /root/.ssh/known_hosts
|
||||
ln -sf ${sshDir}/known_hosts /root/.ssh/known_hosts
|
||||
)
|
||||
'';
|
||||
deps = [];
|
||||
};
|
||||
};
|
||||
}
|
8
nyx/modules/core/common/system/os/boot/default.nix
Normal file
8
nyx/modules/core/common/system/os/boot/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./loaders # per-bootloader configurations
|
||||
./secure-boot.nix # secure boot module
|
||||
./generic.nix # generic configuration, such as kernel and tmpfs setup
|
||||
./plymouth.nix # plymouth boot splash
|
||||
];
|
||||
}
|
180
nyx/modules/core/common/system/os/boot/generic.nix
Normal file
180
nyx/modules/core/common/system/os/boot/generic.nix
Normal file
|
@ -0,0 +1,180 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkDefault mkForce mkOverride mkMerge mkIf optionals;
|
||||
|
||||
sys = config.modules.system;
|
||||
in {
|
||||
config.boot = {
|
||||
# kernel console loglevel
|
||||
consoleLogLevel = 3;
|
||||
|
||||
# always use the latest kernel instead of the old-ass lts one
|
||||
kernelPackages = mkOverride 500 sys.boot.kernel;
|
||||
|
||||
# additional packages supplying kernel modules
|
||||
extraModulePackages = mkDefault sys.boot.extraModulePackages;
|
||||
|
||||
# configuration to be appended to the generated modprobe.conf
|
||||
extraModprobeConfig = mkDefault sys.boot.extraModprobeConfig;
|
||||
|
||||
# whether to enable support for Linux MD RAID arrays
|
||||
# I don't know why this defaults to true, how many people use RAID anyway?
|
||||
# also on > 23.11, this will throw a warning if neither MAILADDR nor PROGRAM are set
|
||||
swraid.enable = mkDefault false;
|
||||
|
||||
# settings shared between bootloaders
|
||||
# they are set unless system.boot.loader != none
|
||||
loader = {
|
||||
# if set to 0, space needs to be held to get the boot menu to appear
|
||||
timeout = mkForce 2;
|
||||
|
||||
# whether to copy the necessary boot files into /boot
|
||||
# so that /nix/store is not needed by the boot loader.
|
||||
generationsDir.copyKernels = true;
|
||||
|
||||
# allow installation to modify EFI variables
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
|
||||
# instructions on how /tmp should be handled
|
||||
# if your system is low on ram, you should avoid tmpfs to prevent hangups while compiling
|
||||
tmp = {
|
||||
# /tmp on tmpfs, lets it live on your ram
|
||||
# it defaults to FALSE, which means you will use disk space instead of ram
|
||||
# enable tmpfs tmp on anything except servers and builders
|
||||
useTmpfs = sys.boot.tmpOnTmpfs;
|
||||
|
||||
# If not using tmpfs, which is naturally purged on reboot, we must clean
|
||||
# /tmp ourselves. /tmp should be volatile storage!
|
||||
cleanOnBoot = mkDefault (!config.boot.tmp.useTmpfs);
|
||||
|
||||
# The size of the tmpfs, in percentage form
|
||||
# this defaults to 50% of your ram, which is a good default
|
||||
# but should be tweaked based on your systems capabilities
|
||||
tmpfsSize = mkDefault "75%";
|
||||
};
|
||||
|
||||
# initrd and kernel tweaks
|
||||
# if you intend to copy paste this section, read what each parameter or module does before doing so
|
||||
# or perish, I am not responsible for your broken system. if you copy paste this section without reading
|
||||
# and later realise your mistake, you are a moron.
|
||||
initrd = mkMerge [
|
||||
(mkIf sys.boot.initrd.enableTweaks {
|
||||
# Verbosity of the initrd
|
||||
# disabling verbosity removes only the mandatory messages generated by the NixOS
|
||||
verbose = false;
|
||||
|
||||
systemd = {
|
||||
# enable systemd in initrd
|
||||
# extremely experimental, just the way I like it on a production machine
|
||||
enable = true;
|
||||
|
||||
# strip copied binaries and libraries from inframs
|
||||
# saves 30~ mb space according to the nix derivation
|
||||
strip = true;
|
||||
|
||||
# packages that will be added to the PATH in initrd
|
||||
# this is useful for debugging if the host provides
|
||||
# emergency access
|
||||
storePaths = with pkgs; [util-linux pciutils];
|
||||
extraBin = {
|
||||
fdisk = "${pkgs.util-linux}/bin/fdisk";
|
||||
lsblk = "${pkgs.util-linux}/bin/lsblk";
|
||||
lspci = "${pkgs.pciutils}/bin/lspci";
|
||||
};
|
||||
};
|
||||
|
||||
# List of modules that are always loaded by the initrd
|
||||
kernelModules = [
|
||||
"ahci"
|
||||
"nvme"
|
||||
"xhci_pci"
|
||||
"btrfs"
|
||||
"sd_mod"
|
||||
"dm_mod"
|
||||
"tpm"
|
||||
];
|
||||
|
||||
# the set of kernel modules in the initial ramdisk used during the boot process
|
||||
availableKernelModules = [
|
||||
"usbhid"
|
||||
"sd_mod"
|
||||
"sr_mod"
|
||||
"dm_mod"
|
||||
"uas"
|
||||
"usb_storage"
|
||||
"rtsx_usb_sdmmc"
|
||||
"rtsx_pci_sdmmc" # Realtek PCI-Express SD/MMC Card Interface driver
|
||||
"ata_piix"
|
||||
"virtio_pci"
|
||||
"virtio_scsi"
|
||||
"ehci_pci"
|
||||
];
|
||||
})
|
||||
|
||||
(mkIf sys.boot.initrd.optimizeCompressor
|
||||
{
|
||||
compressor = "zstd";
|
||||
compressorArgs = ["-19" "-T0"];
|
||||
})
|
||||
];
|
||||
|
||||
# https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
|
||||
kernelParams =
|
||||
(optionals sys.boot.enableKernelTweaks [
|
||||
# https://en.wikipedia.org/wiki/Kernel_page-table_isolation
|
||||
# auto means kernel will automatically decide the pti state
|
||||
"pti=auto" # on | off
|
||||
|
||||
# CPU idle behaviour
|
||||
# poll: slightly improve performance at cost of a hotter system (not recommended)
|
||||
# halt: halt is forced to be used for CPU idle
|
||||
# nomwait: Disable mwait for CPU C-states
|
||||
"idle=nomwait" # poll | halt | nomwait
|
||||
|
||||
# enable IOMMU for devices used in passthrough
|
||||
# and provide better host performance in virtualization
|
||||
"iommu=pt"
|
||||
|
||||
# disable usb autosuspend
|
||||
"usbcore.autosuspend=-1"
|
||||
|
||||
# disables resume and restores original swap space
|
||||
"noresume"
|
||||
|
||||
# allows systemd to set and save the backlight state
|
||||
"acpi_backlight=native" # none | vendor | video | native
|
||||
|
||||
# prevent the kernel from blanking plymouth out of the fb
|
||||
"fbcon=nodefer"
|
||||
|
||||
# disable the cursor in vt to get a black screen during intermissions
|
||||
"vt.global_cursor_default=0"
|
||||
|
||||
# disable displaying of the built-in Linux logo
|
||||
"logo.nologo"
|
||||
])
|
||||
++ (optionals sys.boot.silentBoot [
|
||||
# tell the kernel to not be verbose
|
||||
"quiet"
|
||||
|
||||
# kernel log message level
|
||||
"loglevel=3" # 1: sustem is unusable | 3: error condition | 7: very verbose
|
||||
|
||||
# udev log message level
|
||||
"udev.log_level=3"
|
||||
|
||||
# lower the udev log level to show only errors or worse
|
||||
"rd.udev.log_level=3"
|
||||
|
||||
# disable systemd status messages
|
||||
# rd prefix means systemd-udev will be used instead of initrd
|
||||
"systemd.show_status=auto"
|
||||
"rd.systemd.show_status=auto"
|
||||
]);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
_: {
|
||||
imports = [
|
||||
./grub
|
||||
./systemd-boot
|
||||
];
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkDefault mkIf;
|
||||
|
||||
cfg = config.modules.system;
|
||||
in {
|
||||
config = mkIf (cfg.boot.loader == "grub") {
|
||||
boot.loader = {
|
||||
grub = {
|
||||
enable = mkDefault true;
|
||||
useOSProber = true;
|
||||
efiSupport = true;
|
||||
enableCryptodisk = mkDefault false;
|
||||
device = cfg.boot.grub.device;
|
||||
theme = null;
|
||||
backgroundColor = null;
|
||||
splashImage = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkForce;
|
||||
|
||||
cfg = config.modules.system;
|
||||
in {
|
||||
config = mkIf (cfg.boot.loader == "none") {
|
||||
boot.loader = {
|
||||
grub.enable = mkForce false;
|
||||
systemd-boot.enable = mkForce false;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkDefault mkIf optionalAttrs;
|
||||
|
||||
cfg = config.modules.system;
|
||||
in {
|
||||
config = mkIf (cfg.boot.loader == "systemd-boot") {
|
||||
boot.loader = {
|
||||
systemd-boot =
|
||||
{
|
||||
enable = mkDefault true;
|
||||
configurationLimit = null; # unlimited
|
||||
consoleMode = mkDefault "max"; # the default is "keep", can be overriden per host if need be
|
||||
|
||||
# Fix a security hole in place for backwards compatibility. See desc in
|
||||
# nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
|
||||
editor = false;
|
||||
}
|
||||
// optionalAttrs cfg.boot.memtest.enable {
|
||||
# https://matrix.to/#/!sgkZKRutwatDMkYBHU:nixos.org/$iKnJUt1L_7E5bq7hStDPwv6_2HTBvNjwfcWxlKlF-k8?via=nixos.org&via=matrix.org&via=nixos.dev
|
||||
extraFiles."efi/memtest86plus/memtest.efi" = "${cfg.boot.memtest.package}/memtest.efi";
|
||||
extraEntries."memtest86plus.conf" = ''
|
||||
title MemTest86+
|
||||
efi /efi/memtest86plus/memtest.efi
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
39
nyx/modules/core/common/system/os/boot/plymouth.nix
Normal file
39
nyx/modules/core/common/system/os/boot/plymouth.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
self',
|
||||
...
|
||||
}: let
|
||||
inherit (pkgs) plymouth;
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.modules.system.boot.plymouth;
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
# configure plymouth theme
|
||||
# <https://github.com/adi1090x/plymouth-themes>
|
||||
boot.plymouth = let
|
||||
pack = cfg.pack;
|
||||
theme = cfg.theme;
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
}
|
||||
// lib.optionalAttrs cfg.withThemes {
|
||||
themePackages = [(self'.packages.plymouth-themes.override {inherit pack theme;})];
|
||||
|
||||
inherit theme;
|
||||
};
|
||||
|
||||
# make plymouth work with sleep
|
||||
powerManagement = {
|
||||
powerDownCommands = ''
|
||||
${plymouth} --show-splash
|
||||
'';
|
||||
resumeCommands = ''
|
||||
${plymouth} --quit
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
36
nyx/modules/core/common/system/os/boot/secure-boot.nix
Normal file
36
nyx/modules/core/common/system/os/boot/secure-boot.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system.boot;
|
||||
in {
|
||||
imports = [
|
||||
inputs.lanzaboote.nixosModules.lanzaboote
|
||||
];
|
||||
|
||||
config = mkIf sys.secureBoot {
|
||||
environment.systemPackages = [
|
||||
# For debugging and troubleshooting Secure Boot.
|
||||
pkgs.sbctl
|
||||
];
|
||||
|
||||
# Lanzaboote currently replaces the systemd-boot module.
|
||||
# This setting is usually set to true in configuration.nix
|
||||
# generated at installation time. So we force it to false
|
||||
# for now.
|
||||
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||
|
||||
boot = {
|
||||
bootspec.enable = true;
|
||||
lanzaboote = {
|
||||
enable = true;
|
||||
pkiBundle = "/etc/secureboot";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
15
nyx/modules/core/common/system/os/default.nix
Normal file
15
nyx/modules/core/common/system/os/default.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
imports = [
|
||||
./activation # activation system for nixos-rebuild
|
||||
./boot # boot and bootloader configurations
|
||||
./display # display protocol (wayland/xorg)
|
||||
./environment # system environment e.g. locale, timezone, packages
|
||||
./fs # filesystem support options
|
||||
./misc # things that don't fit anywhere else
|
||||
./networking # network configuration & tcp optimizations
|
||||
./programs # general programs
|
||||
./services # gemeral services
|
||||
./theme # theming for desktop toolkits e.g. gtk, qt
|
||||
./users # per user configurations
|
||||
];
|
||||
}
|
6
nyx/modules/core/common/system/os/display/default.nix
Normal file
6
nyx/modules/core/common/system/os/display/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./wayland
|
||||
./xorg
|
||||
];
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./wms
|
||||
|
||||
./environment.nix
|
||||
./xdg-portals.nix
|
||||
./services.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system.video;
|
||||
env = config.modules.usrEnv;
|
||||
in {
|
||||
config = mkIf (sys.enable && env.isWayland) {
|
||||
environment.etc."greetd/environments".text = ''
|
||||
${lib.optionalString (env.desktop == "Hyprland") "Hyprland"}
|
||||
zsh
|
||||
'';
|
||||
|
||||
environment = {
|
||||
variables = {
|
||||
NIXOS_OZONE_WL = "1";
|
||||
_JAVA_AWT_WM_NONEREPARENTING = "1";
|
||||
GDK_BACKEND = "wayland,x11";
|
||||
ANKI_WAYLAND = "1";
|
||||
MOZ_ENABLE_WAYLAND = "1";
|
||||
XDG_SESSION_TYPE = "wayland";
|
||||
SDL_VIDEODRIVER = "wayland";
|
||||
CLUTTER_BACKEND = "wayland";
|
||||
#WLR_DRM_NO_ATOMIC = "1";
|
||||
#WLR_BACKEND = "vulkan";
|
||||
#__GL_GSYNC_ALLOWED = "0";
|
||||
#__GL_VRR_ALLOWED = "0";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf getExe;
|
||||
|
||||
cfg = config.modules.system.video;
|
||||
env = config.modules.usrEnv;
|
||||
in {
|
||||
config = mkIf (cfg.enable && env.isWayland) {
|
||||
systemd.services = {
|
||||
seatd = {
|
||||
enable = true;
|
||||
description = "Seat management daemon";
|
||||
script = "${getExe pkgs.seatd} -g wheel";
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
RestartSec = "1";
|
||||
};
|
||||
wantedBy = ["multi-user.target"];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./hyprland
|
||||
];
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs',
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
env = config.modules.usrEnv;
|
||||
in {
|
||||
# disables Nixpkgs Hyprland module to avoid conflicts
|
||||
disabledModules = ["programs/hyprland.nix"];
|
||||
|
||||
config = mkIf (sys.video.enable && (env.desktop == "Hyprland" && env.isWayland)) {
|
||||
services.xserver.displayManager.sessionPackages = [inputs'.hyprland.packages.default];
|
||||
|
||||
xdg.portal = {
|
||||
extraPortals = [
|
||||
inputs'.xdg-portal-hyprland.packages.xdg-desktop-portal-hyprland
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
sys = config.modules.system;
|
||||
env = config.modules.usrEnv;
|
||||
inherit (lib) mkForce mkIf;
|
||||
in {
|
||||
config = mkIf sys.video.enable {
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
|
||||
extraPortals = [pkgs.xdg-desktop-portal-gtk];
|
||||
|
||||
config = {
|
||||
common = let
|
||||
portal =
|
||||
if env.desktop == "Hyprland"
|
||||
then "hyprland"
|
||||
else if env.desktop == "sway"
|
||||
then "wlr"
|
||||
else "gtk"; # FIXME: does this actually implement what we need?
|
||||
in {
|
||||
default = [
|
||||
"hyprland"
|
||||
"gtk"
|
||||
];
|
||||
|
||||
# for flameshot to work
|
||||
# https://github.com/flameshot-org/flameshot/issues/3363#issuecomment-1753771427
|
||||
"org.freedesktop.impl.portal.Screencast" = "${portal}";
|
||||
"org.freedesktop.impl.portal.Screenshot" = "${portal}";
|
||||
};
|
||||
};
|
||||
|
||||
# xdg-desktop-wlr (this section) is no longer needed, xdg-desktop-portal-hyprland
|
||||
# will (and should) override this one
|
||||
# however in case I run a different compositor on a Wayland host, it can be enabled
|
||||
wlr = {
|
||||
enable = mkForce (env.isWayland && env.desktop != "Hyprland");
|
||||
settings = {
|
||||
screencast = {
|
||||
max_fps = 60;
|
||||
chooser_type = "simple";
|
||||
chooser_cmd = "${pkgs.slurp}/bin/slurp -f %o -or";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./environment.nix
|
||||
./xserver.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system.video;
|
||||
env = config.modules.usrEnv;
|
||||
in {
|
||||
config = mkIf (sys.enable && !env.isWayland) {
|
||||
environment.etc."greetd/environments".text = ''
|
||||
${lib.optionalString (env.desktop == "i3") "i3"}
|
||||
${lib.optionalString (env.desktop == "awesome") "awesome"}
|
||||
zsh
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{pkgs, ...}: {
|
||||
services.xserver.excludePackages = [
|
||||
pkgs.xterm
|
||||
];
|
||||
}
|
19
nyx/modules/core/common/system/os/environment/aliases.nix
Normal file
19
nyx/modules/core/common/system/os/environment/aliases.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
environment.shellAliases = let
|
||||
nr = "${pkgs.nixos-rebuild}/bin/nixos-rebuild";
|
||||
in {
|
||||
# nix aliases
|
||||
rebuild = "nix-store --verify; pushd ~dotfiles ; ${nr} switch --flake .#$1 --use-remote-sudo && notify-send \"Done\" ; popd";
|
||||
deploy = "${nr} switch --flake .#$1 --target-host $1 --use-remote-sudo -Lv";
|
||||
|
||||
# things I do to keep my home directory clean
|
||||
wget = "wget --hsts-file='\${XDG_DATA_HOME}/wget-hsts'";
|
||||
|
||||
# init a LICENSE file with my go-to gpl3 license
|
||||
"gpl" = "${lib.getExe pkgs.curl} https://www.gnu.org/licenses/gpl-3.0.txt -o LICENSE";
|
||||
};
|
||||
}
|
10
nyx/modules/core/common/system/os/environment/default.nix
Normal file
10
nyx/modules/core/common/system/os/environment/default.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
imports = [
|
||||
./aliases.nix
|
||||
./etc.nix
|
||||
./locale.nix
|
||||
./packages.nix
|
||||
./paths.nix
|
||||
./variables.nix
|
||||
];
|
||||
}
|
8
nyx/modules/core/common/system/os/environment/etc.nix
Normal file
8
nyx/modules/core/common/system/os/environment/etc.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
# https://github.com/NixOS/nixpkgs/issues/72394#issuecomment-549110501
|
||||
# the service is enabled by default, but this is not set. so by default, you will seee the error
|
||||
# why?
|
||||
environment.etc."mdadm.conf".text = ''
|
||||
MAILADDR root
|
||||
'';
|
||||
}
|
59
nyx/modules/core/common/system/os/environment/locale.nix
Normal file
59
nyx/modules/core/common/system/os/environment/locale.nix
Normal file
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkDefault;
|
||||
in {
|
||||
time = {
|
||||
timeZone = "Europe/Istanbul";
|
||||
hardwareClockInLocalTime = true;
|
||||
};
|
||||
|
||||
services.xserver.xkb = {
|
||||
layout = "tr";
|
||||
variant = "";
|
||||
};
|
||||
|
||||
i18n = let
|
||||
defaultLocale = "en_US.UTF-8";
|
||||
tr = "tr_TR.UTF-8";
|
||||
in {
|
||||
inherit defaultLocale;
|
||||
|
||||
extraLocaleSettings = {
|
||||
LANG = defaultLocale;
|
||||
LC_COLLATE = defaultLocale;
|
||||
LC_CTYPE = defaultLocale;
|
||||
LC_MESSAGES = defaultLocale;
|
||||
|
||||
LC_ADDRESS = tr;
|
||||
LC_IDENTIFICATION = tr;
|
||||
LC_MEASUREMENT = tr;
|
||||
LC_MONETARY = tr;
|
||||
LC_NAME = tr;
|
||||
LC_NUMERIC = tr;
|
||||
LC_PAPER = tr;
|
||||
LC_TELEPHONE = tr;
|
||||
LC_TIME = tr;
|
||||
};
|
||||
|
||||
supportedLocales = mkDefault [
|
||||
"en_US.UTF-8/UTF-8"
|
||||
"tr_TR.UTF-8/UTF-8"
|
||||
];
|
||||
|
||||
# ime configuration
|
||||
inputMethod = {
|
||||
enabled = "fcitx5"; # Needed for fcitx5 to work in qt6
|
||||
fcitx5.addons = with pkgs; [
|
||||
fcitx5-gtk
|
||||
fcitx5-lua
|
||||
libsForQt5.fcitx5-qt
|
||||
|
||||
# themes
|
||||
fcitx5-material-color
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
27
nyx/modules/core/common/system/os/environment/packages.nix
Normal file
27
nyx/modules/core/common/system/os/environment/packages.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
environment = {
|
||||
# nixos ships a bunch of packages by default under environment.defaultPackages
|
||||
# those do not add much to the system closure, but for a little added extra security
|
||||
# and in an attempt to reduce my system closure size, I would like those to be
|
||||
# removed from my packages
|
||||
defaultPackages = lib.mkForce [];
|
||||
|
||||
# packages that will be shared across all users and and all systems
|
||||
# this should generally include tools used for debugging
|
||||
# or system administration
|
||||
systemPackages = with pkgs; [
|
||||
git
|
||||
curl
|
||||
wget
|
||||
pciutils
|
||||
lshw
|
||||
man-pages
|
||||
rsync
|
||||
bind.dnsutils
|
||||
];
|
||||
};
|
||||
}
|
9
nyx/modules/core/common/system/os/environment/paths.nix
Normal file
9
nyx/modules/core/common/system/os/environment/paths.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
# enable completions for system packages
|
||||
# and other stuff
|
||||
environment.pathsToLink = [
|
||||
"/share/zsh" # zsh completions
|
||||
"/share/bash-completion" # bash completions
|
||||
"/share/nix-direnv" # direnv completions
|
||||
];
|
||||
}
|
18
nyx/modules/core/common/system/os/environment/variables.nix
Normal file
18
nyx/modules/core/common/system/os/environment/variables.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
_: {
|
||||
# variables that I want to set globally on all systems
|
||||
|
||||
environment.variables = {
|
||||
FLAKE = "/home/notashelf/.config/nyx";
|
||||
SSH_AUTH_SOCK = "/run/user/\${UID}/keyring/ssh";
|
||||
|
||||
# editors
|
||||
EDITOR = "nvim";
|
||||
VISUAL = "nvim";
|
||||
SUDO_EDITOR = "nvim";
|
||||
|
||||
# pager stuff
|
||||
SYSTEMD_PAGERSECURE = "true";
|
||||
PAGER = "less -FR";
|
||||
MANPAGER = "nvim +Man!";
|
||||
};
|
||||
}
|
52
nyx/modules/core/common/system/os/fs/default.nix
Normal file
52
nyx/modules/core/common/system/os/fs/default.nix
Normal file
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkMerge;
|
||||
|
||||
sys = config.modules.system;
|
||||
in {
|
||||
config = mkMerge [
|
||||
(mkIf (builtins.elem "btrfs" sys.fs) {
|
||||
# scrub btrfs devices
|
||||
services.btrfs.autoScrub = {
|
||||
enable = true;
|
||||
fileSystems = ["/"];
|
||||
};
|
||||
|
||||
# this fixes initrd.systemd.enable for whatever reason
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs"];
|
||||
initrd = {
|
||||
supportedFilesystems = ["btrfs"];
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf (builtins.elem "ext4" sys.fs) {
|
||||
boot = {
|
||||
supportedFilesystems = ["ext4"];
|
||||
initrd = {
|
||||
supportedFilesystems = ["ext4"];
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf (builtins.elem "exfat" sys.fs) {
|
||||
boot = {
|
||||
supportedFilesystems = ["exfat"];
|
||||
initrd = {
|
||||
supportedFilesystems = ["exfat"];
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
# accept both ntfs and ntfs3 as valid values
|
||||
(mkIf ((builtins.elem "ntfs" sys.fs) || (builtins.elem "ntfs3" sys.fs)) {
|
||||
boot = {
|
||||
supportedFilesystems = ["ntfs"];
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
41
nyx/modules/core/common/system/os/misc/console.nix
Normal file
41
nyx/modules/core/common/system/os/misc/console.nix
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) attrValues mkDefault;
|
||||
in {
|
||||
console = let
|
||||
variant = "v18n";
|
||||
in {
|
||||
enable = mkDefault true;
|
||||
earlySetup = true;
|
||||
keyMap = "trq";
|
||||
|
||||
font = "ter-powerline-${variant}";
|
||||
packages = attrValues {inherit (pkgs) terminus_font powerline-fonts;};
|
||||
};
|
||||
|
||||
# FIXME: kmscon, in my testing, is working as advertised and a performance difference
|
||||
# is observable. However, enabling kmscon seems to *completely* ignore silent boot
|
||||
# parameters. Not sure if this is a potential conflict with earlySetup (probably not)
|
||||
# or kmscon not respecting the kernel parameters (more likely). Either way, I will
|
||||
# revisit this in the future.
|
||||
services.kmscon = {
|
||||
enable = false;
|
||||
hwRender = true;
|
||||
fonts = [
|
||||
{
|
||||
name = "Source Code Pro";
|
||||
package = pkgs.source-code-pro;
|
||||
}
|
||||
];
|
||||
|
||||
extraOptions = "--term xterm-256color";
|
||||
extraConfig = ''
|
||||
font-size=14
|
||||
xkb-layout=${config.console.layout}
|
||||
'';
|
||||
};
|
||||
}
|
12
nyx/modules/core/common/system/os/misc/crash.nix
Normal file
12
nyx/modules/core/common/system/os/misc/crash.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
systemd = {
|
||||
# TODO: those tend to include sensitie information, maybe we want to disable this?
|
||||
# it could be an override in the security module
|
||||
tmpfiles.rules = [
|
||||
# Enables storing of the kernel log (including stack trace) into pstore upon a panic or crash.
|
||||
"w /sys/module/kernel/parameters/crash_kexec_post_notifiers - - - - Y"
|
||||
# Enables storing of the kernel log upon a normal shutdown (shutdown, reboot, halt).
|
||||
"w /sys/module/printk/parameters/always_kmsg_dump - - - - N"
|
||||
];
|
||||
};
|
||||
}
|
9
nyx/modules/core/common/system/os/misc/default.nix
Normal file
9
nyx/modules/core/common/system/os/misc/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./realtime.nix
|
||||
./crash.nix
|
||||
./journald.nix
|
||||
./console.nix
|
||||
./xdg-portals.nix
|
||||
];
|
||||
}
|
20
nyx/modules/core/common/system/os/misc/journald.nix
Normal file
20
nyx/modules/core/common/system/os/misc/journald.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
# https://wiki.archlinux.org/title/Systemd/Journal#Persistent_journals
|
||||
# limit systemd journal size
|
||||
# journals get big really fasti and on desktops they are not audited often
|
||||
# on servers, however, they are important for both security and stability
|
||||
# thus, persisting them as is remains a good idea
|
||||
services.journald.extraConfig = mkIf (dev.type != "server") ''
|
||||
SystemMaxUse=100M
|
||||
RuntimeMaxUse=50M
|
||||
SystemMaxFileSize=50M
|
||||
'';
|
||||
}
|
35
nyx/modules/core/common/system/os/misc/realtime.nix
Normal file
35
nyx/modules/core/common/system/os/misc/realtime.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{config, ...}: {
|
||||
# port of https://gitlab.archlinux.org/archlinux/packaging/packages/realtime-privileges
|
||||
# see https://wiki.archlinux.org/title/Realtime_process_management
|
||||
# tldr: realtime processes have higher priority than normal processes
|
||||
# and that's a good thing
|
||||
users = {
|
||||
users."${config.modules.system.mainUser}".extraGroups = ["realtime"];
|
||||
groups.realtime = {};
|
||||
};
|
||||
|
||||
services.udev.extraRules = ''
|
||||
KERNEL=="cpu_dma_latency", GROUP="realtime"
|
||||
'';
|
||||
|
||||
security.pam.loginLimits = [
|
||||
{
|
||||
domain = "@realtime";
|
||||
type = "-";
|
||||
item = "rtprio";
|
||||
value = 98;
|
||||
}
|
||||
{
|
||||
domain = "@realtime";
|
||||
type = "-";
|
||||
item = "memlock";
|
||||
value = "unlimited";
|
||||
}
|
||||
{
|
||||
domain = "@realtime";
|
||||
type = "-";
|
||||
item = "nice";
|
||||
value = -11;
|
||||
}
|
||||
];
|
||||
}
|
18
nyx/modules/core/common/system/os/misc/xdg-portals.nix
Normal file
18
nyx/modules/core/common/system/os/misc/xdg-portals.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
sys = config.modules.system;
|
||||
inherit (lib) mkIf;
|
||||
in {
|
||||
config = mkIf sys.video.enable {
|
||||
xdg.portal.config = {
|
||||
common = {
|
||||
"org.freedesktop.impl.portal.Secret" = [
|
||||
"gnome-keyring"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
16
nyx/modules/core/common/system/os/networking/blocker.nix
Normal file
16
nyx/modules/core/common/system/os/networking/blocker.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{config, ...}: let
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
# this should block *most* junk sites
|
||||
networking = {
|
||||
stevenblack = {
|
||||
enable = dev.type != "server"; # don't touch hosts file on a server
|
||||
block = [
|
||||
"fakenews"
|
||||
"gambling"
|
||||
"porn"
|
||||
#"social" # blocks stuff like reddit, which I occasionally visit
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
108
nyx/modules/core/common/system/os/networking/default.nix
Normal file
108
nyx/modules/core/common/system/os/networking/default.nix
Normal file
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkForce mkDefault;
|
||||
in {
|
||||
imports = [
|
||||
./firewall
|
||||
|
||||
./blocker.nix
|
||||
./network-manager.nix
|
||||
./optimize.nix
|
||||
./resolved.nix
|
||||
./ssh.nix
|
||||
./tailscale.nix
|
||||
./tcpcrypt.nix
|
||||
./wireless.nix
|
||||
];
|
||||
|
||||
# network tools that are helpful and nice to have
|
||||
boot.kernelModules = ["af_packet"];
|
||||
environment.systemPackages = with pkgs; [
|
||||
mtr
|
||||
tcpdump
|
||||
traceroute
|
||||
];
|
||||
|
||||
networking = {
|
||||
# generate a unique hostname by hashing the hostname
|
||||
# with md5 and taking the first 8 characters of the hash
|
||||
# this is especially helpful while using zfs but still
|
||||
# ensures that there will be a unique hostId even when
|
||||
# we are not using zfs
|
||||
hostId = builtins.substring 0 8 (builtins.hashString "md5" config.networking.hostName);
|
||||
|
||||
# global dhcp has been deprecated upstream
|
||||
# use the new networkd service instead of the legacy
|
||||
# "script-based" network setups. Host may contain individual
|
||||
# dhcp interfaces or systemd-networkd configurations in host
|
||||
# specific directories
|
||||
useDHCP = mkForce false;
|
||||
useNetworkd = mkForce true;
|
||||
|
||||
# interfaces are assigned names that contain topology information (e.g. wlp3s0)
|
||||
# and thus should be consistent across reboots
|
||||
# this already defaults to true, we set it in case it changes upstream
|
||||
usePredictableInterfaceNames = mkDefault true;
|
||||
|
||||
# dns
|
||||
nameservers = [
|
||||
# cloudflare, yuck
|
||||
# shares data
|
||||
"1.1.1.1"
|
||||
"1.0.0.1"
|
||||
"2606:4700:4700::1111"
|
||||
"2606:4700:4700::1001"
|
||||
|
||||
# quad9, said to be the best
|
||||
# shares *less* data
|
||||
"9.9.9.9"
|
||||
"149.112.112.112"
|
||||
"2620:fe::fe"
|
||||
"2620:fe::9"
|
||||
];
|
||||
|
||||
# search paths used when resolving domain names
|
||||
# this can allow us to find hosts on private networks
|
||||
# e.g. wireguard, tailscale and headscale
|
||||
search = [
|
||||
"notashelf.dev" # referss to the server itself
|
||||
"notashelf.notashelf.dev" # headscale network
|
||||
];
|
||||
};
|
||||
|
||||
# enable wireless database, it helps with finding the right channels
|
||||
hardware.wirelessRegulatoryDatabase = true;
|
||||
|
||||
# allow for the system to boot without waiting for the network interfaces are online
|
||||
# speeds up boot times
|
||||
systemd = let
|
||||
# TODO: allow for the hosts to define those interfaces
|
||||
ethernetDevices = [
|
||||
"wlp1s0f0u8" # wifi dongle
|
||||
];
|
||||
in {
|
||||
# according to 23.11 release notes, wait-online target has long been fixed
|
||||
# spoiler: no it's not.
|
||||
network.wait-online.enable = false;
|
||||
services =
|
||||
{
|
||||
NetworkManager-wait-online.enable = false;
|
||||
|
||||
# disable networkd and resolved from being restarted on configuration changes
|
||||
# lets me avoid a short network outage when I change the configuration
|
||||
# also means that I **must** reboot to make sure my network changes are
|
||||
# are properly propagated
|
||||
systemd-networkd.stopIfChanged = false;
|
||||
systemd-resolved.stopIfChanged = false;
|
||||
}
|
||||
// lib.concatMapAttrs (_: v: v) (lib.genAttrs ethernetDevices (device: {
|
||||
# Assign an IP address when the device is plugged in rather than on startup. Needed to prevent
|
||||
# blocking the boot sequence when the device is unavailable, as it is hotpluggable.
|
||||
"network-addresses-${device}".wantedBy = lib.mkForce ["sys-subsystem-net-devices-${device}.device"];
|
||||
}));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkForce;
|
||||
dev = config.modules.device;
|
||||
cfg = config.networking.nftables;
|
||||
in {
|
||||
imports = [
|
||||
./nftables
|
||||
|
||||
./fail2ban.nix
|
||||
./tarpit.nix
|
||||
];
|
||||
|
||||
config = {
|
||||
# enable opensnitch firewall
|
||||
# inactive until opensnitch UI is opened
|
||||
# since the UI cannot be opened on servers, we
|
||||
# disable it if dev.type is server
|
||||
services.opensnitch.enable = dev.type != "server";
|
||||
|
||||
networking.firewall = {
|
||||
enable = !cfg.enable;
|
||||
package =
|
||||
if cfg.enable
|
||||
then pkgs.iptables-nftables-compat
|
||||
else pkgs.iptables;
|
||||
allowedTCPPorts = [443 8080];
|
||||
allowedUDPPorts = [];
|
||||
allowPing = dev.type == "server";
|
||||
logReversePathDrops = true;
|
||||
logRefusedConnections = false; # avoid log spam
|
||||
# Leaks IPv6 route table entries due to kernel bug. This leads to degraded
|
||||
# IPv6 performance in some situations.
|
||||
# checkReversePath = config.boot.kernelPackages.kernelAtLeast "5.16";
|
||||
checkReversePath = mkForce false; # Don't filter DHCP packets, according to nixops-libvirtd
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf mkMerge mkForce;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
|
||||
sys = config.modules.system;
|
||||
in {
|
||||
# fail2ban firewall jail
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
extraPackages = [pkgs.nftables]; # make nftables accessible to fail2ban service
|
||||
|
||||
ignoreIP = [
|
||||
"127.0.0.0/8" # localhost
|
||||
"10.0.0.0/8" # wireguard
|
||||
"100.64.0.0/16" # tailscale
|
||||
"192.168.0.0/16" # local network
|
||||
];
|
||||
|
||||
maxretry = 7;
|
||||
bantime-increment = {
|
||||
enable = true;
|
||||
rndtime = "12m";
|
||||
overalljails = true;
|
||||
multipliers = "4 8 16 32 64 128 256 512 1024 2048";
|
||||
maxtime = "5000h"; # get banned for 5000 hours idiot
|
||||
};
|
||||
|
||||
jails = mkMerge [
|
||||
{
|
||||
# sshd jail
|
||||
sshd = mkForce ''
|
||||
enabled = true
|
||||
port = ${concatStringsSep "," (map toString config.services.openssh.ports)}
|
||||
mode = aggressive
|
||||
'';
|
||||
}
|
||||
{
|
||||
# nftables jail
|
||||
nftables-common = mkForce ''
|
||||
enabled = true
|
||||
banaction = nftables-multiport
|
||||
chain = input
|
||||
'';
|
||||
}
|
||||
|
||||
(mkIf sys.services.vaultwarden.enable {
|
||||
# vaultwarden and vaultwarden admin interface jails
|
||||
vaultwarden = ''
|
||||
enabled = true
|
||||
port = 80,443,8822
|
||||
filter = vaultwarden
|
||||
banaction = %(banaction_allports)s
|
||||
logpath = /var/log/vaultwarden.log
|
||||
maxretry = 3
|
||||
bantime = 14400
|
||||
findtime = 14400
|
||||
'';
|
||||
|
||||
vaultwarden-admin = ''
|
||||
enabled = true
|
||||
port = 80,443
|
||||
filter = vaultwarden-admin
|
||||
banaction = %(banaction_allports)s
|
||||
logpath = /var/log/vaultwarden.log
|
||||
maxretry = 3
|
||||
bantime = 14400
|
||||
findtime = 14400
|
||||
'';
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkRuleset;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = config.networking.nftables;
|
||||
|
||||
check-results =
|
||||
pkgs.runCommand "check-nft-ruleset" {
|
||||
ruleset = pkgs.writeText "nft-ruleset" cfg.ruleset;
|
||||
} ''
|
||||
mkdir -p $out
|
||||
${pkgs.nftables}/bin/nft -c -f $ruleset 2>&1 > $out/message \
|
||||
&& echo false > $out/assertion \
|
||||
|| echo true > $out/assertion
|
||||
'';
|
||||
in {
|
||||
imports = [./rules.nix];
|
||||
config = mkIf sys.networking.nftables.enable {
|
||||
networking.nftables = {
|
||||
enable = true;
|
||||
|
||||
# flush ruleset on each reload
|
||||
flushRuleset = true;
|
||||
|
||||
# nftables.tables is semi-verbatim configuration
|
||||
# that is inserted **before** nftables.ruleset
|
||||
# as per the nftables module.
|
||||
tables = {
|
||||
"fail2ban" = {
|
||||
name = "fail2ban-nftables";
|
||||
family = "ip";
|
||||
content = ''
|
||||
# <https://wiki.gbe0.com/en/linux/firewalling-and-filtering/nftables/fail2ban>
|
||||
chain input {
|
||||
type filter hook input priority 100;
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# our ruleset, built with our local ruleset builder from lib/network/firewall.nix
|
||||
# I prefer using this to the nftables.tables.* and verbatim nftables.ruleset = ""
|
||||
# kinds of configs, as it allows me to programmatically approach to my ruleset
|
||||
# instead of structuring it inside a multiline string. nftables.rules, which is
|
||||
# located in ./rules.nix, is easily parsable and modifiable with the help of Nix.
|
||||
ruleset = mkRuleset cfg.rules;
|
||||
};
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = import "${check-results}/assertion";
|
||||
message = ''
|
||||
Bad config:
|
||||
${builtins.readFile "${check-results}/message"}
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# pin IFD as a system dependency
|
||||
# this makes sure the IFD result is realised in time
|
||||
# without making the IFD a part of the system
|
||||
# unlike system.extraDependencies
|
||||
system.checks = [check-results];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) entryBefore entryBetween entryAfter entryAnywhere;
|
||||
in {
|
||||
networking.nftables.rules = {
|
||||
inet = {
|
||||
filter = {
|
||||
input = {
|
||||
loopback = entryAnywhere {
|
||||
field = "iifname";
|
||||
value = "lo";
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
established-locally = entryAfter ["loopback"] {
|
||||
protocol = "ct";
|
||||
field = "state";
|
||||
value = ["established" "related"];
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
basic-icmp6 = entryAfter ["loopback" "established-locally"] {
|
||||
protocol = "ip6 nexthdr icmpv6 icmpv6";
|
||||
field = "type";
|
||||
value = [
|
||||
"destination-unreachable"
|
||||
"packet-too-big"
|
||||
"time-exceeded"
|
||||
"parameter-problem"
|
||||
"nd-router-advert"
|
||||
"nd-neighbor-solicit"
|
||||
"nd-neighbor-advert"
|
||||
#"mld-listener-query" "nd-router-solicit" # for routers
|
||||
];
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
basic-icmp = entryAfter ["loopback" "established-locally"] {
|
||||
protocol = "ip protocol icmp icmp";
|
||||
field = "type";
|
||||
value = [
|
||||
"destination-unreachable"
|
||||
"router-advertisement"
|
||||
"time-exceeded"
|
||||
"parameter-problem"
|
||||
];
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
ping6 = entryBefore ["basic-icmp6"] {
|
||||
protocol = "ip6 nexthdr icmpv6 icmpv6";
|
||||
field = "type";
|
||||
value = "echo-request";
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
ping = entryBefore ["basic-icmp"] {
|
||||
protocol = "ip protocol icmp icmp";
|
||||
field = "type";
|
||||
value = "echo-request";
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
ssh = entryBetween ["basic-icmp6" "basic-icmp" "ping6" "ping"] ["default"] {
|
||||
protocol = "tcp";
|
||||
field = "dport";
|
||||
value = config.services.openssh.ports;
|
||||
policy = "accept";
|
||||
};
|
||||
|
||||
default = entryAfter ["loopback" "established-locally" "basic-icmp6" "basic-icmp" "ping6" "ping"] {
|
||||
policy = lib.mkDefault "drop";
|
||||
};
|
||||
};
|
||||
|
||||
# accept all outgoing traffic
|
||||
output = {
|
||||
default = entryAnywhere {
|
||||
policy = "accept";
|
||||
};
|
||||
};
|
||||
|
||||
# let nftables forward traffic
|
||||
# we decide whether the host can forward traffic
|
||||
# via sysctl settings elsewhere
|
||||
forward = {
|
||||
default = entryAnywhere {
|
||||
policy = "accept";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
# jebait agressive port scanners by wasting their time with connection that'll never make it in
|
||||
# this *does* have performance implications, however, so be careful which hosts you enable it for
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.networking.tarpit;
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
services.endlessh-go = {
|
||||
enable = true;
|
||||
port = 22;
|
||||
openFirewall = true;
|
||||
|
||||
extraOptions = [
|
||||
"-alsologtostderr"
|
||||
"-geoip_supplier max-mind-db"
|
||||
"-max_mind_db ${pkgs.clash-geoip}/etc/clash/Country.mmdb"
|
||||
];
|
||||
|
||||
prometheus = {
|
||||
enable = true;
|
||||
port = 9105;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf mkForce;
|
||||
|
||||
dev = config.modules.device;
|
||||
sys = config.modules.system;
|
||||
|
||||
inherit (sys.networking) wireless;
|
||||
in {
|
||||
# we use networkmanager manage network devices locally
|
||||
networking.networkmanager = {
|
||||
enable = true;
|
||||
plugins = mkForce []; # disable all plugins, we don't need them
|
||||
dns = "systemd-resolved"; # use systemd-resolved as dns backend
|
||||
unmanaged = [
|
||||
"interface-name:tailscale*"
|
||||
"interface-name:br-*"
|
||||
"interface-name:rndis*"
|
||||
"interface-name:docker*"
|
||||
"interface-name:virbr*"
|
||||
];
|
||||
|
||||
wifi = {
|
||||
inherit (wireless) backend; # this can be iwd or wpa_supplicant, use wpa_supp. until iwd support is stable
|
||||
macAddress = "random"; # use a random mac address on every boot
|
||||
powersave = true; # enable wifi powersaving
|
||||
scanRandMacAddress = true; # MAC address randomization of a Wi-Fi device during scanning
|
||||
};
|
||||
|
||||
ethernet.macAddress = mkIf (dev.type != "server") "random"; # causes server to be unreachable over SSH
|
||||
};
|
||||
}
|
78
nyx/modules/core/common/system/os/networking/optimize.nix
Normal file
78
nyx/modules/core/common/system/os/networking/optimize.nix
Normal file
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
sys = config.modules.system.networking;
|
||||
inherit (lib) mkIf;
|
||||
in {
|
||||
config = mkIf sys.optimizeTcp {
|
||||
boot = {
|
||||
kernelModules = ["tls" "tcp_bbr"];
|
||||
kernel.sysctl = {
|
||||
# TCP hardening
|
||||
# Prevent bogus ICMP errors from filling up logs.
|
||||
"net.ipv4.icmp_ignore_bogus_error_responses" = 1;
|
||||
# Reverse path filtering causes the kernel to do source validation of
|
||||
# packets received from all interfaces. This can mitigate IP spoofing.
|
||||
"net.ipv4.conf.default.rp_filter" = 1;
|
||||
"net.ipv4.conf.all.rp_filter" = 1;
|
||||
# Do not accept IP source route packets (we're not a router)
|
||||
"net.ipv4.conf.all.accept_source_route" = 0;
|
||||
"net.ipv6.conf.all.accept_source_route" = 0;
|
||||
# Don't send ICMP redirects (again, we're on a router)
|
||||
"net.ipv4.conf.all.send_redirects" = 0;
|
||||
"net.ipv4.conf.default.send_redirects" = 0;
|
||||
# Refuse ICMP redirects (MITM mitigations)
|
||||
"net.ipv4.conf.all.accept_redirects" = 0;
|
||||
"net.ipv4.conf.default.accept_redirects" = 0;
|
||||
"net.ipv4.conf.all.secure_redirects" = 0;
|
||||
"net.ipv4.conf.default.secure_redirects" = 0;
|
||||
"net.ipv6.conf.all.accept_redirects" = 0;
|
||||
"net.ipv6.conf.default.accept_redirects" = 0;
|
||||
# Protects against SYN flood attacks
|
||||
"net.ipv4.tcp_syncookies" = 1;
|
||||
# Incomplete protection again TIME-WAIT assassination
|
||||
"net.ipv4.tcp_rfc1337" = 1;
|
||||
# And other stuff
|
||||
"net.ipv4.conf.all.log_martians" = true;
|
||||
"net.ipv4.conf.default.log_martians" = true;
|
||||
"net.ipv4.icmp_echo_ignore_broadcasts" = true;
|
||||
"net.ipv6.conf.default.accept_ra" = 0;
|
||||
"net.ipv6.conf.all.accept_ra" = 0;
|
||||
"net.ipv4.tcp_timestamps" = 0;
|
||||
|
||||
# TCP optimization
|
||||
# TCP Fast Open is a TCP extension that reduces network latency by packing
|
||||
# data in the sender’s initial TCP SYN. Setting 3 = enable TCP Fast Open for
|
||||
# both incoming and outgoing connections:
|
||||
"net.ipv4.tcp_fastopen" = 3;
|
||||
# Bufferbloat mitigations + slight improvement in throughput & latency
|
||||
"net.ipv4.tcp_congestion_control" = "bbr";
|
||||
"net.core.default_qdisc" = "cake";
|
||||
|
||||
# Other stuff that I am too lazy to document
|
||||
"net.core.optmem_max" = 65536;
|
||||
"net.core.rmem_default" = 1048576;
|
||||
"net.core.rmem_max" = 16777216;
|
||||
"net.core.somaxconn" = 8192;
|
||||
"net.core.wmem_default" = 1048576;
|
||||
"net.core.wmem_max" = 16777216;
|
||||
"net.ipv4.ip_local_port_range" = "16384 65535";
|
||||
"net.ipv4.tcp_max_syn_backlog" = 8192;
|
||||
"net.ipv4.tcp_max_tw_buckets" = 2000000;
|
||||
"net.ipv4.tcp_mtu_probing" = 1;
|
||||
"net.ipv4.tcp_rmem" = "4096 1048576 2097152";
|
||||
"net.ipv4.tcp_slow_start_after_idle" = 0;
|
||||
"net.ipv4.tcp_tw_reuse" = 1;
|
||||
"net.ipv4.tcp_wmem" = "4096 65536 16777216";
|
||||
"net.ipv4.udp_rmem_min" = 8192;
|
||||
"net.ipv4.udp_wmem_min" = 8192;
|
||||
"net.netfilter.nf_conntrack_generic_timeout" = 60;
|
||||
"net.netfilter.nf_conntrack_max" = 1048576;
|
||||
"net.netfilter.nf_conntrack_tcp_timeout_established" = 600;
|
||||
"net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
34
nyx/modules/core/common/system/os/networking/resolved.nix
Normal file
34
nyx/modules/core/common/system/os/networking/resolved.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
services = {
|
||||
resolved = {
|
||||
# enable systemd DNS resolver daemon
|
||||
enable = true;
|
||||
|
||||
# this is necessary to get tailscale picking up your headscale instance
|
||||
# and allows you to ping connected hosts by hostname
|
||||
domains = ["~."];
|
||||
|
||||
# DNSSEC provides to DNS clients (resolvers) origin authentication of DNS data, authenticated denial of existence
|
||||
# and data integrity but not availability or confidentiality.
|
||||
# this is considered EXPERIMENTAL and UNSTABLE according to upstream
|
||||
# PLEASE SEE <https://github.com/systemd/systemd/issues/25676#issuecomment-1634810897>
|
||||
# before you decide to set this. I have it set to false as the issue
|
||||
# does not inspire confidence in systemd's ability to manage this
|
||||
dnssec = "false";
|
||||
|
||||
# additional configuration to be appeneded to systemd-resolved configuration
|
||||
extraConfig = ''
|
||||
# <https://wiki.archlinux.org/title/Systemd-resolved#DNS_over_TLS>
|
||||
# apparently upstream (systemd) recommends this to be false
|
||||
# `allow-downgrade` is vulnerable to downgrade attacks
|
||||
DNSOverTLS=yes # or allow-downgrade
|
||||
'';
|
||||
|
||||
# ideally our fallbackDns should be something more widely available
|
||||
# but I do not want my last resort to sell my data to every company available
|
||||
# NOTE: DNS fallback is not a recovery DNS
|
||||
# See <https://github.com/systemd/systemd/issues/5771#issuecomment-296673115>
|
||||
fallbackDns = ["9.9.9.9"];
|
||||
};
|
||||
};
|
||||
}
|
131
nyx/modules/core/common/system/os/networking/ssh.nix
Normal file
131
nyx/modules/core/common/system/os/networking/ssh.nix
Normal file
|
@ -0,0 +1,131 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkForce mkDefault;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
inherit (lib.lists) elemAt;
|
||||
in {
|
||||
services.openssh = {
|
||||
# enable openssh
|
||||
enable = true;
|
||||
openFirewall = true; # the ssh port(s) should be automatically passed to the firewall's allowedTCPports
|
||||
ports = [30]; # the port(s) openssh daemon should listen on
|
||||
startWhenNeeded = true; # automatically start the ssh daemon when it's required
|
||||
settings = {
|
||||
# no root login
|
||||
PermitRootLogin = mkForce "no";
|
||||
|
||||
# no password auth
|
||||
# force publickey authentication only
|
||||
PasswordAuthentication = false;
|
||||
AuthenticationMethods = "publickey";
|
||||
PubkeyAuthentication = "yes";
|
||||
ChallengeResponseAuthentication = "no";
|
||||
UsePAM = "no";
|
||||
|
||||
# remove sockets as they get stale
|
||||
# this will unbind gnupg sockets if they exists
|
||||
StreamLocalBindUnlink = "yes";
|
||||
|
||||
KbdInteractiveAuthentication = mkDefault false;
|
||||
UseDns = false; # no
|
||||
X11Forwarding = false; # ew xorg
|
||||
|
||||
# key exchange algorithms recommended by `nixpkgs#ssh-audit`
|
||||
KexAlgorithms = [
|
||||
"curve25519-sha256"
|
||||
"curve25519-sha256@libssh.org"
|
||||
"diffie-hellman-group16-sha512"
|
||||
"diffie-hellman-group18-sha512"
|
||||
"diffie-hellman-group-exchange-sha256"
|
||||
"sntrup761x25519-sha512@openssh.com"
|
||||
];
|
||||
|
||||
# message authentication code algorithms recommended by `nixpkgs#ssh-audit`
|
||||
Macs = [
|
||||
"hmac-sha2-512-etm@openssh.com"
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"umac-128-etm@openssh.com"
|
||||
];
|
||||
|
||||
# kick out inactive sessions
|
||||
ClientAliveCountMax = 5;
|
||||
ClientAliveInterval = 60;
|
||||
|
||||
# max auth attempts
|
||||
MaxAuthTries = 3;
|
||||
};
|
||||
|
||||
hostKeys = mkDefault [
|
||||
{
|
||||
bits = 4096;
|
||||
path = "/etc/ssh/ssh_host_rsa_key";
|
||||
type = "rsa";
|
||||
}
|
||||
{
|
||||
bits = 4096;
|
||||
path = "/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
programs.ssh = let
|
||||
# a list of hosts that are connected over Tailscale
|
||||
# it would be better to construct this list dynamically
|
||||
# but we hardcode it because we cannot check if a host is
|
||||
# authenticated - that needs manual intervention
|
||||
hosts = ["helios" "enyo" "hermes"];
|
||||
|
||||
# generate the ssh config for the hosts
|
||||
mkHostConfig = hostname: ''
|
||||
# Configuration for ${hostname}
|
||||
Host ${hostname}
|
||||
HostName ${hostname}
|
||||
Port ${toString (elemAt config.services.openssh.ports 0)}
|
||||
StrictHostKeyChecking=accept-new
|
||||
'';
|
||||
|
||||
hostConfig = concatStringsSep "\n" (map mkHostConfig hosts);
|
||||
in {
|
||||
startAgent = !config.modules.system.yubikeySupport.enable;
|
||||
extraConfig = ''
|
||||
${hostConfig}
|
||||
'';
|
||||
|
||||
# ship github/gitlab/sourcehut host keys to avoid MiM (man in the middle) attacks
|
||||
knownHosts = mapAttrs (_: mkForce) {
|
||||
github-rsa = {
|
||||
hostNames = ["github.com"];
|
||||
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==";
|
||||
};
|
||||
|
||||
github-ed25519 = {
|
||||
hostNames = ["github.com"];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||
};
|
||||
|
||||
gitlab-rsa = {
|
||||
hostNames = ["gitlab.com"];
|
||||
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9";
|
||||
};
|
||||
gitlab-ed25519 = {
|
||||
hostNames = ["gitlab.com"];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf";
|
||||
};
|
||||
|
||||
sourcehut-rsa = {
|
||||
hostNames = ["git.sr.ht"];
|
||||
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ+l/lvYmaeOAPeijHL8d4794Am0MOvmXPyvHTtrqvgmvCJB8pen/qkQX2S1fgl9VkMGSNxbp7NF7HmKgs5ajTGV9mB5A5zq+161lcp5+f1qmn3Dp1MWKp/AzejWXKW+dwPBd3kkudDBA1fa3uK6g1gK5nLw3qcuv/V4emX9zv3P2ZNlq9XRvBxGY2KzaCyCXVkL48RVTTJJnYbVdRuq8/jQkDRA8lHvGvKI+jqnljmZi2aIrK9OGT2gkCtfyTw2GvNDV6aZ0bEza7nDLU/I+xmByAOO79R1Uk4EYCvSc1WXDZqhiuO2sZRmVxa0pQSBDn1DB3rpvqPYW+UvKB3SOz";
|
||||
};
|
||||
|
||||
sourcehut-ed25519 = {
|
||||
hostNames = ["git.sr.ht"];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
96
nyx/modules/core/common/system/os/networking/tailscale.nix
Normal file
96
nyx/modules/core/common/system/os/networking/tailscale.nix
Normal file
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkDefault optionals mkBefore;
|
||||
inherit (config.services) tailscale;
|
||||
|
||||
sys = config.modules.system.networking;
|
||||
cfg = sys.tailscale;
|
||||
|
||||
upFlags =
|
||||
cfg.flags.default
|
||||
++ ["--authkey file:${config.age.secrets.tailscale-client.path}"]
|
||||
++ optionals cfg.isServer ["--advertise-exit-node"]
|
||||
++ optionals (cfg.endpoint != null) ["--login-server ${cfg.endpoint}"]
|
||||
# TODO: test if specifying an operator messes with the autologin service
|
||||
# which, as you expect, does not run as the operator user
|
||||
++ optionals (cfg.operator != null) ["--operator" cfg.operator];
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
# make the tailscale command usable to users
|
||||
environment.systemPackages = [pkgs.tailscale];
|
||||
|
||||
networking.firewall = {
|
||||
# always allow traffic from the designated tailscale interface
|
||||
trustedInterfaces = ["${tailscale.interfaceName}"];
|
||||
checkReversePath = "loose";
|
||||
|
||||
# allow
|
||||
allowedUDPPorts = [tailscale.port];
|
||||
};
|
||||
|
||||
boot.kernel = {
|
||||
sysctl = {
|
||||
# # Enable IP forwarding
|
||||
# required for Wireguard & Tailscale/Headscale subnet feature
|
||||
# See <https://tailscale.com/kb/1019/subnets/?tab=linux#step-1-install-the-tailscale-client>
|
||||
"net.ipv4.ip_forward" = true;
|
||||
"net.ipv6.conf.all.forwarding" = true;
|
||||
};
|
||||
};
|
||||
|
||||
# enable tailscale, inter-machine VPN service
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
permitCertUid = "root";
|
||||
useRoutingFeatures = mkDefault "both";
|
||||
# TODO: these flags still need to be specified with `tailscale up`
|
||||
# for some reason
|
||||
extraUpFlags = upFlags;
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
# lets not send our logs to log.tailscale.io
|
||||
# unless I get to know what they do with the logs
|
||||
tailscaled.serviceConfig.Environment = mkBefore ["TS_NO_LOGS_NO_SUPPORT=true"];
|
||||
|
||||
# oneshot tailscale authentication servcie
|
||||
# TODO: this implies tailscale has been authenticated before with our own login server
|
||||
# ideally we should have a way to authenticate tailscale with our own login server in
|
||||
# this service, likely through an option in the system module
|
||||
tailscale-autoconnect = {
|
||||
description = "Automatic connection to Tailscale";
|
||||
|
||||
# make sure tailscale is running before trying to connect to tailscale
|
||||
after = ["network-pre.target" "tailscale.service"];
|
||||
wants = ["network-pre.target" "tailscale.service"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
# set this service as a oneshot job
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
# have the job run this shell script
|
||||
script = ''
|
||||
# wait for tailscaled to settle
|
||||
sleep 2
|
||||
|
||||
# check if we are already authenticated to tailscale
|
||||
status="$(${pkgs.tailscale}/bin/tailscale status -json | ${pkgs.jq}/bin/jq -r .BackendState)"
|
||||
if [ $status = "Running" ]; then # if so, then do nothing
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# otherwise authenticate with tailscale
|
||||
${pkgs.tailscale}/bin/tailscale up ${toString upFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
network.wait-online.ignoredInterfaces = ["${tailscale.interfaceName}"];
|
||||
};
|
||||
};
|
||||
}
|
101
nyx/modules/core/common/system/os/networking/tcpcrypt.nix
Normal file
101
nyx/modules/core/common/system/os/networking/tcpcrypt.nix
Normal file
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
dev = config.modules.device;
|
||||
in {
|
||||
# get rid of the tcpcrypt module provided by nixpkgs
|
||||
# it is unmaintained and I cannot be arsed to PR a fix
|
||||
disabledModules = ["services/networking/tcpcrypt.nix"];
|
||||
config = mkIf (dev.type != "server") {
|
||||
# FIXME: the upstream tcpcrypd service is unmaintained and poorly designed
|
||||
# networking.tcpcrypt.enable = true;
|
||||
|
||||
# create a system user for the tcpcrypt service
|
||||
# this is the user we will use the systemd service as
|
||||
users = {
|
||||
groups.tcpcryptd = {};
|
||||
users.tcpcryptd = {
|
||||
description = "tcpcrypt daemon user";
|
||||
group = "tcpcryptd";
|
||||
uid = config.ids.uids.tcpcryptd; # nixpkgs already defines a hardcoded uid, use it
|
||||
};
|
||||
};
|
||||
|
||||
# enable opportunistic TCP encryption
|
||||
# this is NOT a pancea, however, if the receiver supports encryption and the attacker is passive
|
||||
# privacy will be more plausible (but not guaranteed, unlike what the option docs suggest)
|
||||
# NOTE: the systemd service below is rewritten to be an alternative to networking.tcpcrypt.enable
|
||||
# it lacks hardening and SHOULD NOT BE USED until further notice.
|
||||
systemd.services.tcpcrypt = let
|
||||
# borrowed from fedora's tcpcrypt rpm spec
|
||||
# <https://src.fedoraproject.org/rpms/tcpcrypt/blob/rawhide/f/tcpcryptd-firewall>
|
||||
tcpcryptd-firewall = pkgs.writeShellApplication {
|
||||
name = "tcpcryptd-firewall";
|
||||
runtimeInputs = [pkgs.iptables];
|
||||
text = ''
|
||||
|
||||
# use iptables manually
|
||||
if [ "$1" = "start" ]; then
|
||||
iptables -t raw -N nixos-tcpcrypt
|
||||
iptables -t raw -A nixos-tcpcrypt -p tcp -m mark --mark 0x0/0x10 -j NFQUEUE --queue-num 666
|
||||
iptables -t raw -I PREROUTING -j nixos-tcpcrypt
|
||||
|
||||
iptables -t mangle -N nixos-tcpcrypt
|
||||
iptables -t mangle -A nixos-tcpcrypt -p tcp -m mark --mark 0x0/0x10 -j NFQUEUE --queue-num 666
|
||||
iptables -t mangle -I POSTROUTING -j nixos-tcpcrypt
|
||||
fi
|
||||
|
||||
if [ "$1" = "stop" ]; then
|
||||
iptables -t mangle -D POSTROUTING -j nixos-tcpcrypt || true
|
||||
iptables -t raw -D PREROUTING -j nixos-tcpcrypt || true
|
||||
|
||||
iptables -t raw -F nixos-tcpcrypt || true
|
||||
iptables -t raw -X nixos-tcpcrypt || true
|
||||
|
||||
iptables -t mangle -F nixos-tcpcrypt || true
|
||||
iptables -t mangle -X nixos-tcpcrypt || true
|
||||
fi
|
||||
'';
|
||||
};
|
||||
in {
|
||||
description = "tcpcrypt, opportunistic tcp encryption";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target" "syslog.target"];
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
|
||||
RuntimeDirectory = "tcpcryptd";
|
||||
RuntimeDirectoryMode = "0750";
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
echo -en "Starting tcpcryptd\n"
|
||||
${pkgs.procps}/bin/sysctl -n net.ipv4.tcp_ecn > /run/tcpcryptd/pre-tcpcrypt-ecn-state
|
||||
${pkgs.procps}/bin/sysctl -w net.ipv4.tcp_ecn=0
|
||||
|
||||
# start the firewall
|
||||
${tcpcryptd-firewall}/bin/tcpcryptd-firewall start
|
||||
'';
|
||||
|
||||
# -f disables network test
|
||||
script = "${pkgs.tcpcrypt}/bin/tcpcryptd -v -f -x 0x10 ";
|
||||
|
||||
postStop = ''
|
||||
echo -en "Stopped tcpcrypd, restoring tcp_enc state\n"
|
||||
if [ -f /run/tcpcryptd/pre-tcpcrypt-ecn-state ]; then
|
||||
${pkgs.procps}/bin/sysctl -w net.ipv4.tcp_ecn=$(cat /run/tcpcryptd/pre-tcpcrypt-ecn-state)
|
||||
fi
|
||||
|
||||
# stop the firewall
|
||||
${tcpcryptd-firewall}/bin/tcpcryptd-firewall stop
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
71
nyx/modules/core/common/system/os/networking/wireless.nix
Normal file
71
nyx/modules/core/common/system/os/networking/wireless.nix
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.lists) optionals;
|
||||
inherit (lib.attrsets) optionalAttrs;
|
||||
inherit (lib.meta) getExe;
|
||||
|
||||
sys = config.modules.system;
|
||||
|
||||
inherit (sys.networking) wireless;
|
||||
in {
|
||||
config = {
|
||||
environment.systemPackages = optionals (wireless.backend == "iwd") pkgs.iwgtk;
|
||||
networking.wireless =
|
||||
{
|
||||
enable = wireless.backend == "wpa_supplicant";
|
||||
|
||||
# configure iwd
|
||||
iwd = {
|
||||
enable = wireless.backend == "iwd";
|
||||
settings = {
|
||||
#Rank.BandModifier5Ghz = 2.0;
|
||||
#Scan.DisablePeriodicScan = true;
|
||||
Settings.AutoConnect = true;
|
||||
|
||||
General = {
|
||||
AddressRandomization = "network";
|
||||
AddressRandomizationRange = "full";
|
||||
EnableNetworkConfiguration = true;
|
||||
RoamRetryInterval = 15;
|
||||
};
|
||||
|
||||
Network = {
|
||||
EnableIPv6 = true;
|
||||
RoutePriorityOffset = 300;
|
||||
# NameResolvingService = "resolvconf";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
// optionalAttrs wireless.allowImperative {
|
||||
# Imperative Configuration
|
||||
userControlled.enable = true;
|
||||
allowAuxiliaryImperativeNetworks = true; # patches wpa_supplicant
|
||||
|
||||
extraConfig = ''
|
||||
update_config=1
|
||||
'';
|
||||
};
|
||||
|
||||
# launch indicator as a daemon on login if wireless backend
|
||||
# is defined as iwd
|
||||
systemd = {
|
||||
# make sure we ensure the existence of wpa_supplicant config
|
||||
# before we run the wpa_supplicant service
|
||||
services.wpa_supplicant.preStart = ''
|
||||
touch /etc/wpa_supplicant.conf
|
||||
'';
|
||||
|
||||
user.services.iwgtk = mkIf (wireless.backend == "iwd") {
|
||||
serviceConfig.ExecStart = "${getExe pkgs.iwgtk} -i";
|
||||
wantedBy = ["graphical-session.target"];
|
||||
partOf = ["graphical-session.target"];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
39
nyx/modules/core/common/system/os/programs/default.nix
Normal file
39
nyx/modules/core/common/system/os/programs/default.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./direnv.nix
|
||||
./nano.nix
|
||||
];
|
||||
|
||||
programs = {
|
||||
bash = {
|
||||
# when entering the interactive shell, set the history file to
|
||||
# the config directory to avoid cluttering the $HOME directory
|
||||
interactiveShellInit = ''
|
||||
export HISTFILE="$XDG_STATE_HOME"/bash_history
|
||||
'';
|
||||
|
||||
# initialize starship in impromptu bash sessions
|
||||
# (e.g. when running a command without entering a shell)
|
||||
promptInit = ''
|
||||
eval "$(${lib.getExe pkgs.starship} init bash)"
|
||||
'';
|
||||
};
|
||||
|
||||
# less pager
|
||||
less.enable = true;
|
||||
|
||||
# home-manager is quirky as ever, and wants this to be set in system config
|
||||
# instead of just home-manager
|
||||
zsh.enable = true;
|
||||
|
||||
# run commands without installing the programs
|
||||
comma.enable = true;
|
||||
|
||||
# type "fuck" to fix the last command that made you go "fuck"
|
||||
thefuck.enable = true;
|
||||
};
|
||||
}
|
103
nyx/modules/core/common/system/os/programs/direnv.nix
Normal file
103
nyx/modules/core/common/system/os/programs/direnv.nix
Normal file
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
programs.direnv = {
|
||||
enable = true;
|
||||
|
||||
# shut up. SHUT UP
|
||||
silent = true;
|
||||
|
||||
# faster, persistent implementation of use_nix and use_flake
|
||||
nix-direnv = {
|
||||
enable = true;
|
||||
package = pkgs.nix-direnv.override {
|
||||
nix = config.nix.package;
|
||||
};
|
||||
};
|
||||
|
||||
# enable loading direnv in nix-shell nix shell or nix develop
|
||||
loadInNixShell = true;
|
||||
|
||||
direnvrcExtra = ''
|
||||
: ''${XDG_CACHE_HOME:=$HOME/.cache}
|
||||
declare -A direnv_layout_dirs
|
||||
|
||||
# https://github.com/direnv/direnv/wiki/Customizing-cache-location#hashed-directories
|
||||
direnv_layout_dir() {
|
||||
echo "''${direnv_layout_dirs[$PWD]:=$(
|
||||
echo -n "$XDG_CACHE_HOME"/direnv/layouts/
|
||||
echo -n "$PWD" | ${pkgs.perl}/bin/shasum | cut -d ' ' -f 1
|
||||
)}"
|
||||
}
|
||||
|
||||
# Usage: daemonize <name> [<command> [...<args>]]
|
||||
#
|
||||
# Starts the command in the background with an exclusive lock on $name.
|
||||
#
|
||||
# If no command is passed, it uses the name as the command.
|
||||
#
|
||||
# Logs are in .direnv/$name.log
|
||||
#
|
||||
# To kill the process, run `kill $(< .direnv/$name.pid)`.
|
||||
daemonize() {
|
||||
local name=$1
|
||||
shift
|
||||
local pid_file=$(direnv_layout_dir)/$name.pid
|
||||
local log_file=$(direnv_layout_dir)/$name.log
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
cmd=$name
|
||||
else
|
||||
cmd=$1
|
||||
shift
|
||||
fi
|
||||
|
||||
if ! has "$cmd"; then
|
||||
echo "ERROR: $cmd not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p "$(direnv_layout_dir)"
|
||||
|
||||
# Open pid_file on file descriptor 200
|
||||
exec 200>"$pid_file"
|
||||
|
||||
# Check that we have exclusive access
|
||||
if ! flock --nonblock 200; then
|
||||
echo "daemonize[$name] is already running as pid $(< "$pid_file")"
|
||||
return
|
||||
fi
|
||||
|
||||
# Start the process in the background. This requires two forks to escape the
|
||||
# control of bash.
|
||||
|
||||
# First fork
|
||||
(
|
||||
# Second fork
|
||||
(
|
||||
echo "daemonize[$name:$BASHPID]: starting $cmd $*" >&2
|
||||
|
||||
# Record the PID for good measure
|
||||
echo "$BASHPID" >&200
|
||||
|
||||
# Redirect standard file descriptors
|
||||
exec 0</dev/null
|
||||
exec 1>"$log_file"
|
||||
exec 2>&1
|
||||
# Used by direnv
|
||||
exec 3>&-
|
||||
exec 4>&-
|
||||
|
||||
# Run command
|
||||
exec "$cmd" "$@"
|
||||
) &
|
||||
) &
|
||||
|
||||
# Release that file descriptor
|
||||
exec 200>&-
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
48
nyx/modules/core/common/system/os/programs/nano.nix
Normal file
48
nyx/modules/core/common/system/os/programs/nano.nix
Normal file
|
@ -0,0 +1,48 @@
|
|||
{pkgs, ...}: {
|
||||
programs.nano = {
|
||||
# enabled by default anyway, we can keep it in case my neovim config breaks
|
||||
enable = true;
|
||||
nanorc = ''
|
||||
include ${pkgs.nanorc}/share/*.nanorc # extended syntax highlighting
|
||||
|
||||
# Options
|
||||
# https://github.com/davidhcefx/Modern-Nano-Keybindings
|
||||
set tabsize 4
|
||||
set tabstospaces
|
||||
set linenumbers
|
||||
set numbercolor yellow,normal
|
||||
set indicator # side-bar for indicating cur position
|
||||
set smarthome # `Home` jumps to line start first
|
||||
set afterends # `Ctrl+Right` move to word ends instead of word starts
|
||||
set wordchars "_" # recognize '_' as part of a word
|
||||
set zap # delete selected text as a whole
|
||||
set historylog # remember search history
|
||||
set multibuffer # read files into multibuffer instead of insert
|
||||
set mouse # enable mouse support
|
||||
bind M-R redo main
|
||||
bind ^C copy main
|
||||
bind ^X cut main
|
||||
bind ^V paste main
|
||||
bind ^K zap main
|
||||
bind ^H chopwordleft all
|
||||
bind ^Q exit all
|
||||
bind ^Z suspend main
|
||||
bind M-/ comment main
|
||||
bind ^Space complete main
|
||||
|
||||
bind M-C location main
|
||||
bind ^E wherewas all
|
||||
bind M-E findprevious all
|
||||
bind ^R replace main
|
||||
bind ^B pageup all # vim-like support
|
||||
bind ^F pagedown all
|
||||
bind ^G firstline all
|
||||
bind M-G lastline all
|
||||
|
||||
bind M-1 help all # fix ^G been used
|
||||
bind Sh-M-C constantshow main # fix M-C, M-F and M-b been used
|
||||
bind Sh-M-F formatter main
|
||||
bind Sh-M-B linter main
|
||||
'';
|
||||
};
|
||||
}
|
12
nyx/modules/core/common/system/os/services/default.nix
Normal file
12
nyx/modules/core/common/system/os/services/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
imports = [
|
||||
./systemd
|
||||
|
||||
./fstrim.nix
|
||||
./fwupd.nix
|
||||
./logrotate.nix
|
||||
./lvm.nix
|
||||
./thermald.nix
|
||||
./zram.nix
|
||||
];
|
||||
}
|
39
nyx/modules/core/common/system/os/services/fstrim.nix
Normal file
39
nyx/modules/core/common/system/os/services/fstrim.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
in {
|
||||
# if lvm is enabled, then tell it to issue discards
|
||||
# (this is good for SSDs and has almost no downsides on HDDs, so
|
||||
# it's a good idea to enable it unconditionally)
|
||||
environment.etc."lvm/lvm.conf".text = mkIf config.services.lvm.enable ''
|
||||
devices {
|
||||
issue_discards = 1
|
||||
}
|
||||
'';
|
||||
|
||||
# discard blocks that are not in use by the filesystem, good for SSDs
|
||||
services.fstrim = {
|
||||
# we may enable this unconditionally across all systems becuase it's performance
|
||||
# impact is negligible on systems without a SSD - which means it's a no-op with
|
||||
# almost no downsides aside from the service firing once per week
|
||||
enable = true;
|
||||
|
||||
# the default value, good enough for average-load systems
|
||||
interval = "weekly";
|
||||
};
|
||||
|
||||
# tweak fstim service to run only when on AC power
|
||||
# and to be nice to other processes
|
||||
# (this is a good idea for any service that runs periodically)
|
||||
systemd.services.fstrim = {
|
||||
unitConfig.ConditionACPower = true;
|
||||
|
||||
serviceConfig = {
|
||||
Nice = 19;
|
||||
IOSchedulingClass = "idle";
|
||||
};
|
||||
};
|
||||
}
|
13
nyx/modules/core/common/system/os/services/fwupd.nix
Normal file
13
nyx/modules/core/common/system/os/services/fwupd.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{config, ...}: {
|
||||
# firmware updater for machine hardware
|
||||
services.fwupd = {
|
||||
enable = true;
|
||||
daemonSettings.EspLocation = config.boot.loader.efi.efiSysMountPoint;
|
||||
|
||||
# newer hardware may have their firmware in testing
|
||||
# e.g. Framework devices don't have their firmware in stable yet
|
||||
# TODO: make a system-level option that sets this value for hosts
|
||||
# that have testing firmware
|
||||
# extraRemotes = [ "lvfs-testing" ];
|
||||
};
|
||||
}
|
28
nyx/modules/core/common/system/os/services/logrotate.nix
Normal file
28
nyx/modules/core/common/system/os/services/logrotate.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
services.logrotate.settings.header = {
|
||||
# general
|
||||
global = true;
|
||||
dateext = true;
|
||||
dateformat = "-%Y-%m-%d";
|
||||
nomail = true;
|
||||
missingok = true;
|
||||
copytruncate = true;
|
||||
|
||||
# rotation frequency
|
||||
priority = 1;
|
||||
frequency = "weekly";
|
||||
rotate = 7; # special value, means every 7 days
|
||||
minage = 7; # avoid removing logs that are less than 7 days old
|
||||
|
||||
# compression
|
||||
compress = true; # lets compress logs to save space
|
||||
compresscmd = "${lib.getExe' pkgs.zstd "zstd"}";
|
||||
compressoptions = " -Xcompression-level 10";
|
||||
compressext = "zst";
|
||||
uncompresscmd = "${lib.getExe' pkgs.zstd "unzstd"}";
|
||||
};
|
||||
}
|
6
nyx/modules/core/common/system/os/services/lvm.nix
Normal file
6
nyx/modules/core/common/system/os/services/lvm.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{lib, ...}: let
|
||||
inherit (lib) mkDefault;
|
||||
in {
|
||||
# I don't use lvm, can be disabled
|
||||
services.lvm.enable = mkDefault false;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config) modules;
|
||||
env = modules.usrEnv;
|
||||
|
||||
cfg = env.brightness;
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services."system-brightnessd" = {
|
||||
description = "Automatic backlight management with systemd";
|
||||
|
||||
# TODO: maybe this needs to be a part of graphical-session.target?
|
||||
# I am not very sure how wantedBy and partOf really work
|
||||
wantedBy = ["default.target"];
|
||||
partOf = ["graphical-session.target"];
|
||||
|
||||
# TODO: this needs to be hardened
|
||||
# not that a backlight service is a security risk, but it's a good habit
|
||||
# to keep our systemd services as secure as possible
|
||||
serviceConfig = {
|
||||
Type = "${cfg.serviceType}";
|
||||
ExecStart = "${lib.getExe cfg.package}";
|
||||
Restart = "never";
|
||||
RestartSec = "5s";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./brightnessd.nix
|
||||
./oomd.nix
|
||||
];
|
||||
}
|
31
nyx/modules/core/common/system/os/services/systemd/oomd.nix
Normal file
31
nyx/modules/core/common/system/os/services/systemd/oomd.nix
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
systemd = {
|
||||
# Systemd OOMd
|
||||
# Fedora enables these options by default. See the 10-oomd-* files here:
|
||||
# https://src.fedoraproject.org/rpms/systemd/tree/3211e4adfcca38dfe24188e28a65b1cf385ecfd6
|
||||
# by default it only kills cgroups. So either systemd services marked for killing under OOM
|
||||
# or (disabled by default, enabled by us) the entire user slice. Fedora used to kill root
|
||||
# and system slices, but their oomd configuration has since changed.
|
||||
# TODO: maybe disable user slice by default?
|
||||
oomd = {
|
||||
enable = !config.systemd.enableUnifiedCgroupHierarchy;
|
||||
enableRootSlice = true;
|
||||
enableSystemSlice = true;
|
||||
enableUserSlices = true;
|
||||
extraConfig = {
|
||||
"DefaultMemoryPressureDurationSec" = "20s";
|
||||
};
|
||||
};
|
||||
|
||||
# make it that nix builds are more likely killed than important services.
|
||||
# 100 is the default for user slices and 500 is systemd-coredumpd@
|
||||
# this is important because as my system got huge, nix flake check started
|
||||
# causing OOMs and killing my desktop environment - which I do not like
|
||||
# nuke nix-daemon if it gets too memory hungry
|
||||
services.nix-daemon.serviceConfig.OOMScoreAdjust = lib.mkDefault 350;
|
||||
};
|
||||
}
|
4
nyx/modules/core/common/system/os/services/thermald.nix
Normal file
4
nyx/modules/core/common/system/os/services/thermald.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
# monitor and control temparature
|
||||
services.thermald.enable = true;
|
||||
}
|
34
nyx/modules/core/common/system/os/services/zram.nix
Normal file
34
nyx/modules/core/common/system/os/services/zram.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
in {
|
||||
# compress half of the ram to use as swap
|
||||
# basically, get more memory per memory
|
||||
zramSwap = {
|
||||
enable = true;
|
||||
algorithm = "zstd";
|
||||
memoryPercent = 90; # defaults to 50
|
||||
};
|
||||
|
||||
# <https://www.kernel.org/doc/html/latest/admin-guide/sysctl/vm.html>
|
||||
boot.kernel.sysctl = mkIf config.zramSwap.enable {
|
||||
# zram is relatively cheap, prefer swap
|
||||
# swappiness refers to the kernel's willingness prefer swap
|
||||
# over memory. higher values mean that we'll utilize swap more often
|
||||
# which preserves memory, but will cause performance issues as well
|
||||
# as wear on the drive
|
||||
"vm.swappiness" = 180; # 0-200
|
||||
# level of reclaim when memory is being fragmented
|
||||
"vm.watermark_boost_factor" = 0; # 0 to disable
|
||||
# aggressiveness of kswapd
|
||||
# it defines the amount of memory left in a node/system before kswapd is woken up
|
||||
"vm.watermark_scale_factor" = 125; # 0-300
|
||||
# zram is in memory, no need to readahead
|
||||
# page-cluster refers to the number of pages up to which
|
||||
# consecutive pages are read in from swap in a single attempt
|
||||
"vm.page-cluster" = 0;
|
||||
};
|
||||
}
|
5
nyx/modules/core/common/system/os/theme/default.nix
Normal file
5
nyx/modules/core/common/system/os/theme/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./qt.nix
|
||||
];
|
||||
}
|
16
nyx/modules/core/common/system/os/theme/qt.nix
Normal file
16
nyx/modules/core/common/system/os/theme/qt.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
environment.variables = let
|
||||
qmlPackages = with pkgs; [
|
||||
plasma5Packages.qqc2-desktop-style
|
||||
plasma5Packages.kirigami2
|
||||
];
|
||||
|
||||
qtVersion = pkgs.qt515.qtbase.version;
|
||||
in {
|
||||
"QML2_IMPORT_PATH" = "${lib.concatStringsSep ":" (builtins.map (p: "${p}/lib/qt-${qtVersion}/qml") qmlPackages)}";
|
||||
};
|
||||
}
|
9
nyx/modules/core/common/system/os/users/default.nix
Normal file
9
nyx/modules/core/common/system/os/users/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
# we want to handle user configurations on a per-file basis
|
||||
# users that are not in users/<username>.nix don't get to be a real user
|
||||
imports = [
|
||||
./notashelf.nix
|
||||
./nix-builder.nix
|
||||
./root.nix
|
||||
];
|
||||
}
|
17
nyx/modules/core/common/system/os/users/nix-builder.nix
Normal file
17
nyx/modules/core/common/system/os/users/nix-builder.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
users = {
|
||||
groups.nix = {};
|
||||
|
||||
users.nix-builder = {
|
||||
useDefaultShell = true;
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
group = "nix";
|
||||
home = "/var/tmp/nix-builder";
|
||||
openssh.authorizedKeys = {
|
||||
keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK3Oglg7aVYQJzGa4JhnvDhRYx0jkLHwDT/9IyiLUNS2 notashelf@enyo"];
|
||||
# keyFiles = []; # TODO: can this be used with agenix?
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue