diff options
| author | seth <[email protected]> | 2024-03-20 08:12:19 -0400 |
|---|---|---|
| committer | seth <[email protected]> | 2024-03-20 08:12:19 -0400 |
| commit | d48ab1b30a4b6c093c2d7ff27dfb0b6d7a2bafdd (patch) | |
| tree | 0ab828f6c6738ec495aafbdf29c46c3cc3a5cbfe /nix/deployment | |
| parent | 0f280dd61c1c138e4c41b715e27fc292f24bbac9 (diff) | |
nix: naersk -> rustPlatform
Diffstat (limited to 'nix/deployment')
| -rw-r--r-- | nix/deployment/default.nix | 35 | ||||
| -rw-r--r-- | nix/deployment/module.nix | 146 | ||||
| -rw-r--r-- | nix/deployment/static.nix | 50 |
3 files changed, 231 insertions, 0 deletions
diff --git a/nix/deployment/default.nix b/nix/deployment/default.nix new file mode 100644 index 0000000..7fd379f --- /dev/null +++ b/nix/deployment/default.nix @@ -0,0 +1,35 @@ +{ + flake-parts-lib, + withSystem, + ... +}: { + imports = [./static.nix]; + + flake.nixosModules.default = flake-parts-lib.importApply ./module.nix { + inherit withSystem; + }; + + perSystem = { + lib, + pkgs, + self', + ... + }: let + containerFor = arch: + pkgs.dockerTools.buildLayeredImage { + name = "teawiebot"; + tag = "latest-${arch}"; + contents = [pkgs.dockerTools.caCertificates]; + config.Cmd = [ + (lib.getExe self'.packages."teawiebot-static-${arch}") + ]; + + architecture = withSystem "${arch}-linux" ({pkgs, ...}: pkgs.pkgsStatic.go.GOARCH); + }; + in { + packages = { + container-x86_64 = containerFor "x86_64"; + container-aarch64 = containerFor "aarch64"; + }; + }; +} diff --git a/nix/deployment/module.nix b/nix/deployment/module.nix new file mode 100644 index 0000000..09999f1 --- /dev/null +++ b/nix/deployment/module.nix @@ -0,0 +1,146 @@ +{withSystem, ...}: { + config, + lib, + pkgs, + ... +}: let + cfg = config.services.teawiebot; + defaultUser = "teawiebot"; + + inherit + (lib) + getExe + literalExpression + mdDoc + mkEnableOption + mkIf + mkOption + mkPackageOption + optionals + types + ; +in { + options.services.teawiebot = { + enable = mkEnableOption "teawiebot"; + package = mkPackageOption ( + withSystem pkgs.stdenv.hostPlatform.system ({self', ...}: self'.packages) + ) "teawiebot" {}; + + user = mkOption { + description = mdDoc '' + User under which the service should run. If this is the default value, + the user will be created, with the specified group as the primary + group. + ''; + type = types.str; + default = defaultUser; + example = literalExpression '' + "bob" + ''; + }; + + group = mkOption { + description = mdDoc '' + Group under which the service should run. If this is the default value, + the group will be created. + ''; + type = types.str; + default = defaultUser; + example = literalExpression '' + "discordbots" + ''; + }; + + redisUrl = mkOption { + description = mdDoc '' + Connection to a redis server. If this needs to include credentials + that shouldn't be world-readable in the Nix store, set environmentFile + and override the `REDIS_URL` entry. + Pass the string `local` to setup a local Redis database. + ''; + type = types.str; + default = "local"; + example = literalExpression '' + "redis://localhost/" + ''; + }; + + environmentFile = mkOption { + description = mdDoc '' + Environment file as defined in {manpage}`systemd.exec(5)` + ''; + type = types.nullOr types.path; + default = null; + example = literalExpression '' + "/run/agenix.d/1/teawieBot" + ''; + }; + }; + + config = mkIf cfg.enable { + services.redis.servers.teawiebot = mkIf (cfg.redisUrl == "local") { + enable = true; + inherit (cfg) user; + port = 0; # disable tcp listener + }; + + systemd.services."teawiebot" = { + enable = true; + wantedBy = ["multi-user.target"]; + after = + ["network.target"] + ++ optionals (cfg.redisUrl == "local") ["redis-teawiebot.service"]; + + script = '' + ${getExe cfg.package} + ''; + + environment = { + REDIS_URL = + if cfg.redisUrl == "local" + then "unix:${config.services.redis.servers.teawiebot.unixSocket}" + else cfg.redisUrl; + }; + + serviceConfig = { + Type = "simple"; + Restart = "always"; + + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; + + User = cfg.user; + Group = cfg.group; + + # hardening + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + RestrictNamespaces = "uts ipc pid user cgroup"; + RestrictSUIDSGID = true; + Umask = "0007"; + }; + }; + + users = { + users = mkIf (cfg.user == defaultUser) { + ${defaultUser} = { + isSystemUser = true; + inherit (cfg) group; + }; + }; + + groups = mkIf (cfg.group == defaultUser) { + ${defaultUser} = {}; + }; + }; + }; +} diff --git a/nix/deployment/static.nix b/nix/deployment/static.nix new file mode 100644 index 0000000..dcdf0f3 --- /dev/null +++ b/nix/deployment/static.nix @@ -0,0 +1,50 @@ +{ + perSystem = { + lib, + pkgs, + inputs', + self', + ... + }: let + targets = with pkgs.pkgsCross; { + x86_64 = musl64.pkgsStatic; + aarch64 = aarch64-multiplatform.pkgsStatic; + }; + + toolchain = let + fenix = inputs'.fenix.packages; + in + with fenix; + combine ( + [minimal.cargo minimal.rustc] + ++ map ( + pkgs: + fenix.targets.${pkgs.stdenv.hostPlatform.config}.latest.rust-std + ) (lib.attrValues targets) + ); + + rustPlatforms = + lib.mapAttrs ( + lib.const (pkgs: + pkgs.makeRustPlatform ( + lib.genAttrs ["cargo" "rustc"] (lib.const toolchain) + )) + ) + targets; + + buildTeawieWith = rustPlatform: + self'.packages.teawiebot.override { + inherit rustPlatform; + lto = true; + optimizeSize = true; + }; + in { + packages = lib.optionalAttrs pkgs.stdenv.isLinux ( + lib.mapAttrs' ( + target: rustPlatform: + lib.nameValuePair "teawiebot-static-${target}" (buildTeawieWith rustPlatform) + ) + rustPlatforms + ); + }; +} |
