diff options
Diffstat (limited to 'sys')
47 files changed, 1752 insertions, 0 deletions
diff --git a/sys/boot/boot_pictures/gnu.png b/sys/boot/boot_pictures/gnu.png new file mode 100755 index 00000000..d07dee3e --- /dev/null +++ b/sys/boot/boot_pictures/gnu.png Binary files differdiff --git a/sys/boot/boot_pictures/gnulin_emb_1.png b/sys/boot/boot_pictures/gnulin_emb_1.png new file mode 100755 index 00000000..483f2681 --- /dev/null +++ b/sys/boot/boot_pictures/gnulin_emb_1.png Binary files differdiff --git a/sys/boot/boot_pictures/gnulin_emb_2.png b/sys/boot/boot_pictures/gnulin_emb_2.png new file mode 100755 index 00000000..48cd6ad7 --- /dev/null +++ b/sys/boot/boot_pictures/gnulin_emb_2.png Binary files differdiff --git a/sys/boot/default.nix b/sys/boot/default.nix new file mode 100644 index 00000000..9606c7b3 --- /dev/null +++ b/sys/boot/default.nix @@ -0,0 +1,41 @@ +{ + pkgs, + lib, + ... +}: { + boot = { + initrd = { + #compressor = "lz4"; + #compressorArgs = ["-9"]; + kernelModules = ["nvme" "btrfs"]; + }; + + kernelPackages = pkgs.linuxPackages_latest; + + lanzaboote = { + enable = true; + pkiBundle = "/etc/secureboot"; + }; + + loader = { + # 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. + systemd-boot.enable = lib.mkForce false; + + grub = { + enable = false; + # theme = pkgs.nixos-grub2-theme; + splashImage = ./boot_pictures/gnu.png; + efiSupport = true; + device = "nodev"; # only for efi + }; + + efi = { + canTouchEfiVariables = true; + efiSysMountPoint = "/boot"; + }; + }; + }; +} diff --git a/sys/default.nix b/sys/default.nix new file mode 100644 index 00000000..e263988f --- /dev/null +++ b/sys/default.nix @@ -0,0 +1,25 @@ +{lib, ...}: { + imports = [ + ./boot + ./disks + ./font + ./hardware + ./impermanence + ./libvirtd + ./locale + ./network + #./nixpkgs already at flake level imported + ./options + ./polkit + ./power + ./svcs + ./secrets + ./sound + ./tempfiles + ./users # the position of this item is fully arbitrary + ]; + # remove all the bloat, which nixos installs by default + environment = { + defaultPackages = lib.mkForce []; + }; +} diff --git a/sys/disks/default.nix b/sys/disks/default.nix new file mode 100644 index 00000000..d238d89a --- /dev/null +++ b/sys/disks/default.nix @@ -0,0 +1,130 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.soispha.disks; + defaultMountOptions = [ + "compress-force=zstd:15" # This saves disk space, at a performance cost + "noatime" # should have some performance upsides, and I don't use it anyways + "lazytime" # make time changes in memory + ]; +in { + options.soispha.disks = { + enable = lib.mkEnableOption "disk setup with disko"; + disk = lib.mkOption { + type = lib.types.path; + example = lib.literalExpression "/dev/disk/by-uuid/0442cb6d-f13a-4635-b487-fa76189774c5"; + description = lib.mdDoc "The disk used for installing the OS"; + }; + ssd = lib.mkOption { + type = lib.types.bool; + example = lib.literalExpression "true"; + default = false; + description = lib.mdDoc "Enable ssd specific improvements, like trim"; + }; + swap = { + uuid = lib.mkOption { + type = lib.types.str; + example = lib.literalExpression "d1d20ae7-3d8a-44da-86da-677dbbb10c89"; + description = lib.mdDoc "The uuid of the swapfile"; + }; + resumeOffset = lib.mkOption { + type = lib.types.str; + example = lib.literalExpression "134324224"; + description = lib.mdDoc "The resume offset of the swapfile"; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd = lib.recursiveUpdate (import ./hibernate.nix {inherit pkgs;}) (import ./fstrim.nix {inherit pkgs lib cfg;}); + + disko.devices = { + disk = { + main = { + device = cfg.disk; + content = { + type = "gpt"; + partitions = { + root = { + size = "100%"; + name = "root"; + content = { + type = "luks"; + name = "nixos"; + extraOpenArgs = ["--allow-discards"]; + content = { + type = "btrfs"; + extraArgs = ["-f" "--label nixos"]; # Override existing partitions + subvolumes = { + "nix" = { + mountpoint = "/nix"; + mountOptions = defaultMountOptions; + }; + "persistent-storage" = { + mountpoint = "/srv"; + mountOptions = defaultMountOptions; + }; + "persistent-storage@snapshots" = { + mountpoint = "/srv/.snapshots"; + mountOptions = defaultMountOptions; + }; + "swap" = { + mountpoint = "/swap"; + mountOptions = defaultMountOptions; + }; + }; + }; + }; + }; + boot = { + type = "EF00"; + size = "512M"; + name = "boot"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + }; + }; + }; + }; + nodev = { + "/" = { + fsType = "tmpfs"; + mountOptions = ["defaults" "size=8G" "mode=755"]; + }; + }; + }; + fileSystems = { + "/srv" = { + neededForBoot = true; + }; + "/swap" = { + neededForBoot = true; + }; + }; + swapDevices = [ + #{ + # device = "/swap/swapfile"; + # priority = 1; # lower than zramSwap, just in case + # # size = 2048; # TODO: can nixos create a btrfs swapfile correctly? + #} + ]; + zramSwap = { + enable = true; + priority = 10; # needs to be higher than hardware-swap + }; + boot = { + kernelParams = [ + "resume_offset=${cfg.swap.resumeOffset}" + "zswap.enabled=0" # zswap and zram are not really compatible + ]; + resumeDevice = "/dev/disk/by-uuid/${cfg.swap.uuid}"; + }; + }; +} diff --git a/sys/disks/fstrim.nix b/sys/disks/fstrim.nix new file mode 100644 index 00000000..6daeb65e --- /dev/null +++ b/sys/disks/fstrim.nix @@ -0,0 +1,42 @@ +{ + pkgs, + lib, + cfg, +}: { + timers.fstrim = lib.mkIf cfg.ssd { + wantedBy = ["timers.target"]; + wants = ["fstrim.service"]; + unitConfig = { + Description = "Discard unused blocks once a week"; + Documentation = "man:fstrim"; + ConditionVirtualization = "!container"; + ConditionPathExists = "!/etc/initrd-release"; + }; + timerConfig = { + OnCalendar = "weekly"; + AccuracySec = "1h"; + Persistent = "true"; + RandomizedDelaySec = "6000"; + }; + }; + services.fstrim = lib.mkIf cfg.ssd { + wantedBy = lib.mkForce []; + unitConfig = { + Description = "Discard unused blocks on filesystems from /etc/fstab"; + Documentation = "man:fstrim(8)"; + ConditionVirtualization = "!container"; + }; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.util-linux}/bin/fstrim --listed-in /etc/fstab:/proc/self/mountinfo --verbose --quiet-unsupported"; + PrivateDevices = "no"; + PrivateNetwork = "yes"; + PrivateUsers = "no"; + ProtectKernelTunables = "yes"; + ProtectKernelModules = "yes"; + ProtectControlGroups = "yes"; + MemoryDenyWriteExecute = "yes"; + SystemCallFilter = "@default @file-system @basic-io @system-service"; + }; + }; +} diff --git a/sys/disks/hibernate.nix b/sys/disks/hibernate.nix new file mode 100644 index 00000000..b0aed423 --- /dev/null +++ b/sys/disks/hibernate.nix @@ -0,0 +1,45 @@ +{pkgs}: { + services = { + hibernate-preparation = { + # TODO: check if they work + wantedBy = ["systemd-hibernate.service"]; + unitConfig = { + Description = "Enable swap file and disable zram before hibernate"; + Before = "systemd-hibernate.service"; + }; + serviceConfig = { + Type = "oneshot"; + User = "root"; + ExecStart = "${pkgs.bash}/bin/bash -c \"${pkgs.util-linux}/bin/swapon /swap/swapfile && ${pkgs.util-linux}/bin/swapoff /dev/zram0\""; + }; + }; + hibernate-resume = { + wantedBy = ["systemd-hibernate.service"]; + unitConfig = { + Description = "Disable swap after resuming from hibernation"; + After = "hibernate.target"; + }; + serviceConfig = { + Type = "oneshot"; + User = "root"; + ExecStart = "${pkgs.util-linux}/bin/swapoff /swap/swapfile"; + }; + }; + # swapoff-start = { + # wantedBy = ["multi-user.target"]; + # unitConfig = { + # Description = "Disable hardware swap after booting"; + # }; + # serviceConfig = { + # Type = "oneshot"; + # User = "root"; + # ExecStart = "${pkgs.util-linux}/bin/swapoff /swap/swapfile"; + # }; + # }; + systemd-hibernate.serviceConfig.Environment = "SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1"; + systemd-logind.serviceConfig.Environment = "SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1"; + }; + sleep.extraConfig = '' + HibernateDelaySec=5m + ''; +} diff --git a/sys/font/default.nix b/sys/font/default.nix new file mode 100644 index 00000000..303efcf7 --- /dev/null +++ b/sys/font/default.nix @@ -0,0 +1,21 @@ +{pkgs, ...}: let + nerdFont = pkgs.nerdfonts.override { + fonts = [ + "SourceCodePro" + ]; + }; +in { + # TODO: maybe add other fonts? + fonts = { + packages = [ + nerdFont + ]; + fontconfig = { + defaultFonts = { + # serif = ["Vazir"]; + # sansSerif = ["Vazir"]; + monospace = ["SourceCodePro"]; + }; + }; + }; +} diff --git a/sys/hardware/default.nix b/sys/hardware/default.nix new file mode 100644 index 00000000..77d3d3f0 --- /dev/null +++ b/sys/hardware/default.nix @@ -0,0 +1,46 @@ +{ + config, + pkgs, + ... +}: { + hardware = { + keyboard.zsa.enable = false; + onlykey.enable = true; + opengl = { + enable = true; + extraPackages = builtins.attrValues { + inherit + (pkgs) + vaapiVdpau + libvdpau-va-gl + ; + }; + }; + }; + services.udev.extraRules = '' + # Rules for Oryx web flashing and live training + KERNEL=="hidraw*", ATTRS{idVendor}=="16c0", MODE="0664", GROUP="plugdev" + KERNEL=="hidraw*", ATTRS{idVendor}=="3297", MODE="0664", GROUP="plugdev" + + # Legacy rules for live training over webusb (Not needed for firmware v21+) + # Rule for all ZSA keyboards + SUBSYSTEM=="usb", ATTR{idVendor}=="3297", GROUP="plugdev" + # Rule for the Moonlander + SUBSYSTEM=="usb", ATTR{idVendor}=="3297", ATTR{idProduct}=="1969", GROUP="plugdev" + # Rule for the Ergodox EZ + SUBSYSTEM=="usb", ATTR{idVendor}=="feed", ATTR{idProduct}=="1307", GROUP="plugdev" + # Rule for the Planck EZ + SUBSYSTEM=="usb", ATTR{idVendor}=="feed", ATTR{idProduct}=="6060", GROUP="plugdev" + + # Wally Flashing rules for the Ergodox EZ + ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1" + ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1" + SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", MODE:="0666" + KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", MODE:="0666" + + # Wally Flashing rules for the Moonlander and Planck EZ + SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", \ + MODE:="0666", \ + SYMLINK+="stm32_dfu" + ''; +} diff --git a/sys/impermanence/default.nix b/sys/impermanence/default.nix new file mode 100644 index 00000000..a9be951a --- /dev/null +++ b/sys/impermanence/default.nix @@ -0,0 +1,52 @@ +{ + config, + lib, + ... +}: let + cfg = config.soispha.impermanence; + networkmanager = + if config.networking.networkmanager.enable + then [ + "/etc/NetworkManager" # store the networkmanager configs + ] + else []; + secureboot = + if config.boot.lanzaboote.enable + then [ + "/etc/secureboot" + ] + else []; + directories = + [ + "/etc/nixos" + "/var/log" + # TODO: the following entries need to be checked + #"/var/lib/bluetooth" + #"/var/lib/nixos" + #"/var/lib/systemd/coredump" + ] + ++ networkmanager + ++ secureboot; +in { + options.soispha.impermanence = { + enable = lib.mkOption { + type = lib.types.bool; + default = true; + description = lib.mdDoc "Disk setup with disko"; + }; + }; + config = lib.mkIf cfg.enable { + # needed for the hm impermanence config + programs.fuse.userAllowOther = true; + + environment.persistence = { + "/srv" = { + hideMounts = true; + inherit directories; + files = [ + "/etc/machine-id" + ]; + }; + }; + }; +} diff --git a/sys/libvirtd/default.nix b/sys/libvirtd/default.nix new file mode 100644 index 00000000..3b9c7d85 --- /dev/null +++ b/sys/libvirtd/default.nix @@ -0,0 +1,27 @@ +{pkgs, ...}: { + virtualisation = { + spiceUSBRedirection.enable = true; # TODO: this allows usb access to any user, which shouldn't be that bad + # cores = 8; + # diskSize = 25000; + # useEFIBoot = true; + # resolution = { + # x = 1920; + # y = 1080; + # }; + # memorySize = 8024; + # sharedDirectories = {}; # TODO: add some + libvirtd = { + enable = true; + qemu = { + package = pkgs.qemu_full; + ovmf = { + enable = true; + packages = [pkgs.OVMFFull.fd]; + }; + }; + }; + }; + users.users.soispha.extraGroups = [ + "libvirtd" # to run libvirt stuff as this user + ]; +} diff --git a/sys/locale/default.nix b/sys/locale/default.nix new file mode 100644 index 00000000..1e7786cc --- /dev/null +++ b/sys/locale/default.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + ... +}: let + cfg = config.soispha.locale; +in { + options.soispha.locale = { + enable = lib.mkEnableOption (lib.mdDoc "locale"); + keyMap = lib.mkOption { + type = lib.types.str; + example = "us"; + default = "dvorak"; + }; + }; + + config = lib.mkIf cfg.enable { + # Set your time zone. + time.timeZone = "Europe/Berlin"; + + # Select internationalisation properties. + i18n = { + defaultLocale = "en_CA.UTF-8"; + extraLocaleSettings = { + LANGUAGE = "en_CA:en_US:en"; + LC_TIME = "en_DK.UTF-8"; + LC_COLLATE = "C.UTF-8"; + }; + }; + + # Layout + console = { + inherit (cfg) keyMap; + }; + }; +} diff --git a/sys/network/default.nix b/sys/network/default.nix new file mode 100644 index 00000000..9c570f3b --- /dev/null +++ b/sys/network/default.nix @@ -0,0 +1,51 @@ +{ + config, + lib, + ... +}: +{ + systemd.network = { + networks = { + "tap0" = { + name = "tap0"; + bridge = [ + "virbr0" + ]; + }; + "enp4s0" = { + name = "enp4s0"; + networkConfig = { + DHCP = "yes"; + DNSOverTLS = "yes"; + DNSSEC = "yes"; + }; + bridge = [ + "virbr0" + ]; + }; + }; + netdevs = { + "tap0" = { + netdevConfig = { + Name = "tap0"; + Kind = "tap"; + }; + tapConfig = { + User = "${config.users.users.soispha.uid}"; + Group = "libvirtd"; + }; + }; + "virbr0" = { + netdevConfig = { + Name = "br0"; + Kind = "bridge"; + }; + }; + }; + }; +} +// lib.mkIf config.networking.networkmanager.enable { + users.users.soispha.extraGroups = [ + "networkmanager" # allows to configure networkmanager as this user + ]; +} diff --git a/sys/nixpkgs/default.nix b/sys/nixpkgs/default.nix new file mode 100644 index 00000000..c37d5582 --- /dev/null +++ b/sys/nixpkgs/default.nix @@ -0,0 +1,20 @@ +{ + lib, + system, + overlays ? [], +}: { + # TODO: inheriting system here is discouraged, localSystem or hostSystem should be inspected + inherit system overlays; + config = { + # TODO: this fails because of the root tempsize, which should be increased + #contentAddressedByDefault = true; + + allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + "steam" + "steam-original" + "steam-runtime" + "steam-run" + ]; + }; +} diff --git a/sys/options/default.nix b/sys/options/default.nix new file mode 100644 index 00000000..72ebc4fb --- /dev/null +++ b/sys/options/default.nix @@ -0,0 +1,26 @@ +{ + lib, + config, + ... +}: let + cfg = config.soispha; +in { + options.soispha = { + laptop = { + enable = lib.mkEnableOption "Laptop improvemens"; + backlight = lib.mkOption { + type = lib.types.str; + example = lib.mdDoc "intel_backlight"; + description = lib.mdDoc "Which backlight to query for the screen brightness"; + }; + }; + secrets = { + #enable = lib.mkEnableOption "Secrets through agenix"; + enable = lib.mkOption { + type = lib.types.bool; + default = true; + description = lib.mdDoc "Enable secrets through agenix"; + }; + }; + }; +} diff --git a/sys/polkit/default.nix b/sys/polkit/default.nix new file mode 100644 index 00000000..9de68f35 --- /dev/null +++ b/sys/polkit/default.nix @@ -0,0 +1,3 @@ +{...}: { + security.polkit.enable = true; +} diff --git a/sys/power/default.nix b/sys/power/default.nix new file mode 100644 index 00000000..d20a97f2 --- /dev/null +++ b/sys/power/default.nix @@ -0,0 +1,19 @@ +{...}: { + # see this for reference: https://github.com/NixOS/nixpkgs/issues/211345 + services = { + # conflicts with tlp + power-profiles-daemon.enable = false; + thermald.enable = true; + tlp = { + enable = true; + settings = { + CPU_BOOST_ON_AC = 1; + CPU_BOOST_ON_BAT = 0; + CPU_SCALING_GOVERNOR_ON_AC = "performance"; + CPU_SCALING_GOVERNOR_ON_BAT = "powersave"; + SATA_LINKPWR_ON_AC = "max_performance"; + SATA_LINKPWR_ON_BAT = "min_power"; + }; + }; + }; +} diff --git a/sys/secrets/default.nix b/sys/secrets/default.nix new file mode 100644 index 00000000..d1fc1714 --- /dev/null +++ b/sys/secrets/default.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + ... +}: let + name = config.networking.hostName; +in { + config = lib.mkIf config.soispha.secrets.enable { + age = { + secrets = { + nheko = { + file = ./nheko/conf. + name; + mode = "700"; + owner = "soispha"; + group = "users"; + }; + serverphoneCa = { + file = ./serverphone/ca.key; + mode = "700"; + owner = "serverphone"; + group = "serverphone"; + }; + serverphoneServer = { + file = ./serverphone/server.key; + mode = "700"; + owner = "serverphone"; + group = "serverphone"; + }; + }; + }; + }; +} diff --git a/sys/secrets/nheko/conf.apzu b/sys/secrets/nheko/conf.apzu new file mode 100644 index 00000000..a4f704ea --- /dev/null +++ b/sys/secrets/nheko/conf.apzu @@ -0,0 +1,45 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYUVBnV3NkVlZuN0IrdzdZ +UmlXZUF5cmFvd1pzOGFZNlJuRzdFY3pWV25vCjVVNksrYjhPRi9ZTy9DOXA4anY2 +N3AxWXJTT0dZZU0zOEFCSUo2dUZhK0EKLT4gc3NoLWVkMjU1MTkgN0hmRlV3IC9U +UUhPY29BU2tVY2Z3YTJicjVwZjc0dVVRVHd5bzlqS3pKMDlDc1hjM3MKVmRxc3c2 +SkZvdk9nTzhSdkV2OEdrRjFqT3gyOTFZN3BRT1pZb09nQUg1SQotPiBiLWdyZWFz +ZSBsR0txeUoKanFDNm5BCi0tLSBqWCtNdWk2cWh6WDFXRTBsTjBHaXNRdDVlY2ps +dENOeVc1YmZnNEpZVWRrCpj1HsID0+Oi3IoVUCsFVPIxeKsvptv+8T+Zycu8tmfS +gZZm0XHdJHJFh81d75YyHRBhAhuq/Rg5sR5Wdu9UAAo0NqDIlKICFfKmdrbxEj8D +QL/W6TThKeR/rDZNy2E8Y1hRgQz5y1YG91kjoZpUQReNZBugaq5P0n1UiI4YYa2Y +Dp2E0S53pnLfd3f8UyVkli8fxciFCD0l3h+pueRhEalpaJlJAublyMLXO1rPFvw5 +MiqeP77+kcEtXWC3icfPwNdVhQJEIdOHNsUh6CdD37WORZmg8Kwq2vN0cO+xlZt0 +5zRe3pcBFSzqVmVC8BYRfeJPyygEo70kqbqd5JmnC4wcqvwbHyB8JNBspqkVc0Kh ++u2iYGFjtz6hN6wCxssIOxKLhgqmY5mS0qC21stDa3MrH83cAthtTWEf4IIHduHC +qDnmcpD4dJtB5fboxBrgZ4K3TxMPgRx7J+2tqY3wtxZUEonFFH1L7MyEGmJ6cFiU +RV1cbJRwOYH5nesA4nqAP7/d42vB0unbeTrkYOpTaUSa/hOXfycCtqhtHWFB5378 +2I5wvDdZeTzt+FmQO12Qj01Pqy19FbjMmUeQtKfAiBgOSdvdGOKBA7VmFlG1sow2 +vsU09JluQok/cuDEqunun4cHxLlzTJtH9eGAKceXx3trnKz/zyzbWw55G7VQqM7a +snpi0rsikr+7i0/oxAcrMoBOEX6EDShS6Vio6IIz8KNU5zUPQW5tNbbkfMQW1GM7 +rlZScSlk4N2CmR34BwtEUbAEKzPuNZU3zOX/urDd7rN6gjqwTwa8AGH8bCItMWSI +xxzPq00znHsf2hQkLOI40ENrs84/9ZiW4X3lJSPGaT/t1plzjiPUiIb37hSA6rhR +95zo5qzsjhVJqLB5V4S9wkWJ2vN5Yc4CY6hgoRnZz3n4XoxRed/rdXZ5eUQr2kg8 +h07CNpzeCUfx73kzsrFFIkBiNe0pd3ss2UXR8ilKyY2qMjqQc9Ypd0dLFU34nK+J +t8rQShs+288ni6kXu4PgBVzT891LRuwSxzv8lIZGHtUQ7XJFSJaeFBl+jIGo3iP2 +bdxlFuikGkhyvo+H/RFrAsmxHKgVs4y+ccCkMoapyUiVRvHA2X+LK935EEbGdTI/ +wNmUTPNmB3xlnIsrPxjqw4iUCf3OXZGFd1tSGc4C+5+IYryPPX4rln8fEnmYWq8f +mbHwIjri7YOuC/dVmI+fh74M0tqL7qGtTm8j//AYo1U1a0kgOPItiRzJRLX1TZ7M +JnjQbCmyPX17liRAVbeTJGLAorYIHhCXMRSf7TYwBGgOFHGcdQteFYms2eh9asDe +Zt6Zlmk5yJxz1je+ayWFzp7rms/wEkHR3kZ9dKUMtvAtLzusWcLL4A0zuBU9+GpW +thA+tcskvhX+UR8sYLT3d71JjGPqXujdHFpp4kM/RN+vdpdF+tOm0HVIn/ZuVcNV +pvGdAcKddXH9NXrc/5EDfQWfHbUrjgdHdZVo+BcD/4EZ/k7pQ4Q8EP9IXDvYmORU +5buuZsphAs8JFnuAu0FkwOuQQHX1NjVv0XGjwWMJsTDtRpZTfTL1wJmIdolqJRcZ +5EvhzViERXdZaOOXvUzy5N2BeZA/lX8Ls5P9ygOiCfF5rDajfk6CZLqrvJ+czW6m +07lkpfCo1CsxYGQPcNWlVQOnvO9lW7EtErEOcjdt1VcWJEm462O4FiILVm6Ef0Ax +/qDJUPwFd1NjmvW9e+GkHMXHDnADKxNxQU/KJJsLVdUyZVX4BzQ3W86N/kMyyWQd +1kgAzH1Aba1XyjDGyBAwC0ll0jwemqsD1F5Wzsvmm1dHMWev9y8P/jnQ3hsZ2j1c +n91KbPiZSaqK8ARRROzaVwJMGJIqnGAtqlwD/h1dE1cfHly/OxBHoo5VXPX8R9r7 +W31vHWjKrH7ZlZUa095f3X3xxUvhhnlFFhAwXluWc+FO5IlcqWMdfaeZKYORANdR +sB/moDP0n9WDQZrql15gfca+TQZMNcba8bsa9xnnkow+Gnl3LXE8SPTCE/nWK7lr +gXczbdNe7hpj4cK4lpQMlfk4iMeHYj47k8FFBEh0dbkAz9EpZQcRTjwJScybD51S +XhcOtSD1DJsNcl4RlaraDI4LRlfPqkTGbdmWfxaBmxgSupezF3wa9IC7iXmZeCt+ +doPKlB4LGmrr9ZHX0mDEJZtdrLT1x3xR80afZPlHCI4p3bKIgcmIKyxKxDpoKCou +OPpi0J2mtDZRG7M+u4dDJhiTiYPnhWxOmlL3yHGgN09xb2ZlmO6PhH5yL7eqiItS +n/iJA0bOZE/wT19+D5DofKzs2yjGTx4L+W4= +-----END AGE ENCRYPTED FILE----- diff --git a/sys/secrets/nheko/conf.isimud b/sys/secrets/nheko/conf.isimud new file mode 100644 index 00000000..ef6c52b6 --- /dev/null +++ b/sys/secrets/nheko/conf.isimud @@ -0,0 +1,47 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwa0Fvb0p0aU5yRGFCSm5h +d1lNSWc3aWl1NS9FcXpsalVVVGpuZGNRMnlrClVBM2R3aXpSa3pjZFpQbEV0Njcv +QUkySlJRNkV3THBjYUt3RWY3ZWRtaTgKLT4gc3NoLWVkMjU1MTkgN0hmRlV3IHda +dUU2WEwxdjNIZ0R2Wi9rbFQyb1l1TlFBZUJMWlFuMXZNSWZaZFIza2MKVGwyOExv +cW5GK0JsOFVRLzloaVUyQjhvYzR5QnNIc1RTaStISXdnT003ZwotPiBjejctZ3Jl +YXNlIFR9UFRJZyAwTjpdfCBrXlc4TXVnCmlHWTBMOUhPWU4vTzV1ZWFZVTVzTTRC +aitrNHJMQlBrMm85bWhBU29ONHpvSnkvSEFzcnZOTk5Ma1FNM20yVDUKMGF0M25C +UzR5RDdrN3cKLS0tIFNUQk1jU05lSStkQXdYMkttYjY2UVczMi9xZkhZYkdIQWw1 +RkpIOTBvWncKIACBrSaYzKJ84Kjpj57B/WC2vjIvvDAfy3TF1gVEWFOUgYkCpO52 +4sjWpd3JVpdLzsJczS7Ty0HZYBlmz3Qtejf7x6b4xftJSari5WUK6loGtmGKbgJW +lk2LZonpTsnyyALFavanlQKkv1isR9jqWxRe0KZu76zbX/QTUVfHyjV+4m6kleUI +ZJj1mLUKxYdJn2aGyTr4kwTfbLYR8/xxJYGqPUmCrFrLhsr7qy/yBXvPyIfJ+sd/ +ab2/Qz2U8wE8d0JRiwoguFaRTbrIKBzliF84CrbDznJtLQjn02zbc78lzn4n/7MV +3VArXkqw1pICkbrfLl1+own3Mw6ge73tDnSunzgJWBKSOFOrs/b/J1uMMjoiTGWi +THy8+asIFw/zZTmrUnlfmm0gE20nm/HYTJ+428nGrMwdh++LqgocxqX+CNcNTT56 +QhXwR3JuliST8jptRaFo8fzoJUImclSj+o3X2/KORm4fS8u67lcDA6KB/lw6WOie +UE09CVsrkR4X7ACe5Y7PYr0fWYNh1PrYxIabYttQq3aus5SunfkrCX+/+xtbMNsm +FX0TxMintrp3UV4eWEZzsHNz18PaXtyZTFCF4sTmnxjfP7TelZRTHNh/LbKLFrqL +kna9ChqIUiHIEYbugkZsSWUICWMbEGBWQxD4CT6DfGuve4vOgw5FWtqdvHz43f0j +9Agjvab5H+fBvDJTbJiHOFn681Wl219hR4z1plM1eVu+59JIFECVeEePoDrjGy9n +K50HUNs5Vq0p8RFus2BbjTuECmggkzd0P7mZb34bVo6K/89lCny21WeGyhwim8Hr +KKBmpm+hCh7gikBKXP0tnpmt4A5sPg30+YxePgaKCNtUjLLnN4moEGzzAsks1qsJ +GYvzSZv7AmTfyww2cjVm9ZSrlo4EHL5dMPEVBHpy6pcSV6WotkZiDklYPD4g0ZO2 +wgbLU5/YDhve9FOKoP7Y4wocP18O6ffjiPVeCg9XDUmoKq5Y/Ea1d317q973G2hf +YxUD8z9I8+fGlfqmgIjJZx8/0wTFlrCxI1oam6xPDmbSjrdVI+nr/2lfNqy/VOYN +SQMr/Po7DcAwB5SS4ItxYXKYo9FAFyoHAljYhV156l7dveqehZDKaqBzBF+pCefQ +BfiwvYg3by/R9jtMdh6MwfMeF1Z0siJdrPouIKmsuITLexuj85GkzPzSPDa69H2s +iInDepGDX2YvH2BUsUi8QPwoxRXROFwDqaIpA/aaPf224YN7D46TzU+a2HQzlpmV +xWqh/pBEwKdTpbgtdoG9GLrETDD5/2FV9FiQXxQgvV8934nlOAvdwHEJqGMlNIT2 +mlNhZyx49lOfx8BFP+NXb2adUY49Aahkdx4/uB6fN0H/RyNh39R74DCbjvIQUxRV +OUKyWZ2a2wSbZbA6tNmB5sXYtfCUOZLfE8mUwJgUSVrEccQ7UlSlEy9+gZDiHjS+ +OYnTBdRdG2AjPy3mBAdfqooTdzQwT5HNnFskg7Q3wnWRf230yZ6Qr2lBOyBgtnm1 +Hj8fI9VrACfAtYMIWUarBAnnoWHB1pHfoZOui6Zr4jtqlH7lgOAUFx/b60g4SsSF +jAJnRCFyUYbTv53GefabjkDg3WkCiyxrNhr7gS7oONa1qHai/1TQeWPCe9zj9kaR +nMRZQKI1/wmK8szhH7sA+tShtM3ktqkNlIWXuwId3OJ8ne2vcES92NRfyUI8qY39 +atndXRUg47+2MubBZhP1pnLEdxpvdOQVgDIzoNx3mu0mWkSi2K3Dy/Y4mZGVaee/ +K98cPo3S42eKEulsN/iyTWD1nJpaDNp4fWDCDMSK8dy7vSWYcT3htzzR3a4WIlLk +PV3/7l99y/HLjlJmqUwRri1hydRdC74Lk3FSV6gc6snn54WnaLUCVOpCIgHefNVr +zYmUR+4I6zioxp9540zrD8YvrK8YSSs47PtbpDYI8E9O4L7+uy7gujwJtSupZVRc +BP48+5NddK3gpQt4BagYj6CO/vENwDmUiA+kUM9WdQbnV/lmeNPdqm2VjVbxNObZ +5xHlXODOOCVg+LSpFybFT+3A2MNA/jRKGID5Kai0a9c7jY/XIrUdIaCpyVylj2dX +4JDC6AsRb1VXu7FaqhLhOabZZzW+o8m94ZjayWA2BT3IMf5Kd6eq+v9zh5RPlvtu +vcoLBTEsLPZeAyERpaTto431yRqzSKMvDQ6nwpXbdIcHLIvbp+utRoaqtel2JGO4 +PBz21qEI/ACc6sDhyUHHLz+MybEQilTSrBJ+jYSohFfm0DEpG8cThgm6mMSDUMEM +6ehgKHIYdlMa7YIBcIpJBsl8Xs6If2+FA7cbeh6xqbw= +-----END AGE ENCRYPTED FILE----- diff --git a/sys/secrets/nheko/conf.tiamat b/sys/secrets/nheko/conf.tiamat new file mode 100644 index 00000000..51cab7df --- /dev/null +++ b/sys/secrets/nheko/conf.tiamat @@ -0,0 +1,45 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCUDQ4ZUtkcEVTVWpTQ0Zy +Yi9naWRDaDJFYm9GR0k1QVhJR3V2Rmc0a2hNClNxeTQ2YmFHRkxRWnhlc3IrKzJE +eHpWNGFSTEV2WDR0OHNwTEZiMGdxOFEKLT4gc3NoLWVkMjU1MTkgelpFb25nIDFH +M3orVXZFMndGc0hPN1hWY0xyeXJuYmFLVks4bFVqdHFQVEN5eUhNRmcKUWlZdjlH +ZWtrcGlnZ2ZGVHBwNEZrM29CT3c0MERBNm5SVjhMdWxGbEgvbwotPiBULWdyZWFz +ZSBoOGYKdzBOVGpYNVJFdXoxK1dZdU9rdG5jU21UbUp4UjJYZXRoTTJqNnJvCi0t +LSBwZTJaUS9XRVRINmpNVFhxMnkvdGxkVTJaNkZTZG1PUGVZN0F5QmpJWkxrCohN +YfE5W/OxshJPerGCFWpYkFcQhJaz/HEknz13rCqH4yXfp3M7uoHWKfEFi1uzFdZs +H9MnIKS5NN8bLW4xssBaogalqCAigEUDuLPKmep8224Y4h9i+7fWOMBhgHjU322N +7iJCjnHiKT2tM4uv95c9Fa676xHcfZwzaCFDxbasQZmZL3G3U1wDseSK7EHCZ78R +sXqqd54ApUQyAwdSLPFVvX/YlhOIL6MMUWvhmmgHcNRYa71cQcoojleJI28fu53w +6X0qez81+/D8txyCEtF07m7ckCtYTe7oKT+mF5cvT99lHqEJBJzq/PxUIQt2dA2y +AQr09/7LJ5h8RYVG8emwlqzBasvCdLFXwtCNRMQGb5kDJ5CcZKy50SIpYvDdj269 +Ap4Lq/luQIeOMXQudbc+ECToxbrRKy4gcG8oKsvIXytIOszA8x4WjR14zSBTNunx +Z4mOb0zDy1GdKWsgPcyYdiOBIKzEpTLvjCbWYWJunGSPIlsksBvAAP6MsCbV0WQo +brp48ds24jlCjtqW+AdSIvo5+YVdyCEho8Gdw7k134cIhjoC0SU1vmNNzh1swoW0 +yRKG8ql2Tj6myIDcLM/KDozsgu/gNC2ugRwTCDv+gcApZBmKUXN2w0abhI2UMksH +FEw2ITrWDhPE87bXWNua+vdaBa619lg43xoJTGeJHqF5gXEV3blZ5bTvVjT2H7Dy +uBfCk+XQ4G51Dwh5iyjrQyWxCkYS0FJGD6WUTBU0nrxc6d9UERcxVurtPr7I9Tmf +IVdl6jkrjpfVIL/Imo+YgfdG9CvhyEl/x50c4umDsLxEi67v8TE/yEBhY+o5RnKD +EU0NjdHDIgtI9+Fa0KujnkIN6DqJ0V+QHKv7K8yiR8BScIq2YD1LOOApb6pom7+4 +440vZwmo4NgPsPyM/GgGUIyTeR4tU42BPyMTPjKEuN97ZwWZqIFreUl+nyLzViK/ +bGLYcRfVjjHTJPIeZRosYUo0ZMFggXAuslx5trQcb1B4iHvL7k2jjnMRJmyYZX2d +CWohscc+7+1iFNdH++tefcED8T8HCGpM1RxSM31kfpnKnINeBdo9E9ZDmNCElZm+ +nds5fgTm/MLKsuC/t+MecVdfeHTufc/Akh343DMdIMNmZ35xLcpNLmxTJ+iCALS7 +nheIWAFUaTh6GB6IGocSSjQ0RwS0wIftka4QdW+UEtEjnvB0D/CjwDLSO3pUl0mj +44r8fH8IZVcQcnqhuEsFoih/XOlH3N95O0HxXCvUcI13/HaSpUKdJqyAIn8w/jBM +FL/boJVA1zOH5sIY0AD2IMavuS5b/ZgJtPsESrc0LUiL4nztDVdAEtpHUM0OEzb9 +tSAIN888UKTC8MFSIwA+4cXIyCEpxXP3HbSNaar5gp75oG5/BqOu1aF5sC0kKpmn +9C9+z9sLTDigzV1GKlPpUGd9lVOeH2JpAY8ZUyn2gxh7C6IHwwUbWUclEPy2siYd +HcAMneEwXpm6DfJevMi2o0wOdVakcpN+YUNzIgferM/IU5FbgtC8gNBpDCBo2yLe +X7ERSzP177QWwXLIF2WhZeG4Cvszj4tySYsRJhoZPc9jpRjiK/ccOoNo8A1UKbJC +H/836MNskBmmbNoPsS979mLv8ijpRzvjnwbWn+ZlCo3gZAKVM7PcXuTODcWfoAJ4 +2ugEHCAiOobGQtGUp5HOhXYfAK2Wene0a9RmSAT3SgPmx95u1Fy8n+m/PDK2opIe +REpj9UTcoT0+5aHIwp2gqLVpQH2953Prd0qaNfc1t6gQKwDXDDU+b+QmxAaPBwpu +0TEIEYKsx237lX314XSaq+Nt7Ko1OPABR4gkz/ELL4WOKwFbf7oAAV3UiNPwweY8 +R3cpVvQ70y+M2Nnwepxf7wSruo+FDtgsic9vtobdpwBViPC+AG2QbI1hTD3uhslE +KunFtbO08ARcTMeMgZ0BE3XXnrgxdKjXmPEybQiyObFxDGbV1EX/2i1MKArQdQzs +MxCpKOzDi5axr3Qd/W6Y/foMZWfRYgb+0xITHU7haR8QRD80uTbt9TfsqK98H1A1 +UMosMKhkzKG70qdNvTiEh+OqBAIbUL42IKNn4SCiZt7ZCQ6/QqwcCi6ND0w8+dO1 +u8vZdRF+r/3AAPpa3W7BiIiLUmmU8IUI8A/72cCrY6PyrjaomXnpVWlZjQ616i9Q +TU9IwBahMa2j/a4317pv/7ltQQCpCkRs/HweQy5CQS+yFuOcoOVikL0ZHd9XC4YX +QJ/T6R5+OngxkJgoPRtJ +-----END AGE ENCRYPTED FILE----- diff --git a/sys/secrets/secrets.nix b/sys/secrets/secrets.nix new file mode 100644 index 00000000..36757546 --- /dev/null +++ b/sys/secrets/secrets.nix @@ -0,0 +1,15 @@ +let + soispha = "age1mshh4ynzhhzhff25tqwkg4j054g3xwrfznh98ycchludj9wjj48qn2uffn"; + + tiamat = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMD87QQIUXdEv3TaNRrI9clD9VgpsuVLFg2CrNGa5lVB"; + apzu = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBivF5b6PyxsR/t+4Qg4IEDXHVXrjmZpslTUNXpvcVbO"; +in { + "nheko/conf.tiamat".publicKeys = [soispha tiamat]; + "nheko/conf.apzu".publicKeys = [soispha apzu]; + + # only here to satisfy the nix evaluation + "nheko/conf.isimud".publicKeys = [soispha]; + + "serverphone/ca.key".publicKeys = [soispha tiamat apzu]; + "serverphone/server.key".publicKeys = [soispha tiamat apzu]; +} diff --git a/sys/secrets/serverphone/ca.key b/sys/secrets/serverphone/ca.key new file mode 100644 index 00000000..d49c5395 --- /dev/null +++ b/sys/secrets/serverphone/ca.key @@ -0,0 +1,19 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyaGJNQkRRVy9MRXZ3b2tJ +Q2R1NUcrYUNGRE5uQkNyUDdkSm5rUWYxaXpjCjduMG1FSG1VamozdnJoVFFZUDYz +T2pyK1k3ekZ4RnFMaDFKdUZPWVNuR3MKLT4gc3NoLWVkMjU1MTkgelpFb25nIEpP +d0xwS3Nia3AwNmppRjZhODdzNXhEcnRsZW5rUzBQcTN6NWhWeTNiQ0EKTkpUZ1Jk +NHE3WVRzVEhpMnJGaVFpdkFBVW5QNThCSUdFSHVQR1RrQUJsZwotPiBzc2gtZWQy +NTUxOSA3SGZGVXcgdjJKUUtlRjE5UFEyR2tBOWhEbHNMVlNSOUMyZ1dkYkhYZWRW +by9QZ2UxTQpVSnhJcFFYay9LSStrSFFJcXJPWUxydXNGbUNXRVpLcHJibjM2TDlw +RnlVCi0+IGNHPjMiSyQtZ3JlYXNlIGcgdWZkbApmY0YzMmhDdzBWT0RKaWlUUmZP +bmRPOExuRVJ3Yk5mMFhYSnhlRENqWXJxK1VWdnBibUxzNWV1NHMyNVNXN054CmR0 +VFAzYUR0RHVaZUpOTlB3USt2TXVDcXdLOGtpZwotLS0gaTliQzBjbjdUYkVidURX +em9wcU04cDhNMHB6KzNBSVMyMmtSRERKS240SQryB70ZEgDQ4eJ/pjIWh6MBEUQr +iAx2i+J+XJu+74bC9DfB5rWpR4/HAdp8EF6wmi05TuEPUpG9brwm/mHi+FB/Drpu +00viGfM3dlCyALz1jB2W/MbruouK85o2L3RWDCgc+eT1gA+u2C7ZxO6iYA3aP4lu +ShDcSHlsKkh9lx4cRsNTua/8N+GQZLciSC7iMDroruxWj1HET9IxeeVN+VSuqcjW +ocX3LU2uU8vP9WT9zT1lbQB5Z0EM7W+ez61SjGpzrpXB2mpmi+SHOIWF3VdG1H8R +18BIyRjKIj5Op+8XD7qAe6nl9SSCnMURH+arc7yjNMgEbzFykfldfug2ibI2G/kW +OxeiEBoSFlC+V8ivS6I= +-----END AGE ENCRYPTED FILE----- diff --git a/sys/secrets/serverphone/server.key b/sys/secrets/serverphone/server.key new file mode 100644 index 00000000..a2720406 --- /dev/null +++ b/sys/secrets/serverphone/server.key @@ -0,0 +1,19 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJZnBXSzF4K0ljR3B1Rkk1 +M0lSSkVmVlA2Tjcrd0JCRmhHWDY4bzNoYnhjCmsvQjJmYU5vNVh1Umw0dzhCQjNF +WVRhVHpUTUIzRVBxaXhFWHpuenZHN0kKLT4gc3NoLWVkMjU1MTkgelpFb25nIHAz +aG02dkxiNVRreVNadXJjbnc0bXBtSFRSNDhrYjljanUrNldwVFlabXcKU2c2L25r +VlNjeDFENUdQeWllenRGWlRqRW53UU5VNEdCaUZsbHpaL1ZFTQotPiBzc2gtZWQy +NTUxOSA3SGZGVXcgZytvUUhZSXhwQ01mQmtkZmhzdHJUd2tlQS9yYkxCdTBYZ2pJ +UEd4WEF4SQp4WVh2UEJReDVES2tCWlpqQS9aanQzRGRsSTA4S0VXSWZxZ2hoKzZq +YllzCi0+IEc4eC1ncmVhc2UgaGQhIGFydERoaS4gLERUcQprczdDdHhaOXpmN1VU +MDlHNlYzVmMxY09Oa2xzTVN6M0ZyYnpRSzJEMS9nMmlqRVo4Wk1qN1lKZnp0N0RT +UStuCm51L01Rb3ZxNUhEa0c5Z3orYlp0YmlXMkhpeHVJMjNkRFZYWmR3QmV2Zwot +LS0gdWJDeHZvc0xOMU9uUjUyMlRGUnlGSW9PZzVKWWNoa3pWbVM1OE9LdFk2NAo+ +WS82jL1us5iVw+xWVI80luHMs31hxZfQgJDBuFbtpY0nKkM97U7rusl6t8P+s93c +R0IYBEUuz6n33GTeVOLipDqkZftlOOvSZkFneZ766+GpEO01dCjeSW9KViDC1jI/ +721IXq9TQNZw0Ou3Vf5E0nDypsfG0UhEoLCy6QZL9YCIyl5s//kyFFnpQjyaGT/P +pRHGhD0BxZa2ib07WDWzBpsTFtVemwcn9lqAx7DlYV2X3UwCT3qVOVjDuA/j6qUt +8bCDoXs4/dWleHNHzpwRhe+j2W4OWDKp7o0zYqxkUuPpEWXL7+A+B/+/08nAtZQk +ZvJyaZSL5wicIPAjLxrD00z2QcE/ZPyUrXsi0gOovuk= +-----END AGE ENCRYPTED FILE----- diff --git a/sys/sound/default.nix b/sys/sound/default.nix new file mode 100644 index 00000000..318dcb8b --- /dev/null +++ b/sys/sound/default.nix @@ -0,0 +1,23 @@ +{pkgs, ...}: { + # Enable sound with pipewire. + sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + jack.enable = true; + }; + environment.etc.pipewire-pulse-config = { + target = "pipewire/pipewire-pulse.conf.d/pipewire-pulse-config.conf"; + text = '' + # Extra scripts can be started here. Setup in default.pa can be moved in + # a script or in pulse.cmd below + context.exec = [ + { path = "${pkgs.pulseaudio}/bin/pactl" args = "set-sink-volume 0 13%" } + ] + ''; + }; +} diff --git a/sys/svcs/backup/default.nix b/sys/svcs/backup/default.nix new file mode 100644 index 00000000..171f1043 --- /dev/null +++ b/sys/svcs/backup/default.nix @@ -0,0 +1,67 @@ +{ + lib, + sysLib, + pkgs, + config, + ... +}: let + snap-sync-forked = sysLib.writeShellScriptWithLibrary { + name = "snap-sync-forked"; + src = ./snap-sync-forked; + dependencies = with pkgs; [ + bash + btrfs-progs + coreutils + gawk + gnugrep + snapper + util-linux + + # optional: + libnotify + openssh + pv + rsync + sudo + ]; + }; + backup-script = pkgs.writeShellScriptBin "backsnap" '' + ${pkgs.util-linux}/bin/mount --mkdir "/dev/disk/by-uuid/${cfg.backupDiskUuid}" "/run/media/${cfg.backupDiskUuid}"; + ${snap-sync-forked}/bin/snap-sync-forked --UUID "${cfg.backupDiskUuid}" --noconfirm; + ${pkgs.util-linux}/bin/umount "/run/media/${cfg.backupDiskUuid}"; + ''; + cfg = config.soispha.fs.backup; +in { + options.soispha.fs.backup = { + enable = lib.mkEnableOption (lib.mdDoc "backups with snap-sync"); + backupDiskUuid = lib.mkOption { + type = lib.types.str; + example = lib.literalExpression "d1d20ae7-3d8a-44da-86da-677dbbb10c89"; + description = lib.mdDoc "The UUID of the backup disk"; + }; + }; + config = lib.mkIf cfg.enable { + systemd = { + services.backup = { + wantedBy = lib.mkForce []; + unitConfig = { + Description = "Backup the last snapshots of the persitent-storage subvolume."; + }; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${backup-script}/bin/backsnap"; + }; + }; + timers.backup = { + wantedBy = ["timers.target"]; + unitConfig = { + Description = "Backup 15min after boot and every 8 hours"; + }; + timerConfig = { + OnBootSec = "15min"; + OnUnitActiveSec = "8h"; + }; + }; + }; + }; +} diff --git a/sys/svcs/backup/snap-sync-forked b/sys/svcs/backup/snap-sync-forked new file mode 100755 index 00000000..a66f31ae --- /dev/null +++ b/sys/svcs/backup/snap-sync-forked @@ -0,0 +1,529 @@ +#!/usr/bin/env bash +# snap-sync +# https://github.com/wesbarnett/snap-sync +# Copyright (C) 2016-2021 Wes Barnett + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., + +# ------------------------------------------------------------------------- + +# Takes snapshots of each snapper configuration. It then sends the snapshot to +# a location on an external drive. After the initial transfer, it does +# incremental snapshots on later calls. It's important not to delete the +# snapshot created on your system since that will be used to determine the +# difference for the next incremental snapshot. + +set -o errtrace + +version="0.7" +name="snap-sync" + +printf "\nsnap-sync version %s, Copyright (C) 2016-2021 Wes Barnett\n" "$version" +printf "snap-sync comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the license for more information. \n\n" + +# The following line is modified by the Makefile or +# find_snapper_config script +SNAPPER_CONFIG=/etc/sysconfig/snapper + +donotify=0 +if ! command -v notify-send &> /dev/null; then + donotify=1 +fi + +doprogress=0 +if ! command -v pv &> /dev/null; then + doprogress=1 +fi + +error() { + printf "==> ERROR: %s\n" "$@" + notify_error 'Error' 'Check journal for more information.' +} >&2 + +die() { + error "$@" + exit 1 +} + +traperror() { + printf "Exited due to error on line %s.\n" "$1" + printf "exit status: %s\n" "$2" + printf "command: %s\n" "$3" + printf "bash line: %s\n" "$4" + printf "function name: %s\n" "$5" + exit 1 +} + +trapkill() { + die "Exited due to user intervention." +} + +trap 'traperror ${LINENO} $? "$BASH_COMMAND" $BASH_LINENO "${FUNCNAME[@]}"' ERR +trap trapkill SIGTERM SIGINT + +usage() { + cat <<EOF +$name $version +Usage: $name [options] + +Options: + -c, --config <config> snapper configuration to backup + -d, --description <desc> snapper description + -h, --help print this message + -n, --noconfirm do not ask for confirmation + -k, --keepold keep old incremental snapshots instead of deleting them + after backup is performed + -p, --port <port> remote port; used with '--remote'. + -q, --quiet do not send notifications; instead print them. + -r, --remote <address> ip address of a remote machine to backup to + --sudo use sudo on the remote machine + -s, --subvolid <subvlid> subvolume id of the mounted BTRFS subvolume to back up to + -u, --UUID <UUID> UUID of the mounted BTRFS subvolume to back up to + +See 'man snap-sync' for more details. +EOF +} + +ssh="" +sudo=0 +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + -d|--description) + description="$2" + shift 2 + ;; + -c|--config) + selected_configs="$2" + shift 2 + ;; + -u|--UUID) + uuid_cmdline="$2" + shift 2 + ;; + -s|--subvolid) + subvolid_cmdline="$2" + shift 2 + ;; + -k|--keepold) + keep="yes" + shift + ;; + -n|--noconfirm) + noconfirm="yes" + shift + ;; + -h|--help) + usage + exit 1 + ;; + -q|--quiet) + donotify=1 + shift + ;; + -r|--remote) + remote=$2 + shift 2 + ;; + -p|--port) + port=$2 + shift 2 + ;; + --sudo) + sudo=1 + shift + ;; + *) + die "Unknown option: '$key'. Run '$name -h' for valid options." + ;; + esac +done + +notify() { + for u in $(users | tr ' ' '\n' | sort -u); do + sudo -u "$u" DISPLAY=:0 \ + DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(sudo -u "$u" id -u)/bus" \ + notify-send -a $name "$1" "$2" --icon="dialog-$3" + done +} + +notify_info() { + if [[ $donotify -eq 0 ]]; then + notify "$1" "$2" "information" + else + printf '%s\n' "$1: $2" + fi +} + +notify_error() { + if [[ $donotify -eq 0 ]]; then + notify "$1" "$2" "error" + else + printf '%s\n' "$1: $2" + fi +} + +[[ $EUID -ne 0 ]] && die "Script must be run as root. See '$name -h' for a description of options" +! [[ -f $SNAPPER_CONFIG ]] && die "$SNAPPER_CONFIG does not exist." + +description=${description:-"latest incremental backup"} +uuid_cmdline=${uuid_cmdline:-"none"} +subvolid_cmdline=${subvolid_cmdline:-"5"} +noconfirm=${noconfirm:-"no"} + +if [[ -z $remote ]]; then + if ! command -v rsync &> /dev/null; then + die "--remote specified but rsync command not found" + fi +fi + +if [[ "$uuid_cmdline" != "none" ]]; then + if [[ -z $remote ]]; then + notify_info "Backup started" "Starting backups to $uuid_cmdline subvolid=$subvolid_cmdline..." + else + notify_info "Backup started" "Starting backups to $uuid_cmdline subvolid $subvolid_cmdline at $remote..." + fi +else + if [[ -z $remote ]]; then + notify_info "Backup started" "Starting backups. Use command line menu to select disk." + else + notify_info "Backup started" "Starting backups. Use command line menu to select disk on $remote." + fi +fi + +if [[ -n $remote ]]; then + ssh="ssh $remote" + if [[ -n $port ]]; then + ssh="$ssh -p $port" + fi + if [[ $sudo -eq 1 ]]; then + ssh="$ssh sudo" + fi +fi + +if [[ "$($ssh findmnt -n -v --target / -o FSTYPE)" == "btrfs" ]]; then + EXCLUDE_UUID=$($ssh findmnt -n -v -t btrfs --target / -o UUID) + TARGETS=$($ssh findmnt -n -v -t btrfs -o UUID,TARGET --list | grep -v "$EXCLUDE_UUID" | awk '{print $2}') + UUIDS=$($ssh findmnt -n -v -t btrfs -o UUID,TARGET --list | grep -v "$EXCLUDE_UUID" | awk '{print $1}') +else + TARGETS=$($ssh findmnt -n -v -t btrfs -o TARGET --list) + UUIDS=$($ssh findmnt -n -v -t btrfs -o UUID --list) +fi + +declare -a TARGETS_ARRAY +declare -a UUIDS_ARRAY +declare -a SUBVOLIDS_ARRAY + +i=0 +for x in $TARGETS; do + SUBVOLIDS_ARRAY[$i]=$($ssh btrfs subvolume show "$x" | awk '/Subvolume ID:/ { print $3 }') + TARGETS_ARRAY[$i]=$x + i=$((i+1)) +done + +i=0 +disk=-1 +disk_count=0 +for x in $UUIDS; do + UUIDS_ARRAY[$i]=$x + if [[ "$x" == "$uuid_cmdline" && ${SUBVOLIDS_ARRAY[$((i))]} == "$subvolid_cmdline" ]]; then + disk=$i + disk_count=$((disk_count+1)) + fi + i=$((i+1)) +done + +if [[ "${#UUIDS_ARRAY[$@]}" -eq 0 ]]; then + die "No external btrfs subvolumes found to backup to. Run '$name -h' for more options." +fi + +if [[ "$disk_count" -gt 1 ]]; then + printf "Multiple mount points were found with UUID %s and subvolid %s.\n" "$uuid_cmdline" "$subvolid_cmdline" + disk="-1" +fi + +if [[ "$disk" == -1 ]]; then + if [[ "$disk_count" == 0 && "$uuid_cmdline" != "none" ]]; then + error "A device with UUID $uuid_cmdline and subvolid $subvolid_cmdline was not found to be mounted, or it is not a BTRFS device." + fi + if [[ -z $ssh ]]; then + printf "Select a mounted BTRFS device on your local machine to backup to.\nFor more options, exit and run '%s -h'.\n" "$name" + else + printf "Select a mounted BTRFS device on %s to backup to.\nFor more options, exit and run '%s -h'.\n" "$remote" "$name" + fi + while [[ $disk -lt 0 || $disk -gt $i ]]; do + for x in "${!TARGETS_ARRAY[@]}"; do + printf "%4s) %s (uuid=%s, subvolid=%s)\n" "$((x+1))" "${TARGETS_ARRAY[$x]}" "${UUIDS_ARRAY[$x]}" "${SUBVOLIDS_ARRAY[$x]}" + done + printf "%4s) Exit\n" "0" + read -e -r -p "Enter a number: " disk + if ! [[ $disk == ?(-)+([0-9]) ]] || [[ $disk -lt 0 || $disk -gt $i ]]; then + printf "\nNo disk selected. Select a disk to continue.\n" + disk=-1 + fi + done + if [[ $disk == 0 ]]; then + exit 0 + fi + disk=$((disk-1)) +fi + +selected_subvolid="${SUBVOLIDS_ARRAY[$((disk))]}" +selected_uuid="${UUIDS_ARRAY[$((disk))]}" +selected_mnt="${TARGETS_ARRAY[$((disk))]}" +printf "\nYou selected the disk with uuid=%s, subvolid=%s.\n" "$selected_uuid" "$selected_subvolid" +if [[ -z $ssh ]]; then + printf "The disk is mounted at '%s'.\n" "$selected_mnt" +else + printf "The disk is mounted at '%s:%s'.\n" "$remote" "$selected_mnt" +fi + +# shellcheck source=/etc/default/snapper +source "$SNAPPER_CONFIG" + +if [[ -z $selected_configs ]]; then + printf "\nInteractively cycling through all snapper configurations...\n" +fi +selected_configs=${selected_configs:-$SNAPPER_CONFIGS} + +declare -a BACKUPDIRS_ARRAY +declare -a MYBACKUPDIR_ARRAY +declare -a OLD_NUM_ARRAY +declare -a OLD_SNAP_ARRAY +declare -a NEW_NUM_ARRAY +declare -a NEW_SNAP_ARRAY +declare -a NEW_INFO_ARRAY +declare -a BACKUPLOC_ARRAY +declare -a CONT_BACKUP_ARRAY + +# Initial configuration of where backup directories are +i=0 +for x in $selected_configs; do + + if [[ "$(snapper -c "$x" list --disable-used-space -t single | awk '/'"subvolid=$selected_subvolid, uuid=$selected_uuid"'/ {cnt++} END {print cnt}')" -gt 1 ]]; then + error "More than one snapper entry found with UUID $selected_uuid subvolid $selected_subvolid for configuration $x. Skipping configuration $x." + continue + fi + + if [[ "$(snapper -c "$x" list --disable-used-space -t single | awk '/'$name' backup in progress/ {cnt++} END {print cnt}')" -gt 0 ]]; then + printf "\nNOTE: Previous failed %s backup snapshots found for '%s'.\n" "$name" "$x" + if [[ $noconfirm == "yes" ]]; then + printf "'noconfirm' option passed. Failed backups will not be deleted.\n" + else + read -e -r -p "Delete failed backup snapshot(s)? (These local snapshots from failed backups are not used.) [y/N]? " delete_failed + while [[ -n "$delete_failed" && "$delete_failed" != [Yy]"es" && + "$delete_failed" != [Yy] && "$delete_failed" != [Nn]"o" && + "$delete_failed" != [Nn] ]]; do + read -e -r -p "Delete failed backup snapshot(s)? (These local snapshots from failed backups are not used.) [y/N] " delete_failed + if [[ -n "$delete_failed" && "$delete_failed" != [Yy]"es" && + "$delete_failed" != [Yy] && "$delete_failed" != [Nn]"o" && + "$delete_failed" != [Nn] ]]; then + printf "Select 'y' or 'N'.\n" + fi + done + if [[ "$delete_failed" == [Yy]"es" || "$delete_failed" == [Yy] ]]; then + # explicit split list of snapshots (on whitespace) into multiple arguments + # shellcheck disable=SC2046 + snapper -c "$x" delete $(snapper -c "$x" list --disable-used-space | awk '/'$name' backup in progress/ {print $1}') + fi + fi + fi + + SNAP_SYNC_EXCLUDE=no + + if [[ -f "/etc/snapper/configs/$x" ]]; then + # shellcheck source=/etc/snapper/config-templates/default + source "/etc/snapper/configs/$x" + else + die "Selected snapper configuration $x does not exist." + fi + + if [[ $SNAP_SYNC_EXCLUDE == "yes" ]]; then + continue + fi + + printf "\n" + + old_num=$(snapper -c "$x" list --disable-used-space -t single | awk '/'"subvolid=$selected_subvolid, uuid=$selected_uuid"'/ {print $1}') + old_snap=$SUBVOLUME/.snapshots/$old_num/snapshot + + OLD_NUM_ARRAY[$i]=$old_num + OLD_SNAP_ARRAY[$i]=$old_snap + + if [[ -z "$old_num" ]]; then + printf "No backups have been performed for '%s' on this disk.\n" "$x" + read -e -r -p "Enter name of subvolume to store backups, relative to $selected_mnt (to be created if not existing): " mybackupdir + printf "This will be the initial backup for snapper configuration '%s' to this disk. This could take awhile.\n" "$x" + BACKUPDIR="$selected_mnt/$mybackupdir" + $ssh test -d "$BACKUPDIR" || $ssh btrfs subvolume create "$BACKUPDIR" + else + mybackupdir=$(snapper -c "$x" list --disable-used-space -t single | awk -F"|" '/'"subvolid=$selected_subvolid, uuid=$selected_uuid"'/ {print $5}' | awk -F "," '/backupdir/ {print $1}' | awk -F"=" '{print $2}') + BACKUPDIR="$selected_mnt/$mybackupdir" + $ssh test -d "$BACKUPDIR" || die "%s is not a directory on %s.\n" "$BACKUPDIR" "$selected_uuid" + fi + BACKUPDIRS_ARRAY[$i]="$BACKUPDIR" + MYBACKUPDIR_ARRAY[$i]="$mybackupdir" + + printf "Creating new local snapshot for '%s' configuration...\n" "$x" + new_num=$(snapper -c "$x" create --print-number -d "$name backup in progress") + new_snap=$SUBVOLUME/.snapshots/$new_num/snapshot + new_info=$SUBVOLUME/.snapshots/$new_num/info.xml + sync + backup_location=$BACKUPDIR/$x/$new_num/ + if [[ -z $ssh ]]; then + printf "Will backup %s to %s\n" "$new_snap" "$backup_location/snapshot" + else + printf "Will backup %s to %s\n" "$new_snap" "$remote":"$backup_location/snapshot" + fi + + if ($ssh test -d "$backup_location/snapshot") ; then + printf "WARNING: Backup directory '%s' already exists. This configuration will be skipped!\n" "$backup_location/snapshot" + printf "Move or delete destination directory and try backup again.\n" + fi + + NEW_NUM_ARRAY[$i]="$new_num" + NEW_SNAP_ARRAY[$i]="$new_snap" + NEW_INFO_ARRAY[$i]="$new_info" + BACKUPLOC_ARRAY[$i]="$backup_location" + + cont_backup="K" + CONT_BACKUP_ARRAY[$i]="yes" + if [[ $noconfirm == "yes" ]]; then + cont_backup="yes" + else + while [[ -n "$cont_backup" && "$cont_backup" != [Yy]"es" && + "$cont_backup" != [Yy] && "$cont_backup" != [Nn]"o" && + "$cont_backup" != [Nn] ]]; do + read -e -r -p "Proceed with backup of '$x' configuration [Y/n]? " cont_backup + if [[ -n "$cont_backup" && "$cont_backup" != [Yy]"es" && + "$cont_backup" != [Yy] && "$cont_backup" != [Nn]"o" && + "$cont_backup" != [Nn] ]]; then + printf "Select 'Y' or 'n'.\n" + fi + done + fi + + if [[ "$cont_backup" != [Yy]"es" && "$cont_backup" != [Yy] && -n "$cont_backup" ]]; then + CONT_BACKUP_ARRAY[$i]="no" + printf "Not backing up '%s' configuration.\n" "$x" + snapper -c "$x" delete "$new_num" + fi + + i=$((i+1)) + +done + +# Actual backing up +printf "\nPerforming backups...\n" +i=-1 +for x in $selected_configs; do + + i=$((i+1)) + + SNAP_SYNC_EXCLUDE=no + + if [[ -f "/etc/snapper/configs/$x" ]]; then + # shellcheck source=/etc/snapper/config-templates/default + source "/etc/snapper/configs/$x" + else + die "Selected snapper configuration $x does not exist." + fi + + cont_backup=${CONT_BACKUP_ARRAY[$i]} + if [[ $cont_backup == "no" || $SNAP_SYNC_EXCLUDE == "yes" ]]; then + notify_info "Backup in progress" "NOTE: Skipping $x configuration." + continue + fi + + notify_info "Backup in progress" "Backing up $x configuration." + + printf "\n" + + old_num="${OLD_NUM_ARRAY[$i]}" + old_snap="${OLD_SNAP_ARRAY[$i]}" + BACKUPDIR="${BACKUPDIRS_ARRAY[$i]}" + mybackupdir="${MYBACKUPDIR_ARRAY[$i]}" + new_num="${NEW_NUM_ARRAY[$i]}" + new_snap="${NEW_SNAP_ARRAY[$i]}" + new_info="${NEW_INFO_ARRAY[$i]}" + backup_location="${BACKUPLOC_ARRAY[$i]}" + + if ($ssh test -d "$backup_location/snapshot") ; then + printf "ERROR: Backup directory '%s' already exists. Skipping backup of this configuration!\n" "$backup_location/snapshot" + continue + fi + + $ssh mkdir -p "$backup_location" + + if [[ -z "$old_num" ]]; then + printf "Sending first snapshot for '%s' configuration...\n" "$x" + if [[ $doprogress -eq 0 ]]; then + btrfs send "$new_snap" | pv | $ssh btrfs receive "$backup_location" &>/dev/null + else + btrfs send "$new_snap" | $ssh btrfs receive "$backup_location" &>/dev/null + fi + else + + printf "Sending incremental snapshot for '%s' configuration...\n" "$x" + # Sends the difference between the new snapshot and old snapshot to the + # backup location. Using the -c flag instead of -p tells it that there + # is an identical subvolume to the old snapshot at the receiving + # location where it can get its data. This helps speed up the transfer. + + if [[ $doprogress -eq 0 ]]; then + btrfs send -c "$old_snap" "$new_snap" | pv | $ssh btrfs receive "$backup_location" + else + btrfs send -c "$old_snap" "$new_snap" | $ssh btrfs receive "$backup_location" + fi + + if [[ $keep == "yes" ]]; then + printf "Modifying data for old local snapshot for '%s' configuration...\n" "$x" + snapper -v -c "$x" modify -d "old snap-sync snapshot (you may remove)" -u "backupdir=,subvolid=,uuid=" -c "number" "$old_num" + else + printf "Deleting old snapshot for %s...\n" "$x" + snapper -c "$x" delete "$old_num" + fi + + fi + + if [[ -z $remote ]]; then + cp "$new_info" "$backup_location" + else + if [[ -z $port ]]; then + rsync -avzq "$new_info" "$remote":"$backup_location" + else + rsync -avzqe "ssh -p $port" "$new_info" "$remote":"$backup_location" + fi + fi + + # It's important not to change this userdata in the snapshots, since that's how + # we find the previous one. + + userdata="backupdir=$mybackupdir, subvolid=$selected_subvolid, uuid=$selected_uuid" + + # Tag new snapshot as the latest + printf "Tagging local snapshot as latest backup for '%s' configuration...\n" "$x" + snapper -v -c "$x" modify -d "$description" -u "$userdata" "$new_num" + + printf "Backup complete for '%s' configuration.\n" "$x" + +done + +printf "\nDone!\n" + +if [[ "$uuid_cmdline" != "none" ]]; then + notify_info "Finished" "Backups to $uuid_cmdline complete!" +else + notify_info "Finished" "Backups complete!" +fi diff --git a/sys/svcs/dconf/default.nix b/sys/svcs/dconf/default.nix new file mode 100644 index 00000000..db35208e --- /dev/null +++ b/sys/svcs/dconf/default.nix @@ -0,0 +1,10 @@ +{ + config, + lib, + pkgs, + ... +}: { + # needed to make home-manager play nice with some apps. See: + # https://nix-community.github.io/home-manager/index.html#_why_do_i_get_an_error_message_about_literal_ca_desrt_dconf_literal_or_literal_dconf_service_literal + programs.dconf.enable = true; +} diff --git a/sys/svcs/default.nix b/sys/svcs/default.nix new file mode 100644 index 00000000..c4b95394 --- /dev/null +++ b/sys/svcs/default.nix @@ -0,0 +1,17 @@ +{...}: { + imports = [ + ./backup + ./dconf + ./fwupd + ./nix + ./openssh + ./postgresql + ./printing + ./scanning + #./serverphone + ./snapper + ./steam + ./swaylock + ./xdg + ]; +} diff --git a/sys/svcs/fwupd/default.nix b/sys/svcs/fwupd/default.nix new file mode 100644 index 00000000..999ca72b --- /dev/null +++ b/sys/svcs/fwupd/default.nix @@ -0,0 +1,3 @@ +{...}: { + services.fwupd.enable = true; +} diff --git a/sys/svcs/nix/default.nix b/sys/svcs/nix/default.nix new file mode 100644 index 00000000..97b7220d --- /dev/null +++ b/sys/svcs/nix/default.nix @@ -0,0 +1,39 @@ +{ + pkgs, + nixpkgs_as_input, + templates, + ... +}: let + nixpkgs = nixpkgs_as_input; +in { + nix = { + package = pkgs.nixStable; + + registry = { + nixpkgs.flake = nixpkgs; + n.flake = nixpkgs; + t.flake = templates; + }; + + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 7d"; + }; + settings = { + auto-optimise-store = true; + experimental-features = [ + "nix-command" + "flakes" + #"ca-derivations" + ]; + + #substituters = ["https://cache.ngi0.nixos.org/"]; + #trusted-public-keys = ["cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA="]; + fallback = true; # TODO: what does this do? + + keep-failed = true; # keep failed tmp build dirs + pure-eval = true; # restrict file system and network access to hash + }; + }; +} diff --git a/sys/svcs/openssh/default.nix b/sys/svcs/openssh/default.nix new file mode 100644 index 00000000..b733dbe7 --- /dev/null +++ b/sys/svcs/openssh/default.nix @@ -0,0 +1,15 @@ +{...}: { + services.openssh = { + enable = true; + hostKeys = [ + { + path = "/srv/sshd/ssh_host_ed25519_key"; + rounds = 1000; + type = "ed25519"; + } + ]; + settings = { + PasswordAuthentication = false; + }; + }; +} diff --git a/sys/svcs/postgresql/default.nix b/sys/svcs/postgresql/default.nix new file mode 100644 index 00000000..4fc26034 --- /dev/null +++ b/sys/svcs/postgresql/default.nix @@ -0,0 +1,5 @@ +{...}: { + services.postgresql = { + enable = false; + }; +} diff --git a/sys/svcs/printing/default.nix b/sys/svcs/printing/default.nix new file mode 100644 index 00000000..7b8a871e --- /dev/null +++ b/sys/svcs/printing/default.nix @@ -0,0 +1,26 @@ +{pkgs, ...}: { + services.avahi = { + enable = true; + nssmdns = true; + openFirewall = true; + }; + services.printing = { + enable = true; + startWhenNeeded = true; + webInterface = false; + drivers = []; + }; + hardware = { + printers = { + ensurePrinters = [ + { + name = "Brother"; + description = "Brother DCP-9022CDW"; + model = "everywhere"; + deviceUri = "ipp://BRWACD1B84F4503.local:631/ipp/print"; + } + ]; + ensureDefaultPrinter = "Brother"; + }; + }; +} diff --git a/sys/svcs/scanning/default.nix b/sys/svcs/scanning/default.nix new file mode 100644 index 00000000..6621e08f --- /dev/null +++ b/sys/svcs/scanning/default.nix @@ -0,0 +1,12 @@ +{pkgs, ...}: { + hardware = { + sane = { + enable = true; + extraBackends = [pkgs.sane-airscan]; + }; + }; + + users.users.soispha.extraGroups = [ + "scanner" # for permission to access the scanner. + ]; +} diff --git a/sys/svcs/serverphone/certificates/ca.crt b/sys/svcs/serverphone/certificates/ca.crt new file mode 100644 index 00000000..7a4ae6f9 --- /dev/null +++ b/sys/svcs/serverphone/certificates/ca.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBXDCCAQOgAwIBAgIIRQ2wXiaD5pMwCgYIKoZIzj0EAwIwGTEXMBUGA1UEAwwO +U2VydmVycGhvbmUgQ0EwHhcNMjMwNjA2MTIzNzM3WhcNMzMwNjAzMTIzNzM3WjAZ +MRcwFQYDVQQDDA5TZXJ2ZXJwaG9uZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEH +A0IABDZMtz3liWniBedisStXDO2sxFCKBH239ezH7uADu8g5peGssmNu1rXEDrg1 +sFwVUjQeJAocYYNoUeHiVpODf1ejNTAzMB0GA1UdDgQWBBST5oMmXrANRbCLIQpN +W7e5uSCL3DASBgNVHRMBAf8ECDAGAQH/AgEBMAoGCCqGSM49BAMCA0cAMEQCIFig +xA3MvRNP4uXaUEWwdP1pYL/R8N46G4NZrPEfiNV4AiA+NJSTFRCOUqEsvSb7PTFx +YuMuJF4XxWnmStz3ym7xXA== +-----END CERTIFICATE----- diff --git a/sys/svcs/serverphone/certificates/server.crt b/sys/svcs/serverphone/certificates/server.crt new file mode 100644 index 00000000..f994cdc8 --- /dev/null +++ b/sys/svcs/serverphone/certificates/server.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBTjCB9KADAgECAgkAhKrdjsoiOrkwCgYIKoZIzj0EAwIwGTEXMBUGA1UEAwwO +U2VydmVycGhvbmUgQ0EwHhcNMjMwNjA2MTIzOTIwWhcNMjQwNjA1MTIzOTIwWjAm +MSQwIgYDVQQDDBtDbGllbnQgcnVubmluZyBvbiBsb2NhbGhvc3QwWTATBgcqhkjO +PQIBBggqhkjOPQMBBwNCAAS1ILQo8ae8ydqFlt5RncUT7joQiozk6Omunb0vxVz5 +toJRDmVqc1s6KhpCTipUV5coTcaK1TBz0+fft+9VH7cwoxgwFjAUBgNVHREEDTAL +gglsb2NhbGhvc3QwCgYIKoZIzj0EAwIDSQAwRgIhAN7ohtsBLrjlgmSe9ngovxZM +z61n0+/7w2mtX/OrLMWIAiEAu+D2S2o0s7E9pp2Rkug8cT5T4GCWgFgEHk5x2L/E +RVI= +-----END CERTIFICATE----- diff --git a/sys/svcs/serverphone/default.nix b/sys/svcs/serverphone/default.nix new file mode 100644 index 00000000..20125a75 --- /dev/null +++ b/sys/svcs/serverphone/default.nix @@ -0,0 +1,49 @@ +{ + config, + serverphone, + system, + lib, + ... +}: { + config = lib.mkIf config.soispha.secrets.enable { + services.serverphone = { + package = "${serverphone.packages.${system}.default}"; + enable = true; + domain = "localhost"; + configureDoas = true; + acceptedSshKeys = [ + "AAAAC3NzaC1lZDI1NTE5AAAAIGBFuTNNn71Rhfnop2cdz3r/RhWWlCePnSBOhTBbu2ME" + ]; + authorized = { + acceptedGpgKeys = [ + { + source = ./keys/key_1; + trust = "ultimate"; + } + { + source = ./keys/key_2; + trust = "ultimate"; + } + ]; + }; + caCertificate = "${./certificates/ca.crt}"; + certificate = "${./certificates/server.crt}"; + privateKey = config.age.secrets.serverphoneServer.path; + certificateRequest = { + acceptedUsers = [ + "soispha $argon2id$v=19$m=19456,t=2,p=1$EvhPENIBqL5b1RO5waNMWA$pJ8vDrCNJKDlqwB5bVDLjHVPEXm9McQhtt9OXSD8Zkc" + ]; + caPrivateKey = config.age.secrets.serverphoneCa.path; + }; + }; + + users.users.serverphone = { + group = "serverphone"; + isSystemUser = true; + home = "/run/serverphone"; + }; + users.groups.serverphone = { + members = ["serverphone"]; + }; + }; +} diff --git a/sys/svcs/serverphone/keys/key_1 b/sys/svcs/serverphone/keys/key_1 new file mode 120000 index 00000000..67720882 --- /dev/null +++ b/sys/svcs/serverphone/keys/key_1 @@ -0,0 +1 @@ +../../../../home-manager/soispha/config/gpg/keys/key_1 \ No newline at end of file diff --git a/sys/svcs/serverphone/keys/key_2 b/sys/svcs/serverphone/keys/key_2 new file mode 120000 index 00000000..24df7207 --- /dev/null +++ b/sys/svcs/serverphone/keys/key_2 @@ -0,0 +1 @@ +../../../../home-manager/soispha/config/gpg/keys/key_2 \ No newline at end of file diff --git a/sys/svcs/snapper/default.nix b/sys/svcs/snapper/default.nix new file mode 100644 index 00000000..41e4b381 --- /dev/null +++ b/sys/svcs/snapper/default.nix @@ -0,0 +1,41 @@ +{...}: { + services.snapper = { + configs = { + srv = { + SUBVOLUME = "/srv"; + FSTYPE = "btrfs"; + # users and groups allowed to work with config + ALLOW_GROUPS = ["wheel"]; + + # sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots + # directory + SYNC_ACL = true; + + # run daily number cleanup + NUMBER_CLEANUP = false; + + # limit for number cleanup + NUMBER_MIN_AGE = 1800; + NUMBER_LIMIT = 50; + NUMBER_LIMIT_IMPORTANT = 10; + + # create hourly snapshots + TIMELINE_CREATE = true; + + # cleanup hourly snapshots after some time + TIMELINE_CLEANUP = true; + + # limits for timeline cleanup + TIMELINE_MIN_AGE = 1800; + TIMELINE_LIMIT_HOURLY = 7; + TIMELINE_LIMIT_DAILY = 3; + TIMELINE_LIMIT_WEEKLY = 2; + TIMELINE_LIMIT_MONTHLY = 0; + TIMELINE_LIMIT_YEARLY = 2; + + # cleanup empty pre-post-pairs + EMPTY_PRE_POST_CLEANUP = true; + }; + }; + }; +} diff --git a/sys/svcs/steam/default.nix b/sys/svcs/steam/default.nix new file mode 100644 index 00000000..54091493 --- /dev/null +++ b/sys/svcs/steam/default.nix @@ -0,0 +1,23 @@ +{ + lib, + config, + pkgs, + ... +}: let + cfg = config.soispha.services.steam; +in { + options.soispha.services.steam = { + enable = lib.mkOption { + default = false; + description = lib.mdDoc "Steam"; + }; + }; + config = lib.mkIf cfg.enable { + programs.steam = { + enable = true; + }; + environment.systemPackages = [ + pkgs.wineWowPackages.waylandFull + ]; + }; +} diff --git a/sys/svcs/swaylock/default.nix b/sys/svcs/swaylock/default.nix new file mode 100644 index 00000000..6cbcef28 --- /dev/null +++ b/sys/svcs/swaylock/default.nix @@ -0,0 +1,4 @@ +{...}: { + # otherwise swaylock can't access the user password. + security.pam.services.swaylock = {}; +} diff --git a/sys/svcs/xdg/default.nix b/sys/svcs/xdg/default.nix new file mode 100644 index 00000000..297928ce --- /dev/null +++ b/sys/svcs/xdg/default.nix @@ -0,0 +1,11 @@ +{pkgs, ...}: { + xdg = { + portal = { + enable = true; + # TODO: only enable the below, when on river (or wlr based compositor) + wlr.enable = true; + extraPortals = [pkgs.xdg-desktop-portal-wlr]; + }; + }; + # TODO: mime = {}; +} diff --git a/sys/tempfiles/default.nix b/sys/tempfiles/default.nix new file mode 100644 index 00000000..2d48b02e --- /dev/null +++ b/sys/tempfiles/default.nix @@ -0,0 +1,6 @@ +{config, ...}: { + systemd.tmpfiles.rules = [ + # this file is needed to trash stuff on the temp fs + "d /.Trash 1777 root root" # TODO: move this to the lf config + ]; +} diff --git a/sys/users/default.nix b/sys/users/default.nix new file mode 100644 index 00000000..365ffd41 --- /dev/null +++ b/sys/users/default.nix @@ -0,0 +1,44 @@ +{ + config, + pkgs, + lib, + ... +}: let + cfg = config.soispha.users; +in { + options.soispha.users = { + # enable = lib.mkEnableOption (lib.mdDoc "users"); + hashedPassword = lib.mkOption { + type = lib.types.str; + example = lib.literalExpression "$y$jFT$ONrCqZIJKB7engmfA4orD/$0GO58/wV5wrYWj0cyONhyujZPjFmbT0XKtx2AvXLG0B"; + default = "$y$jFT$ONrCqZIJKB7engmfA4orD/$0GO58/wV5wrYWj0cyONhyujZPjFmbT0XKtx2AvXLG0B"; + description = lib.mdDoc "Hashed password for the user"; + }; + }; + config = { + # I was told, that this solves some nasty problems: + programs.zsh.enable = true; + + users = { + groups = { + plugdev.members = ["soispha"]; + }; + mutableUsers = false; + users.soispha = { + isNormalUser = true; + home = "/home/soispha"; + createHome = true; + shell = pkgs.zsh; + initialHashedPassword = cfg.hashedPassword; + extraGroups = [ + "plugdev" # although deprecated, this helps with old udev rules, that still use this group. TODO: check for an open issue + "wheel" + ]; + uid = 1000; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBFuTNNn71Rhfnop2cdz3r/RhWWlCePnSBOhTBbu2ME soispha" + ]; + }; + }; + }; +} |