From a05e0614c1bb75f77717a943dc4ac75a0cca4652 Mon Sep 17 00:00:00 2001 From: Preston Pan Date: Sun, 1 Mar 2026 23:51:02 -0800 Subject: add everything; add CI --- .pre-commit-config.yaml | 1 + config/nix.org | 1064 ++++++++++++++++++++--------------- config/result | 1 + config/spontaneity.qcow2 | Bin 0 -> 23330816 bytes config/vm-boot.log | 26 + nix/flake.nix | 217 ++++--- nix/modules/cgit.nix | 17 +- nix/modules/conduit.nix | 183 +++++- nix/modules/configuration.nix | 391 ++++++++----- nix/modules/default.nix | 64 ++- nix/modules/git-daemon.nix | 3 + nix/modules/gitolite.nix | 8 + nix/modules/gotosocial.nix | 2 +- nix/modules/home/default.nix | 334 +++++------ nix/modules/home/gtk.nix | 38 +- nix/modules/home/pantalaimon.nix | 2 +- nix/modules/home/secrets.nix | 45 +- nix/modules/home/user.nix | 187 +++--- nix/modules/i2pd.nix | 8 +- nix/modules/icecast.nix | 26 +- nix/modules/maddy.nix | 164 +++++- nix/modules/nginx.nix | 248 ++------ nix/modules/ngircd.nix | 37 +- nix/modules/ntfy-sh.nix | 41 +- nix/modules/ollama.nix | 23 +- nix/modules/secrets.nix | 210 ++++--- nix/modules/ssh.nix | 7 +- nix/modules/xserver.nix | 24 +- nix/spontaneity.qcow2 | Bin 0 -> 21954560 bytes nix/systems/affinity/default.nix | 6 - nix/systems/affinity/home.nix | 3 - nix/systems/continuity/default.nix | 1 + nix/systems/continuity/home.nix | 1 - nix/systems/rpi-zero/default.nix | 1 - nix/systems/spontaneity/default.nix | 169 +----- nix/systems/spontaneity/home.nix | 1 - nix/vm-boot.log | 26 + 37 files changed, 2017 insertions(+), 1562 deletions(-) create mode 120000 .pre-commit-config.yaml create mode 120000 config/result create mode 100644 config/spontaneity.qcow2 create mode 100644 config/vm-boot.log create mode 100644 nix/modules/gitolite.nix create mode 100644 nix/spontaneity.qcow2 create mode 100644 nix/vm-boot.log diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 120000 index 0000000..c126ff6 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1 @@ +/nix/store/56zq1myp4b1cr3jddc927hg6j1p64hks-pre-commit-config.json \ No newline at end of file diff --git a/config/nix.org b/config/nix.org index ca4bec7..555fbe6 100644 --- a/config/nix.org +++ b/config/nix.org @@ -111,6 +111,7 @@ and now for the main flake: deep-research, impermanence, nixpak, + git-hooks, ... } @attrs: @@ -178,8 +179,34 @@ and now for the main flake: name = "${hostname}"; value = self.nixosConfigurations."${hostname}".config.monorepo.vars.diskoSpec; }); + + pre-commit-check = git-hooks.lib.${system}.run { + src = ./.; + hooks = { + # 1. Formatting + nixpkgs-fmt.enable = false; + + # 2. Linting + statix.enable = true; + deadnix.enable = true; + + # 3. Custom VM Boot Check (The "Integration" part) + # This runs the build-vm derivation to ensure it compiles + vm-build-check = { + enable = true; + name = "vps-vm-build"; + description = "Ensure VPS configuration is buildable as a VM"; + entry = "nix build .#nixosConfigurations.vps.config.system.build.vm --no-link"; + pass_filenames = false; + }; + }; + }; in { + checks."${system}" = { + inherit pre-commit-check; + }; + nixosConfigurations = builtins.listToAttrs (mkConfigs vars.hostnames); evalDisko = builtins.listToAttrs (mkDiskoFiles (builtins.filter (x: x != "installer") vars.hostnames)); @@ -196,6 +223,7 @@ and now for the main flake: }; devShell."${system}" = with pkgs; mkShell { + inherit (pre-commit-check) shellHook; buildInputs = [ fira-code python3 @@ -474,12 +502,21 @@ under ~default.nix~ in the ~systems~ folder. secureBoot.enable = lib.mkEnableOption "Enables secure boot. See sbctl."; pipewire.enable = lib.mkEnableOption "Enables pipewire low latency audio setup"; tor.enable = lib.mkEnableOption "Enables tor along with torsocks"; - home.enable = lib.mkEnableOption "Enables home user"; - server.enable = lib.mkEnableOption "Enables server services"; + + server = { + enable = lib.mkEnableOption "Enables server services"; + interface = lib.mkOption { type = lib.types.str; default = "eth0"; }; + ipv4 = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; + ipv6 = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; + gateway = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; + }; + ttyonly.enable = lib.mkEnableOption "TTY only, no xserver"; grub.enable = lib.mkEnableOption "Enables grub instead of systemd-boot"; workstation.enable = lib.mkEnableOption "Enables workstation services"; + desktop.enable = lib.mkEnableOption "Enables everything common to desktops"; impermanence.enable = lib.mkEnableOption "Enables imperamanence"; + home.enable = lib.mkEnableOption "Enables home profiles"; }; }; }; @@ -504,13 +541,30 @@ under ~default.nix~ in the ~systems~ folder. enable = true; }; + assertions = [ + { + assertion = !(config.monorepo.profiles.workstation.enable && config.monorepo.profiles.server.enable); + message = '' + You can't enable both workstation and server profile together. Please select only one. + ''; + } + { + assertion = !(config.monorepo.profiles.desktop.enable && config.monorepo.profiles.server.enable); + message = '' + You can't enable both desktop and server profile together. Please select only one. + ''; + } + ]; monorepo = { profiles = { + desktop.enable = lib.mkDefault config.monorepo.profiles.workstation.enable; documentation.enable = lib.mkDefault true; pipewire.enable = lib.mkDefault true; tor.enable = lib.mkDefault true; - home.enable = lib.mkDefault true; impermanence.enable = lib.mkDefault false; + server.enable = lib.mkDefault false; + ttyonly.enable = lib.mkDefault config.monorepo.profiles.server.enable; + home.enable = lib.mkDefault config.monorepo.profiles.desktop.enable; }; }; }; @@ -583,7 +637,7 @@ the yaml file specified. Yes, this is safe to include in the repo. keyFile = "/home/${config.monorepo.vars.userName}/.config/sops/age/keys.txt"; }; - secrets = if ! config.monorepo.profiles.server.enable then { + secrets = if config.monorepo.profiles.desktop.enable then { mail = { format = "yaml"; }; @@ -609,31 +663,16 @@ the yaml file specified. Yes, this is safe to include in the repo. matrix_bridge = { format = "yaml"; }; - livekit_secret = { - format = "yaml"; - mode = "0444"; - }; - livekit = { - format = "yaml"; - }; mail_password = { format = "yaml"; owner = "maddy"; }; - mail_monorepo_password = { - format = "yaml"; - owner = "maddy"; - }; - mail_monorepo_password_pi = { format = "yaml"; owner = "public-inbox"; }; - conduit_secrets = { - format = "yaml"; - }; mautrix_env = { format = "yaml"; }; @@ -647,10 +686,6 @@ the yaml file specified. Yes, this is safe to include in the repo. format = "yaml"; owner = "nginx"; }; - ntfy = { - format = "yaml"; - owner = "ntfy-sh"; - }; }; }; } @@ -668,21 +703,21 @@ Still, it is suitable for using Krita. startx.enable = (! config.monorepo.profiles.ttyonly.enable); }; - windowManager = { - i3 = { - enable = (! config.monorepo.profiles.ttyonly.enable); - }; - }; + # windowManager = { + # i3 = { + # enable = (! config.monorepo.profiles.ttyonly.enable); + # }; + # }; desktopManager = { runXdgAutostartIfNone = true; }; - xkb = { - layout = "us"; - variant = ""; - options = "caps:escape"; - }; + # xkb = { + # layout = "us"; + # variant = ""; + # options = "caps:escape"; + # }; videoDrivers = (if config.monorepo.profiles.cuda.enable then [ "nvidia" ] else []); }; @@ -764,12 +799,13 @@ My SSH daemon configuration. services.openssh = { enable = true; settings = { - PasswordAuthentication = lib.mkDefault (! config.monorepo.profiles.server.enable); - AllowUsers = [ config.monorepo.vars.userName "root" "git" ]; - PermitRootLogin = "prohibit-password"; + PasswordAuthentication = false; + AllowUsers = [ config.monorepo.vars.userName "git" ]; + PermitRootLogin = "no"; KbdInteractiveAuthentication = false; }; }; + networking.firewall.allowedTCPPorts = lib.mkIf config.services.openssh.enable [ 22 ]; } #+end_src ** Tor @@ -829,7 +865,7 @@ I use i2p for some p2p connections. We enable it with the server profile: { config, lib, ... }: { services.i2pd = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault false; address = "0.0.0.0"; inTunnels = { }; @@ -844,7 +880,7 @@ This is an internet radio which will host a ton of music. { lib, config, ... }: { services.icecast = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault false; listen.address = "0.0.0.0"; extraConfig = '' @@ -890,12 +926,18 @@ I run my own IRC server to bridge with my Matrix server and my discord guild. Ports = 6697 ''; }; + environment.etc."motd.txt" = { source = ../data/motd.txt; mode = "644"; user = "ngircd"; group = "ngircd"; }; + + networking.firewall.allowedTCPPorts = if (config.services.ngircd.enable == true) then [ + 6697 + 6667 + ] else []; } #+end_src *** MOTD @@ -961,10 +1003,27 @@ still federating and hosting the same protocol. There is also a configuration for lk-jwt and livekit which is important for configuring p2p calls in matrix. #+begin_src nix :tangle ../nix/modules/conduit.nix { config, lib, ... }: + let + livekitListenPort = 8443; + # secrets.yaml + livekit_secret = "livekit_secret"; + conduit_secret = "conduit_secrets"; + in { + sops.secrets = lib.mkIf config.services.matrix-conduit.enable { + "${livekit_secret}" = lib.mkIf config.services.livekit.enable { + format = "yaml"; + mode = "0444"; + }; + + "${conduit_secret}" = { + format = "yaml"; + }; + }; + services.matrix-conduit = { enable = lib.mkDefault config.monorepo.profiles.server.enable; - secretFile = "/run/secrets/conduit_secrets"; + secretFile = "/run/secrets/${conduit_secret}"; settings.global = { server_name = "matrix.${config.monorepo.vars.orgHost}"; trusted_servers = [ @@ -977,15 +1036,11 @@ for lk-jwt and livekit which is important for configuring p2p calls in matrix. allow_registration = false; }; }; - services.lk-jwt-service = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; - port = 6495; - livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}"; - keyFile = "/run/secrets/livekit_secret"; - }; + + services.livekit = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; - keyFile = "/run/secrets/livekit_secret"; + enable = lib.mkDefault (config.services.matrix-conduit.enable || config.services.matrix-synapse.enable); + keyFile = "/run/secrets/${livekit_secret}"; settings = { port = 7880; turn = { @@ -1006,15 +1061,167 @@ for lk-jwt and livekit which is important for configuring p2p calls in matrix. }; }; }; + + services.lk-jwt-service = { + enable = lib.mkDefault config.services.livekit.enable; + port = 6495; + livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}"; + keyFile = "/run/secrets/${livekit_secret}"; + }; + + # TODO: split into conduit and livekit + networking.firewall.allowedTCPPorts = lib.mkIf config.services.matrix-conduit.enable [ 8448 7881 5349 livekitListenPort ]; + + # this is fine though + networking.firewall.allowedUDPPorts = lib.mkIf config.services.livekit.enable [ 7882 3478 ]; + networking.firewall.allowedUDPPortRanges = lib.mkIf config.services.livekit.enable [ + { from = 49152; to = 65535; } + ]; + + networking.domains.subDomains."matrix.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.matrix-conduit.enable {}; + networking.domains.subDomains."livekit.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.livekit.enable {}; + + services.nginx.virtualHosts."matrix.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.matrix-conduit.enable { + enableACME = lib.mkDefault config.monorepo.profiles.server.enable; + forceSSL = true; + listen = [ + { + addr = "0.0.0.0"; + port = 443; + ssl = true; + } + { + addr = "[::]"; + port = 443; + ssl = true; + } + { + addr = "0.0.0.0"; + port = 8448; + ssl = true; + } + { + addr = "[::]"; + port = 8448; + ssl = true; + } + ]; + locations."/_matrix/" = { + proxyPass = "http://127.0.0.1:${toString config.services.matrix-conduit.settings.global.port}"; + extraConfig = '' + proxy_set_header Host $host; + proxy_buffers 32 16k; + proxy_read_timeout 5m; + ''; + }; + + locations."= /.well-known/matrix/server" = { + extraConfig = '' + default_type application/json; + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + ''; + + return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; + }; + + locations."/.well-known/matrix/client" = { + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + ''; + + return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.${config.monorepo.vars.orgHost}\"}, \"org.matrix.msc4143.rtc_foci\": [{\"type\": \"livekit\", \"livekit_service_url\": \"https://matrix.${config.monorepo.vars.orgHost}:${toString livekitListenPort}\"}]}'"; + }; + + extraConfig = '' + merge_slashes off; + ''; + }; + + + services.nginx.virtualHosts."matrix.${config.monorepo.vars.orgHost}-livekit" = lib.mkIf config.services.livekit.enable { + serverName = "matrix.${config.monorepo.vars.orgHost}"; + listen = [ + { + addr = "0.0.0.0"; + port = livekitListenPort; + ssl = true; + } + { + addr = "[::]"; + port = livekitListenPort; + ssl = true; + } + ]; + addSSL = true; + enableACME = false; + forceSSL = false; + useACMEHost = "matrix.${config.monorepo.vars.orgHost}"; + + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.lk-jwt-service.port}"; + proxyWebsockets = true; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + services.nginx.virtualHosts."livekit.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.livekit.enable { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.livekit.settings.port}"; + proxyWebsockets = true; + extraConfig = '' + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + + # Standard headers for LiveKit + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # --- CORS CONFIGURATION START --- + # 1. Allow all origins (including app.element.io) + add_header 'Access-Control-Allow-Origin' '*' always; + + # 2. Allow specific methods (POST is required for /sfu/get) + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; + + # 3. Allow headers (Content-Type is crucial for JSON) + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; + + # 4. Handle the OPTIONS preflight request immediately + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + # --- CORS CONFIGURATION END --- + ''; + }; + }; } #+end_src -** GoToSocial +** TODO GoToSocial This is a basic ActivityPub server. #+begin_src nix :tangle ../nix/modules/gotosocial.nix { lib, config, ... }: { services.gotosocial = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault false; setupPostgresqlDB = true; settings = { application-name = "Nullring GoToSocial Instance"; @@ -1026,17 +1233,6 @@ This is a basic ActivityPub server. }; } #+end_src -** Matterbridge -I want to connect IRC to discord with matterbridge. -#+begin_src nix :tangle ../nix/modules/matterbridge.nix - { lib, config, ... }: - { - services.matterbridge = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; - configPath = "${config.sops.templates.matterbridge.path}"; - }; - } -#+end_src ** TODO matrix-appservice-irc #+begin_src nix :tangle ../nix/modules/matrix-appservice-irc.nix { lib, config, ... }: @@ -1050,6 +1246,28 @@ I want to connect IRC to discord with matterbridge. }; } #+end_src +** Gitolite +#+begin_src nix :tangle ../nix/modules/gitolite.nix + { lib, config, ... }: + { + services.gitolite = { + enable = lib.mkDefault config.monorepo.profiles.server.enable; + description = "My Gitolite User"; + adminPubkey = config.monorepo.vars.sshKey; + }; + } +#+end_src +** Matterbridge +I want to connect IRC to discord with matterbridge. +#+begin_src nix :tangle ../nix/modules/matterbridge.nix + { lib, config, ... }: + { + services.matterbridge = { + enable = lib.mkDefault config.monorepo.profiles.server.enable; + configPath = "${config.sops.templates.matterbridge.path}"; + }; + } +#+end_src *** Mautrix I use this bridge to bridge myself from Matrix to Discord and vise versa, because Matterbridge is not maintained very well and therefore does not support conduit at the moment. Note that this is not fully declarative and requires that you add @@ -1213,9 +1431,9 @@ Use ollama for serving large language models to my other computers. { # services.open-webui.enable = lib.mkDefault (!config.monorepo.profiles.server.enable); services.ollama = { - enable = lib.mkDefault (!config.monorepo.profiles.server.enable); - package = if (config.monorepo.profiles.workstation.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan; - loadModels = if (config.monorepo.profiles.workstation.enable) then [ + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + package = if (config.monorepo.profiles.cuda.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan; + loadModels = if (config.monorepo.profiles.cuda.enable) then [ "qwen3:30b" "qwen3-coder:latest" "qwen2.5-coder:latest" @@ -1249,27 +1467,43 @@ I run my own git server in order to have a mirror in case github goes down. exportAll = true; basePath = "${config.users.users.git.home}"; }; + networking.firewall.allowedTCPPorts = lib.mkIf config.services.gitDaemon.enable [ + 9418 + ]; } #+end_src ** Ntfy I want to have notifications on my phone, and run my own server to do this. #+begin_src nix :tangle ../nix/modules/ntfy-sh.nix { pkgs, lib, config, ... }: + let + serverName = "ntfy.${config.monorepo.vars.remoteHost}"; + port = 2586; + ntfySecret = "ntfy"; + in { + sops.secrets."${ntfySecret}" = lib.mkIf config.services.ntfy-sh.enable { + format = "yaml"; + owner = "ntfy-sh"; + }; + services.ntfy-sh = { enable = lib.mkDefault config.monorepo.profiles.server.enable; settings = { - base-url = "https://ntfy.${config.monorepo.vars.remoteHost}"; - listen-http = "127.0.0.1:2586"; - envrionmentFile = "/run/secrets/ntfy"; + base-url = "https://${serverName}"; + listen-http = "127.0.0.1:${toString port}"; + envrionmentFile = "/run/secrets/${ntfySecret}"; auth-file = "/var/lib/ntfy-sh/user.db"; auth-default-access = "deny-all"; enable-login = true; }; }; - systemd.services.ntfy-sh = { + + services.nginx.enable = config.services.ntfy-sh.enable; + + systemd.services.ntfy-sh = lib.mkIf config.services.ntfy-sh.enable { serviceConfig = { - EnvironmentFile = "/run/secrets/ntfy"; + EnvironmentFile = "/run/secrets/${ntfySecret}"; }; postStart = lib.mkForce '' # 1. Wait for the server to initialize the database @@ -1301,6 +1535,24 @@ I want to have notifications on my phone, and run my own server to do this. fi ''; }; + + networking.domains.subDomains."${serverName}" = lib.mkIf config.services.ntfy-sh.enable {}; + services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.ntfy-sh.enable { + serverName = "${serverName}"; + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString port}"; + proxyWebsockets = true; + extraConfig = '' + proxy_buffering off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; } #+end_src ** Nginx @@ -1310,198 +1562,30 @@ to the outside world under a domain. #+begin_src nix :tangle ../nix/modules/nginx.nix { config, lib, ... }: { - config = lib.mkIf config.monorepo.profiles.server.enable { - services.nginx = { - enable = true; - user = "nginx"; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedTlsSettings = true; - recommendedProxySettings = false; - virtualHosts = { - "matrix.${config.monorepo.vars.orgHost}" = { - enableACME = config.monorepo.profiles.server.enable; - forceSSL = true; - listen = [ - { - addr = "0.0.0.0"; - port = 443; - ssl = true; - } - { - addr = "[::]"; - port = 443; - ssl = true; - } - { - addr = "0.0.0.0"; - port = 8448; - ssl = true; - } - { - addr = "[::]"; - port = 8448; - ssl = true; - } - ]; - locations."/_matrix/" = { - proxyPass = "http://127.0.0.1:6167"; - extraConfig = '' - proxy_set_header Host $host; - proxy_buffers 32 16k; - proxy_read_timeout 5m; - ''; - }; - locations."= /.well-known/matrix/server" = { - extraConfig = '' - default_type application/json; - add_header Content-Type application/json; - add_header Access-Control-Allow-Origin *; - ''; - - return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; - }; - locations."/.well-known/matrix/client" = { - extraConfig = '' - default_type application/json; - add_header Access-Control-Allow-Origin *; - ''; - - return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.${config.monorepo.vars.orgHost}\"}, \"org.matrix.msc4143.rtc_foci\": [{\"type\": \"livekit\", \"livekit_service_url\": \"https://matrix.${config.monorepo.vars.orgHost}:8443\"}]}'"; - }; + services.nginx = { + enable = lib.mkDefault config.monorepo.profiles.server.enable; + user = "nginx"; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + recommendedProxySettings = false; + virtualHosts = { + "${config.monorepo.vars.remoteHost}" = { + serverName = "${config.monorepo.vars.remoteHost}"; + serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ]; + root = "/var/www/${config.monorepo.vars.internetName}-website/"; + addSSL = true; + enableACME = true; + }; + # the port comes from ssh tunnelling + "music.${config.monorepo.vars.remoteHost}" = lib.mkIf config.monorepo.profiles.server.enable { + addSSL = true; + enableACME = true; + basicAuthFile = config.sops.secrets."mpd_password".path; + locations."/" = { + proxyPass = "http://localhost:8000"; extraConfig = '' - merge_slashes off; - ''; - }; - - "matrix.${config.monorepo.vars.orgHost}-livekit" = { - serverName = "matrix.${config.monorepo.vars.orgHost}"; - listen = [ - { - addr = "0.0.0.0"; - port = 8443; - ssl = true; - } - { - addr = "[::]"; - port = 8443; - ssl = true; - } - ]; - addSSL = true; - enableACME = false; - forceSSL = false; - useACMEHost = "matrix.${config.monorepo.vars.orgHost}"; - - locations."/" = { - proxyPass = "http://127.0.0.1:6495"; - proxyWebsockets = true; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; - }; - }; - - "livekit.${config.monorepo.vars.orgHost}" = { - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://127.0.0.1:7880"; - proxyWebsockets = true; - extraConfig = '' - proxy_read_timeout 3600s; - proxy_send_timeout 3600s; - - # Standard headers for LiveKit - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # --- CORS CONFIGURATION START --- - # 1. Allow all origins (including app.element.io) - add_header 'Access-Control-Allow-Origin' '*' always; - - # 2. Allow specific methods (POST is required for /sfu/get) - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; - - # 3. Allow headers (Content-Type is crucial for JSON) - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; - - # 4. Handle the OPTIONS preflight request immediately - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*' always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain; charset=utf-8'; - add_header 'Content-Length' 0; - return 204; - } - # --- CORS CONFIGURATION END --- - ''; - }; - }; - - "ntfy.${config.monorepo.vars.remoteHost}" = { - serverName = "ntfy.${config.monorepo.vars.remoteHost}"; - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://127.0.0.1:2586"; - proxyWebsockets = true; - extraConfig = '' - proxy_buffering off; - proxy_request_buffering off - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; - }; - }; - - "${config.monorepo.vars.remoteHost}" = { - serverName = "${config.monorepo.vars.remoteHost}"; - serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ]; - root = "/var/www/${config.monorepo.vars.internetName}-website/"; - addSSL = true; - enableACME = true; - }; - - "git.${config.monorepo.vars.orgHost}" = { - forceSSL = true; - enableACME = true; - }; - "list.${config.monorepo.vars.orgHost}" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://localhost:9090"; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; - }; - }; - - # the port comes from ssh tunnelling - "music.${config.monorepo.vars.remoteHost}" = lib.mkIf config.monorepo.profiles.server.enable { - addSSL = true; - enableACME = true; - basicAuthFile = config.sops.secrets."mpd_password".path; - locations."/" = { - proxyPass = "http://localhost:8000"; - extraConfig = '' proxy_buffering off; proxy_http_version 1.1; proxy_set_header Connection ""; @@ -1510,34 +1594,37 @@ to the outside world under a domain. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_read_timeout 36000s; ''; - }; - }; - - "${config.monorepo.vars.orgHost}" = { - serverName = "${config.monorepo.vars.orgHost}"; - root = "/var/www/nullring/"; - addSSL = true; - enableACME = true; }; + }; - "mail.${config.monorepo.vars.orgHost}" = { - serverName = "mail.${config.monorepo.vars.orgHost}"; - root = "/var/www/dummy"; - addSSL = true; - enableACME = true; - }; + "${config.monorepo.vars.orgHost}" = { + serverName = "${config.monorepo.vars.orgHost}"; + root = "/var/www/nullring/"; + addSSL = true; + enableACME = true; }; }; }; + + networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ]; + + networking.domains.subDomains = lib.mkIf config.services.nginx.enable { + "${config.monorepo.vars.remoteHost}" = {}; + "${config.monorepo.vars.orgHost}" = {}; + "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {}; + }; } #+end_src ** CGit Interface I have this cgit interface in order to integrate with public-inbox. #+begin_src nix :tangle ../nix/modules/cgit.nix { lib, config, ... }: + let + serverName = "git.${config.monorepo.vars.orgHost}"; + in { services.cgit."my-projects" = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault config.services.gitDaemon.enable; scanPath = "${config.users.users.git.home}"; settings = { root-title = "Nullring Git Server"; @@ -1546,7 +1633,7 @@ I have this cgit interface in order to integrate with public-inbox. enable-log-filecount = 1; enable-log-linecount = 1; enable-index-owner = 0; - clone-prefix = "https://git.${config.monorepo.vars.orgHost}"; + clone-prefix = "https://${serverName}"; enable-tree-linenumbers = 1; strict-export = "git-daemon-export-ok"; }; @@ -1555,9 +1642,15 @@ I have this cgit interface in order to integrate with public-inbox. checkExportOkFiles = true; }; nginx = { - virtualHost = "git.${config.monorepo.vars.orgHost}"; + virtualHost = "${serverName}"; }; }; + + networking.domains.subDomains."${serverName}" = lib.mkIf config.services.cgit."my-projects".enable {}; + services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.cgit."my-projects".enable { + forceSSL = true; + enableACME = true; + }; } #+end_src ** Nvidia @@ -1603,7 +1696,19 @@ I need CUDA on some computers because I run local LLMs. There is a non declarative part of setting dkims and spf. #+begin_src nix :tangle ../nix/modules/maddy.nix { lib, config, options, ... }: + let + emailServerName = "mail.${config.monorepo.vars.orgHost}"; + serverName = "list.${config.monorepo.vars.orgHost}"; + password_path = "mail_monorepo_password"; + in { + sops.secrets = lib.mkIf config.services.maddy.enable { + "${password_path}" = lib.mkIf config.services.maddy.enable { + format = "yaml"; + owner = "maddy"; + }; + }; + services.maddy = { enable = lib.mkDefault config.monorepo.profiles.server.enable; openFirewall = true; @@ -1629,25 +1734,20 @@ There is a non declarative part of setting dkims and spf. "imap tls://0.0.0.0:993 tcp://0.0.0.0:143" "submission tls://0.0.0.0:465 tcp://0.0.0.0:587" ] options.services.maddy.config.default; + ensureAccounts = (builtins.map (x: "${x}@${config.monorepo.vars.orgHost}") config.monorepo.vars.projects) ++ [ "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" "discussion@${config.monorepo.vars.orgHost}" ]; ensureCredentials = lib.genAttrs config.services.maddy.ensureAccounts (name: { - passwordFile = "/run/secrets/mail_monorepo_password"; + passwordFile = "/run/secrets/${password_path}"; }) // { "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" = { passwordFile = "/run/secrets/mail_password"; }; }; }; - } -#+end_src -*** Public Inbox -This is my mailing list software that I will use to develop software. -#+begin_src nix :tangle ../nix/modules/public_inbox.nix - { lib, config, ... }: - { + systemd.tmpfiles.rules = [ "C+ /var/lib/public-inbox/style.css 0644 public-inbox public-inbox - ${../data/public-inbox.css}" ]; @@ -1705,6 +1805,7 @@ This is my mailing list software that I will use to develop software. settings = { coderepo = lib.genAttrs config.monorepo.vars.projects (name: { dir = "${config.users.users.git.home}/${name}.git"; + # works even if no cgit server running here, this is just the default cgitUrl = "https://git.${config.monorepo.vars.orgHost}/${name}.git"; }); publicinbox.css = ["/var/lib/public-inbox/style.css"]; @@ -1719,18 +1820,71 @@ This is my mailing list software that I will use to develop software. address = [ "${name}@${config.monorepo.vars.orgHost}" ]; inboxdir = "/var/lib/public-inbox/${name}"; url = "https://list.${config.monorepo.vars.orgHost}/${name}"; - watch = [ "imaps://${name}${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ]; + watch = [ "imaps://${name}${config.monorepo.vars.orgHost}@${emailServerName}/INBOX" ]; coderepo = [ "${name}" ]; }) // { "discussion" = { description = "Main Nullring Discussion Mailing List"; address = [ "discussion@${config.monorepo.vars.orgHost}" ]; inboxdir = "/var/lib/public-inbox/discuss"; - url = "https://list.${config.monorepo.vars.orgHost}/discussion"; - watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ]; + url = "https://${serverName}/discussion"; + watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@${emailServerName}/INBOX" ]; + }; + }; + }; + + networking.domains.baseDomains."${config.monorepo.vars.orgHost}" = lib.mkIf config.services.maddy.enable { + mx.data = [ + { + preference = 10; + exchange = "${emailServerName}"; + } + ]; + }; + + networking.domains.subDomains = lib.mkIf config.services.maddy.enable { + "${serverName}" = {}; + "${emailServerName}" = {}; + "_dmarc.${config.monorepo.vars.orgHost}" = { + txt = { + data = "v=DMARC1; p=none"; + }; + }; + "default._domainkey.${config.monorepo.vars.orgHost}" = { + txt = { + data = "v=DKIM1; k=rsa; p=${config.monorepo.vars.dkimKey}"; }; }; }; + + networking.firewall.allowedTCPPorts = lib.mkIf config.services.maddy.enable [ + 143 + 465 + 587 + 993 + ]; + + services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.public-inbox.enable { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://localhost:${toString config.services.public-inbox.http.port}"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + services.nginx.virtualHosts."${emailServerName}" = lib.mkIf config.services.maddy.enable { + serverName = "${emailServerName}"; + root = "/var/www/dummy"; + addSSL = true; + enableACME = true; + }; + } #+end_src *** Public Inbox CSS @@ -2018,6 +2172,13 @@ because they enhance security. "public-inbox" "plugdev" ]; + allDomains = + (lib.attrNames config.networking.domains.baseDomains) ++ + (lib.attrNames config.networking.domains.subDomains); + + # 2. Generate BOTH possible outcomes in advance + prodHosts = map (dom: "${config.monorepo.profiles.server.ipv4} ${dom}") allDomains; + vmHosts = map (dom: "127.0.0.1 ${dom}") allDomains; in { imports = [ @@ -2053,6 +2214,40 @@ because they enhance security. environment.etc."wpa_supplicant.conf".text = '' country=CA ''; + systemd.tmpfiles.rules = [ + "d /srv/git 0755 git git -" + ]; + + zramSwap = lib.mkIf config.monorepo.profiles.desktop.enable { + enable = true; + algorithm = "zstd"; + memoryPercent = 50; + }; + + virtualisation.vmVariant = lib.mkIf config.monorepo.profiles.server.enable { + sops.validateSopsFiles = false; + disko.devices = lib.mkForce {}; + virtualisation.forwardPorts = [ + { from = "host"; host.port = 10443; guest.port = 443; } + { from = "host"; host.port = 9080; guest.port = 80; } + ]; + virtualisation.useNixStoreImage = false; + virtualisation.sharedDirectories.sops-keys = { + source = "/home/preston/.config/sops/age"; # Path to your host key + target = "/home/preston/.config/sops/age"; + }; + networking.extraHosts = lib.mkForce (lib.concatStringsSep "\n" vmHosts); + networking.defaultGateway = lib.mkForce null; + networking.interfaces."${config.monorepo.profiles.server.interface}".useDHCP = lib.mkForce true; + + fileSystems."/" = lib.mkForce { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + }; + systemd.services.sops-nix = { + unitConfig.RequiresMountsFor = "/home/preston/.config/sops/age"; + }; + }; documentation = { enable = lib.mkDefault config.monorepo.profiles.documentation.enable; @@ -2069,6 +2264,19 @@ because they enhance security. }; }; + + systemd.network.enable = lib.mkDefault config.monorepo.profiles.server.enable; + systemd.network.networks."40-${config.monorepo.profiles.server.interface}" = lib.mkIf config.monorepo.profiles.server.enable { + matchConfig.Name = "${config.monorepo.profiles.server.interface}"; + networkConfig = { + IPv6AcceptRA = true; + IPv6PrivacyExtensions = false; + }; + ipv6AcceptRAConfig = { + UseAutonomousPrefix = false; + }; + }; + systemd = { services.NetworkManager-wait-online.enable = false; coredump.enable = false; @@ -2205,7 +2413,10 @@ because they enhance security. "ufs" ]; - kernel.sysctl = { + kernel.sysctl = if config.monorepo.profiles.server.enable then { + "net.ipv6.conf.${config.monorepo.profiles.server.interface}.autoconf" = 0; + "net.ipv6.conf.${config.monorepo.profiles.server.interface}.accept_ra" = 1; + } else { "kernel.ftrace_enabled" = false; "net.core.bpf_jit_enable" = false; "kernel.kptr_restrict" = 2; @@ -2232,10 +2443,51 @@ because they enhance security. }; networking = { + interfaces = lib.mkIf config.monorepo.profiles.server.enable { + "${config.monorepo.profiles.server.interface}" = { + ipv4.addresses = [ + { + address = config.monorepo.profiles.server.ipv4; + prefixLength = 24; + } + ]; + ipv6.addresses = [ + { + address = config.monorepo.profiles.server.ipv6; + prefixLength = 64; + } + ]; + useDHCP = lib.mkForce false; + }; + }; + + defaultGateway = lib.mkIf config.monorepo.profiles.server.enable config.monorepo.profiles.server.gateway; + useDHCP = false; + tempAddresses = lib.mkIf config.monorepo.profiles.server.enable "disabled"; + extraHosts = lib.mkIf config.monorepo.profiles.server.enable (lib.concatStringsSep "\n" prodHosts); + + domains = lib.mkIf config.monorepo.profiles.server.enable { + enable = true; + baseDomains = { + "${config.monorepo.vars.remoteHost}" = { + a.data = config.monorepo.profiles.server.ipv4; + aaaa.data = config.monorepo.profiles.server.ipv6; + }; + "${config.monorepo.vars.orgHost}" = { + a.data = config.monorepo.profiles.server.ipv4; + aaaa.data = config.monorepo.profiles.server.ipv6; + txt = { + data = "v=spf1 ip4:${config.monorepo.profiles.server.ipv4} ip6:${config.monorepo.profiles.server.ipv6} -all"; + }; + }; + }; + }; + + nameservers = [ "8.8.8.8" "1.1.1.1"]; dhcpcd.enable = (! config.monorepo.profiles.server.enable); networkmanager = { - enable = true; + enable = lib.mkForce (! config.monorepo.profiles.server.enable); # rpis need network wifi = { powersave = false; }; @@ -2287,8 +2539,8 @@ because they enhance security. graphics.enable = ! config.monorepo.profiles.ttyonly.enable; bluetooth = { - enable = lib.mkDefault (! config.monorepo.profiles.ttyonly.enable); - powerOnBoot = lib.mkDefault (! config.monorepo.profiles.ttyonly.enable); + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + powerOnBoot = lib.mkDefault config.monorepo.profiles.desktop.enable; }; }; @@ -2338,7 +2590,7 @@ because they enhance security. security = { acme = { acceptTerms = true; - defaults.email = "ret2pop@gmail.com"; + defaults.email = "${config.monorepo.vars.internetName}@gmail.com"; }; apparmor = { enable = true; @@ -2706,6 +2958,7 @@ I have many imports that we'll go through next. ./user.nix ./gtk.nix ./secrets.nix + ./pantalaimon.nix ]; options = { @@ -2854,13 +3107,14 @@ I have many imports that we'll go through next. ]) else []); monorepo.profiles = { - enable = lib.mkDefault true; + enable = lib.mkDefault super.monorepo.profiles.home.enable; music.enable = lib.mkDefault config.monorepo.profiles.enable; - hyprland.enable = lib.mkDefault config.monorepo.profiles.enable; email.enable = lib.mkDefault config.monorepo.profiles.enable; + cuda.enable = lib.mkDefault super.monorepo.profiles.cuda.enable; # Programming graphics.enable = lib.mkDefault (! super.monorepo.profiles.ttyonly.enable); + hyprland.enable = lib.mkDefault config.monorepo.profiles.graphics.enable; lang-c.enable = lib.mkDefault config.monorepo.profiles.enable; lang-rust.enable = lib.mkDefault config.monorepo.profiles.enable; lang-python.enable = lib.mkDefault config.monorepo.profiles.enable; @@ -2877,7 +3131,7 @@ I have many imports that we'll go through next. crypto.enable = lib.mkDefault config.monorepo.profiles.enable; art.enable = lib.mkDefault config.monorepo.profiles.enable; - workstation.enable = lib.mkDefault config.monorepo.profiles.enable; + workstation.enable = lib.mkDefault super.monorepo.profiles.workstation.enable; }; }; } @@ -2896,7 +3150,7 @@ These are some secrets that I use regularly for my programs in home. keyFile = "/home/${super.monorepo.vars.userName}/.config/sops/age/keys.txt"; }; - secrets = if config.monorepo.profiles.graphics.enable then { + secrets = if super.monorepo.profiles.desktop.enable then { mail = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/mail"; @@ -3563,27 +3817,29 @@ here: #+begin_src nix :tangle ../nix/modules/home/gtk.nix { lib, config, pkgs, ... }: { - gtk = { - theme = { - name = "catppuccin-mocha-pink-standard"; - package = pkgs.catppuccin-gtk.override { - variant = "mocha"; - accents = [ "pink" ]; + config = lib.mkIf config.monorepo.profiles.graphics.enable { + gtk = { + theme = { + name = "catppuccin-mocha-pink-standard"; + package = pkgs.catppuccin-gtk.override { + variant = "mocha"; + accents = [ "pink" ]; + }; }; }; - }; - xdg.configFile = { - "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets"; - "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css"; - "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css"; - - "gtk-3.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk.css"; - "gtk-3.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk-dark.css"; - "gtk-3.0/settings.ini".text = '' + xdg.configFile = { + "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets"; + "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css"; + "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css"; + + "gtk-3.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk.css"; + "gtk-3.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk-dark.css"; + "gtk-3.0/settings.ini".text = '' [Settings] gtk-theme-name=${config.gtk.theme.name} gtk-application-prefer-dark-theme=1 ''; + }; }; } #+end_src @@ -4080,7 +4336,7 @@ A classic program that allows you to download from youtube. Also has integration { lib, config, ... }: { services.pantalaimon = { - enable = lib.mkDefault config.monorepo.profiles.enable; + enable = lib.mkDefault false; settings = { Default = { LogLevel = "Debug"; @@ -4287,6 +4543,10 @@ for these configurations. stow */ # manage secrets with gnu stow cd "$HOME" '') + (writeShellScriptBin "spontaneity-ci" + '' + #!/bin/bash + nixos-rebuild build-vm --flake $HOME/monorepo/nix#spontaneity && QEMU_OPTS="-serial stdio" ./result/bin/run-spontaneity-vm 2>&1 | tee vm-boot.log'') ] else [ pfetch # net @@ -4307,7 +4567,7 @@ for these configurations. }; }; xdg.mimeApps = { - enable = true; + enable = lib.mkDefault config.monorepo.profiles.graphics.enable; defaultApplications = { "x-scheme-handler/mailto" = "emacsclient-mail.desktop"; "text/html" = "librewolf.desktop"; @@ -4382,6 +4642,7 @@ This is pretty understandable, if you understand all the above. monorepo = { profiles = { impermanence.enable = true; + desktop.enable = true; }; vars = { device = "/dev/sda"; @@ -4400,7 +4661,6 @@ monorepo home options. imports = [ ../home-common.nix ]; - config.monorepo.profiles.workstation.enable = false; } #+end_src ** Affinity @@ -4414,15 +4674,9 @@ as several other useful services. ../../disko/drive-simple.nix ]; config = { - zramSwap = { - enable = true; - algorithm = "zstd"; - memoryPercent = 50; - }; monorepo = { vars.device = "/dev/nvme0n1"; profiles = { - server.enable = false; cuda.enable = true; workstation.enable = true; }; @@ -4438,9 +4692,6 @@ I want cuda in home manager too. imports = [ ../home-common.nix ]; - config.monorepo = { - profiles.cuda.enable = true; - }; } #+end_src ** rpi-zero @@ -4461,7 +4712,6 @@ I want cuda in home manager too. monorepo = { vars.device = "/dev/mmcblk0"; profiles = { - server.enable = false; ttyonly.enable = true; }; }; @@ -4483,156 +4733,33 @@ Spontaneity is my VPS instance. Note that much of this is not fully reproducible some DNS records to match what you have on your system after deployment. #+begin_src nix :tangle ../nix/systems/spontaneity/default.nix { config, lib, ... }: - let - ipv4addr = "66.42.84.130"; - ipv6addr = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794"; - in - { - imports = [ - ../common.nix - ../../disko/drive-bios.nix - - # nixos-anywhere generates this file - ./hardware-configuration.nix - ]; - config = { - monorepo = { - vars.device = "/dev/vda"; - profiles = { - server.enable = true; - ttyonly.enable = true; - grub.enable = true; - pipewire.enable = false; - tor.enable = false; - home.enable = false; - }; - }; - - boot.loader.grub.device = "nodev"; - boot.kernel.sysctl = { - "net.ipv6.conf.ens3.autoconf" = 0; - # Keep accept_ra = 1 so you still get the default gateway/route! - "net.ipv6.conf.ens3.accept_ra" = 1; - }; + { + imports = [ + ../common.nix + ../../disko/drive-bios.nix - systemd.network.enable = true; - systemd.network.networks."40-ens3" = { - matchConfig.Name = "ens3"; - networkConfig = { - IPv6AcceptRA = true; - IPv6PrivacyExtensions = false; - }; - ipv6AcceptRAConfig = { - UseAutonomousPrefix = false; - }; - }; - networking = { - useDHCP = lib.mkForce false; - networkmanager.enable = lib.mkForce false; - tempAddresses = "disabled"; - extraHosts = '' - 127.0.0.1 livekit.${config.monorepo.vars.orgHost} - 127.0.0.1 matrix.${config.monorepo.vars.orgHost} - ''; - interfaces.ens3.ipv4.addresses = [ - { - address = ipv4addr; - prefixLength = 24; - } - ]; - interfaces.ens3.useDHCP = lib.mkForce false; - interfaces.ens3.ipv6.addresses = [ - { - address = ipv6addr; - prefixLength = 64; - } - ]; - defaultGateway = "66.42.84.1"; - firewall = { - allowedTCPPorts = [ - 80 - 143 - 443 - 465 - 587 - 993 - 3478 - 5349 - 6697 - 6667 - 7881 - 8443 - 8448 - 9418 - ]; - allowedUDPPorts = [ - 3478 5349 7882 - ]; - allowedUDPPortRanges = [ - { from = 49152; to = 65535; } - ]; - }; - domains = { + # nixos-anywhere generates this file + ./hardware-configuration.nix + ]; + config = { + monorepo = { + vars.device = "/dev/vda"; + profiles = { + server = { enable = true; - baseDomains = { - "${config.monorepo.vars.remoteHost}" = { - a.data = ipv4addr; - aaaa.data = ipv6addr; - }; - "${config.monorepo.vars.orgHost}" = { - a.data = ipv4addr; - aaaa.data = ipv6addr; - - mx.data = [ - { - preference = 10; - exchange = "mail.${config.monorepo.vars.orgHost}"; - } - ]; - txt = { - data = "v=spf1 ip4:${ipv4addr} ip6:${ipv6addr} -all"; - }; - }; - }; - subDomains = { - "${config.monorepo.vars.remoteHost}" = {}; - "notes.${config.monorepo.vars.remoteHost}" = { - a.data = "45.76.87.125"; - }; - - "_dmarc.${config.monorepo.vars.orgHost}" = { - txt = { - data = "v=DMARC1; p=none"; - }; - }; - - "default._domainkey.${config.monorepo.vars.orgHost}" = { - txt = { - data = "v=DKIM1; k=rsa; p=${config.monorepo.vars.dkimKey}"; - }; - }; - - "ntfy.${config.monorepo.vars.remoteHost}" = {}; - "matrix.${config.monorepo.vars.remoteHost}" = {}; - "www.${config.monorepo.vars.remoteHost}" = {}; - "music.${config.monorepo.vars.remoteHost}" = {}; - "mail.${config.monorepo.vars.remoteHost}" = { - }; - - "livekit.${config.monorepo.vars.orgHost}" = {}; - "${config.monorepo.vars.orgHost}" = {}; - "git.${config.monorepo.vars.orgHost}" = {}; - "matrix.${config.monorepo.vars.orgHost}" = {}; - "social.${config.monorepo.vars.orgHost}" = {}; - "list.${config.monorepo.vars.orgHost}" = {}; - "talk.${config.monorepo.vars.orgHost}" = {}; - "mail.${config.monorepo.vars.orgHost}" = {}; - "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {}; - }; + ipv4 = "66.42.84.130"; + gateway = "66.42.84.1"; + ipv6 = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794"; + interface = "ens3"; }; + grub.enable = true; + pipewire.enable = false; + tor.enable = false; }; }; - } + boot.loader.grub.device = "nodev"; + }; + } #+end_src ** Home #+begin_src nix :tangle ../nix/systems/spontaneity/home.nix @@ -4641,7 +4768,6 @@ some DNS records to match what you have on your system after deployment. imports = [ ../home-common.nix ]; - config.monorepo.profiles.enable = false; } #+end_src ** Installer diff --git a/config/result b/config/result new file mode 120000 index 0000000..0caf4f3 --- /dev/null +++ b/config/result @@ -0,0 +1 @@ +/nix/store/5hi2hi06brsl1lwm11slqq6hnsbm49z5-nixos-vm \ No newline at end of file diff --git a/config/spontaneity.qcow2 b/config/spontaneity.qcow2 new file mode 100644 index 0000000..258fcdf Binary files /dev/null and b/config/spontaneity.qcow2 differ diff --git a/config/vm-boot.log b/config/vm-boot.log new file mode 100644 index 0000000..76cf664 --- /dev/null +++ b/config/vm-boot.log @@ -0,0 +1,26 @@ +Disk image does not exist, creating the virtualisation disk image... +Formatting '/tmp/tmp.0tqXumfc13', fmt=raw size=1073741824 +mke2fs 1.47.3 (8-Jul-2025) +Discarding device blocks: 0/262144 done +Creating filesystem with 262144 4k blocks and 65536 inodes +Filesystem UUID: 1d5351af-e0ed-41c6-bc5b-bbcd0127b758 +Superblock backups stored on blocks: + 32768, 98304, 163840, 229376 + +Allocating group tables: 0/8 done +Writing inode tables: 0/8 done +Creating journal (8192 blocks): done +Writing superblocks and filesystem accounting information: 0/8 done + +Virtualisation disk image created. +[ 2.096532] systemd-ssh-generator[402]: Failed to query local AF_VSOCK CID: Cannot assign requested address +[ 2.098602] (sd-exec-[390]: /nix/store/5j9cg6adv3d2l403fcfklz4lmf9fd0l8-systemd-258.3/lib/systemd/system-generators/systemd-ssh-generator failed with exit status 1. +[ 2.546892] systemd[1]: sops-nix.service: Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing. +[ 3.080780] kvm_intel: VMX not supported by CPU 0 +[!p]104[?7h[!p]104[?7h]3008;start=5de0f38824c24491abc03809c0b819a3;user=root;hostname=spontaneity;machineid=cc252dcccaee40fc8736d91909226c19;bootid=9a12d11dc2ac4a199201edd0732b062a;pid=1450;pidfdid=1750;comm=(agetty);servicename=serial-getty@ttyS0.service;invocationid=04848fb7ea964d489ea6f2ce7bce288b;type=service\P+q6E616D65\ + +<<< Welcome to NixOS 26.05.20260204.00c21e4 (x86_64) - ttyS0 >>> + +Run 'nixos-help' for the NixOS manual. + +spontaneity login: \ No newline at end of file diff --git a/nix/flake.nix b/nix/flake.nix index 86ce7ac..4ad9dd8 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -18,18 +18,18 @@ }; home-manager = { - url = "github:nix-community/home-manager/release-25.05"; - inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/home-manager/release-25.05"; + inputs.nixpkgs.follows = "nixpkgs"; }; disko = { - url = "github:nix-community/disko"; - inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; }; lanzaboote = { - url = "github:nix-community/lanzaboote/v0.4.1"; - inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/lanzaboote/v0.4.1"; + inputs.nixpkgs.follows = "nixpkgs"; }; nixos-dns = { @@ -48,22 +48,23 @@ }; }; - outputs = { - self, - nixpkgs, - home-manager, - nur, - disko, - lanzaboote, - sops-nix, - nix-topology, - nixos-dns, - deep-research, - impermanence, - nixpak, - ... - } - @attrs: + outputs = + { self + , nixpkgs + , home-manager + , nur + , disko + , lanzaboote + , sops-nix + , nix-topology + , nixos-dns + , deep-research + , impermanence + , nixpak + , git-hooks + , ... + } + @attrs: let vars = import ./flakevars.nix; system = "x86_64-linux"; @@ -89,38 +90,41 @@ value = nixpkgs.lib.nixosSystem { system = hostSystem; specialArgs = attrs; - modules = if (hostname == "installer") then [ - (./. + "/systems/${hostname}/default.nix") - { networking.hostName = "${hostname}"; } - nix-topology.nixosModules.default - ] else (if isRpi then [ - (./. + "/systems/${hostname}/default.nix") - disko.nixosModules.disko - home-manager.nixosModules.home-manager - sops-nix.nixosModules.sops - lanzaboote.nixosModules.lanzaboote - ] else ([ - { - environment.systemPackages = with nixpkgs.lib; [ - deep-research.packages."${system}".deep-research - ]; - } - impermanence.nixosModules.impermanence - nix-topology.nixosModules.default - lanzaboote.nixosModules.lanzaboote - disko.nixosModules.disko - home-manager.nixosModules.home-manager - sops-nix.nixosModules.sops - nixos-dns.nixosModules.dns - { - nixpkgs.overlays = [ nur.overlays.default ]; - home-manager.extraSpecialArgs = attrs // { - systemHostName = "${hostname}"; - }; - networking.hostName = "${hostname}"; - } - (./. + "/systems/${hostname}/default.nix") - ])); + modules = + if (hostname == "installer") then [ + (./. + "/systems/${hostname}/default.nix") + { networking.hostName = "${hostname}"; } + nix-topology.nixosModules.default + ] else + (if isRpi then [ + (./. + "/systems/${hostname}/default.nix") + disko.nixosModules.disko + home-manager.nixosModules.home-manager + sops-nix.nixosModules.sops + lanzaboote.nixosModules.lanzaboote + ] else + ([ + { + environment.systemPackages = with nixpkgs.lib; [ + deep-research.packages."${system}".deep-research + ]; + } + impermanence.nixosModules.impermanence + nix-topology.nixosModules.default + lanzaboote.nixosModules.lanzaboote + disko.nixosModules.disko + home-manager.nixosModules.home-manager + sops-nix.nixosModules.sops + nixos-dns.nixosModules.dns + { + nixpkgs.overlays = [ nur.overlays.default ]; + home-manager.extraSpecialArgs = attrs // { + systemHostName = "${hostname}"; + }; + networking.hostName = "${hostname}"; + } + (./. + "/systems/${hostname}/default.nix") + ])); }; }); @@ -128,54 +132,81 @@ name = "${hostname}"; value = self.nixosConfigurations."${hostname}".config.monorepo.vars.diskoSpec; }); - in - { - nixosConfigurations = builtins.listToAttrs (mkConfigs vars.hostnames); - - evalDisko = builtins.listToAttrs (mkDiskoFiles (builtins.filter (x: x != "installer") vars.hostnames)); - topology."${system}" = import nix-topology { - pkgs = import nixpkgs { - inherit system; - overlays = [ nix-topology.overlays.default ]; + pre-commit-check = git-hooks.lib.${system}.run { + src = ./.; + hooks = { + # 1. Formatting + nixpkgs-fmt.enable = false; + + # 2. Linting + statix.enable = true; + deadnix.enable = true; + + # 3. Custom VM Boot Check (The "Integration" part) + # This runs the build-vm derivation to ensure it compiles + vm-build-check = { + enable = true; + name = "vps-vm-build"; + description = "Ensure VPS configuration is buildable as a VM"; + entry = "nix build .#nixosConfigurations.vps.config.system.build.vm --no-link"; + pass_filenames = false; }; - modules = [ - ./topology/default.nix - { nixosConfigurations = self.nixosConfigurations; } - ]; }; + }; + in + { + checks."${system}" = { + inherit pre-commit-check; + }; + + nixosConfigurations = builtins.listToAttrs (mkConfigs vars.hostnames); - devShell."${system}" = with pkgs; mkShell { - buildInputs = [ - fira-code - python3 - poetry - statix - deadnix - ]; + evalDisko = builtins.listToAttrs (mkDiskoFiles (builtins.filter (x: x != "installer") vars.hostnames)); + + topology."${system}" = import nix-topology { + pkgs = import nixpkgs { + inherit system; + overlays = [ nix-topology.overlays.default ]; }; + modules = [ + ./topology/default.nix + { nixosConfigurations = self.nixosConfigurations; } + ]; + }; + + devShell."${system}" = with pkgs; mkShell { + inherit (pre-commit-check) shellHook; + buildInputs = [ + fira-code + python3 + poetry + statix + deadnix + ]; + }; + + packages."${system}" = { + zoneFiles = generate.zoneFiles dnsConfig; + octodns = generate.octodnsConfig { + inherit dnsConfig; - packages."${system}" = { - zoneFiles = generate.zoneFiles dnsConfig; - octodns = generate.octodnsConfig { - inherit dnsConfig; - - config = { - providers = { - cloudflare = { - class = "octodns_cloudflare.CloudflareProvider"; - token = "env/CLOUDFLARE_TOKEN"; - }; - config = { - check_origin = false; - }; + config = { + providers = { + cloudflare = { + class = "octodns_cloudflare.CloudflareProvider"; + token = "env/CLOUDFLARE_TOKEN"; + }; + config = { + check_origin = false; }; - }; - zones = { - "${vars.remoteHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ]; - "${vars.orgHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ]; }; }; + zones = { + "${vars.remoteHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ]; + "${vars.orgHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ]; + }; }; }; + }; } diff --git a/nix/modules/cgit.nix b/nix/modules/cgit.nix index eb0cc63..5bf888d 100644 --- a/nix/modules/cgit.nix +++ b/nix/modules/cgit.nix @@ -1,8 +1,11 @@ { lib, config, ... }: +let + serverName = "git.${config.monorepo.vars.orgHost}"; +in { services.cgit."my-projects" = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; - scanPath = "${config.users.users.git.home}"; + enable = lib.mkDefault config.services.gitDaemon.enable; + scanPath = "${config.users.users.git.home}"; settings = { root-title = "Nullring Git Server"; root-desc = "Projects and cool things"; @@ -10,7 +13,7 @@ enable-log-filecount = 1; enable-log-linecount = 1; enable-index-owner = 0; - clone-prefix = "https://git.${config.monorepo.vars.orgHost}"; + clone-prefix = "https://${serverName}"; enable-tree-linenumbers = 1; strict-export = "git-daemon-export-ok"; }; @@ -19,7 +22,13 @@ checkExportOkFiles = true; }; nginx = { - virtualHost = "git.${config.monorepo.vars.orgHost}"; + virtualHost = "${serverName}"; }; }; + + networking.domains.subDomains."${serverName}" = lib.mkIf config.services.cgit."my-projects".enable { }; + services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.cgit."my-projects".enable { + forceSSL = true; + enableACME = true; + }; } diff --git a/nix/modules/conduit.nix b/nix/modules/conduit.nix index 4d7a30c..edc8e8b 100644 --- a/nix/modules/conduit.nix +++ b/nix/modules/conduit.nix @@ -1,8 +1,25 @@ { config, lib, ... }: +let + livekitListenPort = 8443; + # secrets.yaml + livekit_secret = "livekit_secret"; + conduit_secret = "conduit_secrets"; +in { + sops.secrets = lib.mkIf config.services.matrix-conduit.enable { + "${livekit_secret}" = lib.mkIf config.services.livekit.enable { + format = "yaml"; + mode = "0444"; + }; + + "${conduit_secret}" = { + format = "yaml"; + }; + }; + services.matrix-conduit = { enable = lib.mkDefault config.monorepo.profiles.server.enable; - secretFile = "/run/secrets/conduit_secrets"; + secretFile = "/run/secrets/${conduit_secret}"; settings.global = { server_name = "matrix.${config.monorepo.vars.orgHost}"; trusted_servers = [ @@ -15,15 +32,11 @@ allow_registration = false; }; }; - services.lk-jwt-service = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; - port = 6495; - livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}"; - keyFile = "/run/secrets/livekit_secret"; - }; + + services.livekit = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; - keyFile = "/run/secrets/livekit_secret"; + enable = lib.mkDefault (config.services.matrix-conduit.enable || config.services.matrix-synapse.enable); + keyFile = "/run/secrets/${livekit_secret}"; settings = { port = 7880; turn = { @@ -44,4 +57,156 @@ }; }; }; + + services.lk-jwt-service = { + enable = lib.mkDefault config.services.livekit.enable; + port = 6495; + livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}"; + keyFile = "/run/secrets/${livekit_secret}"; + }; + + # TODO: split into conduit and livekit + networking.firewall.allowedTCPPorts = lib.mkIf config.services.matrix-conduit.enable [ 8448 7881 5349 livekitListenPort ]; + + # this is fine though + networking.firewall.allowedUDPPorts = lib.mkIf config.services.livekit.enable [ 7882 3478 ]; + networking.firewall.allowedUDPPortRanges = lib.mkIf config.services.livekit.enable [ + { from = 49152; to = 65535; } + ]; + + networking.domains.subDomains."matrix.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.matrix-conduit.enable { }; + networking.domains.subDomains."livekit.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.livekit.enable { }; + + services.nginx.virtualHosts."matrix.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.matrix-conduit.enable { + enableACME = lib.mkDefault config.monorepo.profiles.server.enable; + forceSSL = true; + listen = [ + { + addr = "0.0.0.0"; + port = 443; + ssl = true; + } + { + addr = "[::]"; + port = 443; + ssl = true; + } + { + addr = "0.0.0.0"; + port = 8448; + ssl = true; + } + { + addr = "[::]"; + port = 8448; + ssl = true; + } + ]; + locations."/_matrix/" = { + proxyPass = "http://127.0.0.1:${toString config.services.matrix-conduit.settings.global.port}"; + extraConfig = '' + proxy_set_header Host $host; + proxy_buffers 32 16k; + proxy_read_timeout 5m; + ''; + }; + + locations."= /.well-known/matrix/server" = { + extraConfig = '' + default_type application/json; + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + ''; + + return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; + }; + + locations."/.well-known/matrix/client" = { + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + ''; + + return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.${config.monorepo.vars.orgHost}\"}, \"org.matrix.msc4143.rtc_foci\": [{\"type\": \"livekit\", \"livekit_service_url\": \"https://matrix.${config.monorepo.vars.orgHost}:${toString livekitListenPort}\"}]}'"; + }; + + extraConfig = '' + merge_slashes off; + ''; + }; + + + services.nginx.virtualHosts."matrix.${config.monorepo.vars.orgHost}-livekit" = lib.mkIf config.services.livekit.enable { + serverName = "matrix.${config.monorepo.vars.orgHost}"; + listen = [ + { + addr = "0.0.0.0"; + port = livekitListenPort; + ssl = true; + } + { + addr = "[::]"; + port = livekitListenPort; + ssl = true; + } + ]; + addSSL = true; + enableACME = false; + forceSSL = false; + useACMEHost = "matrix.${config.monorepo.vars.orgHost}"; + + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.lk-jwt-service.port}"; + proxyWebsockets = true; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + services.nginx.virtualHosts."livekit.${config.monorepo.vars.orgHost}" = lib.mkIf config.services.livekit.enable { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.livekit.settings.port}"; + proxyWebsockets = true; + extraConfig = '' + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + + # Standard headers for LiveKit + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # --- CORS CONFIGURATION START --- + # 1. Allow all origins (including app.element.io) + add_header 'Access-Control-Allow-Origin' '*' always; + + # 2. Allow specific methods (POST is required for /sfu/get) + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; + + # 3. Allow headers (Content-Type is crucial for JSON) + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; + + # 4. Handle the OPTIONS preflight request immediately + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + # --- CORS CONFIGURATION END --- + ''; + }; + }; } diff --git a/nix/modules/configuration.nix b/nix/modules/configuration.nix index 564a8b1..bee737f 100644 --- a/nix/modules/configuration.nix +++ b/nix/modules/configuration.nix @@ -13,6 +13,13 @@ let "public-inbox" "plugdev" ]; + allDomains = + (lib.attrNames config.networking.domains.baseDomains) ++ + (lib.attrNames config.networking.domains.subDomains); + + # 2. Generate BOTH possible outcomes in advance + prodHosts = map (dom: "${config.monorepo.profiles.server.ipv4} ${dom}") allDomains; + vmHosts = map (dom: "127.0.0.1 ${dom}") allDomains; in { imports = [ @@ -46,8 +53,42 @@ in ]; environment.etc."wpa_supplicant.conf".text = '' -country=CA -''; + country=CA + ''; + systemd.tmpfiles.rules = [ + "d /srv/git 0755 git git -" + ]; + + zramSwap = lib.mkIf config.monorepo.profiles.desktop.enable { + enable = true; + algorithm = "zstd"; + memoryPercent = 50; + }; + + virtualisation.vmVariant = lib.mkIf config.monorepo.profiles.server.enable { + sops.validateSopsFiles = false; + disko.devices = lib.mkForce { }; + virtualisation.forwardPorts = [ + { from = "host"; host.port = 10443; guest.port = 443; } + { from = "host"; host.port = 9080; guest.port = 80; } + ]; + virtualisation.useNixStoreImage = false; + virtualisation.sharedDirectories.sops-keys = { + source = "/home/preston/.config/sops/age"; # Path to your host key + target = "/home/preston/.config/sops/age"; + }; + networking.extraHosts = lib.mkForce (lib.concatStringsSep "\n" vmHosts); + networking.defaultGateway = lib.mkForce null; + networking.interfaces."${config.monorepo.profiles.server.interface}".useDHCP = lib.mkForce true; + + fileSystems."/" = lib.mkForce { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + }; + systemd.services.sops-nix = { + unitConfig.RequiresMountsFor = "/home/preston/.config/sops/age"; + }; + }; documentation = { enable = lib.mkDefault config.monorepo.profiles.documentation.enable; @@ -57,10 +98,23 @@ country=CA environment = { etc = { - securetty.text = '' - # /etc/securetty: list of terminals on which root is allowed to login. - # See securetty(5) and login(1). - ''; + securetty.text = '' + # /etc/securetty: list of terminals on which root is allowed to login. + # See securetty(5) and login(1). + ''; + }; + }; + + + systemd.network.enable = lib.mkDefault config.monorepo.profiles.server.enable; + systemd.network.networks."40-${config.monorepo.profiles.server.interface}" = lib.mkIf config.monorepo.profiles.server.enable { + matchConfig.Name = "${config.monorepo.profiles.server.interface}"; + networkConfig = { + IPv6AcceptRA = true; + IPv6PrivacyExtensions = false; + }; + ipv6AcceptRAConfig = { + UseAutonomousPrefix = false; }; }; @@ -69,11 +123,11 @@ country=CA coredump.enable = false; network.config.networkConfig.IPv6PrivacyExtensions = "kernel"; tmpfiles.settings = { - "restrictetcnixos"."/etc/nixos/*".Z = { - mode = "0000"; - user = "root"; - group = "root"; - }; + "restrictetcnixos"."/etc/nixos/*".Z = { + mode = "0000"; + user = "root"; + group = "root"; + }; }; }; @@ -85,41 +139,41 @@ country=CA }; extraModprobeConfig = '' - options snd-usb-audio vid=0x1235 pid=0x8200 device_setup=1 - options rtw88_core disable_lps_deep=y power_save=0 disable_aspm_l1ss=y - options rtw88_pci disable_msi=y disable_aspm=y - options rtw_core disable_lps_deep=y - options rtw_pci disable_msi=y disable_aspm=y - options rtw89_core disable_ps_mode=y - options rtw89_pci disable_aspm_l1=y disable_aspm_l1ss=y disable_clkreq=y - options iwlwifi 11n_disable=8 uapsd_disable=1 bt_coex_active=0 disable_11ax=1 power_save=0 -''; + options snd-usb-audio vid=0x1235 pid=0x8200 device_setup=1 + options rtw88_core disable_lps_deep=y power_save=0 disable_aspm_l1ss=y + options rtw88_pci disable_msi=y disable_aspm=y + options rtw_core disable_lps_deep=y + options rtw_pci disable_msi=y disable_aspm=y + options rtw89_core disable_ps_mode=y + options rtw89_pci disable_aspm_l1=y disable_aspm_l1ss=y disable_clkreq=y + options iwlwifi 11n_disable=8 uapsd_disable=1 bt_coex_active=0 disable_11ax=1 power_save=0 + ''; extraModulePackages = [ ]; initrd = { - availableKernelModules = [ - "xhci_pci" - "ahci" - "usb_storage" - "sd_mod" - "nvme" - "sd_mod" - "ehci_pci" - "rtsx_pci_sdmmc" - "usbhid" - ]; - - kernelModules = [ ]; + availableKernelModules = [ + "xhci_pci" + "ahci" + "usb_storage" + "sd_mod" + "nvme" + "sd_mod" + "ehci_pci" + "rtsx_pci_sdmmc" + "usbhid" + ]; + + kernelModules = [ ]; }; lanzaboote = { - enable = config.monorepo.profiles.secureBoot.enable; - pkiBundle = "/var/lib/sbctl"; + enable = config.monorepo.profiles.secureBoot.enable; + pkiBundle = "/var/lib/sbctl"; }; loader = { - systemd-boot.enable = lib.mkForce ((! config.monorepo.profiles.grub.enable) && (! config.monorepo.profiles.secureBoot.enable)); - efi.canTouchEfiVariables = lib.mkForce (! config.monorepo.profiles.grub.enable); + systemd-boot.enable = lib.mkForce ((! config.monorepo.profiles.grub.enable) && (! config.monorepo.profiles.secureBoot.enable)); + efi.canTouchEfiVariables = lib.mkForce (! config.monorepo.profiles.grub.enable); }; kernelModules = [ @@ -144,93 +198,138 @@ country=CA "usbcore.autosuspend=-1" "pcie_aspm=off" "pci=noaer" - # "debugfs=off" - "page_alloc.shuffle=1" - "slab_nomerge" - # "page_poison=1" - - # madaidan - "pti=on" - "randomize_kstack_offset=on" - "vsyscall=none" - # "lockdown=confidentiality" - - # cpu - "spectre_v2=on" - "spec_store_bypass_disable=on" - "tsx=off" - "l1tf=full,force" - "kvm.nx_huge_pages=force" - - # hardened - "extra_latent_entropy" - - # mineral - # "init_on_alloc=1" - # "random.trust_bootloader=off" - # "init_on_free=1" - "quiet" - # "loglevel=0" + # "debugfs=off" + "page_alloc.shuffle=1" + "slab_nomerge" + # "page_poison=1" + + # madaidan + "pti=on" + "randomize_kstack_offset=on" + "vsyscall=none" + # "lockdown=confidentiality" + + # cpu + "spectre_v2=on" + "spec_store_bypass_disable=on" + "tsx=off" + "l1tf=full,force" + "kvm.nx_huge_pages=force" + + # hardened + "extra_latent_entropy" + + # mineral + # "init_on_alloc=1" + # "random.trust_bootloader=off" + # "init_on_free=1" + "quiet" + # "loglevel=0" ]; blacklistedKernelModules = [ - "netrom" - "rose" - - "adfs" - "affs" - "bfs" - "befs" - "cramfs" - "efs" - "erofs" - "exofs" - "freevxfs" - "f2fs" - "hfs" - "hpfs" - "jfs" - "minix" - "nilfs2" - "ntfs" - "omfs" - "qnx4" - "qnx6" - "sysv" - "ufs" + "netrom" + "rose" + + "adfs" + "affs" + "bfs" + "befs" + "cramfs" + "efs" + "erofs" + "exofs" + "freevxfs" + "f2fs" + "hfs" + "hpfs" + "jfs" + "minix" + "nilfs2" + "ntfs" + "omfs" + "qnx4" + "qnx6" + "sysv" + "ufs" ]; - kernel.sysctl = { - "kernel.ftrace_enabled" = false; - "net.core.bpf_jit_enable" = false; - "kernel.kptr_restrict" = 2; - - # madaidan - "kernel.smtcontrol" = "on"; - "vm.swappiness" = 1; - "vm.unprivileged_userfaultfd" = 0; - "dev.tty.ldisc_autoload" = 0; - "kernel.kexec_load_disabled" = 1; - "kernel.sysrq" = 4; - "kernel.perf_event_paranoid" = 3; - - # net - "net.ipv4.ip_forward" = 1; - "net.ipv4.icmp_echo_ignore_broadcasts" = true; - # "net.ipv4.conf.all.accept_redirects" = false; - # "net.ipv4.conf.all.secure_redirects" = false; - # "net.ipv4.conf.default.accept_redirects" = false; - # "net.ipv4.conf.default.secure_redirects" = false; - # "net.ipv6.conf.all.accept_redirects" = false; - # "net.ipv6.conf.default.accept_redirects" = false; - }; + kernel.sysctl = + if config.monorepo.profiles.server.enable then { + "net.ipv6.conf.${config.monorepo.profiles.server.interface}.autoconf" = 0; + "net.ipv6.conf.${config.monorepo.profiles.server.interface}.accept_ra" = 1; + } else { + "kernel.ftrace_enabled" = false; + "net.core.bpf_jit_enable" = false; + "kernel.kptr_restrict" = 2; + + # madaidan + "kernel.smtcontrol" = "on"; + "vm.swappiness" = 1; + "vm.unprivileged_userfaultfd" = 0; + "dev.tty.ldisc_autoload" = 0; + "kernel.kexec_load_disabled" = 1; + "kernel.sysrq" = 4; + "kernel.perf_event_paranoid" = 3; + + # net + "net.ipv4.ip_forward" = 1; + "net.ipv4.icmp_echo_ignore_broadcasts" = true; + # "net.ipv4.conf.all.accept_redirects" = false; + # "net.ipv4.conf.all.secure_redirects" = false; + # "net.ipv4.conf.default.accept_redirects" = false; + # "net.ipv4.conf.default.secure_redirects" = false; + # "net.ipv6.conf.all.accept_redirects" = false; + # "net.ipv6.conf.default.accept_redirects" = false; + }; }; networking = { - nameservers = [ "8.8.8.8" "1.1.1.1"]; + interfaces = lib.mkIf config.monorepo.profiles.server.enable { + "${config.monorepo.profiles.server.interface}" = { + ipv4.addresses = [ + { + address = config.monorepo.profiles.server.ipv4; + prefixLength = 24; + } + ]; + ipv6.addresses = [ + { + address = config.monorepo.profiles.server.ipv6; + prefixLength = 64; + } + ]; + useDHCP = lib.mkForce false; + }; + }; + + defaultGateway = lib.mkIf config.monorepo.profiles.server.enable config.monorepo.profiles.server.gateway; + useDHCP = false; + tempAddresses = lib.mkIf config.monorepo.profiles.server.enable "disabled"; + extraHosts = lib.mkIf config.monorepo.profiles.server.enable (lib.concatStringsSep "\n" prodHosts); + + domains = lib.mkIf config.monorepo.profiles.server.enable { + enable = true; + baseDomains = { + "${config.monorepo.vars.remoteHost}" = { + a.data = config.monorepo.profiles.server.ipv4; + aaaa.data = config.monorepo.profiles.server.ipv6; + }; + "${config.monorepo.vars.orgHost}" = { + a.data = config.monorepo.profiles.server.ipv4; + aaaa.data = config.monorepo.profiles.server.ipv6; + txt = { + data = "v=spf1 ip4:${config.monorepo.profiles.server.ipv4} ip6:${config.monorepo.profiles.server.ipv6} -all"; + }; + }; + }; + }; + + + nameservers = [ "8.8.8.8" "1.1.1.1" ]; dhcpcd.enable = (! config.monorepo.profiles.server.enable); networkmanager = { - enable = true; + enable = lib.mkForce (! config.monorepo.profiles.server.enable); # rpis need network wifi = { powersave = false; }; @@ -270,8 +369,8 @@ country=CA }; }; firewall = { - allowedTCPPorts = [ 22 11434 ]; - allowedUDPPorts = [ ]; + allowedTCPPorts = [ 22 11434 ]; + allowedUDPPorts = [ ]; }; }; @@ -282,8 +381,8 @@ country=CA graphics.enable = ! config.monorepo.profiles.ttyonly.enable; bluetooth = { - enable = lib.mkDefault (! config.monorepo.profiles.ttyonly.enable); - powerOnBoot = lib.mkDefault (! config.monorepo.profiles.ttyonly.enable); + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + powerOnBoot = lib.mkDefault config.monorepo.profiles.desktop.enable; }; }; @@ -304,11 +403,12 @@ country=CA # Misc. udev = { extraRules = ''''; - packages = if config.monorepo.profiles.workstation.enable then with pkgs; [ - platformio-core - platformio-core.udev - openocd - ] else []; + packages = + if config.monorepo.profiles.workstation.enable then with pkgs; [ + platformio-core + platformio-core.udev + openocd + ] else [ ]; }; printing.enable = lib.mkDefault config.monorepo.profiles.workstation.enable; @@ -333,7 +433,7 @@ country=CA security = { acme = { acceptTerms = true; - defaults.email = "ret2pop@gmail.com"; + defaults.email = "${config.monorepo.vars.internetName}@gmail.com"; }; apparmor = { enable = true; @@ -377,16 +477,16 @@ country=CA xdg-desktop-portal-gtk xdg-desktop-portal xdg-desktop-portal-hyprland - ] else []; + ] else [ ]; config.common.default = "*"; }; environment.etc."gitconfig".text = '' - [init] - defaultBranch = main + [init] + defaultBranch = main ''; environment.extraInit = '' - umask 0022 + umask 0022 ''; environment.systemPackages = with pkgs; [ restic @@ -400,31 +500,32 @@ country=CA exiftool (writeShellScriptBin "new-repo" '' - #!/bin/bash - cd ${config.users.users.git.home} - git init --bare "$1" - vim "$1/description" - chown -R git:git "$1" - '' + #!/bin/bash + cd ${config.users.users.git.home} + git init --bare "$1" + vim "$1/description" + chown -R git:git "$1" + '' ) ]; - users.groups = lib.genAttrs userGroups (name: lib.mkDefault {}); + users.groups = lib.genAttrs userGroups (name: lib.mkDefault { }); - users.users = lib.genAttrs userGroups (name: { - isSystemUser = lib.mkDefault true; - group = "${name}"; - extraGroups = [ "acme" "nginx" ]; - }) // { + users.users = lib.genAttrs userGroups + (name: { + isSystemUser = lib.mkDefault true; + group = "${name}"; + extraGroups = [ "acme" "nginx" ]; + }) // { conduit = { isSystemUser = lib.mkDefault true; group = "conduit"; - extraGroups = []; + extraGroups = [ ]; }; matterbridge = { isSystemUser = lib.mkDefault true; group = "matterbridge"; - extraGroups = []; + extraGroups = [ ]; }; public-inbox = { @@ -439,7 +540,7 @@ country=CA group = "ircd"; home = "/home/ircd"; }; - + nginx = { group = "nginx"; isSystemUser = lib.mkDefault true; @@ -472,7 +573,7 @@ country=CA description = config.monorepo.vars.fullName; extraGroups = [ "networkmanager" "wheel" "video" "docker" "jackaudio" "tss" "dialout" "docker" "plugdev" ]; shell = pkgs.zsh; - packages = []; + packages = [ ]; }; }; @@ -486,7 +587,7 @@ country=CA keep-outputs = true; keep-derivations = true; auto-optimise-store = true; - max-jobs = 4; + max-jobs = 4; cores = 0; substituters = [ "https://cache.nixos-cuda.org" diff --git a/nix/modules/default.nix b/nix/modules/default.nix index adf54b9..80c057f 100644 --- a/nix/modules/default.nix +++ b/nix/modules/default.nix @@ -7,27 +7,36 @@ options = { monorepo = { - profiles = { - cuda.enable = lib.mkEnableOption "Enables CUDA support"; - documentation.enable = lib.mkEnableOption "Enables documentation on system."; - secureBoot.enable = lib.mkEnableOption "Enables secure boot. See sbctl."; - pipewire.enable = lib.mkEnableOption "Enables pipewire low latency audio setup"; - tor.enable = lib.mkEnableOption "Enables tor along with torsocks"; - home.enable = lib.mkEnableOption "Enables home user"; - server.enable = lib.mkEnableOption "Enables server services"; + profiles = { + cuda.enable = lib.mkEnableOption "Enables CUDA support"; + documentation.enable = lib.mkEnableOption "Enables documentation on system."; + secureBoot.enable = lib.mkEnableOption "Enables secure boot. See sbctl."; + pipewire.enable = lib.mkEnableOption "Enables pipewire low latency audio setup"; + tor.enable = lib.mkEnableOption "Enables tor along with torsocks"; + + server = { + enable = lib.mkEnableOption "Enables server services"; + interface = lib.mkOption { type = lib.types.str; default = "eth0"; }; + ipv4 = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; + ipv6 = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; + gateway = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; }; + }; + ttyonly.enable = lib.mkEnableOption "TTY only, no xserver"; grub.enable = lib.mkEnableOption "Enables grub instead of systemd-boot"; workstation.enable = lib.mkEnableOption "Enables workstation services"; + desktop.enable = lib.mkEnableOption "Enables everything common to desktops"; impermanence.enable = lib.mkEnableOption "Enables imperamanence"; - }; + home.enable = lib.mkEnableOption "Enables home profiles"; + }; }; }; config = { environment.systemPackages = lib.mkIf config.monorepo.profiles.documentation.enable ((with pkgs; [ - linux-manual - man-pages - man-pages-posix + linux-manual + man-pages + man-pages-posix iproute2 silver-searcher ripgrep @@ -37,20 +46,37 @@ btrfs-snap btrfs-list btrfs-heatmap - ] else [])); + ] else [ ])); boot.loader.grub = lib.mkIf config.monorepo.profiles.grub.enable { enable = true; }; + assertions = [ + { + assertion = !(config.monorepo.profiles.workstation.enable && config.monorepo.profiles.server.enable); + message = '' + You can't enable both workstation and server profile together. Please select only one. + ''; + } + { + assertion = !(config.monorepo.profiles.desktop.enable && config.monorepo.profiles.server.enable); + message = '' + You can't enable both desktop and server profile together. Please select only one. + ''; + } + ]; monorepo = { - profiles = { - documentation.enable = lib.mkDefault true; - pipewire.enable = lib.mkDefault true; - tor.enable = lib.mkDefault true; - home.enable = lib.mkDefault true; + profiles = { + desktop.enable = lib.mkDefault config.monorepo.profiles.workstation.enable; + documentation.enable = lib.mkDefault true; + pipewire.enable = lib.mkDefault true; + tor.enable = lib.mkDefault true; impermanence.enable = lib.mkDefault false; - }; + server.enable = lib.mkDefault false; + ttyonly.enable = lib.mkDefault config.monorepo.profiles.server.enable; + home.enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + }; }; }; } diff --git a/nix/modules/git-daemon.nix b/nix/modules/git-daemon.nix index 5b79304..972ab67 100644 --- a/nix/modules/git-daemon.nix +++ b/nix/modules/git-daemon.nix @@ -5,4 +5,7 @@ exportAll = true; basePath = "${config.users.users.git.home}"; }; + networking.firewall.allowedTCPPorts = lib.mkIf config.services.gitDaemon.enable [ + 9418 + ]; } diff --git a/nix/modules/gitolite.nix b/nix/modules/gitolite.nix new file mode 100644 index 0000000..33f647b --- /dev/null +++ b/nix/modules/gitolite.nix @@ -0,0 +1,8 @@ +{ lib, config, ... }: +{ + services.gitolite = { + enable = lib.mkDefault config.monorepo.profiles.server.enable; + description = "My Gitolite User"; + adminPubkey = config.monorepo.vars.sshKey; + }; +} diff --git a/nix/modules/gotosocial.nix b/nix/modules/gotosocial.nix index 6b81128..b0a0c21 100644 --- a/nix/modules/gotosocial.nix +++ b/nix/modules/gotosocial.nix @@ -1,7 +1,7 @@ { lib, config, ... }: { services.gotosocial = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault false; setupPostgresqlDB = true; settings = { application-name = "Nullring GoToSocial Instance"; diff --git a/nix/modules/home/default.nix b/nix/modules/home/default.nix index 6e92c86..80b28ee 100644 --- a/nix/modules/home/default.nix +++ b/nix/modules/home/default.nix @@ -22,178 +22,198 @@ ./user.nix ./gtk.nix ./secrets.nix + ./pantalaimon.nix ]; options = { monorepo.profiles = { - enable = lib.mkEnableOption "Enables home manager desktop configuration"; - # Programs + enable = lib.mkEnableOption "Enables home manager desktop configuration"; + # Programs graphics.enable = lib.mkEnableOption "Enables graphical programs for user"; - lang-c.enable = lib.mkEnableOption "Enables C language support"; - lang-sh.enable = lib.mkEnableOption "Enables sh language support"; - lang-rust.enable = lib.mkEnableOption "Enables Rust language support"; - lang-python.enable = lib.mkEnableOption "Enables python language support"; - lang-sol.enable = lib.mkEnableOption "Enables solidity language support"; - lang-openscad.enable = lib.mkEnableOption "Enables openscad language support"; - lang-js.enable = lib.mkEnableOption "Enables javascript language support"; - lang-nix.enable = lib.mkEnableOption "Enables nix language support"; - lang-idris.enable = lib.mkEnableOption "Enables idris language support"; - lang-agda.enable = lib.mkEnableOption "Enables agda language support"; - lang-coq.enable = lib.mkEnableOption "Enables coq language support"; + lang-c.enable = lib.mkEnableOption "Enables C language support"; + lang-sh.enable = lib.mkEnableOption "Enables sh language support"; + lang-rust.enable = lib.mkEnableOption "Enables Rust language support"; + lang-python.enable = lib.mkEnableOption "Enables python language support"; + lang-sol.enable = lib.mkEnableOption "Enables solidity language support"; + lang-openscad.enable = lib.mkEnableOption "Enables openscad language support"; + lang-js.enable = lib.mkEnableOption "Enables javascript language support"; + lang-nix.enable = lib.mkEnableOption "Enables nix language support"; + lang-idris.enable = lib.mkEnableOption "Enables idris language support"; + lang-agda.enable = lib.mkEnableOption "Enables agda language support"; + lang-coq.enable = lib.mkEnableOption "Enables coq language support"; lang-lean.enable = lib.mkEnableOption "Enables lean language support"; - lang-haskell.enable = lib.mkEnableOption "Enables haskell language support"; - crypto.enable = lib.mkEnableOption "Enables various cryptocurrency wallets"; - art.enable = lib.mkEnableOption "Enables various art programs"; - music.enable = lib.mkEnableOption "Enables mpd"; - workstation.enable = lib.mkEnableOption "Enables workstation packages (music production and others)"; - cuda.enable = lib.mkEnableOption "Enables CUDA user package builds"; - hyprland.enable = lib.mkEnableOption "Enables hyprland"; - email.enable = lib.mkEnableOption "Enables email"; + lang-haskell.enable = lib.mkEnableOption "Enables haskell language support"; + crypto.enable = lib.mkEnableOption "Enables various cryptocurrency wallets"; + art.enable = lib.mkEnableOption "Enables various art programs"; + music.enable = lib.mkEnableOption "Enables mpd"; + workstation.enable = lib.mkEnableOption "Enables workstation packages (music production and others)"; + cuda.enable = lib.mkEnableOption "Enables CUDA user package builds"; + hyprland.enable = lib.mkEnableOption "Enables hyprland"; + email.enable = lib.mkEnableOption "Enables email"; }; }; config = { - home.packages = (if config.monorepo.profiles.email.enable then [ pkgs.mu ] else []) - ++ - (if config.monorepo.profiles.lang-c.enable then (with pkgs; [ - autobuild - clang - gdb - gnumake - bear - clang-tools - autotools-language-server - ]) else []) - ++ - (if config.monorepo.profiles.workstation.enable then (with pkgs; [ - mumble - ]) else []) - ++ - (if config.monorepo.profiles.lang-js.enable then (with pkgs; [ - nodejs - bun - yarn - typescript - typescript-language-server - vscode-langservers-extracted - ]) else []) - ++ - (if config.monorepo.profiles.lang-rust.enable then (with pkgs; [ - cargo - rust-analyzer - rustfmt - ]) else []) - ++ - (if config.monorepo.profiles.lang-python.enable then (with pkgs; [ - poetry - python3 - python314Packages.python-lsp-server - ]) else []) - ++ - (if config.monorepo.profiles.lang-sol.enable then (with pkgs; [ - solc - ]) else []) - ++ - (if config.monorepo.profiles.lang-openscad.enable then (with pkgs; [ - openscad - openscad-lsp - ]) else []) - ++ - (if config.monorepo.profiles.lang-sh.enable then (with pkgs; [ - bash-language-server - ]) else []) - ++ - (if config.monorepo.profiles.lang-haskell.enable then (with pkgs; [ - haskell-language-server - haskellPackages.hlint - ghc - ]) else []) - ++ - (if config.monorepo.profiles.lang-coq.enable then (with pkgs; [ - coq - ]) else []) - ++ - (if config.monorepo.profiles.lang-lean.enable then (with pkgs; [ - lean4 - ]) else []) - ++ - (if config.monorepo.profiles.lang-agda.enable then (with pkgs; [ - agda - ]) else []) - ++ - (if config.monorepo.profiles.lang-idris.enable then (with pkgs; [ - idris - idris2Packages.idris2Lsp - ]) else []) - ++ - (if config.monorepo.profiles.lang-nix.enable then (with pkgs; [ - nil - nixd - nixfmt - nix-prefetch-scripts - ]) else []) - ++ - (if config.monorepo.profiles.crypto.enable then (with pkgs; [ - bitcoin - # electrum - monero-cli - monero-gui - ]) else []) - ++ - (if config.monorepo.profiles.art.enable then (with pkgs; [ - inkscape - # krita - ]) else []) - ++ - (if config.monorepo.profiles.music.enable then (with pkgs; [ - mpc - sox - ]) else []) - ++ - (if config.monorepo.profiles.workstation.enable then (with pkgs; [ - alsa-utils - alsa-scarlett-gui - ardour - audacity - # blender - foxdot - fluidsynth - qjackctl - qsynth - qpwgraph - imagemagick - supercollider - inkscape - # kdePackages.kdenlive - # kicad - murmur - ]) else []); + home.packages = (if config.monorepo.profiles.email.enable then [ pkgs.mu ] else [ ]) + ++ + (if config.monorepo.profiles.lang-c.enable then + (with pkgs; [ + autobuild + clang + gdb + gnumake + bear + clang-tools + autotools-language-server + ]) else [ ]) + ++ + (if config.monorepo.profiles.workstation.enable then + (with pkgs; [ + mumble + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-js.enable then + (with pkgs; [ + nodejs + bun + yarn + typescript + typescript-language-server + vscode-langservers-extracted + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-rust.enable then + (with pkgs; [ + cargo + rust-analyzer + rustfmt + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-python.enable then + (with pkgs; [ + poetry + python3 + python314Packages.python-lsp-server + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-sol.enable then + (with pkgs; [ + solc + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-openscad.enable then + (with pkgs; [ + openscad + openscad-lsp + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-sh.enable then + (with pkgs; [ + bash-language-server + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-haskell.enable then + (with pkgs; [ + haskell-language-server + haskellPackages.hlint + ghc + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-coq.enable then + (with pkgs; [ + coq + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-lean.enable then + (with pkgs; [ + lean4 + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-agda.enable then + (with pkgs; [ + agda + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-idris.enable then + (with pkgs; [ + idris + idris2Packages.idris2Lsp + ]) else [ ]) + ++ + (if config.monorepo.profiles.lang-nix.enable then + (with pkgs; [ + nil + nixd + nixfmt + nix-prefetch-scripts + ]) else [ ]) + ++ + (if config.monorepo.profiles.crypto.enable then + (with pkgs; [ + bitcoin + # electrum + monero-cli + monero-gui + ]) else [ ]) + ++ + (if config.monorepo.profiles.art.enable then + (with pkgs; [ + inkscape + # krita + ]) else [ ]) + ++ + (if config.monorepo.profiles.music.enable then + (with pkgs; [ + mpc + sox + ]) else [ ]) + ++ + (if config.monorepo.profiles.workstation.enable then + (with pkgs; [ + alsa-utils + alsa-scarlett-gui + ardour + audacity + # blender + foxdot + fluidsynth + qjackctl + qsynth + qpwgraph + imagemagick + supercollider + inkscape + # kdePackages.kdenlive + # kicad + murmur + ]) else [ ]); monorepo.profiles = { - enable = lib.mkDefault true; - music.enable = lib.mkDefault config.monorepo.profiles.enable; - hyprland.enable = lib.mkDefault config.monorepo.profiles.enable; - email.enable = lib.mkDefault config.monorepo.profiles.enable; + enable = lib.mkDefault super.monorepo.profiles.home.enable; + music.enable = lib.mkDefault config.monorepo.profiles.enable; + email.enable = lib.mkDefault config.monorepo.profiles.enable; + cuda.enable = lib.mkDefault super.monorepo.profiles.cuda.enable; - # Programming + # Programming graphics.enable = lib.mkDefault (! super.monorepo.profiles.ttyonly.enable); - lang-c.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-rust.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-python.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-sol.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-sh.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-openscad.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-js.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-nix.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-coq.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-lean.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-haskell.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-idris.enable = lib.mkDefault config.monorepo.profiles.enable; - lang-agda.enable = lib.mkDefault config.monorepo.profiles.enable; + hyprland.enable = lib.mkDefault config.monorepo.profiles.graphics.enable; + lang-c.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-rust.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-python.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-sol.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-sh.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-openscad.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-js.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-nix.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-coq.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-lean.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-haskell.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-idris.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-agda.enable = lib.mkDefault config.monorepo.profiles.enable; - crypto.enable = lib.mkDefault config.monorepo.profiles.enable; - art.enable = lib.mkDefault config.monorepo.profiles.enable; - workstation.enable = lib.mkDefault config.monorepo.profiles.enable; + crypto.enable = lib.mkDefault config.monorepo.profiles.enable; + art.enable = lib.mkDefault config.monorepo.profiles.enable; + workstation.enable = lib.mkDefault super.monorepo.profiles.workstation.enable; }; }; } diff --git a/nix/modules/home/gtk.nix b/nix/modules/home/gtk.nix index 902f993..6283581 100644 --- a/nix/modules/home/gtk.nix +++ b/nix/modules/home/gtk.nix @@ -1,25 +1,27 @@ { lib, config, pkgs, ... }: { - gtk = { - theme = { - name = "catppuccin-mocha-pink-standard"; - package = pkgs.catppuccin-gtk.override { - variant = "mocha"; - accents = [ "pink" ]; + config = lib.mkIf config.monorepo.profiles.graphics.enable { + gtk = { + theme = { + name = "catppuccin-mocha-pink-standard"; + package = pkgs.catppuccin-gtk.override { + variant = "mocha"; + accents = [ "pink" ]; + }; }; }; - }; - xdg.configFile = { - "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets"; - "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css"; - "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css"; + xdg.configFile = { + "gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets"; + "gtk-4.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk.css"; + "gtk-4.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/gtk-dark.css"; - "gtk-3.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk.css"; - "gtk-3.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk-dark.css"; - "gtk-3.0/settings.ini".text = '' - [Settings] - gtk-theme-name=${config.gtk.theme.name} - gtk-application-prefer-dark-theme=1 - ''; + "gtk-3.0/gtk.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk.css"; + "gtk-3.0/gtk-dark.css".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-3.0/gtk-dark.css"; + "gtk-3.0/settings.ini".text = '' + [Settings] + gtk-theme-name=${config.gtk.theme.name} + gtk-application-prefer-dark-theme=1 + ''; + }; }; } diff --git a/nix/modules/home/pantalaimon.nix b/nix/modules/home/pantalaimon.nix index b3a4d42..35e72c3 100644 --- a/nix/modules/home/pantalaimon.nix +++ b/nix/modules/home/pantalaimon.nix @@ -1,7 +1,7 @@ { lib, config, ... }: { services.pantalaimon = { - enable = lib.mkDefault config.monorepo.profiles.enable; + enable = lib.mkDefault false; settings = { Default = { LogLevel = "Debug"; diff --git a/nix/modules/home/secrets.nix b/nix/modules/home/secrets.nix index 8de0f59..00be79b 100644 --- a/nix/modules/home/secrets.nix +++ b/nix/modules/home/secrets.nix @@ -1,33 +1,34 @@ { config, super, ... }: { sops = { - defaultSopsFile = if config.monorepo.profiles.graphics.enable - then ../../secrets/secrets.yaml - else ../../secrets/vps_secrets.yaml; + defaultSopsFile = + if config.monorepo.profiles.graphics.enable + then ../../secrets/secrets.yaml + else ../../secrets/vps_secrets.yaml; age = { keyFile = "/home/${super.monorepo.vars.userName}/.config/sops/age/keys.txt"; }; - secrets = if config.monorepo.profiles.graphics.enable then { - mail = { - format = "yaml"; - path = "${config.sops.defaultSymlinkPath}/mail"; - }; - cloudflare-dns = { - format = "yaml"; - path = "${config.sops.defaultSymlinkPath}/cloudflare-dns"; - }; - digikey = { - format = "yaml"; - path = "${config.sops.defaultSymlinkPath}/digikey"; - }; - dn42 = { - format = "yaml"; - path = "${config.sops.defaultSymlinkPath}/dn42"; - }; - } else { - }; + secrets = + if super.monorepo.profiles.desktop.enable then { + mail = { + format = "yaml"; + path = "${config.sops.defaultSymlinkPath}/mail"; + }; + cloudflare-dns = { + format = "yaml"; + path = "${config.sops.defaultSymlinkPath}/cloudflare-dns"; + }; + digikey = { + format = "yaml"; + path = "${config.sops.defaultSymlinkPath}/digikey"; + }; + dn42 = { + format = "yaml"; + path = "${config.sops.defaultSymlinkPath}/dn42"; + }; + } else { }; defaultSymlinkPath = "/run/user/1000/secrets"; defaultSecretsMountPoint = "/run/user/1000/secrets.d"; }; diff --git a/nix/modules/home/user.nix b/nix/modules/home/user.nix index fc8c2ae..d378fb6 100644 --- a/nix/modules/home/user.nix +++ b/nix/modules/home/user.nix @@ -2,24 +2,24 @@ { home = { activation.startup-files = lib.hm.dag.entryAfter [ "installPackages" ] '' - if [ ! -d "/home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/" ]; then - mkdir -p /home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/ - fi + if [ ! -d "/home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/" ]; then + mkdir -p /home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/ + fi - if [ ! -d "/home/${config.monorepo.vars.userName}/music" ]; then - mkdir -p /home/${config.monorepo.vars.userName}/music - fi + if [ ! -d "/home/${config.monorepo.vars.userName}/music" ]; then + mkdir -p /home/${config.monorepo.vars.userName}/music + fi - if [ ! -d /home/${config.monorepo.vars.userName}/org ]; then - mkdir -p /home/${config.monorepo.vars.userName}/org - fi + if [ ! -d /home/${config.monorepo.vars.userName}/org ]; then + mkdir -p /home/${config.monorepo.vars.userName}/org + fi - if [ ! -d /home/${config.monorepo.vars.userName}/src ]; then - mkdir -p /home/${config.monorepo.vars.userName}/src - fi + if [ ! -d /home/${config.monorepo.vars.userName}/src ]; then + mkdir -p /home/${config.monorepo.vars.userName}/src + fi - touch /home/${config.monorepo.vars.userName}/org/agenda.org - touch /home/${config.monorepo.vars.userName}/org/notes.org + touch /home/${config.monorepo.vars.userName}/org/agenda.org + touch /home/${config.monorepo.vars.userName}/org/notes.org ''; enableNixpkgsReleaseCheck = false; @@ -37,32 +37,61 @@ fzf # passwords - age sops + age + sops # formatting - ghostscript texliveFull pandoc + ghostscript + texliveFull + pandoc # Emacs Deps - graphviz jq + graphviz + jq # Apps # octaveFull - grim swww vim kotatogram-desktop tg qwen-code element-desktop signal-desktop signal-cli thunderbird jami + grim + swww + vim + kotatogram-desktop + tg + qwen-code + element-desktop + signal-desktop + signal-cli + thunderbird + jami # Sound/media - pavucontrol alsa-utils imagemagick ffmpeg helvum + pavucontrol + alsa-utils + imagemagick + ffmpeg + helvum # Net - curl rsync gitFull iamb ungoogled-chromium + curl + rsync + gitFull + iamb + ungoogled-chromium # Tor - torsocks tor-browser + torsocks + tor-browser # For transfering secrets onto new system stow # fonts - nerd-fonts.iosevka noto-fonts noto-fonts-cjk-sans noto-fonts-color-emoji fira-code font-awesome_6 victor-mono + nerd-fonts.iosevka + noto-fonts + noto-fonts-cjk-sans + noto-fonts-color-emoji + fira-code + font-awesome_6 + victor-mono (aspellWithDicts (dicts: with dicts; [ en en-computers en-science ])) @@ -77,60 +106,64 @@ (pkgs.writeShellScriptBin "help" '' -#!/usr/bin/env sh -# Portable, colored, nicely aligned alias list - -# Generate uncolored alias pairs -aliases=$(cat <<'EOF' -${let aliases = config.programs.zsh.shellAliases; - in lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: - "${name} -> ${value}" - ) aliases)} -EOF - ) - -# Align and color using awk -echo "$aliases" | awk ' -BEGIN { - GREEN="\033[0;32m"; - YELLOW="\033[0;33m"; - RESET="\033[0m"; - maxlen=0; - } -{ - # Split line on " -> " - split($0, parts, / -> /); - name[NR]=parts[1]; - cmd[NR]=parts[2]; - if(length(parts[1])>maxlen) maxlen=length(parts[1]); -} -END { - for(i=1;i<=NR;i++) { - # printf with fixed width for alias name - printf "%s%-*s%s -> %s%s%s\n", GREEN, maxlen, name[i], RESET, YELLOW, cmd[i], RESET; - } -}' -'') + #!/usr/bin/env sh + # Portable, colored, nicely aligned alias list + + # Generate uncolored alias pairs + aliases=$(cat <<'EOF' + ${let aliases = config.programs.zsh.shellAliases; + in lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: + "${name} -> ${value}" + ) aliases)} + EOF + ) + + # Align and color using awk + echo "$aliases" | awk ' + BEGIN { + GREEN="\033[0;32m"; + YELLOW="\033[0;33m"; + RESET="\033[0m"; + maxlen=0; + } + { + # Split line on " -> " + split($0, parts, / -> /); + name[NR]=parts[1]; + cmd[NR]=parts[2]; + if(length(parts[1])>maxlen) maxlen=length(parts[1]); + } + END { + for(i=1;i<=NR;i++) { + # printf with fixed width for alias name + printf "%s%-*s%s -> %s%s%s\n", GREEN, maxlen, name[i], RESET, YELLOW, cmd[i], RESET; + } + }' + '') (writeShellScriptBin "remote-build" '' -#!/bin/bash -nixos-rebuild --sudo --ask-sudo-password --target-host "$1" switch --flake $HOME/monorepo/nix#spontaneity -'' + #!/bin/bash + nixos-rebuild --sudo --ask-sudo-password --target-host "$1" switch --flake $HOME/monorepo/nix#spontaneity + '' ) (writeShellScriptBin "install-vps" '' -#!/bin/bash -nix run github:nix-community/nixos-anywhere -- --generate-hardware-config nixos-generate-config $HOME/monorepo/nix/systems/spontaneity/hardware-configuration.nix --flake $HOME/monorepo/nix#spontaneity --target-host "$1" + #!/bin/bash + nix run github:nix-community/nixos-anywhere -- --generate-hardware-config nixos-generate-config $HOME/monorepo/nix/systems/spontaneity/hardware-configuration.nix --flake $HOME/monorepo/nix#spontaneity --target-host "$1" '') (writeShellScriptBin "secrets" '' -#!/bin/bash -cd "$HOME/secrets" -git pull # repo is over LAN -stow */ # manage secrets with gnu stow -cd "$HOME" + #!/bin/bash + cd "$HOME/secrets" + git pull # repo is over LAN + stow */ # manage secrets with gnu stow + cd "$HOME" '') + (writeShellScriptBin "spontaneity-ci" + '' + #!/bin/bash + nixos-rebuild build-vm --flake $HOME/monorepo/nix#spontaneity && QEMU_OPTS="-serial stdio" ./result/bin/run-spontaneity-vm 2>&1 | tee vm-boot.log'') ] else [ pfetch # net @@ -145,22 +178,22 @@ cd "$HOME" pinentry.package = pkgs.pinentry-emacs; enable = true; extraConfig = '' - allow-emacs-pinentry - allow-loopback-pinentry - ''; + allow-emacs-pinentry + allow-loopback-pinentry + ''; }; }; xdg.mimeApps = { - enable = true; + enable = lib.mkDefault config.monorepo.profiles.graphics.enable; defaultApplications = { "x-scheme-handler/mailto" = "emacsclient-mail.desktop"; - "text/html" = "librewolf.desktop"; - "text/xml" = "librewolf.desktop"; - "application/xhtml+xml" = "librewolf.desktop"; - "x-scheme-handler/http" = "librewolf.desktop"; - "x-scheme-handler/https" = "librewolf.desktop"; - "x-scheme-handler/about" = "librewolf.desktop"; - "x-scheme-handler/unknown" = "librewolf.desktop"; + "text/html" = "librewolf.desktop"; + "text/xml" = "librewolf.desktop"; + "application/xhtml+xml" = "librewolf.desktop"; + "x-scheme-handler/http" = "librewolf.desktop"; + "x-scheme-handler/https" = "librewolf.desktop"; + "x-scheme-handler/about" = "librewolf.desktop"; + "x-scheme-handler/unknown" = "librewolf.desktop"; }; }; diff --git a/nix/modules/i2pd.nix b/nix/modules/i2pd.nix index ef4f63f..9e942fa 100644 --- a/nix/modules/i2pd.nix +++ b/nix/modules/i2pd.nix @@ -1,11 +1,9 @@ { config, lib, ... }: { services.i2pd = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault false; address = "0.0.0.0"; - inTunnels = { - }; - outTunnels = { - }; + inTunnels = { }; + outTunnels = { }; }; } diff --git a/nix/modules/icecast.nix b/nix/modules/icecast.nix index 0cef018..7d3d88d 100644 --- a/nix/modules/icecast.nix +++ b/nix/modules/icecast.nix @@ -1,21 +1,21 @@ { lib, config, ... }: { services.icecast = { - enable = lib.mkDefault config.monorepo.profiles.server.enable; + enable = lib.mkDefault false; listen.address = "0.0.0.0"; extraConfig = '' - - 0 - /stream.m3u - 3600 - - - -
- - -''; + + 0 + /stream.m3u + 3600 + + + +
+ + + ''; }; admin.password = "changeme"; } diff --git a/nix/modules/maddy.nix b/nix/modules/maddy.nix index a36e3b4..6cd2350 100644 --- a/nix/modules/maddy.nix +++ b/nix/modules/maddy.nix @@ -1,5 +1,17 @@ { lib, config, options, ... }: +let + emailServerName = "mail.${config.monorepo.vars.orgHost}"; + serverName = "list.${config.monorepo.vars.orgHost}"; + password_path = "mail_monorepo_password"; +in { + sops.secrets = lib.mkIf config.services.maddy.enable { + "${password_path}" = lib.mkIf config.services.maddy.enable { + format = "yaml"; + owner = "maddy"; + }; + }; + services.maddy = { enable = lib.mkDefault config.monorepo.profiles.server.enable; openFirewall = true; @@ -24,17 +36,161 @@ ] [ "imap tls://0.0.0.0:993 tcp://0.0.0.0:143" "submission tls://0.0.0.0:465 tcp://0.0.0.0:587" - ] options.services.maddy.config.default; + ] + options.services.maddy.config.default; + ensureAccounts = (builtins.map (x: "${x}@${config.monorepo.vars.orgHost}") config.monorepo.vars.projects) ++ [ "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" "discussion@${config.monorepo.vars.orgHost}" ]; - ensureCredentials = lib.genAttrs config.services.maddy.ensureAccounts (name: { - passwordFile = "/run/secrets/mail_monorepo_password"; - }) // { + ensureCredentials = lib.genAttrs config.services.maddy.ensureAccounts + (name: { + passwordFile = "/run/secrets/${password_path}"; + }) // { "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" = { passwordFile = "/run/secrets/mail_password"; }; }; }; + + systemd.tmpfiles.rules = [ + "C+ /var/lib/public-inbox/style.css 0644 public-inbox public-inbox - ${../data/public-inbox.css}" + ]; + systemd.services.public-inbox-httpd = + if config.monorepo.profiles.server.enable then { + preStart = '' + # Copy or link the file. + # Using 'cp' is often safer for sandboxed services than linking to the store. Lol. + cp -f ${../data/public-inbox.css} /var/lib/public-inbox/style.css + chmod 644 /var/lib/public-inbox/style.css + ''; + + serviceConfig = { + # Allow the service to see the file it just created + BindPaths = [ + "/var/lib/public-inbox" + "${config.users.users.git.home}" + ]; + ReadOnlyPaths = [ "/var/lib/public-inbox/style.css" ]; + # Ensure it can actually write to the directory during preStart + ReadWritePaths = [ "/var/lib/public-inbox" ]; + }; + } else { }; + + systemd.services.public-inbox-watch = + if config.monorepo.profiles.server.enable then { + after = [ "sops-nix.service" ]; + confinement.enable = lib.mkForce false; + preStart = '' + mkdir -p /var/lib/public-inbox/.tmp + chmod 0700 /var/lib/public-inbox/.tmp + ln -sfn ${config.sops.templates."public-inbox-netrc".path} /var/lib/public-inbox/.netrc + ''; + environment = { + PUBLIC_INBOX_FORCE_IPV4 = "1"; + NETRC = config.sops.templates."public-inbox-netrc".path; + HOME = "/var/lib/public-inbox"; + TMPDIR = "/var/lib/public-inbox/.tmp"; + }; + + serviceConfig = { + RestrictSUIDSGID = lib.mkForce false; + ReadWritePaths = [ "/var/lib/public-inbox" ]; + RestrictAddressFamilies = lib.mkForce [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + PrivateNetwork = lib.mkForce false; + SystemCallFilter = lib.mkForce [ ]; + RootDirectory = lib.mkForce ""; + + CapabilityBoundingSet = lib.mkForce [ "~" ]; + UMask = lib.mkForce "0022"; + ProtectSystem = lib.mkForce false; + }; + } else { }; + + services.public-inbox = { + enable = lib.mkDefault config.monorepo.profiles.server.enable; + settings = { + coderepo = lib.genAttrs config.monorepo.vars.projects (name: { + dir = "${config.users.users.git.home}/${name}.git"; + # works even if no cgit server running here, this is just the default + cgitUrl = "https://git.${config.monorepo.vars.orgHost}/${name}.git"; + }); + publicinbox.css = [ "/var/lib/public-inbox/style.css" ]; + publicinbox.wwwlisting = "all"; + }; + http = { + enable = true; + port = 9090; + }; + inboxes = lib.genAttrs config.monorepo.vars.projects + (name: { + description = "discussion of the ${name} project."; + address = [ "${name}@${config.monorepo.vars.orgHost}" ]; + inboxdir = "/var/lib/public-inbox/${name}"; + url = "https://list.${config.monorepo.vars.orgHost}/${name}"; + watch = [ "imaps://${name}${config.monorepo.vars.orgHost}@${emailServerName}/INBOX" ]; + coderepo = [ "${name}" ]; + }) // { + "discussion" = { + description = "Main Nullring Discussion Mailing List"; + address = [ "discussion@${config.monorepo.vars.orgHost}" ]; + inboxdir = "/var/lib/public-inbox/discuss"; + url = "https://${serverName}/discussion"; + watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@${emailServerName}/INBOX" ]; + }; + }; + }; + + networking.domains.baseDomains."${config.monorepo.vars.orgHost}" = lib.mkIf config.services.maddy.enable { + mx.data = [ + { + preference = 10; + exchange = "${emailServerName}"; + } + ]; + }; + + networking.domains.subDomains = lib.mkIf config.services.maddy.enable { + "${serverName}" = { }; + "${emailServerName}" = { }; + "_dmarc.${config.monorepo.vars.orgHost}" = { + txt = { + data = "v=DMARC1; p=none"; + }; + }; + "default._domainkey.${config.monorepo.vars.orgHost}" = { + txt = { + data = "v=DKIM1; k=rsa; p=${config.monorepo.vars.dkimKey}"; + }; + }; + }; + + networking.firewall.allowedTCPPorts = lib.mkIf config.services.maddy.enable [ + 143 + 465 + 587 + 993 + ]; + + services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.public-inbox.enable { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://localhost:${toString config.services.public-inbox.http.port}"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + + services.nginx.virtualHosts."${emailServerName}" = lib.mkIf config.services.maddy.enable { + serverName = "${emailServerName}"; + root = "/var/www/dummy"; + addSSL = true; + enableACME = true; + }; + } diff --git a/nix/modules/nginx.nix b/nix/modules/nginx.nix index 18fa1eb..f911fc1 100644 --- a/nix/modules/nginx.nix +++ b/nix/modules/nginx.nix @@ -1,222 +1,54 @@ { config, lib, ... }: { - config = lib.mkIf config.monorepo.profiles.server.enable { - services.nginx = { - enable = true; - user = "nginx"; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedTlsSettings = true; - recommendedProxySettings = false; - virtualHosts = { - "matrix.${config.monorepo.vars.orgHost}" = { - enableACME = config.monorepo.profiles.server.enable; - forceSSL = true; - listen = [ - { - addr = "0.0.0.0"; - port = 443; - ssl = true; - } - { - addr = "[::]"; - port = 443; - ssl = true; - } - { - addr = "0.0.0.0"; - port = 8448; - ssl = true; - } - { - addr = "[::]"; - port = 8448; - ssl = true; - } - ]; - locations."/_matrix/" = { - proxyPass = "http://127.0.0.1:6167"; - extraConfig = '' - proxy_set_header Host $host; - proxy_buffers 32 16k; - proxy_read_timeout 5m; - ''; - }; - locations."= /.well-known/matrix/server" = { - extraConfig = '' - default_type application/json; - add_header Content-Type application/json; - add_header Access-Control-Allow-Origin *; - ''; - - return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; - }; - locations."/.well-known/matrix/client" = { - extraConfig = '' - default_type application/json; - add_header Access-Control-Allow-Origin *; - ''; - - return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.${config.monorepo.vars.orgHost}\"}, \"org.matrix.msc4143.rtc_foci\": [{\"type\": \"livekit\", \"livekit_service_url\": \"https://matrix.${config.monorepo.vars.orgHost}:8443\"}]}'"; - }; + services.nginx = { + enable = lib.mkDefault config.monorepo.profiles.server.enable; + user = "nginx"; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + recommendedProxySettings = false; + virtualHosts = { + "${config.monorepo.vars.remoteHost}" = { + serverName = "${config.monorepo.vars.remoteHost}"; + serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ]; + root = "/var/www/${config.monorepo.vars.internetName}-website/"; + addSSL = true; + enableACME = true; + }; + # the port comes from ssh tunnelling + "music.${config.monorepo.vars.remoteHost}" = lib.mkIf config.monorepo.profiles.server.enable { + addSSL = true; + enableACME = true; + basicAuthFile = config.sops.secrets."mpd_password".path; + locations."/" = { + proxyPass = "http://localhost:8000"; extraConfig = '' - merge_slashes off; - ''; - }; - - "matrix.${config.monorepo.vars.orgHost}-livekit" = { - serverName = "matrix.${config.monorepo.vars.orgHost}"; - listen = [ - { - addr = "0.0.0.0"; - port = 8443; - ssl = true; - } - { - addr = "[::]"; - port = 8443; - ssl = true; - } - ]; - addSSL = true; - enableACME = false; - forceSSL = false; - useACMEHost = "matrix.${config.monorepo.vars.orgHost}"; - - locations."/" = { - proxyPass = "http://127.0.0.1:6495"; - proxyWebsockets = true; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; - }; - }; - - "livekit.${config.monorepo.vars.orgHost}" = { - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://127.0.0.1:7880"; - proxyWebsockets = true; - extraConfig = '' - proxy_read_timeout 3600s; - proxy_send_timeout 3600s; - - # Standard headers for LiveKit + proxy_buffering off; + proxy_http_version 1.1; + proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # --- CORS CONFIGURATION START --- - # 1. Allow all origins (including app.element.io) - add_header 'Access-Control-Allow-Origin' '*' always; - - # 2. Allow specific methods (POST is required for /sfu/get) - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; - - # 3. Allow headers (Content-Type is crucial for JSON) - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; - - # 4. Handle the OPTIONS preflight request immediately - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*' always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always; - add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain; charset=utf-8'; - add_header 'Content-Length' 0; - return 204; - } - # --- CORS CONFIGURATION END --- + proxy_read_timeout 36000s; ''; - }; - }; - - "ntfy.${config.monorepo.vars.remoteHost}" = { - serverName = "ntfy.${config.monorepo.vars.remoteHost}"; - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://127.0.0.1:2586"; - proxyWebsockets = true; - extraConfig = '' -proxy_buffering off; -proxy_request_buffering off - -proxy_set_header Host $host; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Proto $scheme; -''; - }; - }; - - "${config.monorepo.vars.remoteHost}" = { - serverName = "${config.monorepo.vars.remoteHost}"; - serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ]; - root = "/var/www/${config.monorepo.vars.internetName}-website/"; - addSSL = true; - enableACME = true; - }; - - "git.${config.monorepo.vars.orgHost}" = { - forceSSL = true; - enableACME = true; - }; - "list.${config.monorepo.vars.orgHost}" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://localhost:9090"; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - ''; - }; - }; - - # the port comes from ssh tunnelling - "music.${config.monorepo.vars.remoteHost}" = lib.mkIf config.monorepo.profiles.server.enable { - addSSL = true; - enableACME = true; - basicAuthFile = config.sops.secrets."mpd_password".path; - locations."/" = { - proxyPass = "http://localhost:8000"; - extraConfig = '' -proxy_buffering off; -proxy_http_version 1.1; -proxy_set_header Connection ""; -proxy_set_header Host $host; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_read_timeout 36000s; -''; - }; - }; - - "${config.monorepo.vars.orgHost}" = { - serverName = "${config.monorepo.vars.orgHost}"; - root = "/var/www/nullring/"; - addSSL = true; - enableACME = true; }; + }; - "mail.${config.monorepo.vars.orgHost}" = { - serverName = "mail.${config.monorepo.vars.orgHost}"; - root = "/var/www/dummy"; - addSSL = true; - enableACME = true; - }; + "${config.monorepo.vars.orgHost}" = { + serverName = "${config.monorepo.vars.orgHost}"; + root = "/var/www/nullring/"; + addSSL = true; + enableACME = true; }; }; }; + + networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ]; + + networking.domains.subDomains = lib.mkIf config.services.nginx.enable { + "${config.monorepo.vars.remoteHost}" = { }; + "${config.monorepo.vars.orgHost}" = { }; + "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = { }; + }; } diff --git a/nix/modules/ngircd.nix b/nix/modules/ngircd.nix index b6c6842..12c719e 100644 --- a/nix/modules/ngircd.nix +++ b/nix/modules/ngircd.nix @@ -3,26 +3,33 @@ services.ngircd = { enable = lib.mkDefault config.monorepo.profiles.server.enable; config = '' -[Global] - Name = ${config.monorepo.vars.orgHost} - Info = NullRing IRC Instance - Listen = ::,0.0.0.0 - MotdFile = /etc/motd.txt - Network = NullRing - Ports = 6667 -[Options] - PAM = no -[SSL] - CertFile = /var/lib/acme/${config.monorepo.vars.orgHost}/fullchain.pem - CipherList = HIGH:!aNULL:@STRENGTH:!SSLv3 - KeyFile = /var/lib/acme/${config.monorepo.vars.orgHost}/key.pem - Ports = 6697 -''; + [Global] + Name = ${config.monorepo.vars.orgHost} + Info = NullRing IRC Instance + Listen = ::,0.0.0.0 + MotdFile = /etc/motd.txt + Network = NullRing + Ports = 6667 + [Options] + PAM = no + [SSL] + CertFile = /var/lib/acme/${config.monorepo.vars.orgHost}/fullchain.pem + CipherList = HIGH:!aNULL:@STRENGTH:!SSLv3 + KeyFile = /var/lib/acme/${config.monorepo.vars.orgHost}/key.pem + Ports = 6697 + ''; }; + environment.etc."motd.txt" = { source = ../data/motd.txt; mode = "644"; user = "ngircd"; group = "ngircd"; }; + + networking.firewall.allowedTCPPorts = + if (config.services.ngircd.enable == true) then [ + 6697 + 6667 + ] else [ ]; } diff --git a/nix/modules/ntfy-sh.nix b/nix/modules/ntfy-sh.nix index 0eeac78..3cbab0e 100644 --- a/nix/modules/ntfy-sh.nix +++ b/nix/modules/ntfy-sh.nix @@ -1,19 +1,32 @@ { pkgs, lib, config, ... }: +let + serverName = "ntfy.${config.monorepo.vars.remoteHost}"; + port = 2586; + ntfySecret = "ntfy"; +in { + sops.secrets."${ntfySecret}" = lib.mkIf config.services.ntfy-sh.enable { + format = "yaml"; + owner = "ntfy-sh"; + }; + services.ntfy-sh = { enable = lib.mkDefault config.monorepo.profiles.server.enable; settings = { - base-url = "https://ntfy.${config.monorepo.vars.remoteHost}"; - listen-http = "127.0.0.1:2586"; - envrionmentFile = "/run/secrets/ntfy"; + base-url = "https://${serverName}"; + listen-http = "127.0.0.1:${toString port}"; + envrionmentFile = "/run/secrets/${ntfySecret}"; auth-file = "/var/lib/ntfy-sh/user.db"; auth-default-access = "deny-all"; enable-login = true; }; }; - systemd.services.ntfy-sh = { + + services.nginx.enable = config.services.ntfy-sh.enable; + + systemd.services.ntfy-sh = lib.mkIf config.services.ntfy-sh.enable { serviceConfig = { - EnvironmentFile = "/run/secrets/ntfy"; + EnvironmentFile = "/run/secrets/${ntfySecret}"; }; postStart = lib.mkForce '' # 1. Wait for the server to initialize the database @@ -45,4 +58,22 @@ fi ''; }; + + networking.domains.subDomains."${serverName}" = lib.mkIf config.services.ntfy-sh.enable { }; + services.nginx.virtualHosts."${serverName}" = lib.mkIf config.services.ntfy-sh.enable { + serverName = "${serverName}"; + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString port}"; + proxyWebsockets = true; + extraConfig = '' + proxy_buffering off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; } diff --git a/nix/modules/ollama.nix b/nix/modules/ollama.nix index 357f6a3..a9144ae 100644 --- a/nix/modules/ollama.nix +++ b/nix/modules/ollama.nix @@ -2,17 +2,18 @@ { # services.open-webui.enable = lib.mkDefault (!config.monorepo.profiles.server.enable); services.ollama = { - enable = lib.mkDefault (!config.monorepo.profiles.server.enable); - package = if (config.monorepo.profiles.workstation.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan; - loadModels = if (config.monorepo.profiles.workstation.enable) then [ - "qwen3:30b" - "qwen3-coder:latest" - "qwen2.5-coder:latest" - "gemma3:12b-it-qat" - ] else [ - "qwen3:0.6b" - "qwen2.5-coder:0.5b" - ]; + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + package = if (config.monorepo.profiles.cuda.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan; + loadModels = + if (config.monorepo.profiles.cuda.enable) then [ + "qwen3:30b" + "qwen3-coder:latest" + "qwen2.5-coder:latest" + "gemma3:12b-it-qat" + ] else [ + "qwen3:0.6b" + "qwen2.5-coder:0.5b" + ]; host = "0.0.0.0"; openFirewall = true; }; diff --git a/nix/modules/secrets.nix b/nix/modules/secrets.nix index f68ed40..dc0a7c3 100644 --- a/nix/modules/secrets.nix +++ b/nix/modules/secrets.nix @@ -1,134 +1,118 @@ { config, ... }: { sops = { - defaultSopsFile = if config.monorepo.profiles.server.enable - then ../secrets/vps_secrets.yaml - else ../secrets/secrets.yaml; + defaultSopsFile = + if config.monorepo.profiles.server.enable + then ../secrets/vps_secrets.yaml + else ../secrets/secrets.yaml; - templates = if config.monorepo.profiles.server.enable then { - "public-inbox-netrc" = { - owner = "public-inbox"; - group = "public-inbox"; - mode = "0400"; - content = (builtins.concatStringsSep "\n" (builtins.map (x: "machine mail.${config.monorepo.vars.orgHost} login ${x}@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}") config.monorepo.vars.projects)) + '' -machine mail.${config.monorepo.vars.orgHost} login discussion@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}''; - }; - "matterbridge" = { - owner = "matterbridge"; - content = '' -[irc.myirc] -Server="127.0.0.1:6667" -Nick="bridge" -RemoteNickFormat="[{PROTOCOL}] <{NICK}> " -UseTLS=false + templates = + if config.monorepo.profiles.server.enable then { + "public-inbox-netrc" = { + owner = "public-inbox"; + group = "public-inbox"; + mode = "0400"; + content = (builtins.concatStringsSep "\n" (builtins.map (x: "machine mail.${config.monorepo.vars.orgHost} login ${x}@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}") config.monorepo.vars.projects)) + '' + machine mail.${config.monorepo.vars.orgHost} login discussion@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}''; + }; + "matterbridge" = { + owner = "matterbridge"; + content = '' + [irc.myirc] + Server="127.0.0.1:6667" + Nick="bridge" + RemoteNickFormat="[{PROTOCOL}] <{NICK}> " + UseTLS=false -[telegram.mytelegram] -Token="${config.sops.placeholder.telegram_token}" -RemoteNickFormat="<({PROTOCOL}){NICK}> " -MessageFormat="HTMLNick :" -QuoteFormat="{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})" -QuoteLengthLimit=46 -IgnoreMessages="^/" + [telegram.mytelegram] + Token="${config.sops.placeholder.telegram_token}" + RemoteNickFormat="<({PROTOCOL}){NICK}> " + MessageFormat="HTMLNick :" + QuoteFormat="{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})" + QuoteLengthLimit=46 + IgnoreMessages="^/" -[discord.mydiscord] -Token="${config.sops.placeholder.discord_token}" -Server="Null Identity" -AutoWebHooks=true -RemoteNickFormat="[{PROTOCOL}] <{NICK}> " -PreserveThreading=true + [discord.mydiscord] + Token="${config.sops.placeholder.discord_token}" + Server="Null Identity" + AutoWebHooks=true + RemoteNickFormat="[{PROTOCOL}] <{NICK}> " + PreserveThreading=true -[[gateway]] -name="gateway1" -enable=true + [[gateway]] + name="gateway1" + enable=true -[[gateway.inout]] -account="irc.myirc" -channel="#nullring" + [[gateway.inout]] + account="irc.myirc" + channel="#nullring" -[[gateway.inout]] -account="discord.mydiscord" -channel="ID:996282946879242262" + [[gateway.inout]] + account="discord.mydiscord" + channel="ID:996282946879242262" -[[gateway.inout]] -account="telegram.mytelegram" -channel="-5290629325" -''; - }; - } else {}; + [[gateway.inout]] + account="telegram.mytelegram" + channel="-5290629325" + ''; + }; + } else { }; age = { keyFile = "/home/${config.monorepo.vars.userName}/.config/sops/age/keys.txt"; }; - secrets = if ! config.monorepo.profiles.server.enable then { - mail = { - format = "yaml"; - }; - cloudflare-dns = { - format = "yaml"; - }; - digikey = { - format = "yaml"; - }; - dn42 = { - format = "yaml"; - }; - } else { - znc = { - format = "yaml"; - }; - znc_password_salt = { - format = "yaml"; - }; - znc_password_hash = { - format = "yaml"; - }; - matrix_bridge = { - format = "yaml"; - }; - livekit_secret = { - format = "yaml"; - mode = "0444"; - }; - livekit = { - format = "yaml"; - }; - mail_password = { - format = "yaml"; - owner = "maddy"; - }; - - mail_monorepo_password = { - format = "yaml"; - owner = "maddy"; - }; + secrets = + if config.monorepo.profiles.desktop.enable then { + mail = { + format = "yaml"; + }; + cloudflare-dns = { + format = "yaml"; + }; + digikey = { + format = "yaml"; + }; + dn42 = { + format = "yaml"; + }; + } else { + znc = { + format = "yaml"; + }; + znc_password_salt = { + format = "yaml"; + }; + znc_password_hash = { + format = "yaml"; + }; + matrix_bridge = { + format = "yaml"; + }; + mail_password = { + format = "yaml"; + owner = "maddy"; + }; - mail_monorepo_password_pi = { - format = "yaml"; - owner = "public-inbox"; - }; + mail_monorepo_password_pi = { + format = "yaml"; + owner = "public-inbox"; + }; - conduit_secrets = { - format = "yaml"; - }; - mautrix_env = { - format = "yaml"; + mautrix_env = { + format = "yaml"; + }; + telegram_token = { + format = "yaml"; + }; + discord_token = { + format = "yaml"; + }; + mpd_password = { + format = "yaml"; + owner = "nginx"; + }; }; - telegram_token = { - format = "yaml"; - }; - discord_token = { - format = "yaml"; - }; - mpd_password = { - format = "yaml"; - owner = "nginx"; - }; - ntfy = { - format = "yaml"; - owner = "ntfy-sh"; - }; - }; }; } diff --git a/nix/modules/ssh.nix b/nix/modules/ssh.nix index db0ebd3..c816f1c 100644 --- a/nix/modules/ssh.nix +++ b/nix/modules/ssh.nix @@ -3,10 +3,11 @@ services.openssh = { enable = true; settings = { - PasswordAuthentication = lib.mkDefault (! config.monorepo.profiles.server.enable); - AllowUsers = [ config.monorepo.vars.userName "root" "git" ]; - PermitRootLogin = "prohibit-password"; + PasswordAuthentication = false; + AllowUsers = [ config.monorepo.vars.userName "git" ]; + PermitRootLogin = "no"; KbdInteractiveAuthentication = false; }; }; + networking.firewall.allowedTCPPorts = lib.mkIf config.services.openssh.enable [ 22 ]; } diff --git a/nix/modules/xserver.nix b/nix/modules/xserver.nix index 7bc40af..e3e0d9d 100644 --- a/nix/modules/xserver.nix +++ b/nix/modules/xserver.nix @@ -6,22 +6,22 @@ startx.enable = (! config.monorepo.profiles.ttyonly.enable); }; - windowManager = { - i3 = { - enable = (! config.monorepo.profiles.ttyonly.enable); - }; - }; + # windowManager = { + # i3 = { + # enable = (! config.monorepo.profiles.ttyonly.enable); + # }; + # }; desktopManager = { - runXdgAutostartIfNone = true; + runXdgAutostartIfNone = true; }; - xkb = { - layout = "us"; - variant = ""; - options = "caps:escape"; - }; + # xkb = { + # layout = "us"; + # variant = ""; + # options = "caps:escape"; + # }; - videoDrivers = (if config.monorepo.profiles.cuda.enable then [ "nvidia" ] else []); + videoDrivers = (if config.monorepo.profiles.cuda.enable then [ "nvidia" ] else [ ]); }; } diff --git a/nix/spontaneity.qcow2 b/nix/spontaneity.qcow2 new file mode 100644 index 0000000..7e34c11 Binary files /dev/null and b/nix/spontaneity.qcow2 differ diff --git a/nix/systems/affinity/default.nix b/nix/systems/affinity/default.nix index 755d6d8..33d6bc6 100644 --- a/nix/systems/affinity/default.nix +++ b/nix/systems/affinity/default.nix @@ -5,15 +5,9 @@ ../../disko/drive-simple.nix ]; config = { - zramSwap = { - enable = true; - algorithm = "zstd"; - memoryPercent = 50; - }; monorepo = { vars.device = "/dev/nvme0n1"; profiles = { - server.enable = false; cuda.enable = true; workstation.enable = true; }; diff --git a/nix/systems/affinity/home.nix b/nix/systems/affinity/home.nix index 7c8a119..59b05fc 100644 --- a/nix/systems/affinity/home.nix +++ b/nix/systems/affinity/home.nix @@ -3,7 +3,4 @@ imports = [ ../home-common.nix ]; - config.monorepo = { - profiles.cuda.enable = true; - }; } diff --git a/nix/systems/continuity/default.nix b/nix/systems/continuity/default.nix index 9433117..d4da62f 100644 --- a/nix/systems/continuity/default.nix +++ b/nix/systems/continuity/default.nix @@ -8,6 +8,7 @@ monorepo = { profiles = { impermanence.enable = true; + desktop.enable = true; }; vars = { device = "/dev/sda"; diff --git a/nix/systems/continuity/home.nix b/nix/systems/continuity/home.nix index 2b133a5..59b05fc 100644 --- a/nix/systems/continuity/home.nix +++ b/nix/systems/continuity/home.nix @@ -3,5 +3,4 @@ imports = [ ../home-common.nix ]; - config.monorepo.profiles.workstation.enable = false; } diff --git a/nix/systems/rpi-zero/default.nix b/nix/systems/rpi-zero/default.nix index f0e4dec..bb56332 100644 --- a/nix/systems/rpi-zero/default.nix +++ b/nix/systems/rpi-zero/default.nix @@ -14,7 +14,6 @@ monorepo = { vars.device = "/dev/mmcblk0"; profiles = { - server.enable = false; ttyonly.enable = true; }; }; diff --git a/nix/systems/spontaneity/default.nix b/nix/systems/spontaneity/default.nix index a7e78fc..823c7b9 100644 --- a/nix/systems/spontaneity/default.nix +++ b/nix/systems/spontaneity/default.nix @@ -1,151 +1,28 @@ { config, lib, ... }: - let - ipv4addr = "66.42.84.130"; - ipv6addr = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794"; - in - { - imports = [ - ../common.nix - ../../disko/drive-bios.nix - - # nixos-anywhere generates this file - ./hardware-configuration.nix - ]; - config = { - monorepo = { - vars.device = "/dev/vda"; - profiles = { - server.enable = true; - ttyonly.enable = true; - grub.enable = true; - pipewire.enable = false; - tor.enable = false; - home.enable = false; - }; - }; - - boot.loader.grub.device = "nodev"; - boot.kernel.sysctl = { - "net.ipv6.conf.ens3.autoconf" = 0; - # Keep accept_ra = 1 so you still get the default gateway/route! - "net.ipv6.conf.ens3.accept_ra" = 1; - }; - - systemd.network.enable = true; - systemd.network.networks."40-ens3" = { - matchConfig.Name = "ens3"; - networkConfig = { - IPv6AcceptRA = true; - IPv6PrivacyExtensions = false; - }; - ipv6AcceptRAConfig = { - UseAutonomousPrefix = false; - }; - }; - networking = { - useDHCP = lib.mkForce false; - networkmanager.enable = lib.mkForce false; - tempAddresses = "disabled"; - extraHosts = '' - 127.0.0.1 livekit.${config.monorepo.vars.orgHost} - 127.0.0.1 matrix.${config.monorepo.vars.orgHost} - ''; - interfaces.ens3.ipv4.addresses = [ - { - address = ipv4addr; - prefixLength = 24; - } - ]; - interfaces.ens3.useDHCP = lib.mkForce false; - interfaces.ens3.ipv6.addresses = [ - { - address = ipv6addr; - prefixLength = 64; - } - ]; - defaultGateway = "66.42.84.1"; - firewall = { - allowedTCPPorts = [ - 80 - 143 - 443 - 465 - 587 - 993 - 3478 - 5349 - 6697 - 6667 - 7881 - 8443 - 8448 - 9418 - ]; - allowedUDPPorts = [ - 3478 5349 7882 - ]; - allowedUDPPortRanges = [ - { from = 49152; to = 65535; } - ]; - }; - domains = { +{ + imports = [ + ../common.nix + ../../disko/drive-bios.nix + + # nixos-anywhere generates this file + ./hardware-configuration.nix + ]; + config = { + monorepo = { + vars.device = "/dev/vda"; + profiles = { + server = { enable = true; - baseDomains = { - "${config.monorepo.vars.remoteHost}" = { - a.data = ipv4addr; - aaaa.data = ipv6addr; - }; - "${config.monorepo.vars.orgHost}" = { - a.data = ipv4addr; - aaaa.data = ipv6addr; - - mx.data = [ - { - preference = 10; - exchange = "mail.${config.monorepo.vars.orgHost}"; - } - ]; - txt = { - data = "v=spf1 ip4:${ipv4addr} ip6:${ipv6addr} -all"; - }; - }; - }; - subDomains = { - "${config.monorepo.vars.remoteHost}" = {}; - "notes.${config.monorepo.vars.remoteHost}" = { - a.data = "45.76.87.125"; - }; - - "_dmarc.${config.monorepo.vars.orgHost}" = { - txt = { - data = "v=DMARC1; p=none"; - }; - }; - - "default._domainkey.${config.monorepo.vars.orgHost}" = { - txt = { - data = "v=DKIM1; k=rsa; p=${config.monorepo.vars.dkimKey}"; - }; - }; - - "ntfy.${config.monorepo.vars.remoteHost}" = {}; - "matrix.${config.monorepo.vars.remoteHost}" = {}; - "www.${config.monorepo.vars.remoteHost}" = {}; - "music.${config.monorepo.vars.remoteHost}" = {}; - "mail.${config.monorepo.vars.remoteHost}" = { - }; - - "livekit.${config.monorepo.vars.orgHost}" = {}; - "${config.monorepo.vars.orgHost}" = {}; - "git.${config.monorepo.vars.orgHost}" = {}; - "matrix.${config.monorepo.vars.orgHost}" = {}; - "social.${config.monorepo.vars.orgHost}" = {}; - "list.${config.monorepo.vars.orgHost}" = {}; - "talk.${config.monorepo.vars.orgHost}" = {}; - "mail.${config.monorepo.vars.orgHost}" = {}; - "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {}; - }; + ipv4 = "66.42.84.130"; + gateway = "66.42.84.1"; + ipv6 = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794"; + interface = "ens3"; }; + grub.enable = true; + pipewire.enable = false; + tor.enable = false; }; }; - } + boot.loader.grub.device = "nodev"; + }; +} diff --git a/nix/systems/spontaneity/home.nix b/nix/systems/spontaneity/home.nix index 205ea02..59b05fc 100644 --- a/nix/systems/spontaneity/home.nix +++ b/nix/systems/spontaneity/home.nix @@ -3,5 +3,4 @@ imports = [ ../home-common.nix ]; - config.monorepo.profiles.enable = false; } diff --git a/nix/vm-boot.log b/nix/vm-boot.log new file mode 100644 index 0000000..c2d5312 --- /dev/null +++ b/nix/vm-boot.log @@ -0,0 +1,26 @@ +Disk image does not exist, creating the virtualisation disk image... +Formatting '/tmp/tmp.ghXtpZvFNR', fmt=raw size=1073741824 +mke2fs 1.47.3 (8-Jul-2025) +Discarding device blocks: 0/262144 done +Creating filesystem with 262144 4k blocks and 65536 inodes +Filesystem UUID: 40fde25e-3bf6-4f1d-b38f-0f1e5bf5c63e +Superblock backups stored on blocks: + 32768, 98304, 163840, 229376 + +Allocating group tables: 0/8 done +Writing inode tables: 0/8 done +Creating journal (8192 blocks): done +Writing superblocks and filesystem accounting information: 0/8 done + +Virtualisation disk image created. +[ 2.098286] systemd-ssh-generator[405]: Failed to query local AF_VSOCK CID: Cannot assign requested address +[ 2.101053] (sd-exec-[393]: /nix/store/5j9cg6adv3d2l403fcfklz4lmf9fd0l8-systemd-258.3/lib/systemd/system-generators/systemd-ssh-generator failed with exit status 1. +[ 2.546593] systemd[1]: sops-nix.service: Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing. +[ 3.073461] kvm_intel: VMX not supported by CPU 0 +[!p]104[?7h[!p]104[?7h]3008;start=0f8977aca4ae4aceb248698121ee52a0;user=root;hostname=spontaneity;machineid=2deb26c4bda24c9d99e20bb2027746c7;bootid=bff39adaca784375af4c4c91ecca3ad9;pid=1436;pidfdid=1736;comm=(agetty);servicename=serial-getty@ttyS0.service;invocationid=9dc6890ff18e4f539a5c570df5f30b70;type=service\P+q6E616D65\ + +<<< Welcome to NixOS 26.05.20260204.00c21e4 (x86_64) - ttyS0 >>> + +Run 'nixos-help' for the NixOS manual. + +spontaneity login: \ No newline at end of file -- cgit v1.3