diff options
| author | seth <[email protected]> | 2023-12-15 02:40:21 -0500 |
|---|---|---|
| committer | seth <[email protected]> | 2023-12-15 16:41:13 -0500 |
| commit | aad424b4ba9989be4536390749ad0de351dd13ef (patch) | |
| tree | fe99931dc498d69c8d09d23c4b5aed7661212231 /nix | |
| parent | 03223e6e6d061a18b66a69092c59e6a0cb6d1d3f (diff) | |
flake: move nix to folder to nix/
Diffstat (limited to 'nix')
| -rw-r--r-- | nix/deployment.nix | 86 | ||||
| -rw-r--r-- | nix/derivation.nix | 58 | ||||
| -rw-r--r-- | nix/dev.nix | 52 | ||||
| -rw-r--r-- | nix/module.nix | 144 | ||||
| -rw-r--r-- | nix/packages.nix | 28 | ||||
| -rw-r--r-- | nix/workflow.nix | 15 |
6 files changed, 383 insertions, 0 deletions
diff --git a/nix/deployment.nix b/nix/deployment.nix new file mode 100644 index 0000000..9fb754e --- /dev/null +++ b/nix/deployment.nix @@ -0,0 +1,86 @@ +{ + inputs, + self, + ... +}: { + flake.nixosModules.default = import ./module.nix self; + + perSystem = { + lib, + pkgs, + system, + config, + inputs', + ... + }: let + name = "getchoo/teawiebot"; + + crossPkgsFor = lib.fix (finalAttrs: { + "x86_64-linux" = { + "x86_64" = pkgs.pkgsStatic; + "aarch64" = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic; + }; + + "aarch64-linux" = { + "x86_64" = pkgs.pkgsCross.musl64; + "aarch64" = pkgs.pkgsStatic; + }; + + "x86_64-darwin" = { + "x86_64" = pkgs.pkgsCross.musl64; + "aarch64" = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic; + }; + + "aarch64-darwin" = finalAttrs."x86_64-darwin"; + }); + + wieFor = arch: let + target = "${arch}-unknown-linux-musl"; + target' = builtins.replaceStrings ["-"] ["_"] target; + targetUpper = lib.toUpper target'; + + toolchain = with inputs'.fenix.packages; + combine [ + minimal.cargo + minimal.rustc + targets.${target}.latest.rust-std + ]; + + naersk' = inputs.naersk.lib.${system}.override { + cargo = toolchain; + rustc = toolchain; + }; + + teawiebot = config.packages.teawiebot.override { + naersk = naersk'; + optimizeSize = true; + }; + + inherit (crossPkgsFor.${system}.${arch}.stdenv) cc; + in + lib.getExe ( + teawiebot.overrideAttrs (_: + lib.fix (finalAttrs: { + CARGO_BUILD_TARGET = target; + "CC_${target'}" = "${cc}/bin/${cc.targetPrefix}cc"; + "CARGO_TARGET_${targetUpper}_RUSTFLAGS" = "-C target-feature=+crt-static"; + "CARGO_TARGET_${targetUpper}_LINKER" = finalAttrs."CC_${target'}"; + })) + ); + + containerFor = arch: + pkgs.dockerTools.buildLayeredImage { + inherit name; + tag = "latest-${arch}"; + contents = [pkgs.dockerTools.caCertificates]; + config.Cmd = [(wieFor arch)]; + + architecture = crossPkgsFor.${system}.${arch}.go.GOARCH; + }; + in { + packages = { + container-x86_64 = containerFor "x86_64"; + container-aarch64 = containerFor "aarch64"; + }; + }; +} diff --git a/nix/derivation.nix b/nix/derivation.nix new file mode 100644 index 0000000..061baea --- /dev/null +++ b/nix/derivation.nix @@ -0,0 +1,58 @@ +{ + lib, + stdenv, + naersk, + CoreFoundation, + Security, + SystemConfiguration, + self, + lto ? false, + optimizeSize ? false, +}: let + filter = path: type: let + path' = toString path; + base = baseNameOf path'; + parent = baseNameOf (dirOf path'); + + dirBlocklist = ["parts"]; + + matches = lib.any (suffix: lib.hasSuffix suffix base) [".rs"]; + isCargo = base == "Cargo.lock" || base == "Cargo.toml"; + isCopypasta = parent == "copypastas"; + isAllowedDir = !(builtins.elem base dirBlocklist); + in + (type == "directory" && isAllowedDir) || matches || isCargo || isCopypasta; + + filterSource = src: + lib.cleanSourceWith { + src = lib.cleanSource src; + inherit filter; + }; +in + naersk.buildPackage { + pname = "teawiebot"; + version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; + + src = filterSource ../.; + + buildInputs = lib.optionals stdenv.hostPlatform.isDarwin [ + CoreFoundation + Security + SystemConfiguration + ]; + + GIT_SHA = builtins.substring 0 7 self.rev or "dirty"; + + RUSTFLAGS = + lib.optionalString lto " -C lto=thin -C embed-bitcode=yes" + + lib.optionalString optimizeSize " -C codegen-units=1 -C strip=symbols -C opt-level=z"; + + meta = with lib; { + mainProgram = "teawiebot"; + description = "funni bot"; + homepage = "https://github.com/getchoo/teawiebot"; + license = licenses.mit; + platforms = with platforms; linux ++ darwin; + maintainers = with maintainers; [getchoo]; + }; + } diff --git a/nix/dev.nix b/nix/dev.nix new file mode 100644 index 0000000..a796912 --- /dev/null +++ b/nix/dev.nix @@ -0,0 +1,52 @@ +{ + perSystem = { + lib, + pkgs, + config, + ... + }: { + pre-commit.settings = { + hooks = { + actionlint.enable = true; + ${config.formatter.pname}.enable = true; + deadnix.enable = true; + nil.enable = true; + prettier.enable = true; + rustfmt.enable = true; + statix.enable = true; + }; + }; + + proc.groups.daemons.processes = { + redis.command = lib.getExe' pkgs.redis "redis-server"; + }; + + devShells = { + default = pkgs.mkShell { + packages = with pkgs; [ + # general + actionlint + nodePackages_latest.prettier + config.proc.groups.daemons.package + + # rust + cargo + rustc + clippy + rustfmt + rust-analyzer + + # nix + config.formatter + deadnix + nil + statix + ]; + + RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; + }; + }; + + formatter = pkgs.alejandra; + }; +} diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..d7709a4 --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,144 @@ +self: { + 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 self.packages.${pkgs.stdenv.hostPlatform.system} "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/packages.nix b/nix/packages.nix new file mode 100644 index 0000000..4e1ab27 --- /dev/null +++ b/nix/packages.nix @@ -0,0 +1,28 @@ +{ + self, + inputs, + ... +}: { + perSystem = { + pkgs, + system, + config, + ... + }: { + packages = { + teawiebot = pkgs.callPackage ./derivation.nix { + inherit self; + inherit + (pkgs.darwin.apple_sdk.frameworks) + CoreFoundation + Security + SystemConfiguration + ; + + naersk = inputs.naersk.lib.${system}; + }; + + default = config.packages.teawiebot; + }; + }; +} diff --git a/nix/workflow.nix b/nix/workflow.nix new file mode 100644 index 0000000..600a1bb --- /dev/null +++ b/nix/workflow.nix @@ -0,0 +1,15 @@ +{ + githubWorkflowGenerator = { + outputs = [ + "checks" + "devShells" + "packages" + ]; + + overrides = { + checks.systems = ["x86_64-linux"]; + devShells.systems = ["x86_64-linux"]; + packages.systems = ["x86_64-linux"]; + }; + }; +} |
