diff options
| author | Nathan Perry <np@nathanperry.dev> | 2022-11-28 10:58:46 -0500 |
|---|---|---|
| committer | Nathan Perry <np@nathanperry.dev> | 2022-11-28 10:58:46 -0500 |
| commit | 20b5cd1498fcd0e03e7c92dd40e78cdb8bc35b8b (patch) | |
| tree | 5e2635c7c1deb959d05d4cd8dbc962bc49e1163f | |
| parent | ba1311124033abe11d9eb10f65fc5907ce890f8f (diff) | |
nix: write nixos module
| -rw-r--r-- | flake.nix | 219 |
1 files changed, 190 insertions, 29 deletions
@@ -25,7 +25,36 @@ nixpkgs, flake-utils, ... - } @ inputs: (flake-utils.lib.eachDefaultSystem (system: + } @ inputs: let + buildToolchain = pkgs: pkgs.rust-bin.nightly."2022-11-20".minimal; + deps = pkgs: with pkgs; [ + openssl + pkgconfig + libopus + postgresql + ]; + + mkPkg = pkgs: let + buildToolchain = buildToolchain pkgs; + + naersk = pkgs.callPackage inputs.naersk { + cargo = buildToolchain; + rustc = buildToolchain; + }; + + inherit (pkgs) lib; + + in naersk.buildPackage { + pname = "thulani"; + version = self.rev or "dirty"; + + src = lib.cleanSource ./.; + + nativeBuildInputs = deps pkgs; + remapPathPrefix = true; + }; + + in (flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; @@ -35,9 +64,7 @@ ]; }; - buildToolchain = pkgs.rust-bin.nightly."2022-11-20".minimal; - - devToolchain = buildToolchain.override { + devToolchain = (buildToolchain pkgs).override { extensions = [ "rust-src" "rust-analyzer" @@ -47,35 +74,13 @@ ]; }; - naersk = pkgs.callPackage inputs.naersk { - cargo = buildToolchain; - rustc = buildToolchain; - }; - - deps = with pkgs; [ - openssl - pkgconfig - libopus - postgresql - ]; - - inherit (pkgs) lib; - - pkg = naersk.buildPackage { - pname = "thulani"; - version = self.rev or "dirty"; - - src = lib.cleanSource ./.; - - nativeBuildInputs = deps; - remapPathPrefix = true; - }; + pkg = mkPkg pkgs; in { devShells.default = pkgs.mkShell { buildInputs = (with pkgs; [ devToolchain - ]) ++ deps; + ]) ++ (deps pkgs); RUST_SRC_PATH = "${devToolchain}/lib/rustlib/src/rust"; }; @@ -85,6 +90,162 @@ type = "app"; program = "${pkg}/bin/thulani"; }; - }) + + }) // { + overlays.default = final: prev: let + withRust = (import inputs.rust-overlay) final prev; + in { + thulani = mkPkg withRust; + }; + + nixosModules.default = { pkgs, lib, config, ... }: let + cfg = config.services.thulani; + in { + options.services.thulani = with lib; with lib.types; { + enable = mkEnableOption "thulani"; + + package = mkOption { + description = "thulani derivation to use"; + type = package; + default = pkgs.thulani; + }; + + environment = mkOption { + description = "literal environment to include"; + type = attrsOf str; + default = {}; + }; + + envFiles = mkOption { + description = "environment files to include"; + type = listOf path; + default = []; + }; + + user = mkOption { + description = "user to run service as"; + type = str; + default = "thulani"; + }; + + group = mkOption { + description = "group to run service as"; + type = str; + default = "thulani"; + }; + + postgres = mkOption { + description = "local postgres server with automatic setup"; + + type = sumodule { + enable = mkEnableOption "postgres"; + + db = mkOption { + description = "db name"; + type = str; + default = "memes"; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.thulani = { + description = "thulani bot"; + + wantedBy = [ + "multi-user.target" + ]; + + bindsTo = [ + "network-online.target" + ]; + + after = [ + "network-online.target" + ]; + + preStart = lib.mkIf (cfg.postgres.enable) (let + invokePsql = "${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/psql"; + + in '' + ${invokePsql} <<EOF + DO $$ + BEGIN + CREATE ROLE ${cfg.user}; + EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE; + END + $$; + + SELECT 'CREATE DATABASE ${cfg.postgres.db}' + WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${cfg.postgres.db}')\gexec + EOF + + echo 'CREATE EXTENSION IF NOT EXISTS pgcrypto' | ${invokePsql} ${cfg.postgres.db} + ''); + + inherit (cfg) environment; + + unitConfig = { + StartLimitBurst = 3; + StartLimitIntervalSec = "1m"; + }; + + serviceConfig = { + Type = "exec"; + ExecStart = "${cfg.package}/bin/thulani"; + + EnvironmentFile = cfg.environmentFiles; + + DynamicUser = true; + User = cfg.user; + Group = cfg.group; + + Restart = "always"; + RestartSec = "10s"; + + TimeoutStopSec = "10s"; + + MemoryHigh = "200M"; + MemoryMax = "300M"; + + ProtectSystem = "strict"; + ProtectProc = "noaccess"; + ProtectHome = true; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + + PrivateDevices = true; + PrivateUsers = true; + PrivateMounts = true; + + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + + MemoryDenyWriteExecute = true; + LockPersonality = true; + NoNewPrivileges = true; + KeyringMode = "private"; + + SystemCallFilter = "@system-service"; + SystemCallErrorNumber = "EPERM"; + }; + }; + + services.postgresql = lib.mkIf cfg.postgres.enable { + enable = true; + + authentication = '' + local ${cfg.postgres.db} ${cfg.user} ident + ''; + }; + }; + }; + } ); } |
