diff --git a/SwarselSystems.org b/SwarselSystems.org index 2b97d28..c6232e5 100644 --- a/SwarselSystems.org +++ b/SwarselSystems.org @@ -574,46 +574,15 @@ This section used to be much longer, since I performed all of my imports right h ]; }; - sandbox = nixpkgs.lib.nixosSystem { - specialArgs = { inherit inputs; }; - modules = [ - inputs.disko.nixosModules.disko - ./profiles/sandbox/disk-config.nix - inputs.sops-nix.nixosModules.sops - ./profiles/sandbox/nixos.nix - ]; - }; - - threed = nixpkgs.lib.nixosSystem { - specialArgs = { inherit inputs; }; - modules = nixModules ++ [ - inputs.lanzaboote.nixosModules.lanzaboote - ./profiles/threed/nixos.nix - inputs.home-manager.nixosModules.home-manager - { - home-manager.users.swarsel.imports = mixedModules ++ [ - ./profiles/threed/home.nix - ]; - } - ]; - }; - - fourside = lib.nixosSystem { - specialArgs = { inherit inputs outputs; }; - modules = nixModules ++ [ - ./profiles/fourside - ]; - }; - nbl-imba-2 = lib.nixosSystem { - specialArgs = { inherit inputs outputs; }; + specialArgs = { inherit self inputs outputs; }; modules = nixModules ++ [ ./profiles/nbl-imba-2 ]; }; winters = lib.nixosSystem { - specialArgs = { inherit inputs outputs; }; + specialArgs = { inherit self inputs outputs; }; modules = [ ./profiles/server/winters ]; @@ -4556,7 +4525,7 @@ Also, the system state version is set here. No need to touch it. **** sops -#+begin_src nix :tangle profiles/server/common/sops.nix +#+begin_src nix :tangle profiles/server/common/nixos/sops.nix { config, ... }: { sops = { @@ -4570,7 +4539,7 @@ Also, the system state version is set here. No need to touch it. **** nfs/samba (smb) -#+begin_src nix :tangle profiles/server/common/nfs.nix +#+begin_src nix :tangle profiles/server/common/nixos/nfs.nix { pkgs, ... }: { services = { @@ -4624,7 +4593,7 @@ Also, the system state version is set here. No need to touch it. **** NGINX -#+begin_src nix :tangle profiles/server/common/nginx.nix +#+begin_src nix :tangle profiles/server/common/nixos/nginx.nix { pkgs, config, ... }: { environment.systemPackages = with pkgs; [ @@ -4664,7 +4633,7 @@ Also, the system state version is set here. No need to touch it. **** ssh -#+begin_src nix :tangle profiles/server/common/ssh.nix +#+begin_src nix :tangle profiles/server/common/nixos/ssh.nix _: { services.openssh = { @@ -4685,7 +4654,7 @@ Also, the system state version is set here. No need to touch it. **** kavita -#+begin_src nix :tangle profiles/server/common/kavita.nix +#+begin_src nix :tangle profiles/server/common/nixos/kavita.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.kavita { @@ -4732,7 +4701,7 @@ Also, the system state version is set here. No need to touch it. **** jellyfin -#+begin_src nix :tangle profiles/server/common/jellyfin.nix +#+begin_src nix :tangle profiles/server/common/nixos/jellyfin.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.jellyfin { @@ -4781,7 +4750,7 @@ Also, the system state version is set here. No need to touch it. **** navidrome -#+begin_src nix :tangle profiles/server/common/navidrome.nix +#+begin_src nix :tangle profiles/server/common/nixos/navidrome.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.navidrome { @@ -4837,7 +4806,8 @@ Also, the system state version is set here. No need to touch it. [ "pch" "alsa/sysdefault:CARD=PCH" ] ]; }; - # Insert these values locally as sops-nix does not work for them + # Switch using --impure as these credential files are not stored within the flake + # sops-nix is not supported for these which is why we need to resort to these LastFM.ApiKey = builtins.readFile /home/swarsel/api/lastfm-secret; LastFM.Secret = builtins.readFile /home/swarsel/api/lastfm-key; Spotify.ID = builtins.readFile /home/swarsel/api/spotify-id; @@ -4878,7 +4848,7 @@ Also, the system state version is set here. No need to touch it. **** spotifyd -#+begin_src nix :tangle profiles/server/common/spotifyd.nix +#+begin_src nix :tangle profiles/server/common/nixos/spotifyd.nix { lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.spotifyd { @@ -4917,7 +4887,7 @@ Also, the system state version is set here. No need to touch it. **** mpd -#+begin_src nix :tangle profiles/server/common/mpd.nix +#+begin_src nix :tangle profiles/server/common/nixos/mpd.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.mpd { @@ -4973,7 +4943,7 @@ Also, the system state version is set here. No need to touch it. **** matrix -#+begin_src nix :tangle profiles/server/common/matrix.nix +#+begin_src nix :tangle profiles/server/common/nixos/matrix.nix { config, lib, pkgs, sops, ... }: let matrixDomain = "swatrix.swarsel.win"; @@ -5296,7 +5266,7 @@ Also, the system state version is set here. No need to touch it. **** nextcloud -#+begin_src nix :tangle profiles/server/common/nextcloud.nix +#+begin_src nix :tangle profiles/server/common/nixos/nextcloud.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.nextcloud { @@ -5344,7 +5314,7 @@ Also, the system state version is set here. No need to touch it. **** immich -#+begin_src nix :tangle profiles/server/common/immich.nix +#+begin_src nix :tangle profiles/server/common/nixos/immich.nix { lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.immich { @@ -5398,7 +5368,7 @@ Also, the system state version is set here. No need to touch it. **** paperless -#+begin_src nix :tangle profiles/server/common/paperless.nix +#+begin_src nix :tangle profiles/server/common/nixos/paperless.nix { lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.paperless { @@ -5453,7 +5423,7 @@ Also, the system state version is set here. No need to touch it. **** transmission -#+begin_src nix :tangle profiles/server/common/transmission.nix +#+begin_src nix :tangle profiles/server/common/nixos/transmission.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.transmission { @@ -5591,7 +5561,7 @@ Also, the system state version is set here. No need to touch it. **** syncthing -#+begin_src nix :tangle profiles/server/common/syncthing.nix +#+begin_src nix :tangle profiles/server/common/nixos/syncthing.nix { lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.syncthing { @@ -5700,7 +5670,7 @@ Also, the system state version is set here. No need to touch it. **** restic -#+begin_src nix :tangle profiles/server/common/restic.nix +#+begin_src nix :tangle profiles/server/common/nixos/restic.nix { lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.restic { @@ -5713,7 +5683,7 @@ Also, the system state version is set here. No need to touch it. **** monitoring -#+begin_src nix :tangle profiles/server/common/monitoring.nix +#+begin_src nix :tangle profiles/server/common/nixos/monitoring.nix { lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.monitoring { @@ -5878,7 +5848,7 @@ Also, the system state version is set here. No need to touch it. **** Jenkins -#+begin_src nix :tangle profiles/server/common/jenkins.nix +#+begin_src nix :tangle profiles/server/common/nixos/jenkins.nix { pkgs, lib, config, ... }: { config = lib.mkIf config.swarselsystems.server.jenkins { diff --git a/profiles/server/common/home/default.nix b/profiles/server/common/home/default.nix new file mode 100644 index 0000000..76457ef --- /dev/null +++ b/profiles/server/common/home/default.nix @@ -0,0 +1,10 @@ +{ self, ... }: +let + profilesPath = "${self}/profiles"; +in +{ + imports = [ + "${profilesPath}/common/home/settings.nix" + ./symlink.nix + ]; +} diff --git a/profiles/server/common/home/symlink.nix b/profiles/server/common/home/symlink.nix new file mode 100644 index 0000000..0ddf9f6 --- /dev/null +++ b/profiles/server/common/home/symlink.nix @@ -0,0 +1,9 @@ +{ self, ... }: +{ + home.file = { + "init.el" = { + source = self + /programs/emacs/server.el; + target = ".emacs.d/init.el"; + }; + }; +} diff --git a/profiles/server/common/nixos/calibre.nix b/profiles/server/common/nixos/calibre.nix new file mode 100644 index 0000000..c450c4c --- /dev/null +++ b/profiles/server/common/nixos/calibre.nix @@ -0,0 +1,32 @@ +{ pkgs, config, ... }: +{ + environment.systemPackages = with pkgs; [ + calibre + ]; + + sops.secrets.kavita = { owner = "kavita"; }; + + services.kavita = { + enable = true; + user = "kavita"; + port = 8080; + tokenKeyFile = config.sops.secrets.kavita.path; + }; + + services.nginx = { + "scroll.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://192.168.1.22:8080"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/default.nix b/profiles/server/common/nixos/default.nix new file mode 100644 index 0000000..c675105 --- /dev/null +++ b/profiles/server/common/nixos/default.nix @@ -0,0 +1,37 @@ +{ self, ... }: +let + profilesPath = "${self}/profiles"; +in +{ + imports = [ + "${profilesPath}/common/nixos/settings.nix" + "${profilesPath}/common/nixos/xserver.nix" + "${profilesPath}/common/nixos/gc.nix" + "${profilesPath}/common/nixos/store.nix" + "${profilesPath}/common/nixos/time.nix" + "${profilesPath}/common/nixos/pipewire.nix" + "${profilesPath}/common/nixos/users.nix" + "${profilesPath}/common/nixos/nix-ld.nix" + ./settings.nix + ./packages.nix + ./sops.nix + ./ssh.nix + ./nfs.nix + ./nginx.nix + ./kavita.nix + ./jellyfin.nix + ./navidrome.nix + ./spotifyd.nix + ./mpd.nix + ./matrix.nix + ./nextcloud.nix + ./immich.nix + ./paperless.nix + ./transmission.nix + ./syncthing.nix + ./restic.nix + ./monitoring.nix + ./jenkins.nix + ./emacs.nix + ]; +} diff --git a/profiles/server/common/nixos/emacs.nix b/profiles/server/common/nixos/emacs.nix new file mode 100644 index 0000000..f4f6606 --- /dev/null +++ b/profiles/server/common/nixos/emacs.nix @@ -0,0 +1,29 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.emacs { + + services.emacs = { + enable = true; + startWithGraphical = false; + }; + + services.nginx = { + virtualHosts = { + "signpost.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:54169"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/immich.nix b/profiles/server/common/nixos/immich.nix new file mode 100644 index 0000000..385db13 --- /dev/null +++ b/profiles/server/common/nixos/immich.nix @@ -0,0 +1,49 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.immich { + + users.users.immich = { + extraGroups = [ "video" "render" "users" ]; + }; + + # sops.secrets.nextcloudadminpass = { owner = "nextcloud"; }; + + services.immich = { + enable = true; + port = 3001; + openFirewall = true; + mediaLocation = "/Vault/Eternor/Immich"; + environment.IMMICH_MACHINE_LEARNING_URL = lib.mkForce "http://localhost:3003"; + }; + + + services.nginx = { + virtualHosts = { + "shots.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:3001"; + extraConfig = '' + client_max_body_size 0; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_redirect off; + + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + ''; + }; + }; + }; + }; + }; + + }; + +} diff --git a/profiles/server/common/nixos/jellyfin.nix b/profiles/server/common/nixos/jellyfin.nix new file mode 100644 index 0000000..8f07590 --- /dev/null +++ b/profiles/server/common/nixos/jellyfin.nix @@ -0,0 +1,44 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.jellyfin { + users.users.jellyfin = { + extraGroups = [ "video" "render" "users" ]; + }; + nixpkgs.config.packageOverrides = pkgs: { + vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; }; + }; + hardware.graphics = { + enable = true; + extraPackages = with pkgs; [ + intel-media-driver # LIBVA_DRIVER_NAME=iHD + vaapiIntel # LIBVA_DRIVER_NAME=i965 (older but works better for Firefox/Chromium) + vaapiVdpau + libvdpau-va-gl + ]; + }; + services.jellyfin = { + enable = true; + user = "jellyfin"; + openFirewall = true; # this works only for the default ports + }; + + services.nginx = { + virtualHosts = { + "screen.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:8096"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/jenkins.nix b/profiles/server/common/nixos/jenkins.nix new file mode 100644 index 0000000..525a808 --- /dev/null +++ b/profiles/server/common/nixos/jenkins.nix @@ -0,0 +1,35 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.jenkins { + + services.jenkins = { + enable = true; + withCLI = true; + port = 8088; + packages = [ pkgs.stdenv pkgs.git pkgs.jdk17 config.programs.ssh.package pkgs.nix ]; + listenAddress = "127.0.0.1"; + home = "/Vault/apps/jenkins"; + }; + + + + services.nginx = { + virtualHosts = { + "servant.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:8088"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/kavita.nix b/profiles/server/common/nixos/kavita.nix new file mode 100644 index 0000000..1ec45a9 --- /dev/null +++ b/profiles/server/common/nixos/kavita.nix @@ -0,0 +1,42 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.kavita { + environment.systemPackages = with pkgs; [ + calibre + ]; + + + users.users.jellyfin = { + extraGroups = [ "users" ]; + }; + + sops.secrets.kavita = { owner = "kavita"; }; + + networking.firewall.allowedTCPPorts = [ 8080 ]; + + services.kavita = { + enable = true; + user = "kavita"; + settings.Port = 8080; + tokenKeyFile = config.sops.secrets.kavita.path; + }; + + services.nginx = { + virtualHosts = { + "scroll.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:8080"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; +} diff --git a/profiles/server/common/nixos/matrix.nix b/profiles/server/common/nixos/matrix.nix new file mode 100644 index 0000000..bf17ecf --- /dev/null +++ b/profiles/server/common/nixos/matrix.nix @@ -0,0 +1,317 @@ +{ config, lib, pkgs, sops, ... }: +let + matrixDomain = "swatrix.swarsel.win"; + baseUrl = "https://${matrixDomain}"; + clientConfig."m.homeserver".base_url = baseUrl; + serverConfig."m.server" = "${matrixDomain}:443"; + mkWellKnown = data: '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '${builtins.toJSON data}'; + ''; +in +{ + + config = lib.mkIf config.swarselsystems.server.matrix { + environment.systemPackages = with pkgs; [ + matrix-synapse + lottieconverter + ffmpeg + ]; + + sops = { + secrets = { + matrixsharedsecret = { owner = "matrix-synapse"; }; + mautrixtelegram_as = { owner = "matrix-synapse"; }; + mautrixtelegram_hs = { owner = "matrix-synapse"; }; + mautrixtelegram_api_id = { owner = "matrix-synapse"; }; + mautrixtelegram_api_hash = { owner = "matrix-synapse"; }; + }; + templates = { + "matrix_user_register.sh".content = '' + register_new_matrix_user -k ${config.sops.placeholder.matrixsharedsecret} http://localhost:8008 + ''; + matrixshared = { + owner = "matrix-synapse"; + content = '' + registration_shared_secret: ${config.sops.placeholder.matrixsharedsecret} + ''; + }; + mautrixtelegram = { + owner = "matrix-synapse"; + content = '' + MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN=${config.sops.placeholder.mautrixtelegram_as} + MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN=${config.sops.placeholder.mautrixtelegram_hs} + MAUTRIX_TELEGRAM_TELEGRAM_API_ID=${config.sops.placeholder.mautrixtelegram_api_id} + MAUTRIX_TELEGRAM_TELEGRAM_API_HASH=${config.sops.placeholder.mautrixtelegram_api_hash} + ''; + }; + }; + }; + + services.postgresql = { + enable = true; + initialScript = pkgs.writeText "synapse-init.sql" '' + CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; + CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + CREATE ROLE "mautrix-telegram" WITH LOGIN PASSWORD 'telegram'; + CREATE DATABASE "mautrix-telegram" WITH OWNER "mautrix-telegram" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + CREATE ROLE "mautrix-whatsapp" WITH LOGIN PASSWORD 'whatsapp'; + CREATE DATABASE "mautrix-whatsapp" WITH OWNER "mautrix-whatsapp" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + CREATE ROLE "mautrix-signal" WITH LOGIN PASSWORD 'signal'; + CREATE DATABASE "mautrix-signal" WITH OWNER "mautrix-signal" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + ''; + }; + + services.matrix-synapse = { + enable = true; + settings = { + app_service_config_files = [ + "/var/lib/matrix-synapse/telegram-registration.yaml" + "/var/lib/matrix-synapse/whatsapp-registration.yaml" + "/var/lib/matrix-synapse/signal-registration.yaml" + "/var/lib/matrix-synapse/doublepuppet.yaml" + ]; + server_name = matrixDomain; + public_baseurl = "https://${matrixDomain}"; + listeners = [ + { + port = 8008; + bind_addresses = [ + "127.0.0.1" + "::1" + ]; + type = "http"; + tls = false; + x_forwarded = true; + resources = [ + { + names = [ "client" "federation" ]; + compress = true; + } + ]; + } + ]; + }; + extraConfigFiles = [ + config.sops.templates.matrixshared.path + ]; + }; + + services.mautrix-telegram = { + enable = true; + environmentFile = config.sops.templates.mautrixtelegram.path; + settings = { + homeserver = { + address = "http://localhost:8008"; + domain = matrixDomain; + }; + appservice = { + address = "http://localhost:29317"; + hostname = "localhost"; + port = "29317"; + provisioning.enabled = true; + id = "telegram"; + # ephemeral_events = true; # not needed due to double puppeting + public = { + enabled = false; + }; + database = "postgresql:///mautrix-telegram?host=/run/postgresql"; + }; + bridge = { + relaybot.authless_portals = true; + allow_avatar_remove = true; + allow_contact_info = true; + sync_channel_members = true; + startup_sync = true; + sync_create_limit = 0; + sync_direct_chats = true; + telegram_link_preview = true; + permissions = { + "*" = "relaybot"; + "@swarsel:${matrixDomain}" = "admin"; + }; + animated_sticker = { + target = "gif"; + args = { + width = 256; + height = 256; + fps = 30; # only for webm + background = "020202"; # only for gif, transparency not supported + }; + }; + }; + }; + }; + systemd.services.mautrix-telegram.path = with pkgs; [ + lottieconverter # for animated stickers conversion, unfree package + ffmpeg # if converting animated stickers to webm (very slow!) + ]; + + services.mautrix-whatsapp = { + enable = true; + registerToSynapse = false; + settings = { + homeserver = { + address = "http://localhost:8008"; + domain = matrixDomain; + }; + appservice = { + address = "http://localhost:29318"; + hostname = "127.0.0.1"; + port = 29318; + database = { + type = "postgres"; + uri = "postgresql:///mautrix-whatsapp?host=/run/postgresql"; + }; + }; + bridge = { + displayname_template = "{{or .FullName .PushName .JID}} (WA)"; + history_sync = { + backfill = true; + max_initial_conversations = -1; + message_count = -1; + request_full_sync = true; + full_sync_config = { + days_limit = 900; + size_mb_limit = 5000; + storage_quota_mb = 5000; + }; + }; + login_shared_secret_map = { + matrixDomain = "as_token:doublepuppet"; + }; + sync_manual_marked_unread = true; + send_presence_on_typing = true; + parallel_member_sync = true; + url_previews = true; + caption_in_message = true; + extev_polls = true; + permissions = { + "*" = "relaybot"; + "@swarsel:${matrixDomain}" = "admin"; + }; + }; + }; + }; + + services.mautrix-signal = { + enable = true; + registerToSynapse = false; + settings = { + homeserver = { + address = "http://localhost:8008"; + domain = matrixDomain; + }; + appservice = { + + address = "http://localhost:29328"; + hostname = "127.0.0.1"; + port = 29328; + database = { + type = "postgres"; + uri = "postgresql:///mautrix-signal?host=/run/postgresql"; + }; + }; + bridge = { + displayname_template = "{{or .ContactName .ProfileName .PhoneNumber}} (Signal)"; + login_shared_secret_map = { + matrixDomain = "as_token:doublepuppet"; + }; + caption_in_message = true; + permissions = { + "*" = "relay"; + "@swarsel:${matrixDomain}" = "admin"; + }; + }; + }; + }; + + # restart the bridges daily. this is done for the signal bridge mainly which stops carrying + # messages out after a while. + + systemd.timers."restart-bridges" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "1d"; + OnUnitActiveSec = "1d"; + Unit = "restart-bridges.service"; + }; + }; + + systemd.services."restart-bridges" = { + script = '' + systemctl restart mautrix-whatsapp.service + systemctl restart mautrix-signal.service + systemctl restart mautrix-telegram.service + ''; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + }; + + services.nginx = { + virtualHosts = { + "swatrix.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + listen = [ + { + addr = "0.0.0.0"; + port = 8448; + ssl = true; + extraParameters = [ + "default_server" + ]; + } + { + addr = "[::0]"; + port = 8448; + ssl = true; + extraParameters = [ + "default_server" + ]; + } + { + addr = "0.0.0.0"; + port = 443; + ssl = true; + } + { + addr = "[::0]"; + port = 443; + ssl = true; + } + ]; + locations = { + "~ ^(/_matrix|/_synapse/client)" = { + # proxyPass = "http://localhost:8008"; + proxyPass = "http://localhost:8008"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; + "= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; + }; + }; + }; + }; + }; + + +} diff --git a/profiles/server/common/nixos/monitoring.nix b/profiles/server/common/nixos/monitoring.nix new file mode 100644 index 0000000..35cb5ed --- /dev/null +++ b/profiles/server/common/nixos/monitoring.nix @@ -0,0 +1,160 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.monitoring { + + sops.secrets = { + grafanaadminpass = { + owner = "grafana"; + }; + prometheusadminpass = { + owner = "grafana"; + }; + }; + + users.users.nextcloud-exporter = { + extraGroups = [ "nextcloud" ]; + }; + + users.users.grafana = { + extraGroups = [ "users" ]; + }; + + services.grafana = { + enable = true; + dataDir = "/Vault/data/grafana"; + provision = { + enable = true; + datasources.settings = { + datasources = [ + { + name = "prometheus"; + type = "prometheus"; + url = "https://status.swarsel.win/prometheus"; + editable = false; + access = "proxy"; + basicAuth = true; + basicAuthUser = "admin"; + jsonData = { + httpMethod = "POST"; + manageAlerts = true; + prometheusType = "Prometheus"; + prometheusVersion = "> 2.50.x"; + cacheLevel = "High"; + disableRecordingRules = false; + incrementalQueryOverlapWindow = "10m"; + }; + secureJsonData = { + basicAuthPassword = "$__file{/run/secrets/prometheusadminpass}"; + }; + } + ]; + }; + }; + + settings = { + security.admin_password = "$__file{/run/secrets/grafanaadminpass}"; + server = { + http_port = 3000; + http_addr = "127.0.0.1"; + protocol = "http"; + domain = "status.swarsel.win"; + }; + }; + }; + + services.prometheus = { + enable = true; + webExternalUrl = "https://status.swarsel.win/prometheus"; + port = 9090; + listenAddress = "127.0.0.1"; + globalConfig = { + scrape_interval = "10s"; + }; + webConfigFile = ../../../programs/server/prometheus/web.config; + scrapeConfigs = [ + { + job_name = "node"; + static_configs = [{ + targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; + }]; + } + { + job_name = "zfs"; + static_configs = [{ + targets = [ "localhost:${toString config.services.prometheus.exporters.zfs.port}" ]; + }]; + } + { + job_name = "nginx"; + static_configs = [{ + targets = [ "localhost:${toString config.services.prometheus.exporters.nginx.port}" ]; + }]; + } + { + job_name = "nextcloud"; + static_configs = [{ + targets = [ "localhost:${toString config.services.prometheus.exporters.nextcloud.port}" ]; + }]; + } + ]; + exporters = { + node = { + enable = true; + port = 9000; + enabledCollectors = [ "systemd" ]; + extraFlags = [ "--collector.ethtool" "--collector.softirqs" "--collector.tcpstat" "--collector.wifi" ]; + }; + zfs = { + enable = true; + port = 9134; + pools = [ + "Vault" + ]; + }; + restic = { + enable = false; + port = 9753; + }; + nginx = { + enable = true; + port = 9113; + sslVerify = false; + scrapeUri = "http://localhost/nginx_status"; + }; + nextcloud = lib.mkIf config.swarselsystems.server.nextcloud { + enable = true; + port = 9205; + url = "https://stash.swarsel.win/ocs/v2.php/apps/serverinfo/api/v1/info"; + username = "admin"; + passwordFile = config.sops.secrets.nextcloudadminpass.path; + }; + }; + }; + + + services.nginx = { + virtualHosts = { + "status.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:3000"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "/prometheus" = { + proxyPass = "http://localhost:9090"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/mpd.nix b/profiles/server/common/nixos/mpd.nix new file mode 100644 index 0000000..0380143 --- /dev/null +++ b/profiles/server/common/nixos/mpd.nix @@ -0,0 +1,51 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.mpd { + users = { + groups = { + mpd = { }; + }; + + users = { + mpd = { + isSystemUser = true; + group = "mpd"; + extraGroups = [ "audio" "utmp" ]; + }; + }; + }; + + sops = { + secrets.mpdpass = { owner = "mpd"; }; + }; + + environment.systemPackages = with pkgs; [ + pciutils + alsa-utils + mpv + ]; + + services.mpd = { + enable = true; + musicDirectory = "/media"; + user = "mpd"; + group = "mpd"; + network = { + port = 3254; + listenAddress = "any"; + }; + credentials = [ + { + passwordFile = config.sops.secrets.mpdpass.path; + permissions = [ + "read" + "add" + "control" + "admin" + ]; + } + ]; + }; + }; + +} diff --git a/profiles/server/common/nixos/navidrome.nix b/profiles/server/common/nixos/navidrome.nix new file mode 100644 index 0000000..61798f9 --- /dev/null +++ b/profiles/server/common/nixos/navidrome.nix @@ -0,0 +1,93 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.navidrome { + environment.systemPackages = with pkgs; [ + pciutils + alsa-utils + mpv + ]; + + users = { + groups = { + navidrome = { + gid = 61593; + }; + }; + + users = { + navidrome = { + isSystemUser = true; + uid = 61593; + group = "navidrome"; + extraGroups = [ "audio" "utmp" "users" "pipewire" ]; + }; + }; + }; + + + hardware = { + # opengl.enable = true; + enableAllFirmware = true; + }; + + networking.firewall.allowedTCPPorts = [ 4040 ]; + + services.navidrome = { + enable = true; + openFirewall = true; + settings = { + LogLevel = "error"; + Address = "127.0.0.1"; + Port = 4040; + MusicFolder = "/Vault/Eternor/Musik"; + EnableSharing = true; + EnableTranscodingConfig = true; + Scanner.GroupAlbumReleases = true; + ScanSchedule = "@every 24h"; + MPVPath = "${pkgs.mpv}/bin/mpv"; + MPVCommandTemplate = "mpv --audio-device=%d --no-audio-display --pause %f"; + Jukebox = { + Enabled = true; + Default = "pch"; + Devices = [ + [ "pch" "alsa/sysdefault:CARD=PCH" ] + ]; + }; + # Switch using --impure as these credential files are not stored within the flake + # sops-nix is not supported for these which is why we need to resort to these + LastFM.ApiKey = builtins.readFile /home/swarsel/api/lastfm-secret; + LastFM.Secret = builtins.readFile /home/swarsel/api/lastfm-key; + Spotify.ID = builtins.readFile /home/swarsel/api/spotify-id; + Spotify.Secret = builtins.readFile /home/swarsel/api/spotify-secret; + UILoginBackgroundUrl = "https://i.imgur.com/OMLxi7l.png"; + UIWelcomeMessage = "~SwarselSound~"; + }; + }; + + services.nginx = { + virtualHosts = { + "sound.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:4040"; + proxyWebsockets = true; + extraConfig = '' + proxy_redirect http:// https://; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + proxy_buffering off; + proxy_request_buffering off; + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + + +} diff --git a/profiles/server/common/nixos/nextcloud.nix b/profiles/server/common/nixos/nextcloud.nix new file mode 100644 index 0000000..f744d4c --- /dev/null +++ b/profiles/server/common/nixos/nextcloud.nix @@ -0,0 +1,43 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.nextcloud { + + sops.secrets.nextcloudadminpass = { + owner = "nextcloud"; + group = "nextcloud"; + mode = "0440"; + }; + + services.nextcloud = { + enable = true; + package = pkgs.nextcloud30; + hostName = "stash.swarsel.win"; + home = "/Vault/apps/nextcloud"; + datadir = "/Vault/data/nextcloud"; + https = true; + configureRedis = true; + maxUploadSize = "4G"; + extraApps = { + inherit (pkgs.nextcloud30Packages.apps) mail calendar contacts cospend phonetrack polls tasks; + }; + config = { + adminuser = "admin"; + adminpassFile = config.sops.secrets.nextcloudadminpass.path; + }; + }; + + + services.nginx = { + virtualHosts = { + "stash.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + # config is automatically added by nixos nextcloud config. + # hence, only provide certificate + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/nfs.nix b/profiles/server/common/nixos/nfs.nix new file mode 100644 index 0000000..3506e8c --- /dev/null +++ b/profiles/server/common/nixos/nfs.nix @@ -0,0 +1,49 @@ +{ pkgs, ... }: +{ + services = { + # add a user with sudo smbpasswd -a + samba = { + package = pkgs.samba4Full; + # extraConfig = '' + # workgroup = WORKGROUP + # server role = standalone server + # dns proxy = no + + # pam password change = yes + # map to guest = bad user + # create mask = 0664 + # force create mode = 0664 + # directory mask = 0775 + # force directory mode = 0775 + # follow symlinks = yes + # ''; + + enable = true; + openFirewall = true; + settings.Eternor = { + browseable = "yes"; + "read only" = "no"; + "guest ok" = "no"; + path = "/Vault/Eternor"; + writable = "true"; + comment = "Eternor"; + "valid users" = "Swarsel"; + }; + }; + + + avahi = { + publish.enable = true; + publish.userServices = true; # Needed to allow samba to automatically register mDNS records without the need for an `extraServiceFile` + nssmdns4 = true; + enable = true; + openFirewall = true; + }; + + # This enables autodiscovery on windows since SMB1 (and thus netbios) support was discontinued + samba-wsdd = { + enable = true; + openFirewall = true; + }; + }; +} diff --git a/profiles/server/common/nixos/nginx.nix b/profiles/server/common/nixos/nginx.nix new file mode 100644 index 0000000..fd0fbc9 --- /dev/null +++ b/profiles/server/common/nixos/nginx.nix @@ -0,0 +1,35 @@ +{ pkgs, config, ... }: +{ + environment.systemPackages = with pkgs; [ + lego + ]; + + # users.users.acme = {}; + + sops = { + # secrets.dnstokenfull = { owner = "acme"; }; + secrets.dnstokenfull = { }; + templates."certs.secret".content = '' + CF_DNS_API_TOKEN=${config.sops.placeholder.dnstokenfull} + ''; + }; + + security.acme = { + acceptTerms = true; + preliminarySelfsigned = false; + defaults.email = "mrswarsel@gmail.com"; + defaults.dnsProvider = "cloudflare"; + defaults.environmentFile = "${config.sops.templates."certs.secret".path}"; + }; + + services.nginx = { + enable = true; + statusPage = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + # virtualHosts are defined in the respective sections + }; + +} diff --git a/profiles/server/common/nixos/packages.nix b/profiles/server/common/nixos/packages.nix new file mode 100644 index 0000000..5d3d744 --- /dev/null +++ b/profiles/server/common/nixos/packages.nix @@ -0,0 +1,10 @@ +{ pkgs, ... }: +{ + environment.systemPackages = with pkgs; [ + gnupg + nix-index + ssh-to-age + git + emacs + ]; +} diff --git a/profiles/server/common/nixos/paperless.nix b/profiles/server/common/nixos/paperless.nix new file mode 100644 index 0000000..26a2041 --- /dev/null +++ b/profiles/server/common/nixos/paperless.nix @@ -0,0 +1,50 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.paperless { + + users.users.paperless = { + extraGroups = [ "users" ]; + }; + + + sops.secrets.paperless_admin = { owner = "paperless"; }; + + services.paperless = { + enable = true; + mediaDir = "/Vault/Eternor/Paperless"; + dataDir = "/Vault/data/paperless"; + user = "paperless"; + port = 28981; + passwordFile = config.sops.secrets.paperless_admin.path; + address = "127.0.0.1"; + settings = { + PAPERLESS_OCR_LANGUAGE = "deu+eng"; + PAPERLESS_URL = "https://scan.swarsel.win"; + PAPERLESS_OCR_USER_ARGS = builtins.toJSON { + optimize = 1; + invalidate_digital_signatures = true; + pdfa_image_compression = "lossless"; + }; + }; + }; + + services.nginx = { + virtualHosts = { + "scan.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:28981"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/restic.nix b/profiles/server/common/nixos/restic.nix new file mode 100644 index 0000000..7b5d6c5 --- /dev/null +++ b/profiles/server/common/nixos/restic.nix @@ -0,0 +1,8 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.restic { + + # TODO + + }; +} diff --git a/profiles/server/common/nixos/settings.nix b/profiles/server/common/nixos/settings.nix new file mode 100644 index 0000000..f9c8931 --- /dev/null +++ b/profiles/server/common/nixos/settings.nix @@ -0,0 +1,14 @@ +{ lib, config, ... }: +{ + environment.shellAliases = lib.recursiveUpdate + { + npswitch = "cd ${config.swarselsystems.flakePath}; git pull; sudo nixos-rebuild --flake .#$(hostname) switch --impure; cd -;"; + nswitch = "cd ${config.swarselsystems.flakePath}; sudo nixos-rebuild --flake .#$(hostname) switch --impure; cd -;"; + } + config.swarselsystems.shellAliases; + + nixpkgs.config.permittedInsecurePackages = [ + "olm-3.2.16" + ]; + +} diff --git a/profiles/server/common/nixos/sops.nix b/profiles/server/common/nixos/sops.nix new file mode 100644 index 0000000..3de53ed --- /dev/null +++ b/profiles/server/common/nixos/sops.nix @@ -0,0 +1,9 @@ +{ config, ... }: +{ + sops = { + age.sshKeyPaths = [ "/etc/ssh/sops" ]; + defaultSopsFile = "${config.swarselsystems.flakePath}/secrets/server/winters/secrets.yaml"; + validateSopsFiles = false; + }; + +} diff --git a/profiles/server/common/nixos/spotifyd.nix b/profiles/server/common/nixos/spotifyd.nix new file mode 100644 index 0000000..06eeb76 --- /dev/null +++ b/profiles/server/common/nixos/spotifyd.nix @@ -0,0 +1,34 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.spotifyd { + users.groups.spotifyd = { + gid = 65136; + }; + + users.users.spotifyd = { + isSystemUser = true; + uid = 65136; + group = "spotifyd"; + extraGroups = [ "audio" "utmp" "pipewire" ]; + }; + + networking.firewall.allowedTCPPorts = [ 1025 ]; + + services.pipewire.systemWide = true; + + services.spotifyd = { + enable = true; + settings = { + global = { + dbus_type = "session"; + use_mpris = false; + device = "sysdefault:CARD=PCH"; + device_name = "SwarselSpot"; + mixer = "alsa"; + zeroconf_port = 1025; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/ssh.nix b/profiles/server/common/nixos/ssh.nix new file mode 100644 index 0000000..05dd3d8 --- /dev/null +++ b/profiles/server/common/nixos/ssh.nix @@ -0,0 +1,16 @@ +_: +{ + services.openssh = { + enable = true; + settings.PermitRootLogin = "yes"; + }; + users.users.swarsel.openssh.authorizedKeys.keyFiles = [ + ../../../secrets/keys/authorized_keys + ../../../secrets/keys/mysticant.pub + ]; + users.users.root.openssh.authorizedKeys.keyFiles = [ + ../../../secrets/keys/authorized_keys + ../../../secrets/keys/mysticant.pub + ]; + +} diff --git a/profiles/server/common/nixos/syncthing.nix b/profiles/server/common/nixos/syncthing.nix new file mode 100644 index 0000000..a6fc5cc --- /dev/null +++ b/profiles/server/common/nixos/syncthing.nix @@ -0,0 +1,104 @@ +{ lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.syncthing { + + users.users.syncthing = { + extraGroups = [ "users" ]; + }; + + services.syncthing = { + enable = true; + user = "syncthing"; + dataDir = "/Vault/data/syncthing"; + configDir = "/Vault/apps/syncthing"; + guiAddress = "0.0.0.0:8384"; + openDefaultPorts = true; + relay.enable = false; + settings = { + urAccepted = -1; + devices = { + "magicant" = { + id = "VMWGEE2-4HDS2QO-KNQOVGN-LXLX6LA-666E4EK-ZBRYRRO-XFEX6FB-6E3XLQO"; + }; + "zenfone9" = { + id = "SEH2NMT-IVRQUU5-VPW2HUQ-3GQYDBF-F6H6OY6-X3DZTUZ-LCRE2DJ-QNIXIQ2"; + }; + "sync (@oracle)" = { + id = "ETW6TST-NPK7MKZ-M4LXMHA-QUPQHDT-VTSHH5X-CR5EIN2-YU7E55F-MGT7DQB"; + }; + "nbl-imba-2" = { + id = "YAPV4BV-I26WPTN-SIP32MV-SQP5TBZ-3CHMTCI-Z3D6EP2-MNDQGLP-53FT3AB"; + }; + }; + folders = { + "Default Folder" = { + path = "/Vault/data/syncthing/Sync"; + type = "receiveonly"; + versioning = null; + devices = [ "sync (@oracle)" "magicant" "zenfone9" "nbl-imba-2" ]; + id = "default"; + }; + "Obsidian" = { + path = "/Vault/data/syncthing/Obsidian"; + type = "receiveonly"; + versioning = { + type = "simple"; + params.keep = "5"; + }; + devices = [ "sync (@oracle)" "magicant" "zenfone9" "nbl-imba-2" ]; + id = "yjvni-9eaa7"; + }; + "Org" = { + path = "/Vault/data/syncthing/Org"; + type = "receiveonly"; + versioning = { + type = "simple"; + params.keep = "5"; + }; + devices = [ "sync (@oracle)" "magicant" "zenfone9" "nbl-imba-2" ]; + id = "a7xnl-zjj3d"; + }; + "Vpn" = { + path = "/Vault/data/syncthing/Vpn"; + type = "receiveonly"; + versioning = { + type = "simple"; + params.keep = "5"; + }; + devices = [ "sync (@oracle)" "magicant" "zenfone9" "nbl-imba-2" ]; + id = "hgp9s-fyq3p"; + }; + "Documents" = { + path = "/Vault/data/syncthing/Documents"; + type = "receiveonly"; + versioning = { + type = "simple"; + params.keep = "5"; + }; + devices = [ "magicant" "nbl-imba-2" ]; + id = "hgr3d-pfu3w"; + }; + }; + }; + }; + + services.nginx = { + virtualHosts = { + "storync.swarsel.win" = { + enableACME = true; + forceSSL = true; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:8384"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + +} diff --git a/profiles/server/common/nixos/transmission.nix b/profiles/server/common/nixos/transmission.nix new file mode 100644 index 0000000..ee88608 --- /dev/null +++ b/profiles/server/common/nixos/transmission.nix @@ -0,0 +1,132 @@ +{ pkgs, lib, config, ... }: +{ + config = lib.mkIf config.swarselsystems.server.transmission { + + # this user/group section is probably unneeded + users = { + groups = { + dockeruser = { + gid = 1155; + }; + radarr = { }; + readarr = { }; + sonarr = { }; + lidarr = { }; + prowlarr = { }; + }; + users = { + dockeruser = { + isSystemUser = true; + uid = 1155; + group = "docker"; + extraGroups = [ "users" ]; + }; + radarr = { + isSystemUser = true; + group = "radarr"; + extraGroups = [ "users" ]; + }; + readarr = { + isSystemUser = true; + group = "readarr"; + extraGroups = [ "users" ]; + }; + sonarr = { + isSystemUser = true; + group = "sonarr"; + extraGroups = [ "users" ]; + }; + lidarr = { + isSystemUser = true; + group = "lidarr"; + extraGroups = [ "users" ]; + }; + prowlarr = { + isSystemUser = true; + group = "prowlarr"; + extraGroups = [ "users" ]; + }; + }; + }; + + virtualisation.docker.enable = true; + environment.systemPackages = with pkgs; [ + docker + ]; + + services = { + radarr = { + enable = true; + openFirewall = true; + dataDir = "/Vault/apps/radarr"; + }; + readarr = { + enable = true; + openFirewall = true; + dataDir = "/Vault/apps/readarr"; + }; + sonarr = { + enable = true; + openFirewall = true; + dataDir = "/Vault/apps/sonarr"; + }; + lidarr = { + enable = true; + openFirewall = true; + dataDir = "/Vault/apps/lidarr"; + }; + prowlarr = { + enable = true; + openFirewall = true; + }; + + nginx = { + virtualHosts = { + "store.swarsel.win" = { + enableACME = false; + forceSSL = false; + acmeRoot = null; + locations = { + "/" = { + proxyPass = "http://localhost:9091"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "/radarr" = { + proxyPass = "http://localhost:7878"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "/readarr" = { + proxyPass = "http://localhost:8787"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "/sonarr" = { + proxyPass = "http://localhost:8989"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "/lidarr" = { + proxyPass = "http://localhost:8686"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + "/prowlarr" = { + proxyPass = "http://localhost:9696"; + extraConfig = '' + client_max_body_size 0; + ''; + }; + }; + }; + }; + }; + }; + }; +}