{ config, lib, pkgs, ... }: with lib; let cfg = config.services.strojnadzor; hsts = '' add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; ''; static = pkgs.runCommand "static" {} '' export STROJNADZOR_STATIC_ROOT="$out" ${cfg.package}/bin/strojnadzor-admin collectstatic ''; in { options = { services.strojnadzor = { enable = mkOption { default = false; description = " Whether to enable Strojnadzor "; }; package = mkOption { type = types.path; default = pkgs.strojnadzor; description = "The Strojnadzor package."; }; hostName = mkOption { default = "golovizin.ru"; type = types.str; description = "Main hostname."; }; hostNameAliases = mkOption { default = [ "www.golovizin.ru" "xn--b1abndboscb.xn--p1ai" "www.xn--b1abndboscb.xn--p1ai" ]; type = types.listOf types.str; description = "Additional hostnames."; }; stateDir = mkOption { default = "/var/lib/strojnadzor"; type = types.str; description = "Data directory."; }; backupDir = mkOption { default = "/var/backup/strojnadzor"; type = types.str; description = "Backup directory."; }; socketPath = mkOption { default = "/run/strojnadzor.sock"; type = types.str; description = "UNIX socket path."; }; borgbackup = { enable = mkEnableOption "backup via borgbackup"; }; }; }; config = mkIf cfg.enable { users.users.strojnadzor = { description = "Strojnadzor user"; isSystemUser = true; group = "strojnadzor"; home = cfg.stateDir; }; users.groups.strojnadzor = {}; systemd.tmpfiles.rules = [ "d '${cfg.stateDir}/db' 0700 strojnadzor strojnadzor - -" "d '${cfg.stateDir}/media' 0755 strojnadzor strojnadzor - -" "d '${cfg.backupDir}/borg' 0700 strojnadzor strojnadzor - -" ]; systemd.sockets.strojnadzor = { description = "Strojnadzor HTTP socket."; wantedBy = [ "sockets.target" ]; socketConfig = { SocketUser = "nginx"; SocketGroup = "nginx"; SocketMode = 0660; ListenStream = "${cfg.socketPath}"; }; }; systemd.services.strojnadzor = { description = "Strojnadzor HTTP server."; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; requires = [ "strojnadzor.socket" ]; serviceConfig = { Type = "notify"; User = "strojnadzor"; Group = "strojnadzor"; ExecStartPre = "${cfg.package}/bin/strojnadzor-admin migrate"; ExecStart = "${cfg.package}/bin/strojnadzor-admin runserver-gunicorn"; StateDirectory = "strojnadzor"; CapabilityBoundingSet = ""; LockPersonality = true; NoNewPrivileges = true; PrivateDevices = true; # PrivateNetwork = true; PrivateTmp = true; PrivateUsers = true; ProtectControlGroups = true; ProtectHome = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectSystem = "strict"; RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictSUIDSGID = true; SystemCallErrorNumber = "EPERM"; SystemCallFilter = "@system-service"; }; environment.STROJNADZOR_DATA_DIR = "${cfg.stateDir}"; }; services.nginx = { enable = true; virtualHosts = { "${cfg.hostName}" = { serverAliases = cfg.hostNameAliases; forceSSL = true; enableACME = true; extraConfig = hsts; locations."/static/".alias = "${static}/"; locations."/media/".alias = "${cfg.stateDir}/media/"; locations."= /favicon.ico".return = "404"; locations."/" = { proxyPass = "http://unix:${cfg.socketPath}"; extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; gzip off; ''; }; }; }; }; services.borgbackup.jobs.strojnadzor = mkIf cfg.borgbackup.enable { paths = [ cfg.stateDir ]; exclude = [ "${cfg.stateDir}/.cache" "${cfg.stateDir}/.config" ]; repo = "${cfg.backupDir}/borg"; compression = "auto,lzma"; encryption.mode = "none"; startAt = "hourly"; user = "strojnadzor"; group = "strojnadzor"; }; }; }