summaryrefslogtreecommitdiff
path: root/modules/core
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-09-20 05:36:20 -0700
committerFuwn <[email protected]>2024-09-20 05:36:20 -0700
commitd9747c64b038943253eaafdc59a49d5face46dab (patch)
treeb452d15a7f20e9f4bb70ec9f9040137bec1072f8 /modules/core
parenthimeji: move containers over from seti (diff)
downloadnixos-config-d9747c64b038943253eaafdc59a49d5face46dab.tar.xz
nixos-config-d9747c64b038943253eaafdc59a49d5face46dab.zip
modules: server and core modules
Diffstat (limited to 'modules/core')
-rw-r--r--modules/core/default.nix11
-rw-r--r--modules/core/hardware/bluetooth.nix19
-rw-r--r--modules/core/hardware/cpu.nix21
-rw-r--r--modules/core/hardware/default.nix14
-rw-r--r--modules/core/hardware/tpm.nix18
-rw-r--r--modules/core/hardware/usb.nix10
-rw-r--r--modules/core/hardware/yubikey.nix18
-rw-r--r--modules/core/networking/caddy.nix17
-rw-r--r--modules/core/networking/default.nix43
-rw-r--r--modules/core/networking/dhcpcd.nix12
-rw-r--r--modules/core/networking/firewall/default.nix11
-rw-r--r--modules/core/networking/firewall/fail2ban.nix20
-rw-r--r--modules/core/networking/i2p.nix86
-rw-r--r--modules/core/networking/ipv6.nix9
-rw-r--r--modules/core/networking/loopback.nix7
-rw-r--r--modules/core/networking/networkmanager.nix22
-rw-r--r--modules/core/networking/optimise.nix73
-rw-r--r--modules/core/networking/resolved.nix17
-rw-r--r--modules/core/networking/tor.nix27
-rw-r--r--modules/core/networking/upnp.nix12
-rw-r--r--modules/core/networking/vpn/default.nix6
-rw-r--r--modules/core/networking/vpn/pia.nix10
-rw-r--r--modules/core/networking/vpn/tailscale.nix15
-rw-r--r--modules/core/nix/default.nix87
-rw-r--r--modules/core/nix/extended.nix48
-rw-r--r--modules/core/nix/nh.nix9
-rw-r--r--modules/core/security/apparmor.nix22
-rw-r--r--modules/core/security/audit.nix17
-rw-r--r--modules/core/security/default.nix20
-rw-r--r--modules/core/security/doas.nix13
-rw-r--r--modules/core/security/kernel.nix160
-rw-r--r--modules/core/security/pam.nix50
-rw-r--r--modules/core/security/pki.nix42
-rw-r--r--modules/core/security/polkit.nix7
-rw-r--r--modules/core/security/sudo.nix75
-rw-r--r--modules/core/software/aagl.nix9
-rw-r--r--modules/core/software/access/default.nix7
-rw-r--r--modules/core/software/access/gnupg.nix18
-rw-r--r--modules/core/software/access/mosh.nix6
-rw-r--r--modules/core/software/access/ssh.nix39
-rw-r--r--modules/core/software/boot/default.nix30
-rw-r--r--modules/core/software/boot/grub.nix22
-rw-r--r--modules/core/software/boot/systemd-boot.nix9
-rw-r--r--modules/core/software/default.nix40
-rw-r--r--modules/core/software/desktop/default.nix6
-rw-r--r--modules/core/software/desktop/gtk.nix8
-rw-r--r--modules/core/software/desktop/xdg-portal.nix15
-rw-r--r--modules/core/software/encryption.nix16
-rw-r--r--modules/core/software/gaming.nix38
-rw-r--r--modules/core/software/input.nix25
-rw-r--r--modules/core/software/locale.nix9
-rw-r--r--modules/core/software/multimedia/audio/default.nix6
-rw-r--r--modules/core/software/multimedia/audio/pipewire.nix164
-rw-r--r--modules/core/software/multimedia/audio/wireplumber.nix42
-rw-r--r--modules/core/software/multimedia/default.nix6
-rw-r--r--modules/core/software/multimedia/video/default.nix11
-rw-r--r--modules/core/software/multimedia/video/graphics.nix21
-rw-r--r--modules/core/software/multimedia/video/libva.nix7
-rw-r--r--modules/core/software/multimedia/video/nvidia.nix38
-rw-r--r--modules/core/software/multimedia/video/vulkan.nix9
-rw-r--r--modules/core/software/programs.nix22
-rw-r--r--modules/core/software/services/adb.nix12
-rw-r--r--modules/core/software/services/ananicy.nix8
-rw-r--r--modules/core/software/services/dbus.nix15
-rw-r--r--modules/core/software/services/default.nix24
-rw-r--r--modules/core/software/services/libinput.nix13
-rw-r--r--modules/core/software/services/logrotate.nix24
-rw-r--r--modules/core/software/services/ollama.nix6
-rw-r--r--modules/core/software/services/printing.nix19
-rw-r--r--modules/core/software/services/xserver.nix10
-rw-r--r--modules/core/software/shell.nix7
-rw-r--r--modules/core/software/systemd.nix11
-rw-r--r--modules/core/software/users.nix46
-rw-r--r--modules/core/variables/default.nix20
-rw-r--r--modules/core/variables/electron.nix7
-rw-r--r--modules/core/variables/fcitx.nix13
-rw-r--r--modules/core/variables/mozilla.nix6
-rw-r--r--modules/core/variables/nvidia.nix12
-rw-r--r--modules/core/variables/opengl.nix7
-rw-r--r--modules/core/variables/qt.nix11
-rw-r--r--modules/core/variables/wayland.nix10
-rw-r--r--modules/core/variables/wlroots.nix12
-rw-r--r--modules/core/virtualisation/default.nix14
-rw-r--r--modules/core/virtualisation/docker.nix32
-rw-r--r--modules/core/virtualisation/libvirtd.nix15
-rw-r--r--modules/core/virtualisation/qemu.nix45
86 files changed, 2070 insertions, 0 deletions
diff --git a/modules/core/default.nix b/modules/core/default.nix
new file mode 100644
index 0000000..44da8e2
--- /dev/null
+++ b/modules/core/default.nix
@@ -0,0 +1,11 @@
+{
+ imports = [
+ ./hardware
+ ./networking
+ ./nix
+ ./security
+ ./software
+ ./variables
+ ./virtualisation
+ ];
+}
diff --git a/modules/core/hardware/bluetooth.nix b/modules/core/hardware/bluetooth.nix
new file mode 100644
index 0000000..9737504
--- /dev/null
+++ b/modules/core/hardware/bluetooth.nix
@@ -0,0 +1,19 @@
+{ pkgs, ... }:
+{
+ boot.kernelParams = [ "btusb" ];
+ services.blueman.enable = true;
+
+ hardware.bluetooth = {
+ enable = true;
+ powerOnBoot = true;
+ package = pkgs.bluez5-experimental;
+ disabledPlugins = [ "sap" ];
+ # hsphfpd.enable = true;
+
+ settings.General = {
+ JustWorksRepairing = "always";
+ MultiProfile = "multiple";
+ Experimental = true;
+ };
+ };
+}
diff --git a/modules/core/hardware/cpu.nix b/modules/core/hardware/cpu.nix
new file mode 100644
index 0000000..1ac3a27
--- /dev/null
+++ b/modules/core/hardware/cpu.nix
@@ -0,0 +1,21 @@
+{ pkgs, config, ... }:
+{
+ environment.systemPackages = [ pkgs.amdctl ];
+
+ powerManagement = {
+ enable = true;
+ cpuFreqGovernor = "performance";
+ };
+
+ boot = {
+ kernelModules = [
+ # "kvm-amd"
+ "amd-pstate"
+ "zenpower"
+ "msr"
+ ];
+
+ kernelParams = [ "amd_iommu=on" ];
+ extraModulePackages = [ config.boot.kernelPackages.zenpower ];
+ };
+}
diff --git a/modules/core/hardware/default.nix b/modules/core/hardware/default.nix
new file mode 100644
index 0000000..167e7c7
--- /dev/null
+++ b/modules/core/hardware/default.nix
@@ -0,0 +1,14 @@
+{
+ imports = [
+ ./cpu.nix
+ ./bluetooth.nix
+ ./usb.nix
+ ./tpm.nix
+ ./yubikey.nix
+ ];
+
+ hardware = {
+ enableRedistributableFirmware = true;
+ enableAllFirmware = true;
+ };
+}
diff --git a/modules/core/hardware/tpm.nix b/modules/core/hardware/tpm.nix
new file mode 100644
index 0000000..b84551e
--- /dev/null
+++ b/modules/core/hardware/tpm.nix
@@ -0,0 +1,18 @@
+{ pkgs, ... }:
+{
+ security.tpm2 = {
+ enable = true;
+ applyUdevRules = true;
+ abrmd.enable = true;
+ tctiEnvironment.enable = true;
+ pkcs11.enable = true;
+ };
+
+ environment.systemPackages = with pkgs; [
+ tpm2-tools
+ tpm2-tss
+ tpm2-abrmd
+ ];
+
+ boot.kernelModules = [ "uhid" ];
+}
diff --git a/modules/core/hardware/usb.nix b/modules/core/hardware/usb.nix
new file mode 100644
index 0000000..f697761
--- /dev/null
+++ b/modules/core/hardware/usb.nix
@@ -0,0 +1,10 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = with pkgs; [
+ usbutils
+ lm_sensors
+ pciutils
+ ];
+
+ boot.kernelParams = [ "usbcore.autosuspend=-1" ];
+}
diff --git a/modules/core/hardware/yubikey.nix b/modules/core/hardware/yubikey.nix
new file mode 100644
index 0000000..6bd4a5c
--- /dev/null
+++ b/modules/core/hardware/yubikey.nix
@@ -0,0 +1,18 @@
+{ pkgs, ... }:
+{
+ hardware.gpgSmartcards.enable = true;
+
+ services = {
+ pcscd.enable = true;
+ udev.packages = [ pkgs.yubikey-personalization ];
+ };
+
+ environment.systemPackages = with pkgs; [
+ yubikey-manager
+ yubikey-manager-qt
+ yubikey-personalization
+ yubikey-personalization-gui
+ yubico-piv-tool
+ yubioath-flutter
+ ];
+}
diff --git a/modules/core/networking/caddy.nix b/modules/core/networking/caddy.nix
new file mode 100644
index 0000000..efba3f6
--- /dev/null
+++ b/modules/core/networking/caddy.nix
@@ -0,0 +1,17 @@
+{
+ services.caddy = {
+ enable = true;
+
+ virtualHosts = {
+ "i2pd.localhost".extraConfig = ''
+ reverse_proxy localhost:7070
+ tls internal
+ '';
+
+ "glance.localhost".extraConfig = ''
+ reverse_proxy localhost:8080
+ tls internal
+ '';
+ };
+ };
+}
diff --git a/modules/core/networking/default.nix b/modules/core/networking/default.nix
new file mode 100644
index 0000000..c26099c
--- /dev/null
+++ b/modules/core/networking/default.nix
@@ -0,0 +1,43 @@
+{ secrets, ... }:
+{
+ imports = [
+ ./firewall
+ ./vpn
+ ./caddy.nix
+ ./dhcpcd.nix
+ ./i2p.nix
+ ./ipv6.nix
+ ./loopback.nix
+ ./networkmanager.nix
+ ./optimise.nix
+ ./resolved.nix
+ ./tor.nix
+ ./upnp.nix
+ ];
+
+ # https://discourse.nixos.org/t/rebuild-error-failed-to-start-network-manager-wait-online/41977/2
+ systemd.network.wait-online.enable = false;
+ boot.initrd.systemd.network.wait-online.enable = false;
+
+ # https://discourse.nixos.org/t/how-to-disable-networkmanager-wait-online-service-in-the-configuration-file/19963/2
+ systemd.services.NetworkManager-wait-online.enable = false;
+
+ networking = {
+ hostName = "kansai";
+ nftables.enable = true;
+
+ nameservers = [
+ "45.90.28.0#${secrets.nextdns_id}.dns.nextdns.io"
+ "2a07:a8c0::#${secrets.nextdns_id}.dns.nextdns.io"
+ "45.90.30.0#${secrets.nextdns_id}.dns.nextdns.io"
+ "2a07:a8c1::#${secrets.nextdns_id}.dns.nextdns.io"
+ ];
+
+ timeServers = [
+ "0.nixos.pool.ntp.org"
+ "1.nixos.pool.ntp.org"
+ "2.nixos.pool.ntp.org"
+ "3.nixos.pool.ntp.org"
+ ];
+ };
+}
diff --git a/modules/core/networking/dhcpcd.nix b/modules/core/networking/dhcpcd.nix
new file mode 100644
index 0000000..f46b657
--- /dev/null
+++ b/modules/core/networking/dhcpcd.nix
@@ -0,0 +1,12 @@
+{
+ networking.dhcpcd = {
+ wait = "background";
+
+ extraConfig = ''
+ noarp
+ nooption domain_name_servers, domain_name, domain_search, host_name
+ nooption ntp_servers
+ nohook resolv.conf, wpa_supplicant
+ '';
+ };
+}
diff --git a/modules/core/networking/firewall/default.nix b/modules/core/networking/firewall/default.nix
new file mode 100644
index 0000000..074f398
--- /dev/null
+++ b/modules/core/networking/firewall/default.nix
@@ -0,0 +1,11 @@
+{
+ imports = [ ./fail2ban.nix ];
+
+ networking.firewall = {
+ enable = true;
+ allowPing = false;
+ logReversePathDrops = true;
+ logRefusedConnections = false;
+ checkReversePath = "loose";
+ };
+}
diff --git a/modules/core/networking/firewall/fail2ban.nix b/modules/core/networking/firewall/fail2ban.nix
new file mode 100644
index 0000000..6311b14
--- /dev/null
+++ b/modules/core/networking/firewall/fail2ban.nix
@@ -0,0 +1,20 @@
+{ pkgs, lib, ... }:
+{
+ services.fail2ban = {
+ enable = false;
+ banaction = "nftables-multiport";
+ banaction-allports = lib.mkDefault "nftables-allport";
+
+ extraPackages = with pkgs; [
+ nftables
+ ipset
+ ];
+
+ ignoreIP = [
+ "10.0.0.0/8"
+ "172.16.0.0/12"
+ "100.64.0.0/16"
+ "192.168.0.0/16"
+ ];
+ };
+}
diff --git a/modules/core/networking/i2p.nix b/modules/core/networking/i2p.nix
new file mode 100644
index 0000000..8bca73e
--- /dev/null
+++ b/modules/core/networking/i2p.nix
@@ -0,0 +1,86 @@
+{
+ # https://voidcruiser.nl/rambles/i2p-on-nixos/
+ containers.i2pd = {
+ autoStart = true;
+
+ config = {
+ system.stateVersion = "24.05";
+
+ networking.firewall.allowedTCPPorts = [
+ 7656
+ 7070
+ 4447
+ 4444
+ ];
+
+ services.i2pd =
+ let
+ address = "0.0.0.0";
+ in
+ {
+ inherit address;
+
+ enable = true;
+ upnp.enable = true;
+ bandwidth = 512;
+ websocket.address = address;
+ yggdrasil.address = address;
+ reseed.verify = true;
+
+ proto = {
+ bob.address = address;
+
+ i2pControl = {
+ inherit address;
+
+ enable = true;
+ };
+
+ socksProxy = {
+ inherit address;
+
+ enable = true;
+ };
+
+ http = {
+ inherit address;
+
+ enable = true;
+ strictHeaders = false;
+ };
+
+ i2cp = {
+ inherit address;
+
+ enable = true;
+ };
+
+ sam = {
+ inherit address;
+
+ enable = true;
+ };
+
+ httpProxy = {
+ inherit address;
+
+ enable = true;
+ # outproxy = "http://false.i2p";
+ # outproxy = "http://purokishi.i2p:4444";
+ # outproxy = "http://outproxy.acetone.i2p:3128";
+ outproxy = "http://exit.stormycloud.i2p:4444";
+ # outproxy = "http://outproxy.bandura.i2p:4444";
+ };
+ };
+
+ addressbook.subscriptions = [
+ "http://inr.i2p/export/alive-hosts.txt"
+ "http://i2p-projekt.i2p/hosts.txt"
+ "http://stats.i2p/cgi-bin/newhosts.txt"
+ "http://reg.i2p/export/hosts.txt"
+ "http://notbob.i2p/hosts.txt"
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/core/networking/ipv6.nix b/modules/core/networking/ipv6.nix
new file mode 100644
index 0000000..274c1ae
--- /dev/null
+++ b/modules/core/networking/ipv6.nix
@@ -0,0 +1,9 @@
+{
+ boot.kernel.sysctl = {
+ "net.ipv6.conf.enp42s0.disable_ipv6" = true;
+ "net.ipv6.conf.wlp4s0.disable_ipv6" = true;
+ "net.ipv6.conf.tun0.disable_ipv6" = true;
+ };
+
+ networking.enableIPv6 = false;
+}
diff --git a/modules/core/networking/loopback.nix b/modules/core/networking/loopback.nix
new file mode 100644
index 0000000..62e745e
--- /dev/null
+++ b/modules/core/networking/loopback.nix
@@ -0,0 +1,7 @@
+{ config, ... }:
+{
+ boot = {
+ kernelModules = [ "v4l2loopback" ];
+ extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback ];
+ };
+}
diff --git a/modules/core/networking/networkmanager.nix b/modules/core/networking/networkmanager.nix
new file mode 100644
index 0000000..7ef0e04
--- /dev/null
+++ b/modules/core/networking/networkmanager.nix
@@ -0,0 +1,22 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = [ pkgs.networkmanagerapplet ];
+
+ networking.networkmanager = {
+ enable = true;
+ plugins = [ pkgs.networkmanager-openvpn ];
+ dns = "none"; # "systemd-resolved"
+ wifi.backend = "iwd";
+
+ unmanaged = [
+ "interface-name:tailscale*"
+ "interface-name:br-*"
+ "interface-name:rndis*"
+ "interface-name:docker*"
+ "interface-name:virbr*"
+ "interface-name:vboxnet*"
+ "interface-name:waydroid*"
+ "type:bridge"
+ ];
+ };
+}
diff --git a/modules/core/networking/optimise.nix b/modules/core/networking/optimise.nix
new file mode 100644
index 0000000..c6f2bec
--- /dev/null
+++ b/modules/core/networking/optimise.nix
@@ -0,0 +1,73 @@
+{
+ 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;
+ };
+ };
+}
diff --git a/modules/core/networking/resolved.nix b/modules/core/networking/resolved.nix
new file mode 100644
index 0000000..82effbe
--- /dev/null
+++ b/modules/core/networking/resolved.nix
@@ -0,0 +1,17 @@
+{ secrets, ... }:
+{
+ services.resolved = {
+ enable = false;
+ dnssec = "true";
+ domains = [ "~." ];
+ dnsovertls = "true";
+ llmnr = "false";
+
+ extraConfig = ''
+ DNS=45.90.28.0#${secrets.nextdns_id}.dns.nextdns.io
+ DNS=2a07:a8c0::#${secrets.nextdns_id}.dns.nextdns.io
+ DNS=45.90.30.0#${secrets.nextdns_id}.dns.nextdns.io
+ DNS=2a07:a8c1::#${secrets.nextdns_id}.dns.nextdns.io
+ '';
+ };
+}
diff --git a/modules/core/networking/tor.nix b/modules/core/networking/tor.nix
new file mode 100644
index 0000000..dfbfb3a
--- /dev/null
+++ b/modules/core/networking/tor.nix
@@ -0,0 +1,27 @@
+{ pkgs, ... }:
+{
+ services.tor = {
+ enable = true;
+ torsocks.enable = true;
+
+ client = {
+ enable = true;
+ dns.enable = true;
+ };
+ };
+
+ programs.proxychains = {
+ enable = true;
+ quietMode = false;
+ proxyDNS = true;
+ package = pkgs.proxychains-ng;
+
+ proxies = {
+ tor = {
+ type = "socks5";
+ host = "127.0.0.1";
+ port = 9050;
+ };
+ };
+ };
+}
diff --git a/modules/core/networking/upnp.nix b/modules/core/networking/upnp.nix
new file mode 100644
index 0000000..998592a
--- /dev/null
+++ b/modules/core/networking/upnp.nix
@@ -0,0 +1,12 @@
+{
+ services.miniupnpd = {
+ enable = true;
+ natpmp = true;
+ externalInterface = "enp42s0";
+
+ internalIPs = [
+ "enp42s0"
+ "wlan0"
+ ];
+ };
+}
diff --git a/modules/core/networking/vpn/default.nix b/modules/core/networking/vpn/default.nix
new file mode 100644
index 0000000..92a11b0
--- /dev/null
+++ b/modules/core/networking/vpn/default.nix
@@ -0,0 +1,6 @@
+{
+ imports = [
+ ./pia.nix
+ ./tailscale.nix
+ ];
+}
diff --git a/modules/core/networking/vpn/pia.nix b/modules/core/networking/vpn/pia.nix
new file mode 100644
index 0000000..d52dbf8
--- /dev/null
+++ b/modules/core/networking/vpn/pia.nix
@@ -0,0 +1,10 @@
+{ secrets, ... }:
+{
+ services.pia = {
+ enable = true;
+
+ authUserPass = {
+ inherit (secrets.pia) username password;
+ };
+ };
+}
diff --git a/modules/core/networking/vpn/tailscale.nix b/modules/core/networking/vpn/tailscale.nix
new file mode 100644
index 0000000..21f471a
--- /dev/null
+++ b/modules/core/networking/vpn/tailscale.nix
@@ -0,0 +1,15 @@
+{ config, ... }:
+{
+ networking.firewall.trustedInterfaces = [ "${config.services.tailscale.interfaceName}" ];
+
+ services.tailscale = {
+ enable = true;
+ useRoutingFeatures = "both";
+ };
+
+ # <https://tailscale.com/kb/1019/subnets/?tab=linux#step-1-install-the-tailscale-client>
+ boot.kernel.sysctl = {
+ "net.ipv4.ip_forward" = true;
+ "net.ipv6.conf.all.forwarding" = true;
+ };
+}
diff --git a/modules/core/nix/default.nix b/modules/core/nix/default.nix
new file mode 100644
index 0000000..6b605ee
--- /dev/null
+++ b/modules/core/nix/default.nix
@@ -0,0 +1,87 @@
+{
+ inputs,
+ pkgs,
+ lib,
+ config,
+ ...
+}:
+{
+ imports = [ ./extended.nix ];
+ nixpkgs.config.allowUnfree = true;
+
+ nix = {
+ gc.automatic = true;
+ optimise.automatic = true;
+ registry.nixpkgs.flake = inputs.nixpkgs;
+ package = pkgs.nixVersions.git;
+ nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
+ channel.enable = false;
+
+ settings = {
+ auto-optimise-store = true;
+ http-connections = 0;
+ warn-dirty = false;
+ log-lines = 30;
+ sandbox-fallback = false;
+ keep-going = true;
+ connect-timeout = 5;
+ stalled-download-timeout = 20;
+ auto-allocate-uids = true;
+ use-cgroups = pkgs.stdenv.isLinux;
+ builders-use-substitutes = true;
+ nix-path = lib.mkForce "nixpkgs=flake:nixpkgs";
+ flake-registry = "${inputs.flake-registry}/flake-registry.json";
+ trusted-users = [ "@wheel" ];
+ max-jobs = "auto";
+ keep-outputs = true;
+
+ system-features = [
+ "nixos-test"
+ "kvm"
+ "recursive-nix"
+ "big-parallel"
+ ];
+
+ allowed-users = [
+ "root"
+ "@wheel"
+ ];
+
+ substituters = [
+ "https://cache.nixos.org/"
+ "https://nix-community.cachix.org"
+ "https://hyprland.cachix.org"
+ "https://nyx.chaotic.cx/"
+ "https://nixpkgs-wayland.cachix.org"
+ "https://cuda-maintainers.cachix.org"
+ "https://nixpkgs-unfree.cachix.org"
+ # "https://cache.flox.dev"
+ "https://cache.iog.io"
+ "https://ezkea.cachix.org"
+ ];
+
+ trusted-public-keys = [
+ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
+ "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
+ "nyx.cachix.org-1:HfnXSw4pj95iI/n17rIDy40agHj12WfF+Gqk6SonIT8="
+ "nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA="
+ "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E="
+ "nixpkgs-unfree.cachix.org-1:hqvoInulhbV4nJ9yJOEr+4wxhDV4xq2d1DK7S6Nj6rs="
+ # "flox-cache-public-1:7F4OyH7ZCnFhcze3fJdfyXYLQw/aV7GEed86nQ7IsOs="
+ "hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
+ "ezkea.cachix.org-1:ioBmUbJTZIKsHmWWXPe1FSFbeVe+afhfgqgTSNd34eI="
+ ];
+
+ experimental-features = [
+ "nix-command"
+ "flakes"
+ "recursive-nix"
+ "ca-derivations"
+ "auto-allocate-uids"
+ "cgroups"
+ "no-url-literals"
+ "dynamic-derivations"
+ ];
+ };
+ };
+}
diff --git a/modules/core/nix/extended.nix b/modules/core/nix/extended.nix
new file mode 100644
index 0000000..4e924cd
--- /dev/null
+++ b/modules/core/nix/extended.nix
@@ -0,0 +1,48 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+{
+ imports = [ ./nh.nix ];
+
+ config = lib.mkIf config.modules.nix.extend {
+ nixpkgs.config.cudaSupport = true;
+ programs.nix-index-database.comma.enable = true;
+
+ nix = {
+ # distributedBuilds = true;
+
+ buildMachines =
+ map
+ (system: {
+ inherit system;
+
+ hostName = "eu.nixbuild.net";
+ maxJobs = 100;
+
+ supportedFeatures = [
+ "benchmark"
+ "big-parallel"
+ ];
+ })
+ [
+ "x86_64-linux"
+ "i686-linux"
+ "aarch64-linux"
+ "armv7l-linux"
+ ];
+
+ settings = {
+ extra-platforms = config.boot.binfmt.emulatedSystems;
+
+ extra-sandbox-paths = [
+ config.programs.ccache.cacheDir
+ "/run/binfmt"
+ "${pkgs.qemu}"
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/core/nix/nh.nix b/modules/core/nix/nh.nix
new file mode 100644
index 0000000..5b54192
--- /dev/null
+++ b/modules/core/nix/nh.nix
@@ -0,0 +1,9 @@
+{ lib, config, ... }:
+{
+ config = lib.mkIf config.modules.nix.extend {
+ programs.nh = {
+ enable = true;
+ clean.enable = false;
+ };
+ };
+}
diff --git a/modules/core/security/apparmor.nix b/modules/core/security/apparmor.nix
new file mode 100644
index 0000000..170838c
--- /dev/null
+++ b/modules/core/security/apparmor.nix
@@ -0,0 +1,22 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = with pkgs; [
+ apparmor-pam
+ apparmor-utils
+ apparmor-parser
+ apparmor-profiles
+ apparmor-bin-utils
+ apparmor-kernel-patches
+ libapparmor
+ ];
+
+ services.dbus.apparmor = "enabled";
+
+ security.apparmor = {
+ enable = true;
+ enableCache = true;
+ killUnconfinedConfinables = true;
+ packages = [ pkgs.apparmor-profiles ];
+ policies.dummy.profile = "/dummy { }";
+ };
+}
diff --git a/modules/core/security/audit.nix b/modules/core/security/audit.nix
new file mode 100644
index 0000000..9922213
--- /dev/null
+++ b/modules/core/security/audit.nix
@@ -0,0 +1,17 @@
+let
+ enable = false;
+in
+{
+ security = {
+ auditd.enable = enable;
+
+ audit = {
+ inherit enable;
+
+ rules = [
+ "-a exit,always -F arch=b64 -S execve"
+ "-a exit,always -F arch=b32 -S execve"
+ ];
+ };
+ };
+}
diff --git a/modules/core/security/default.nix b/modules/core/security/default.nix
new file mode 100644
index 0000000..7a571a9
--- /dev/null
+++ b/modules/core/security/default.nix
@@ -0,0 +1,20 @@
+{ config, lib, ... }:
+{
+ imports = [
+ ./apparmor.nix
+ ./audit.nix
+ ./doas.nix
+ ./kernel.nix
+ ./pam.nix
+ ./pki.nix
+ ./polkit.nix
+ ./sudo.nix
+ ];
+
+ security = {
+ rtkit.enable = lib.modules.mkForce config.services.pipewire.enable;
+ virtualisation.flushL1DataCache = "always";
+ };
+
+ programs.firejail.enable = true;
+}
diff --git a/modules/core/security/doas.nix b/modules/core/security/doas.nix
new file mode 100644
index 0000000..af717ca
--- /dev/null
+++ b/modules/core/security/doas.nix
@@ -0,0 +1,13 @@
+{
+ security.doas = {
+ enable = true;
+ extraRules = [
+ {
+ keepEnv = true;
+ # persist = true;
+ noPass = true;
+ users = [ "ebisu" ];
+ }
+ ];
+ };
+}
diff --git a/modules/core/security/kernel.nix b/modules/core/security/kernel.nix
new file mode 100644
index 0000000..62b2f28
--- /dev/null
+++ b/modules/core/security/kernel.nix
@@ -0,0 +1,160 @@
+{ lib, ... }:
+{
+ boot = {
+ # https://docs.kernel.org/admin-guide/sysctl/vm.html
+ kernel.sysctl = {
+ # The Magic SysRq key is a key combo that allows users connected to the
+ # system console of a Linux kernel to perform some low-level commands.
+ # Disable it, since we don't need it, and is a potential security concern.
+ "kernel.sysrq" = lib.mkForce 0;
+
+ # Restrict ptrace() usage to processes with a pre-defined relationship
+ # (e.g., parent/child)
+ # FIXME: this breaks game launchers, find a way to launch them with privileges (steam)
+ # gamescope wrapped with the capabilities *might* solve the issue
+ # spoiler: it didn't
+ # "kernel.yama.ptrace_scope" = 2;
+
+ # Hide kptrs even for processes with CAP_SYSLOG
+ # also prevents printing kernel pointers
+ "kernel.kptr_restrict" = 2;
+
+ # Disable bpf() JIT (to eliminate spray attacks)
+ "net.core.bpf_jit_enable" = false;
+
+ # Disable ftrace debugging
+ "kernel.ftrace_enabled" = false;
+
+ # Avoid kernel memory address exposures via dmesg (this value can also be set by CONFIG_SECURITY_DMESG_RESTRICT).
+ "kernel.dmesg_restrict" = 1;
+
+ # Prevent creating files in potentially attacker-controlled environments such
+ # as world-writable directories to make data spoofing attacks more difficult
+ "fs.protected_fifos" = 2;
+
+ # Prevent unintended writes to already-created files
+ "fs.protected_regular" = 2;
+
+ # Disable SUID binary dump
+ "fs.suid_dumpable" = 0;
+
+ # Prevent unprivileged users from creating hard or symbolic links to files
+ "fs.protected_symlinks" = 1;
+ "fs.protected_hardlinks" = 1;
+
+ # Disable late module loading
+ # "kernel.modules_disabled" = 1;
+
+ # Disallow profiling at all levels without CAP_SYS_ADMIN
+ "kernel.perf_event_paranoid" = 3;
+
+ # Require CAP_BPF to use bpf
+ "kernel.unprivileged_bpf_disabled" = true;
+
+ # Prevent boot console kernel log information leaks
+ "kernel.printk" = "3 3 3 3";
+
+ # Restrict loading TTY line disciplines to the CAP_SYS_MODULE capability to
+ # prevent unprivileged attackers from loading vulnerable line disciplines with
+ # the TIOCSETD ioctl
+ "dev.tty.ldisc_autoload" = 0;
+
+ # Kexec allows replacing the current running kernel. There may be an edge case where
+ # you wish to boot into a different kernel, but I do not require kexec. Disabling it
+ # patches a potential security hole in our system.
+ "kernel.kexec_load_disabled" = true;
+
+ # Borrowed by NixOS/nixpkgs. Since the security module does not explain what those
+ # options do, it is up you to educate yourself dear reader.
+ # See:
+ # - <https://docs.kernel.org/admin-guide/sysctl/vm.html#mmap-rnd-bits>
+ # - <https://docs.kernel.org/admin-guide/sysctl/vm.html#mmap-min-addr>
+ "vm.mmap_rnd_bits" = 32;
+ "vm.mmap_min_addr" = 65536;
+ };
+
+ # https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
+ kernelParams = [
+ # I'm sure we break hibernation in at least 5 other sections of this config, so
+ # let's disable hibernation explicitly. Allowing hibernation makes it possible
+ # to replace the booted kernel with a malicious one, akin to kexec. This helps
+ # us prevent an attack called "Evil Maid" where an attacker with physical access
+ # to the device. P.S. I chose to mention "Evil Maid" specifically because it sounds
+ # funny. Do not think that is the only attack you are vulnerable to.
+ # See: <https://en.wikipedia.org/wiki/Evil_maid_attack>
+ "nohibernate"
+
+ # make stack-based attacks on the kernel harder
+ "randomize_kstack_offset=on"
+
+ # Disable vsyscalls as they are obsolete and have been replaced with vDSO.
+ # vsyscalls are also at fixed addresses in memory, making them a potential
+ # target for ROP attacks
+ # this breaks really old binaries for security
+ "vsyscall=none"
+
+ # reduce most of the exposure of a heap attack to a single cache
+ # Disable slab merging which significantly increases the difficulty of heap
+ # exploitation by preventing overwriting objects from merged caches and by
+ # making it harder to influence slab cache layout
+ "slab_nomerge"
+
+ # Disable debugfs which exposes a lot of sensitive information about the
+ # kernel. Some programs, such as powertop, use this interface to gather
+ # information about the system, but it is not necessary for the system to
+ # actually publish those. I can live without it.
+ "debugfs=off"
+
+ # Sometimes certain kernel exploits will cause what is known as an "oops".
+ # This parameter will cause the kernel to panic on such oopses, thereby
+ # preventing those exploits
+ "oops=panic"
+
+ # Only allow kernel modules that have been signed with a valid key to be
+ # loaded, which increases security by making it much harder to load a
+ # malicious kernel module
+ "module.sig_enforce=1"
+
+ # The kernel lockdown LSM can eliminate many methods that user space code
+ # could abuse to escalate to kernel privileges and extract sensitive
+ # information. This LSM is necessary to implement a clear security boundary
+ # between user space and the kernel
+ # integrity: kernel features that allow userland to modify the running kernel
+ # are disabled
+ # confidentiality: kernel features that allow userland to extract confidential
+ # information from the kernel are also disabled
+ # ArchWiki recommends opting in for "integrity", however since we avoid modifying
+ # running kernel (by the virtue of using NixOS and locking module hot-loading) the
+ # confidentiality mode is a better solution.
+ "lockdown=confidentiality"
+
+ # enable buddy allocator free poisoning
+ # on: memory will befilled with a specific byte pattern
+ # that is unlikely to occur in normal operation.
+ # off (default): page poisoning will be disabled
+ "page_poison=on"
+
+ # performance improvement for direct-mapped memory-side-cache utilization
+ # reduces the predictability of page allocations
+ "page_alloc.shuffle=1"
+
+ # for debugging kernel-level slab issues
+ "slub_debug=FZP"
+
+ # ignore access time (atime) updates on files
+ # except when they coincide with updates to the ctime or mtime
+ "rootflags=noatime"
+
+ # linux security modules
+ "lsm=landlock,lockdown,yama,integrity,apparmor,bpf,tomoyo,selinux"
+
+ # prevent the kernel from blanking plymouth out of the fb
+ "fbcon=nodefer"
+
+ # the format that will be used for integrity audit logs
+ # 0 (default): basic integrity auditing messages
+ # 1: additional integrity auditing messages
+ "integrity_audit=1"
+ ];
+ };
+}
diff --git a/modules/core/security/pam.nix b/modules/core/security/pam.nix
new file mode 100644
index 0000000..b7eb426
--- /dev/null
+++ b/modules/core/security/pam.nix
@@ -0,0 +1,50 @@
+{
+ security = {
+ pam = {
+ loginLimits = [
+ {
+ domain = "@wheel";
+ item = "nofile";
+ type = "soft";
+ value = "524288";
+ }
+ {
+ domain = "@wheel";
+ item = "nofile";
+ type = "hard";
+ value = "1048576";
+ }
+ ];
+
+ services =
+ let
+ ttyAudit = {
+ enable = true;
+ enablePattern = "*";
+ };
+ in
+ {
+ swaylock.text = "auth include login";
+ gtklock.text = "auth include login";
+
+ login = {
+ inherit ttyAudit;
+
+ setLoginUid = true;
+ };
+
+ sshd = {
+ inherit ttyAudit;
+
+ setLoginUid = true;
+ };
+
+ sudo = {
+ inherit ttyAudit;
+
+ setLoginUid = true;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/core/security/pki.nix b/modules/core/security/pki.nix
new file mode 100644
index 0000000..b804fc5
--- /dev/null
+++ b/modules/core/security/pki.nix
@@ -0,0 +1,42 @@
+{ lib, ... }:
+{
+ security.pki = {
+ certificates = lib.mkForce [ ];
+
+ caCertificateBlacklist = [
+ "AC RAIZ FNMT-RCM SERVIDORES SEGUROS"
+ "Autoridad de Certificacion Firmaprofesional CIF A62634068"
+
+ # China Financial Certification Authority
+ "CFCA EV ROOT"
+
+ # Chunghwa Telecom Co., Ltd
+ "ePKI Root Certification Authority"
+ "HiPKI Root CA - G1"
+
+ # Dhimyotis
+ "Certigna"
+ "Certigna Root CA"
+
+ # GUANG DONG CERTIFICATE AUTHORITY
+ "GDCA TrustAUTH R5 ROOT"
+
+ # Hongkong Post
+ "Hongkong Post Root CA 3"
+
+ # iTrusChina Co.,Ltd.
+ "vTrus ECC Root CA"
+ "vTrus Root CA"
+
+ # Krajowa Izba Rozliczeniowa S.A.
+ "SZAFIR ROOT CA2"
+
+ # NetLock Kft.
+ "NetLock Arany (Class Gold) Főtanúsítvány"
+
+ # TAIWAN-CA
+ "TWCA Root Certification Authority"
+ "TWCA Global Root CA"
+ ];
+ };
+}
diff --git a/modules/core/security/polkit.nix b/modules/core/security/polkit.nix
new file mode 100644
index 0000000..786d1a0
--- /dev/null
+++ b/modules/core/security/polkit.nix
@@ -0,0 +1,7 @@
+{ lib, ... }:
+{
+ security.polkit = {
+ enable = true;
+ debug = lib.modules.mkDefault true;
+ };
+}
diff --git a/modules/core/security/sudo.nix b/modules/core/security/sudo.nix
new file mode 100644
index 0000000..6623b71
--- /dev/null
+++ b/modules/core/security/sudo.nix
@@ -0,0 +1,75 @@
+{ pkgs, lib, ... }:
+let
+ inherit (lib.modules) mkForce;
+in
+{
+ security = {
+ sudo-rs.enable = mkForce false;
+
+ sudo = {
+ enable = true;
+ execWheelOnly = mkForce true;
+ wheelNeedsPassword = lib.modules.mkDefault false;
+
+ extraConfig = ''
+ Defaults lecture = never
+ Defaults pwfeedback
+ Defaults env_keep += "EDITOR PATH DISPLAY"
+ Defaults timestamp_timeout = 300
+ '';
+
+ extraRules = [
+ {
+ groups = [ "wheel" ];
+ commands =
+ map
+ (rule: {
+ command = lib.meta.getExe' rule.package rule.command;
+ options = [ "NOPASSWD" ];
+ })
+ (
+ with pkgs;
+ [
+ {
+ package = coreutils;
+ command = "sync";
+ }
+ {
+ package = hdparm;
+ command = "hdparm";
+ }
+ {
+ package = nixos-rebuild;
+ command = "nixos-rebuild";
+ }
+ {
+ package = nvme-cli;
+ command = "nvme";
+ }
+ {
+ package = systemd;
+ command = "poweroff";
+ }
+ {
+ package = systemd;
+ command = "reboot";
+ }
+ {
+ package = systemd;
+ command = "shutdown";
+ }
+ {
+ package = systemd;
+ command = "systemctl";
+ }
+ {
+ package = util-linux;
+ command = "dmesg";
+ }
+ ]
+ );
+ }
+ ];
+ };
+ };
+}
diff --git a/modules/core/software/aagl.nix b/modules/core/software/aagl.nix
new file mode 100644
index 0000000..b164edb
--- /dev/null
+++ b/modules/core/software/aagl.nix
@@ -0,0 +1,9 @@
+{ inputs, ... }:
+let
+ inherit (inputs) aagl;
+in
+{
+ imports = [ aagl.nixosModules.default ];
+ nix.settings = aagl.nixConfig;
+ programs.anime-game-launcher.enable = true;
+}
diff --git a/modules/core/software/access/default.nix b/modules/core/software/access/default.nix
new file mode 100644
index 0000000..7db7629
--- /dev/null
+++ b/modules/core/software/access/default.nix
@@ -0,0 +1,7 @@
+{
+ imports = [
+ ./gnupg.nix
+ ./mosh.nix
+ ./ssh.nix
+ ];
+}
diff --git a/modules/core/software/access/gnupg.nix b/modules/core/software/access/gnupg.nix
new file mode 100644
index 0000000..e60da30
--- /dev/null
+++ b/modules/core/software/access/gnupg.nix
@@ -0,0 +1,18 @@
+{ pkgs, ... }:
+{
+ programs.gnupg.agent = {
+ enable = true;
+ enableSSHSupport = true;
+ pinentryPackage = pkgs.pinentry-curses;
+ enableExtraSocket = true;
+ enableBrowserSocket = true;
+
+ settings = {
+ enable-ssh-support = "";
+ ttyname = "$GPG_TTY";
+ default-cache-ttl = 34560000; # 60
+ max-cache-ttl = 34560000; # 120
+ allow-loopback-pinentry = "";
+ };
+ };
+}
diff --git a/modules/core/software/access/mosh.nix b/modules/core/software/access/mosh.nix
new file mode 100644
index 0000000..c9af5bf
--- /dev/null
+++ b/modules/core/software/access/mosh.nix
@@ -0,0 +1,6 @@
+{
+ programs.mosh = {
+ enable = true;
+ openFirewall = false;
+ };
+}
diff --git a/modules/core/software/access/ssh.nix b/modules/core/software/access/ssh.nix
new file mode 100644
index 0000000..665532f
--- /dev/null
+++ b/modules/core/software/access/ssh.nix
@@ -0,0 +1,39 @@
+{ lib, config, ... }:
+{
+ programs.ssh.startAgent = false;
+ security.pam.sshAgentAuth.enable = true;
+
+ services = {
+ fail2ban.jails.sshd.settings = {
+ enabled = true;
+ filter = "sshd[mode=aggressive]";
+ port = lib.strings.concatStringsSep "," (map toString config.services.openssh.ports);
+ };
+
+ openssh = {
+ enable = true;
+ ports = [ 22 ];
+ openFirewall = false;
+
+ settings = {
+ StreamLocalBindUnlink = "yes";
+ GatewayPorts = "clientspecified";
+
+ KexAlgorithms = [
+ "curve25519-sha256"
+ "diffie-hellman-group16-sha512"
+ "diffie-hellman-group18-sha512"
+ "diffie-hellman-group-exchange-sha256"
+ ];
+
+ Macs = [
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/core/software/boot/default.nix b/modules/core/software/boot/default.nix
new file mode 100644
index 0000000..9fe77a0
--- /dev/null
+++ b/modules/core/software/boot/default.nix
@@ -0,0 +1,30 @@
+{ pkgs, ... }:
+{
+ imports = [
+ ./grub.nix
+ ./systemd-boot.nix
+ ];
+
+ boot = {
+ tmp.cleanOnBoot = true;
+ crashDump.enable = false;
+ consoleLogLevel = 3;
+ kernelPackages = pkgs.linuxPackages_zen;
+ binfmt.emulatedSystems = [ "aarch64-linux" ];
+
+ kernelParams = [
+ "iommu=pt"
+ "threadirqs"
+ ];
+
+ loader = {
+ timeout = 1;
+ generationsDir.copyKernels = true;
+
+ efi = {
+ canTouchEfiVariables = true;
+ efiSysMountPoint = "/boot";
+ };
+ };
+ };
+}
diff --git a/modules/core/software/boot/grub.nix b/modules/core/software/boot/grub.nix
new file mode 100644
index 0000000..3932713
--- /dev/null
+++ b/modules/core/software/boot/grub.nix
@@ -0,0 +1,22 @@
+{ pkgs, ... }:
+{
+ boot.loader.grub = {
+ enable = true;
+ device = "nodev";
+ efiSupport = true;
+ useOSProber = true;
+ memtest86.enable = true;
+ gfxmodeEfi = "1920x1080x32";
+ gfxmodeBios = "1920x1080x32";
+ gfxpayloadBios = "keep";
+ gfxpayloadEfi = "keep";
+ splashMode = "normal";
+
+ theme = pkgs.fetchFromGitHub {
+ owner = "Lxtharia";
+ repo = "minegrub-theme";
+ rev = "193b3a7c3d432f8c6af10adfb465b781091f56b3";
+ sha256 = "1bvkfmjzbk7pfisvmyw5gjmcqj9dab7gwd5nmvi8gs4vk72bl2ap";
+ };
+ };
+}
diff --git a/modules/core/software/boot/systemd-boot.nix b/modules/core/software/boot/systemd-boot.nix
new file mode 100644
index 0000000..b51a896
--- /dev/null
+++ b/modules/core/software/boot/systemd-boot.nix
@@ -0,0 +1,9 @@
+{
+ boot.loader.systemd-boot = {
+ enable = false;
+ editor = true;
+ consoleMode = "max";
+ memtest86.enable = true;
+ netbootxyz.enable = true;
+ };
+}
diff --git a/modules/core/software/default.nix b/modules/core/software/default.nix
new file mode 100644
index 0000000..f0de576
--- /dev/null
+++ b/modules/core/software/default.nix
@@ -0,0 +1,40 @@
+{ pkgs, ... }:
+{
+ imports = [
+ ./access
+ ./boot
+ ./desktop
+ ./multimedia
+ ./services
+ ./aagl.nix
+ ./encryption.nix
+ ./gaming.nix
+ ./input.nix
+ ./locale.nix
+ ./programs.nix
+ ./shell.nix
+ ./systemd.nix
+ ./users.nix
+ ];
+
+ system = {
+ autoUpgrade = {
+ enable = false;
+ allowReboot = false;
+ };
+
+ switch = {
+ enable = false;
+ enableNg = true;
+ };
+ };
+
+ environment.enableAllTerminfo = true;
+
+ console = {
+ earlySetup = true;
+ keyMap = "us";
+ font = "ter-v16n";
+ packages = [ pkgs.terminus_font ];
+ };
+}
diff --git a/modules/core/software/desktop/default.nix b/modules/core/software/desktop/default.nix
new file mode 100644
index 0000000..bd2c811
--- /dev/null
+++ b/modules/core/software/desktop/default.nix
@@ -0,0 +1,6 @@
+{
+ imports = [
+ ./gtk.nix
+ ./xdg-portal.nix
+ ];
+}
diff --git a/modules/core/software/desktop/gtk.nix b/modules/core/software/desktop/gtk.nix
new file mode 100644
index 0000000..4357e75
--- /dev/null
+++ b/modules/core/software/desktop/gtk.nix
@@ -0,0 +1,8 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = with pkgs; [
+ gtk2
+ gtk3
+ gtk4
+ ];
+}
diff --git a/modules/core/software/desktop/xdg-portal.nix b/modules/core/software/desktop/xdg-portal.nix
new file mode 100644
index 0000000..72bcb97
--- /dev/null
+++ b/modules/core/software/desktop/xdg-portal.nix
@@ -0,0 +1,15 @@
+{ pkgs, ... }:
+{
+ xdg.portal = {
+ enable = true;
+ config.common.default = "*";
+ # wlr.enable = true;
+ # xdgOpenUsePortal = true;
+
+ extraPortals = with pkgs; [
+ xdg-desktop-portal-wlr
+ xdg-desktop-portal-gtk
+ xdg-desktop-portal-gnome
+ ];
+ };
+}
diff --git a/modules/core/software/encryption.nix b/modules/core/software/encryption.nix
new file mode 100644
index 0000000..53a24bb
--- /dev/null
+++ b/modules/core/software/encryption.nix
@@ -0,0 +1,16 @@
+{
+ boot = {
+ initrd.availableKernelModules = [
+ # "aesni_intel"
+ # "cryptd"
+ "usb_storage"
+ ];
+
+ # <https://wiki.archlinux.org/title/Dm-crypt/System_configuration#Timeout>
+ kernelParams = [
+ "luks.options=timeout=0"
+ "rd.luks.options=timeout=0"
+ "rootflags=x-systemd.device-timeout=0"
+ ];
+ };
+}
diff --git a/modules/core/software/gaming.nix b/modules/core/software/gaming.nix
new file mode 100644
index 0000000..675aee9
--- /dev/null
+++ b/modules/core/software/gaming.nix
@@ -0,0 +1,38 @@
+{ pkgs, ... }:
+{
+ programs = {
+ steam =
+ let
+ openFirewall = false;
+ in
+ {
+ enable = true;
+ remotePlay.openFirewall = openFirewall;
+ localNetworkGameTransfers.openFirewall = openFirewall;
+ dedicatedServer.openFirewall = openFirewall;
+ extest.enable = true;
+ # gamescopeSession.enable = true;
+
+ package = pkgs.steam-small.override {
+ extraEnv = {
+ MANGOHUD = true;
+ # SDL_VIDEODRIVER = "x11";
+ };
+ };
+
+ extraCompatPackages = [ pkgs.proton-ge-bin.steamcompattool ];
+ };
+
+ gamemode = {
+ enable = true;
+ enableRenice = false;
+ };
+
+ gamescope.enable = true;
+ };
+
+ environment.systemPackages = with pkgs; [
+ mangohud
+ steamtinkerlaunch
+ ];
+}
diff --git a/modules/core/software/input.nix b/modules/core/software/input.nix
new file mode 100644
index 0000000..2d9f651
--- /dev/null
+++ b/modules/core/software/input.nix
@@ -0,0 +1,25 @@
+{ pkgs, secrets, ... }:
+{
+ i18n = {
+ defaultLocale = secrets.i18n.locale;
+
+ inputMethod = {
+ enable = true;
+ type = "fcitx5";
+
+ fcitx5 = {
+ waylandFrontend = true;
+
+ addons = with pkgs; [
+ fcitx5-configtool
+ fcitx5-gtk
+ fcitx5-hangul
+ fcitx5-mozc
+ fcitx5-rime
+ rime-data
+ catppuccin-fcitx5
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/core/software/locale.nix b/modules/core/software/locale.nix
new file mode 100644
index 0000000..8ebd49b
--- /dev/null
+++ b/modules/core/software/locale.nix
@@ -0,0 +1,9 @@
+{ secrets, ... }:
+{
+ location.provider = "geoclue2";
+
+ time = {
+ timeZone = "${secrets.i18n.timezone}";
+ hardwareClockInLocalTime = false;
+ };
+}
diff --git a/modules/core/software/multimedia/audio/default.nix b/modules/core/software/multimedia/audio/default.nix
new file mode 100644
index 0000000..f4e7f0a
--- /dev/null
+++ b/modules/core/software/multimedia/audio/default.nix
@@ -0,0 +1,6 @@
+{
+ imports = [
+ ./pipewire.nix
+ # ./wireplumber.nix
+ ];
+}
diff --git a/modules/core/software/multimedia/audio/pipewire.nix b/modules/core/software/multimedia/audio/pipewire.nix
new file mode 100644
index 0000000..2824176
--- /dev/null
+++ b/modules/core/software/multimedia/audio/pipewire.nix
@@ -0,0 +1,164 @@
+# { lib, ... }:
+# let
+# inherit (lib.modules) mkBefore;
+# inherit (lib.lists) singleton;
+# inherit (builtins) toString;
+# mapOptionDefault = lib.attrsets.mapAttrs (_: lib.modules.mkOptionDefault);
+# quantum = toString 64;
+# rate = toString 48000;
+# qr = "${quantum}/${rate}";
+# in
+{
+ services.pipewire = {
+ enable = true;
+ wireplumber.enable = true;
+ jack.enable = true;
+ pulse.enable = true;
+ audio.enable = true;
+
+ alsa = {
+ enable = true;
+ support32Bit = true;
+ };
+
+ extraConfig = {
+ pipewire = {
+ "10-logging" = {
+ "context.properties"."log.level" = 3;
+ };
+
+ # "10-defaults" = {
+ # "context.properties" = mapOptionDefault {
+ # "clock.power-of-two-quantum" = true;
+ # "core.daemon" = true;
+ # "core.name" = "pipewire-0";
+ # "link.max-buffers" = 16;
+ # "settings.check-quantum" = true;
+ # };
+
+ # "context.spa-libs" = mapOptionDefault {
+ # "audio.convert.*" = "audioconvert/libspa-audioconvert";
+ # "avb.*" = "avb/libspa-avb";
+ # "api.alsa.*" = "alsa/libspa-alsa";
+ # "api.v4l2.*" = "v4l2/libspa-v4l2";
+ # "api.libcamera.*" = "libcamera/libspa-libcamera";
+ # "api.bluez5.*" = "bluez5/libspa-bluez5";
+ # "api.vulkan.*" = "vulkan/libspa-vulkan";
+ # "api.jack.*" = "jack/libspa-jack";
+ # "support.*" = "support/libspa-support";
+ # "video.convert.*" = "videoconvert/libspa-videoconvert";
+ # };
+ # };
+ };
+
+ # pipewire-pulse = {
+ # "10-defaults" = {
+ # "context.spa-libs" = mapOptionDefault {
+ # "audio.convert.*" = "audioconvert/libspa-audioconvert";
+ # "support.*" = "support/libspa-support";
+ # };
+
+ # "pulse.cmd" = mkBefore [
+ # {
+ # cmd = "load-module";
+ # args = "module-always-sink";
+ # flags = [ ];
+ # }
+ # ];
+
+ # "pulse.properties" = {
+ # "server.address" = mkBefore [ "unix:native" ];
+ # };
+
+ # "pulse.rules" = mkBefore [
+ # {
+ # matches = [
+ # { "application.process.binary" = "teams"; }
+ # { "application.process.binary" = "teams-insiders"; }
+ # { "application.process.binary" = "skypeforlinux"; }
+ # ];
+
+ # actions.quirks = [ "force-s16-info" ];
+ # }
+ # {
+ # matches = singleton { "application.process.binary" = "firefox"; };
+ # actions.quirks = [ "remove-capture-dont-move" ];
+ # }
+ # {
+ # matches = singleton { "application.name" = "~speech-dispatcher*"; };
+
+ # actions = {
+ # update-props = {
+ # "pulse.min.req" = "1024/48000"; # 21 milliseconds
+ # "pulse.min.quantum " = "1024/48000"; # 21 milliseconds
+ # };
+ # };
+ # }
+ # ];
+ # };
+ # };
+
+ # pipewire."92-low-latency" = {
+ # "context.properties" = {
+ # "default.clock.rate" = rate;
+ # "default.clock.quantum" = quantum;
+ # "default.clock.min-quantum" = quantum;
+ # "default.clock.max-quantum" = quantum;
+ # "default.clock.allowed-rates" = [ rate ];
+ # };
+
+ # # "context.modules" = [
+ # # {
+ # # name = "libpipewire-module-rtkit";
+
+ # # flags = [
+ # # "ifexists"
+ # # "nofail"
+ # # ];
+
+ # # args = {
+ # # "nice.level" = -15;
+ # # "rt.prio" = 90;
+ # # "rt.time.soft" = 200000;
+ # # "rt.time.hard" = 200000;
+ # # };
+ # # }
+ # # {
+ # # name = "libpipewire-module-protocol-pulse";
+
+ # # args = {
+ # # "server.address" = [ "unix:native" ];
+ # # "pulse.min.quantum" = qr;
+ # # "pulse.min.req" = qr;
+ # # "pulse.min.frag" = qr;
+ # # };
+ # # }
+ # # ];
+
+ # "stream.properties" = {
+ # "node.latency" = qr;
+ # "resample.quality" = 1;
+ # };
+ # };
+
+ # pipewire-pulse."92-low-latency" = {
+ # "context.modules" = singleton {
+ # name = "libpipewire-module-protocol-pulse";
+
+ # args = {
+ # "pulse.min.req" = qr;
+ # "pulse.default.req" = qr;
+ # "pulse.max.req" = qr;
+ # "pulse.min.quantum" = qr;
+ # "pulse.max.quantum" = qr;
+ # };
+ # };
+
+ # "stream.properties" = {
+ # "node.latency" = qr;
+ # "resample.quality" = 4;
+ # };
+ # };
+ };
+ };
+}
diff --git a/modules/core/software/multimedia/audio/wireplumber.nix b/modules/core/software/multimedia/audio/wireplumber.nix
new file mode 100644
index 0000000..970396f
--- /dev/null
+++ b/modules/core/software/multimedia/audio/wireplumber.nix
@@ -0,0 +1,42 @@
+let
+ rate = builtins.toString 48000;
+in
+{
+ services.pipewire.wireplumber = {
+ enable = true;
+
+ extraConfig = {
+ "10-log-level-debug" = {
+ "context.properties"."log.level" = "D";
+ };
+
+ "10-default-volume" = {
+ "wireplumber.settings"."device.routes.default-sink-volume" = 1.0;
+ };
+
+ "92-low-latency" = {
+ "monitor.alsa.rules" = [
+ {
+ matches = [
+ { "device.name" = "~alsa_card.*"; }
+ { "node.name" = "~alsa_output.*"; }
+ ];
+
+ actions.update-props = {
+ "node.description" = "ALSA Low Latency Output";
+ "audio.rate" = rate;
+ "audio.format" = "S32LE";
+ "resample.quality" = 4;
+ "resample.disable" = false;
+ "session.suspend-timeout-seconds" = 0;
+ "api.alsa.period-size" = 2;
+ "api.alsa.headroom" = 128;
+ "api.alsa.period-num" = 2;
+ "api.alsa.disable-batch" = false;
+ };
+ }
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/core/software/multimedia/default.nix b/modules/core/software/multimedia/default.nix
new file mode 100644
index 0000000..7bf261a
--- /dev/null
+++ b/modules/core/software/multimedia/default.nix
@@ -0,0 +1,6 @@
+{
+ imports = [
+ ./audio
+ ./video
+ ];
+}
diff --git a/modules/core/software/multimedia/video/default.nix b/modules/core/software/multimedia/video/default.nix
new file mode 100644
index 0000000..31cdfd5
--- /dev/null
+++ b/modules/core/software/multimedia/video/default.nix
@@ -0,0 +1,11 @@
+{ pkgs, ... }:
+{
+ imports = [
+ ./graphics.nix
+ ./libva.nix
+ ./nvidia.nix
+ ./vulkan.nix
+ ];
+
+ environment.systemPackages = [ pkgs.mediastreamer-openh264 ];
+}
diff --git a/modules/core/software/multimedia/video/graphics.nix b/modules/core/software/multimedia/video/graphics.nix
new file mode 100644
index 0000000..13da295
--- /dev/null
+++ b/modules/core/software/multimedia/video/graphics.nix
@@ -0,0 +1,21 @@
+{ pkgs, ... }:
+{
+ hardware.graphics = {
+ enable = true;
+ enable32Bit = true;
+
+ extraPackages = with pkgs; [
+ nvidia-vaapi-driver
+ vaapiVdpau
+ libvdpau-va-gl
+ ];
+
+ extraPackages32 = with pkgs; [
+ nvidia-vaapi-driver
+ vaapiVdpau
+ libvdpau-va-gl
+ ];
+ };
+
+ environment.systemPackages = [ pkgs.mesa ];
+}
diff --git a/modules/core/software/multimedia/video/libva.nix b/modules/core/software/multimedia/video/libva.nix
new file mode 100644
index 0000000..d420495
--- /dev/null
+++ b/modules/core/software/multimedia/video/libva.nix
@@ -0,0 +1,7 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = with pkgs; [
+ libva
+ libva-utils
+ ];
+}
diff --git a/modules/core/software/multimedia/video/nvidia.nix b/modules/core/software/multimedia/video/nvidia.nix
new file mode 100644
index 0000000..c133bc2
--- /dev/null
+++ b/modules/core/software/multimedia/video/nvidia.nix
@@ -0,0 +1,38 @@
+{ pkgs, config, ... }:
+{
+ environment = {
+ systemPackages = with pkgs; [
+ nvidia-container-toolkit
+ nvidia-docker
+ ];
+
+ shellAliases.nvidia-settings = "nvidia-settings --config='$XDG_CONFIG_HOME'/nvidia/settings";
+ };
+
+ boot = {
+ blacklistedKernelModules = [ "nouveau" ];
+
+ kernelParams = [
+ "nvidia-drm.fbdev=1"
+ "nvidia-drm.modeset=1"
+ "nvidia.NVreg_PreserveVideoMemoryAllocations=1"
+ ];
+ };
+
+ hardware = {
+ nvidia-container-toolkit.enable = true;
+
+ nvidia = {
+ modesetting.enable = true;
+ open = false;
+ nvidiaSettings = true;
+ package = config.boot.kernelPackages.nvidiaPackages.production;
+ forceFullCompositionPipeline = true;
+
+ powerManagement = {
+ enable = true;
+ finegrained = false;
+ };
+ };
+ };
+}
diff --git a/modules/core/software/multimedia/video/vulkan.nix b/modules/core/software/multimedia/video/vulkan.nix
new file mode 100644
index 0000000..be37e0e
--- /dev/null
+++ b/modules/core/software/multimedia/video/vulkan.nix
@@ -0,0 +1,9 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = with pkgs; [
+ vulkan-loader
+ vulkan-validation-layers
+ vulkan-tools
+ vulkan-extension-layer
+ ];
+}
diff --git a/modules/core/software/programs.nix b/modules/core/software/programs.nix
new file mode 100644
index 0000000..a1025fb
--- /dev/null
+++ b/modules/core/software/programs.nix
@@ -0,0 +1,22 @@
+{ pkgs, ... }:
+{
+ programs = {
+ fish.enable = true;
+ mtr.enable = true;
+ dconf.enable = true;
+ ccache.enable = true;
+ fuse.userAllowOther = true;
+
+ bash.interactiveShellInit = ''
+ export HISTFILE="$XDG_STATE_HOME/bash/history"
+ '';
+ };
+
+ environment.systemPackages = with pkgs; [
+ vim
+ wget
+ git
+ pinentry
+ runc
+ ];
+}
diff --git a/modules/core/software/services/adb.nix b/modules/core/software/services/adb.nix
new file mode 100644
index 0000000..d106ead
--- /dev/null
+++ b/modules/core/software/services/adb.nix
@@ -0,0 +1,12 @@
+{ pkgs, ... }:
+{
+ programs.adb.enable = true;
+
+ services.udev = {
+ packages = [ pkgs.android-udev-rules ];
+
+ extraRules = ''
+ SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", MODE="0666", GROUP="adbusers"
+ '';
+ };
+}
diff --git a/modules/core/software/services/ananicy.nix b/modules/core/software/services/ananicy.nix
new file mode 100644
index 0000000..bdc9bbd
--- /dev/null
+++ b/modules/core/software/services/ananicy.nix
@@ -0,0 +1,8 @@
+{ pkgs, ... }:
+{
+ services.ananicy = {
+ enable = false;
+ package = pkgs.ananicy-cpp;
+ rulesProvider = pkgs.ananicy-rules-cachyos;
+ };
+}
diff --git a/modules/core/software/services/dbus.nix b/modules/core/software/services/dbus.nix
new file mode 100644
index 0000000..8b25bf9
--- /dev/null
+++ b/modules/core/software/services/dbus.nix
@@ -0,0 +1,15 @@
+{ pkgs, ... }:
+{
+ services.dbus = {
+ enable = true;
+ implementation = "broker";
+
+ packages = with pkgs; [
+ dconf
+ gcr
+ udisks2
+ # flatpak
+ # xdg-desktop-portal
+ ];
+ };
+}
diff --git a/modules/core/software/services/default.nix b/modules/core/software/services/default.nix
new file mode 100644
index 0000000..4b9ccf6
--- /dev/null
+++ b/modules/core/software/services/default.nix
@@ -0,0 +1,24 @@
+{ pkgs, ... }:
+{
+ imports = [
+ # ./adb.nix
+ ./ananicy.nix
+ ./dbus.nix
+ ./libinput.nix
+ ./logrotate.nix
+ ./ollama.nix
+ # ./printing.nix
+ ./xserver.nix
+ ];
+
+ services = {
+ printing.enable = false;
+ gnome.gnome-keyring.enable = true;
+ fstrim.enable = false;
+ gvfs.enable = true;
+ udev.packages = with pkgs; [ pkgs.logitech-udev-rules ];
+ thermald.enable = true;
+ irqbalance.enable = true;
+ gpm.enable = true;
+ };
+}
diff --git a/modules/core/software/services/libinput.nix b/modules/core/software/services/libinput.nix
new file mode 100644
index 0000000..643f814
--- /dev/null
+++ b/modules/core/software/services/libinput.nix
@@ -0,0 +1,13 @@
+{
+ services.libinput = {
+ enable = true;
+
+ mouse = {
+ accelProfile = "flat";
+ };
+
+ touchpad = {
+ accelProfile = "flat";
+ };
+ };
+}
diff --git a/modules/core/software/services/logrotate.nix b/modules/core/software/services/logrotate.nix
new file mode 100644
index 0000000..2dedf2e
--- /dev/null
+++ b/modules/core/software/services/logrotate.nix
@@ -0,0 +1,24 @@
+{ pkgs, lib, ... }:
+{
+ services.logrotate.settings = {
+ "/var/log/audit/audit.log" = { };
+
+ header = {
+ global = true;
+ dateext = true;
+ dateformat = "-%Y-%m-%d";
+ nomail = true;
+ missingok = true;
+ copytruncate = true;
+ priority = 1;
+ frequency = "daily";
+ rotate = 7;
+ minage = 1;
+ compress = true;
+ compresscmd = "${lib.getExe' pkgs.zstd "zstd"}";
+ compressoptions = " -Xcompression-level 10";
+ compressext = "zst";
+ uncompresscmd = "${lib.getExe' pkgs.zstd "unzstd"}";
+ };
+ };
+}
diff --git a/modules/core/software/services/ollama.nix b/modules/core/software/services/ollama.nix
new file mode 100644
index 0000000..d737250
--- /dev/null
+++ b/modules/core/software/services/ollama.nix
@@ -0,0 +1,6 @@
+{
+ services.ollama = {
+ enable = true;
+ acceleration = "cuda";
+ };
+}
diff --git a/modules/core/software/services/printing.nix b/modules/core/software/services/printing.nix
new file mode 100644
index 0000000..f7a38de
--- /dev/null
+++ b/modules/core/software/services/printing.nix
@@ -0,0 +1,19 @@
+{ pkgs, ... }:
+{
+ services = {
+ printing = {
+ enable = true;
+
+ drivers = with pkgs; [
+ gutenprint
+ hplip
+ ];
+ };
+
+ avahi = {
+ enable = true;
+ nssmdns4 = true;
+ openFirewall = true;
+ };
+ };
+}
diff --git a/modules/core/software/services/xserver.nix b/modules/core/software/services/xserver.nix
new file mode 100644
index 0000000..f1833a4
--- /dev/null
+++ b/modules/core/software/services/xserver.nix
@@ -0,0 +1,10 @@
+{
+ services.xserver = {
+ xkb = {
+ layout = "us";
+ options = "caps:escape";
+ };
+
+ videoDrivers = [ "nvidia" ];
+ };
+}
diff --git a/modules/core/software/shell.nix b/modules/core/software/shell.nix
new file mode 100644
index 0000000..0b3508f
--- /dev/null
+++ b/modules/core/software/shell.nix
@@ -0,0 +1,7 @@
+{ pkgs, ... }:
+{
+ environment = with pkgs; {
+ binsh = "${dash}/bin/dash";
+ shells = [ fish ];
+ };
+}
diff --git a/modules/core/software/systemd.nix b/modules/core/software/systemd.nix
new file mode 100644
index 0000000..c475d96
--- /dev/null
+++ b/modules/core/software/systemd.nix
@@ -0,0 +1,11 @@
+{ pkgs, ... }:
+{
+ boot.initrd.systemd.enable = true;
+
+ systemd.services.containerd.path = with pkgs; [
+ containerd
+ runc
+ iptables
+ nvidia-docker
+ ];
+}
diff --git a/modules/core/software/users.nix b/modules/core/software/users.nix
new file mode 100644
index 0000000..ab3fe03
--- /dev/null
+++ b/modules/core/software/users.nix
@@ -0,0 +1,46 @@
+{ pkgs, secrets, ... }:
+let
+ initialHashedPassword = secrets.initial_hashed_password;
+in
+{
+ users = {
+ mutableUsers = false;
+
+ users = {
+ root = {
+ inherit initialHashedPassword;
+
+ shell = pkgs.bash;
+ };
+
+ ebisu = {
+ inherit initialHashedPassword;
+
+ isNormalUser = true;
+ shell = pkgs.fish;
+
+ extraGroups = [
+ "wheel"
+ "systemd-journal"
+ "audio"
+ "video"
+ "input"
+ "plugdev"
+ "lp"
+ "tss"
+ "power"
+ "nix"
+ "network"
+ "networkmanager"
+ "wireshark"
+ "mysql"
+ "docker"
+ "podman"
+ "git"
+ "libvirtd"
+ "kvm"
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/core/variables/default.nix b/modules/core/variables/default.nix
new file mode 100644
index 0000000..8315ceb
--- /dev/null
+++ b/modules/core/variables/default.nix
@@ -0,0 +1,20 @@
+{
+ imports = [
+ ./electron.nix
+ ./fcitx.nix
+ ./mozilla.nix
+ ./nvidia.nix
+ ./opengl.nix
+ ./qt.nix
+ ./wayland.nix
+ ./wlroots.nix
+ ];
+
+ environment.variables = {
+ _JAVA_AWT_WM_NONREPARENTING = "1";
+ PROTON_ENABLE_NGX_UPDATER = "1";
+ GTK_USE_PORTAL = "1";
+ DIRENV_LOG_FORMAT = "";
+ SSH_AUTH_SOCK = "/run/user/1000/keyring/ssh";
+ };
+}
diff --git a/modules/core/variables/electron.nix b/modules/core/variables/electron.nix
new file mode 100644
index 0000000..62e7c72
--- /dev/null
+++ b/modules/core/variables/electron.nix
@@ -0,0 +1,7 @@
+{
+ environment.variables = {
+ # ELECTRON_OZONE_PLATFORM_HINT = "auto";
+ # OZONE_PLATFORM = "wayland";
+ NIXOS_OZONE_WL = "1";
+ };
+}
diff --git a/modules/core/variables/fcitx.nix b/modules/core/variables/fcitx.nix
new file mode 100644
index 0000000..0ac550f
--- /dev/null
+++ b/modules/core/variables/fcitx.nix
@@ -0,0 +1,13 @@
+{
+ environment.variables = {
+ # https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland
+ QT_IM_MODULE = "fcitx";
+ XMODIFIERS = "@im=fcitx";
+ # GTK_IM_MODULE = "wayland";
+ # GTK_IM_MODULE = "fcitx";
+ SDL_IM_MODULE = "fcitx";
+ GLFW_IM_MODULE = "ibus";
+ INPUT_METHOD = "fcitx";
+ CUDA_CACHE_PATH = "$XDG_CACHE_HOME/nv";
+ };
+}
diff --git a/modules/core/variables/mozilla.nix b/modules/core/variables/mozilla.nix
new file mode 100644
index 0000000..e85d27c
--- /dev/null
+++ b/modules/core/variables/mozilla.nix
@@ -0,0 +1,6 @@
+{
+ environment.variables = {
+ MOZ_ENABLE_WAYLAND = "1";
+ MOZ_DISABLE_RDD_SANDBOX = "1";
+ };
+}
diff --git a/modules/core/variables/nvidia.nix b/modules/core/variables/nvidia.nix
new file mode 100644
index 0000000..3d50fdf
--- /dev/null
+++ b/modules/core/variables/nvidia.nix
@@ -0,0 +1,12 @@
+{ pkgs, ... }:
+{
+ environment.variables = {
+ LIBVA_DRIVER_NAME = "nvidia";
+ __GLX_VENDOR_LIBRARY_NAME = "nvidia";
+ GBM_BACKEND = "nvidia-drm";
+ __VK_LAYER_NV_optimus = "NVIDIA_only";
+ __NV_PRIME_RENDER_OFFLOAD = "1";
+ NVD_BACKEND = "direct";
+ CUDA_PATH = "${pkgs.cudatoolkit}";
+ };
+}
diff --git a/modules/core/variables/opengl.nix b/modules/core/variables/opengl.nix
new file mode 100644
index 0000000..1edce45
--- /dev/null
+++ b/modules/core/variables/opengl.nix
@@ -0,0 +1,7 @@
+{
+ environment.variables = {
+ __GL_GSYNC_ALLOWED = "1";
+ __GL_VRR_ALLOWED = "0";
+ __GL_MaxFramesAllowed = "1";
+ };
+}
diff --git a/modules/core/variables/qt.nix b/modules/core/variables/qt.nix
new file mode 100644
index 0000000..cedf6a0
--- /dev/null
+++ b/modules/core/variables/qt.nix
@@ -0,0 +1,11 @@
+{
+ environment.variables = {
+ QT_AUTO_SCREEN_SCALE_FACTOR = "1";
+ QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
+ QT_QPA_PLATFORM = "wayland;xcb";
+ DISABLE_QT5_COMPAT = "0";
+ DISABLE_QT_COMPAT = "0";
+ QT_QPA_PLATFORMTHEME = "qt5ct";
+ # QT_STYLE_OVERRIDE = "kvantum";
+ };
+}
diff --git a/modules/core/variables/wayland.nix b/modules/core/variables/wayland.nix
new file mode 100644
index 0000000..ee21d52
--- /dev/null
+++ b/modules/core/variables/wayland.nix
@@ -0,0 +1,10 @@
+{
+ environment.variables = {
+ GDK_BACKEND = "wayland,x11,*";
+ SDL_VIDEODRIVER = "wayland";
+ CLUTTER_BACKEND = "wayland";
+ XWAYLAND_NO_GLAMOR = "0"; # Gamescope
+ ANKI_WAYLAND = "1";
+ XDG_SESSION_TYPE = "wayland";
+ };
+}
diff --git a/modules/core/variables/wlroots.nix b/modules/core/variables/wlroots.nix
new file mode 100644
index 0000000..25aaf4d
--- /dev/null
+++ b/modules/core/variables/wlroots.nix
@@ -0,0 +1,12 @@
+{
+ environment.variables = {
+ WLR_NO_HARDWARE_CURSORS = "1";
+ WLR_DRM_NO_ATOMIC = "1";
+ WLR_USE_LIBINPUT = "1";
+ WLR_RENDERER_ALLOW_SOFTWARE = "1";
+ WLR_DRM_DEVICES = "/dev/dri/card0";
+ WLR_EGL_NO_MODIFIERS = "1";
+ WLR_BACKEND = "vulkan";
+ WLR_RENDERER = "vulkan";
+ };
+}
diff --git a/modules/core/virtualisation/default.nix b/modules/core/virtualisation/default.nix
new file mode 100644
index 0000000..97aa4b9
--- /dev/null
+++ b/modules/core/virtualisation/default.nix
@@ -0,0 +1,14 @@
+{
+ imports = [
+ ./docker.nix
+ ./libvirtd.nix
+ ./qemu.nix
+ ];
+
+ programs.extra-container.enable = true;
+
+ virtualisation = {
+ kvmgt.enable = true;
+ spiceUSBRedirection.enable = true;
+ };
+}
diff --git a/modules/core/virtualisation/docker.nix b/modules/core/virtualisation/docker.nix
new file mode 100644
index 0000000..c35beb6
--- /dev/null
+++ b/modules/core/virtualisation/docker.nix
@@ -0,0 +1,32 @@
+{ lib, ... }:
+{
+ virtualisation.docker = {
+ enable = true;
+ storageDriver = "overlay2";
+ enableOnBoot = false;
+ liveRestore = true;
+ enableNvidia = lib.mkForce true;
+
+ daemon.settings = {
+ default-runtime = "nvidia";
+ experimental = true;
+ iptables = false;
+ };
+
+ autoPrune = {
+ enable = true;
+ dates = "daily";
+ };
+
+ rootless = {
+ enable = false;
+ setSocketVariable = true;
+
+ daemon.settings = {
+ default-runtime = "nvidia";
+ experimental = true;
+ iptables = false;
+ };
+ };
+ };
+}
diff --git a/modules/core/virtualisation/libvirtd.nix b/modules/core/virtualisation/libvirtd.nix
new file mode 100644
index 0000000..556135b
--- /dev/null
+++ b/modules/core/virtualisation/libvirtd.nix
@@ -0,0 +1,15 @@
+{ pkgs, ... }:
+{
+ boot.extraModprobeConfig = "options kvm_intel nested=1";
+
+ environment.systemPackages = with pkgs; [
+ virt-manager
+ virt-viewer
+ ];
+
+ virtualisation.libvirtd = {
+ enable = true;
+ onBoot = "ignore";
+ onShutdown = "shutdown";
+ };
+}
diff --git a/modules/core/virtualisation/qemu.nix b/modules/core/virtualisation/qemu.nix
new file mode 100644
index 0000000..849ead1
--- /dev/null
+++ b/modules/core/virtualisation/qemu.nix
@@ -0,0 +1,45 @@
+{ pkgs, ... }:
+{
+ environment.systemPackages = with pkgs; [
+ qemu_kvm
+ qemu
+ ];
+
+ hardware.pulseaudio.extraConfig = ''
+ load-module module-native-protocol-unix auth-group=qemu-libvirtd socket=/tmp/pulse-socket
+ '';
+
+ boot.kernelModules = [ "vfio-pci" ];
+
+ networking.firewall.trustedInterfaces = [
+ "virbr0"
+ "br0"
+ ];
+
+ services.udev.extraRules = ''
+ SUBSYSTEM=="vfio", OWNER="root", GROUP="kvm"
+ '';
+
+ virtualisation.libvirtd.qemu = {
+ package = pkgs.qemu_kvm;
+ runAsRoot = true;
+ swtpm.enable = true;
+
+ ovmf = {
+ enable = true;
+
+ packages = [
+ (pkgs.OVMFFull.override {
+ secureBoot = true;
+ tpmSupport = true;
+ }).fd
+ ];
+ };
+
+ verbatimConfig = ''
+ namespaces = []
+
+ dynamic_ownership = 0
+ '';
+ };
+}