From 293b48f4946cb1e88f21abe665dcd18106b48e11 Mon Sep 17 00:00:00 2001 From: Valentin Date: Tue, 11 Nov 2025 13:34:09 +0100 Subject: Konfiguration klarer nach Aspekten unterteilt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Insbesondere behandelt das Modul für die Website nur noch dieses spezifische Anliegen. --- cgit.nix | 100 -------------------------------------- default.nix | 9 +--- nextcloud.nix | 106 ---------------------------------------- tharos.nix | 133 --------------------------------------------------- tharos/boot.nix | 51 ++++++++++++++++++++ tharos/caddy.nix | 29 +++++++++++ tharos/cgit.nix | 99 ++++++++++++++++++++++++++++++++++++++ tharos/default.nix | 49 +++++++++++++++++++ tharos/nextcloud.nix | 106 ++++++++++++++++++++++++++++++++++++++++ tharos/security.nix | 46 ++++++++++++++++++ www/caddy.nix | 29 +++-------- 11 files changed, 388 insertions(+), 369 deletions(-) delete mode 100644 cgit.nix delete mode 100644 nextcloud.nix delete mode 100644 tharos.nix create mode 100644 tharos/boot.nix create mode 100644 tharos/caddy.nix create mode 100644 tharos/cgit.nix create mode 100644 tharos/default.nix create mode 100644 tharos/nextcloud.nix create mode 100644 tharos/security.nix diff --git a/cgit.nix b/cgit.nix deleted file mode 100644 index 542245f..0000000 --- a/cgit.nix +++ /dev/null @@ -1,100 +0,0 @@ -{ self, ... }: -{ - - flake.machines.tharos = - let - path = "/git/infra"; - in - { - nixos = - { - config, - pkgs, - lib, - ... - }: - let - cgit = config.services.cgit.infra.nginx.virtualHost; - nginx = lib.head config.services.nginx.virtualHosts.${cgit}.listen; - in - { - users.groups.git = { }; - users.users = lib.mapAttrs (_: _': { extraGroups = [ "git" ]; }) self.keys; - environment.systemPackages = with pkgs; [ git ]; - - systemd.services.init-git-repos = { - wantedBy = [ "multi-user.target" ]; - before = [ "cgit.service" ]; - - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - - script = '' - if [ ! -f ${path} ]; then - ${lib.getExe pkgs.git} init --shared=group --bare ${path} - fi - ''; - }; - - systemd.tmpfiles.rules = [ - "d ${path} 2775 root git -" - ]; - - services.cgit.infra = rec { - enable = true; - nginx.virtualHost = "git.${self.domain}"; - repos.infra = { - desc = "Quellcode für die technische Infrastruktur des Stadtteilbeirats Heimfeld"; - inherit path; - clone-url = "https://${nginx.virtualHost}/$CGIT_REPO_URL ssh://${self.domain}${path}"; - }; - settings = { - about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh"; - readme = ":README.md"; - enable-commit-graph = true; - }; - }; - services.nginx.virtualHosts.${cgit}.listen = [ - { - addr = "127.0.0.1"; - port = 8083; - } - ]; - services.caddy.virtualHosts.${cgit}.extraConfig = '' - reverse_proxy localhost:${toString nginx.port} - ''; - }; - vm = - { - config, - pkgs, - lib, - ... - }: - let - httpPort = 700; - cgit = config.services.cgit.infra.nginx.virtualHost; - in - { - services.cgit.infra = { - nginx.virtualHost = lib.mkForce "git.localhost"; - - repos.infra.clone-url = lib.mkForce "http://${cgit}:${ - with config.virtualisation; toString (portOffset + exposedPorts.http.port) - }/$CGIT_REPO_URL ssh://localhost:${ - toString (config.virtualisation.portOffset + lib.head config.services.openssh.ports) - }${path}"; - }; - - services.caddy.virtualHosts = { - "http://${cgit}:${toString config.virtualisation.exposedPorts.http.port}".extraConfig = - config.services.caddy.virtualHosts.${cgit}.extraConfig; - }; - services.getty.helpLine = lib.mkBefore '' - cgit: http://${cgit}:${with config.virtualisation; toString (portOffset + exposedPorts.http.port)} - ''; - }; - }; -} diff --git a/default.nix b/default.nix index 86ccd40..1e20ba6 100644 --- a/default.nix +++ b/default.nix @@ -30,14 +30,7 @@ flake-parts.lib.mkFlake with lib.fileset; toList ( # Alle Nix-Dateien in diesem Projekt sind Flake-Parts-Module - fileFilter ( - file: - file.hasExt "nix" - && !lib.elem file.name [ - "flake.nix" - "default.nix" - ] - ) ./. + difference (fileFilter (file: file.hasExt "nix" && file.name != "flake.nix") ./.) ./default.nix ); systems = [ "x86_64-linux" ]; } diff --git a/nextcloud.nix b/nextcloud.nix deleted file mode 100644 index eedb507..0000000 --- a/nextcloud.nix +++ /dev/null @@ -1,106 +0,0 @@ -{ self, ... }: -{ - flake.machines.tharos = { - nixos = - { config, lib, ... }: - let - apps = config.services.nextcloud.package.packages.apps; - nextcloud = config.services.nextcloud.hostName; - nginx = lib.head config.services.nginx.virtualHosts.${nextcloud}.listen; - in - { - services.nextcloud = { - enable = true; - hostName = "nextcloud.${self.domain}"; - database.createLocally = true; - config.dbtype = "pgsql"; - extraAppsEnable = true; - extraApps = { - inherit (apps) - contacts - calendar - tables - spreed # Videokonferenzen - # cospend # Rudimentäre Buchhaltung - # deck # Issue-Tracker - ; - }; - settings = { - trusted_proxies = [ nginx.addr ]; - mail_smtpmode = "smtp"; - mail_smtphost = "smtp.tharos-net.de"; - mail_smtpport = 587; - mail_smtpauth = true; - mail_smtptimeout = 30; - mail_smtpname = "nextcloud@${self.domain}"; - mail_from_address = "nextcloud"; - mail_domain = self.domain; - mail_smtpstreamoptions = { - /* - ACHTUNG: Hier ist Angriffsfläche! - Dringend den Mailserver ordentlich einrichten! - */ - ssl = { - allow_self_signed = true; - verify_peer = false; - verify_peer_name = false; - }; - }; - }; - /* - Vor erstmaligem Anwenden der Konfiguration: - - echo $PASSWORT | ssh tharos 'sudo install -m 600 /dev/stdin /var/lib/nextcloud/initialrootpassword' - cat $SECRETS | ssh tharos 'sudo install -m 600 -o nextcloud -g nextcloud /dev/stdin /var/lib/nextcloud/secrets.json' - - Die Dateien bleiben auf dem System! - Das einmalige Root-Passwort wird nicht wieder verwendet. - - Besser wäre natürlich zentralisiertes Management von geheimen Daten. - */ - secretFile = "/var/lib/nextcloud/secrets.json"; - config.adminpassFile = "/var/lib/nextcloud/initialrootpassword"; - }; - services.nginx.virtualHosts.${nextcloud} = { - listen = [ - { - addr = "127.0.0.1"; - port = 8080; - } - ]; - }; - services.caddy = { - virtualHosts.${nextcloud}.extraConfig = '' - reverse_proxy http://${nginx.addr}:${toString nginx.port} - ''; - }; - }; - vm = - { config, lib, ... }: - - let - nextcloud = config.services.nextcloud.hostName; - in - { - services.nextcloud = { - https = lib.mkForce false; - hostName = lib.mkForce "nextcloud.localhost"; - }; - - systemd.tmpfiles.rules = [ - "f /var/lib/nextcloud/secrets.json 0600 nextcloud nextcloud - {}" - "f /var/lib/nextcloud/initialrootpassword 0600 nextcloud nextcloud - root" - ]; - - services.caddy.virtualHosts = { - "http://${nextcloud}:${toString config.virtualisation.exposedPorts.http.port}".extraConfig = - config.services.caddy.virtualHosts.${nextcloud}.extraConfig; - }; - services.getty.helpLine = lib.mkBefore '' - Nextcloud: http://${nextcloud}:${ - with config.virtualisation; toString (portOffset + exposedPorts.http.port) - } - ''; - }; - }; -} diff --git a/tharos.nix b/tharos.nix deleted file mode 100644 index 6d96754..0000000 --- a/tharos.nix +++ /dev/null @@ -1,133 +0,0 @@ -{ - self, - inputs, - lib, - ... -}: -{ - flake.machines.tharos = { - bootstrap-target = "root@${self.machines.tharos.deploy-target}"; - # Administratoren verbinden sich mit ihrem selbst festgelegten Nutzernamen - deploy-target = "81.169.239.254"; - nixos = - { - config, - pkgs, - modulesPath, - ... - }: - - { - imports = [ - inputs.disko.nixosModules.default - "${modulesPath}/profiles/qemu-guest.nix" - ]; - - nixpkgs.hostPlatform = "x86_64-linux"; - system.stateVersion = "25.05"; - - services.cloud-init = { - enable = true; - network.enable = true; - }; - # `cloud-init` übernimmt Netzwerkeinstellungen - networking.useDHCP = false; - - # Kein Login für Nutzer die nicht explizit deklariert sind - users.mutableUsers = false; - users.users = lib.mapAttrs (username: keyFiles: { - isNormalUser = true; - openssh.authorizedKeys.keyFiles = keyFiles; - # ANMERKUNG: Der Einfachheit halber sind bis auf Weiteres alle Nutzer mit SSH-Zugang auch Administratoren - extraGroups = [ "wheel" ]; - }) self.keys; - - /* - `sudo` über SSH ohne Passworteingabe - ANMERKUNG: Nutzer sollten in ihrem ` ~/.ssh/config` für die Maschine einstellen: - - ForwardAgent: yes - */ - security.pam.sshAgentAuth.enable = true; - security.pam.services.sudo.sshAgentAuth = true; - - # Nur Administratoren können den angemeldeten Benutzer wechseln - security.pam.services.su.requireWheel = true; - - networking.firewall.allowPing = true; - services.openssh = { - enable = true; - settings = { - PasswordAuthentication = false; - PermitRootLogin = "prohibit-password"; - }; - }; - - nix = { - settings.trusted-users = [ - "root" - "@wheel" - ]; - settings.experimental-features = [ - "nix-command" - "flakes" - ]; - }; - - disko.devices.disk.main = { - device = "/dev/vda"; - type = "disk"; - content = { - type = "gpt"; - partitions = { - # Die KVM läuft auf SeaBIOS, daher muss es hier eine MBR-Partition sein - boot = { - size = "1M"; - type = "EF02"; - }; - root = { - size = "100%"; - content = { - type = "filesystem"; - format = "ext4"; - mountpoint = "/"; - }; - }; - }; - }; - }; - - /* - ANMERKUNG: Erhalten durch: - - nix run .#machines.infect-tharos -- --no-reboot --generate-hardware-config nixos-hardware-config - */ - boot.initrd.availableKernelModules = [ - "ata_piix" - "uhci_hcd" - "virtio_pci" - "virtio_blk" - ]; - boot.kernelModules = [ "kvm-amd" ]; - }; - - vm = - { - config, - lib, - pkgs, - ... - }: - { - virtualisation = { - memorySize = 4096; - diskSize = 4096; - cores = 2; - graphics = false; - }; - - services.cloud-init.enable = lib.mkForce false; - networking.useDHCP = lib.mkForce true; - }; - }; -} diff --git a/tharos/boot.nix b/tharos/boot.nix new file mode 100644 index 0000000..1843e63 --- /dev/null +++ b/tharos/boot.nix @@ -0,0 +1,51 @@ +{ inputs, ... }: +{ + flake.machines.tharos = { + nixos = + { + modulesPath, + ... + }: + { + imports = [ + inputs.disko.nixosModules.default + "${modulesPath}/profiles/qemu-guest.nix" + ]; + disko.devices.disk.main = { + device = "/dev/vda"; + type = "disk"; + content = { + type = "gpt"; + partitions = { + # Die KVM läuft auf SeaBIOS, daher muss es hier eine MBR-Partition sein + boot = { + size = "1M"; + type = "EF02"; + }; + root = { + size = "100%"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + }; + }; + }; + }; + }; + + /* + ANMERKUNG: Erhalten durch: + + nix run .#machines.infect-tharos -- --no-reboot --generate-hardware-config nixos-hardware-config + */ + boot.initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "virtio_pci" + "virtio_blk" + ]; + boot.kernelModules = [ "kvm-amd" ]; + }; + }; +} diff --git a/tharos/caddy.nix b/tharos/caddy.nix new file mode 100644 index 0000000..fc152c7 --- /dev/null +++ b/tharos/caddy.nix @@ -0,0 +1,29 @@ +{ self, ... }: +{ + flake.domain = "heimfeld.hamburg"; + flake.machines.tharos = { + nixos = + { ... }: + { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + services.caddy = { + enable = true; + email = "redaktion@${self.domain}"; + }; + }; + + vm = + { pkgs, ... }: + { + services.caddy.globalConfig = '' + local_certs + ''; + + systemd.services.caddy.path = [ pkgs.nssTools ]; # Irrelevante Warnung unterdrücken + }; + }; +} diff --git a/tharos/cgit.nix b/tharos/cgit.nix new file mode 100644 index 0000000..b4a75c3 --- /dev/null +++ b/tharos/cgit.nix @@ -0,0 +1,99 @@ +{ self, ... }: +{ + + flake.machines.tharos = + let + path = "/git/infra"; + in + { + nixos = + { + config, + pkgs, + lib, + ... + }: + let + cgit = config.services.cgit.infra.nginx.virtualHost; + nginx = lib.head config.services.nginx.virtualHosts.${cgit}.listen; + in + { + users.groups.git = { }; + users.users = lib.mapAttrs (_: _': { extraGroups = [ "git" ]; }) self.keys; + environment.systemPackages = with pkgs; [ git ]; + + systemd.services.init-git-repos = { + wantedBy = [ "multi-user.target" ]; + before = [ "cgit.service" ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = '' + if [ ! -f ${path} ]; then + ${lib.getExe pkgs.git} init --shared=group --bare ${path} + fi + ''; + }; + + systemd.tmpfiles.rules = [ + "d ${path} 2775 root git -" + ]; + + services.cgit.infra = rec { + enable = true; + nginx.virtualHost = "git.${self.domain}"; + repos.infra = { + desc = "Quellcode für die technische Infrastruktur des Stadtteilbeirats Heimfeld"; + inherit path; + clone-url = "https://${nginx.virtualHost}/$CGIT_REPO_URL ssh://${self.domain}${path}"; + }; + settings = { + about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh"; + readme = ":README.md"; + enable-commit-graph = true; + }; + }; + services.nginx.virtualHosts.${cgit}.listen = [ + { + addr = "127.0.0.1"; + port = 8083; + } + ]; + services.caddy.virtualHosts.${cgit}.extraConfig = '' + reverse_proxy localhost:${toString nginx.port} + ''; + }; + vm = + { + config, + lib, + ... + }: + let + httpPort = 700; + cgit = config.services.cgit.infra.nginx.virtualHost; + in + { + services.cgit.infra = { + nginx.virtualHost = lib.mkForce "git.localhost"; + + repos.infra.clone-url = lib.mkForce "http://${cgit}:${ + with config.virtualisation; toString (portOffset + exposedPorts.http.port) + }/$CGIT_REPO_URL ssh://localhost:${ + toString (config.virtualisation.portOffset + lib.head config.services.openssh.ports) + }${path}"; + }; + + services.caddy.virtualHosts = { + "http://${cgit}:${toString config.virtualisation.exposedPorts.http.port}".extraConfig = + config.services.caddy.virtualHosts.${cgit}.extraConfig; + }; + services.getty.helpLine = lib.mkBefore '' + cgit: http://${cgit}:${with config.virtualisation; toString (portOffset + exposedPorts.http.port)} + ''; + }; + }; +} diff --git a/tharos/default.nix b/tharos/default.nix new file mode 100644 index 0000000..65f2024 --- /dev/null +++ b/tharos/default.nix @@ -0,0 +1,49 @@ +{ + self, + ... +}: +{ + flake.machines.tharos = { + bootstrap-target = "root@${self.machines.tharos.deploy-target}"; + # Administratoren verbinden sich mit ihrem selbst festgelegten Nutzernamen + deploy-target = "81.169.239.254"; + nixos = + { ... }: + { + nixpkgs.hostPlatform = "x86_64-linux"; + system.stateVersion = "25.05"; + + services.cloud-init = { + enable = true; + network.enable = true; + }; + # `cloud-init` übernimmt Netzwerkeinstellungen + networking.useDHCP = false; + + nix = { + settings.trusted-users = [ + "root" + "@wheel" + ]; + settings.experimental-features = [ + "nix-command" + "flakes" + ]; + }; + }; + + vm = + { lib, ... }: + { + virtualisation = { + memorySize = 4096; + diskSize = 4096; + cores = 2; + graphics = false; + }; + + services.cloud-init.enable = lib.mkForce false; + networking.useDHCP = lib.mkForce true; + }; + }; +} diff --git a/tharos/nextcloud.nix b/tharos/nextcloud.nix new file mode 100644 index 0000000..eedb507 --- /dev/null +++ b/tharos/nextcloud.nix @@ -0,0 +1,106 @@ +{ self, ... }: +{ + flake.machines.tharos = { + nixos = + { config, lib, ... }: + let + apps = config.services.nextcloud.package.packages.apps; + nextcloud = config.services.nextcloud.hostName; + nginx = lib.head config.services.nginx.virtualHosts.${nextcloud}.listen; + in + { + services.nextcloud = { + enable = true; + hostName = "nextcloud.${self.domain}"; + database.createLocally = true; + config.dbtype = "pgsql"; + extraAppsEnable = true; + extraApps = { + inherit (apps) + contacts + calendar + tables + spreed # Videokonferenzen + # cospend # Rudimentäre Buchhaltung + # deck # Issue-Tracker + ; + }; + settings = { + trusted_proxies = [ nginx.addr ]; + mail_smtpmode = "smtp"; + mail_smtphost = "smtp.tharos-net.de"; + mail_smtpport = 587; + mail_smtpauth = true; + mail_smtptimeout = 30; + mail_smtpname = "nextcloud@${self.domain}"; + mail_from_address = "nextcloud"; + mail_domain = self.domain; + mail_smtpstreamoptions = { + /* + ACHTUNG: Hier ist Angriffsfläche! + Dringend den Mailserver ordentlich einrichten! + */ + ssl = { + allow_self_signed = true; + verify_peer = false; + verify_peer_name = false; + }; + }; + }; + /* + Vor erstmaligem Anwenden der Konfiguration: + + echo $PASSWORT | ssh tharos 'sudo install -m 600 /dev/stdin /var/lib/nextcloud/initialrootpassword' + cat $SECRETS | ssh tharos 'sudo install -m 600 -o nextcloud -g nextcloud /dev/stdin /var/lib/nextcloud/secrets.json' + + Die Dateien bleiben auf dem System! + Das einmalige Root-Passwort wird nicht wieder verwendet. + + Besser wäre natürlich zentralisiertes Management von geheimen Daten. + */ + secretFile = "/var/lib/nextcloud/secrets.json"; + config.adminpassFile = "/var/lib/nextcloud/initialrootpassword"; + }; + services.nginx.virtualHosts.${nextcloud} = { + listen = [ + { + addr = "127.0.0.1"; + port = 8080; + } + ]; + }; + services.caddy = { + virtualHosts.${nextcloud}.extraConfig = '' + reverse_proxy http://${nginx.addr}:${toString nginx.port} + ''; + }; + }; + vm = + { config, lib, ... }: + + let + nextcloud = config.services.nextcloud.hostName; + in + { + services.nextcloud = { + https = lib.mkForce false; + hostName = lib.mkForce "nextcloud.localhost"; + }; + + systemd.tmpfiles.rules = [ + "f /var/lib/nextcloud/secrets.json 0600 nextcloud nextcloud - {}" + "f /var/lib/nextcloud/initialrootpassword 0600 nextcloud nextcloud - root" + ]; + + services.caddy.virtualHosts = { + "http://${nextcloud}:${toString config.virtualisation.exposedPorts.http.port}".extraConfig = + config.services.caddy.virtualHosts.${nextcloud}.extraConfig; + }; + services.getty.helpLine = lib.mkBefore '' + Nextcloud: http://${nextcloud}:${ + with config.virtualisation; toString (portOffset + exposedPorts.http.port) + } + ''; + }; + }; +} diff --git a/tharos/security.nix b/tharos/security.nix new file mode 100644 index 0000000..03b59dc --- /dev/null +++ b/tharos/security.nix @@ -0,0 +1,46 @@ +{ + self, + inputs, + ... +}: +{ + flake.machines.tharos = { + nixos = + { + lib, + modulesPath, + ... + }: + { + # Kein Login für Nutzer die nicht explizit deklariert sind + users.mutableUsers = false; + users.users = lib.mapAttrs (username: keyFiles: { + isNormalUser = true; + openssh.authorizedKeys.keyFiles = keyFiles; + # ANMERKUNG: Der Einfachheit halber sind bis auf Weiteres alle Nutzer mit SSH-Zugang auch Administratoren + extraGroups = [ "wheel" ]; + }) self.keys; + + /* + `sudo` über SSH ohne Passworteingabe + ANMERKUNG: Nutzer sollten in ihrem ` ~/.ssh/config` für die Maschine einstellen: + + ForwardAgent: yes + */ + security.pam.sshAgentAuth.enable = true; + security.pam.services.sudo.sshAgentAuth = true; + + # Nur Administratoren können den angemeldeten Benutzer wechseln + security.pam.services.su.requireWheel = true; + + networking.firewall.allowPing = true; + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "prohibit-password"; + }; + }; + }; + }; +} diff --git a/www/caddy.nix b/www/caddy.nix index 8797204..6721316 100644 --- a/www/caddy.nix +++ b/www/caddy.nix @@ -8,27 +8,17 @@ let }; in { - flake.domain = "heimfeld.hamburg"; flake.machines.tharos = { nixos = { lib, ... }: { - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; - - services.caddy = { - enable = true; - email = "redaktion@${self.domain}"; - virtualHosts.${self.domain} = { - serverAliases = [ "www.${self.domain}" ]; - extraConfig = '' - file_server - root * /var/www/${self.domain} - encode gzip - ''; - }; + services.caddy.virtualHosts.${self.domain} = { + serverAliases = [ "www.${self.domain}" ]; + extraConfig = '' + file_server + root * /var/www/${self.domain} + encode gzip + ''; }; systemd.tmpfiles.rules = [ @@ -45,16 +35,11 @@ in ... }: { - services.caddy.globalConfig = '' - local_certs - ''; services.caddy.virtualHosts = { "http://www.localhost:${toString config.virtualisation.exposedPorts.http.port}".extraConfig = config.services.caddy.virtualHosts.${self.domain}.extraConfig; }; - systemd.services.caddy.path = [ pkgs.nssTools ]; # Irrelevante Warnung unterdrücken - services.getty.helpLine = lib.mkBefore '' ${self.domain}: http://www.localhost:${ with config.virtualisation; toString (portOffset + exposedPorts.http.port) -- cgit v1.2.3