feat: add nix package, module, and container

Signed-off-by: seth <getchoo@tuta.io>
This commit is contained in:
seth 2023-12-03 04:14:20 -05:00
parent 45403e9d9b
commit e928eb67df
No known key found for this signature in database
GPG key ID: D31BD0D494BBEE86
7 changed files with 497 additions and 67 deletions

84
nix/deployment.nix Normal file
View file

@ -0,0 +1,84 @@
{
inputs,
self,
...
}: {
flake.nixosModules.default = import ./module.nix self;
perSystem = {
lib,
pkgs,
system,
config,
inputs',
...
}: let
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";
});
exeFor = 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;
};
refraction = config.packages.refraction.override {
naersk = naersk';
optimizeSize = true;
};
inherit (crossPkgsFor.${system}.${arch}.stdenv) cc;
in
lib.getExe (
refraction.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 {
name = "refraction";
tag = "latest-${arch}";
contents = [pkgs.dockerTools.caCertificates];
config.Cmd = [(exeFor arch)];
architecture = crossPkgsFor.${system}.${arch}.go.GOARCH;
};
in {
legacyPackages = {
container-x86_64 = containerFor "x86_64";
container-aarch64 = containerFor "aarch64";
};
};
}

51
nix/derivation.nix Normal file
View file

@ -0,0 +1,51 @@
{
lib,
stdenv,
naersk,
CoreFoundation,
Security,
SystemConfiguration,
version,
optimizeSize ? false,
}: let
filter = path: type: let
path' = toString path;
base = baseNameOf path';
dirBlocklist = ["nix"];
matches = lib.any (suffix: lib.hasSuffix suffix base) [".rs"];
isCargo = base == "Cargo.lock" || base == "Cargo.toml";
isAllowedDir = !(builtins.elem base dirBlocklist);
in
(type == "directory" && isAllowedDir) || matches || isCargo;
filterSource = src:
lib.cleanSourceWith {
src = lib.cleanSource src;
inherit filter;
};
in
naersk.buildPackage {
pname = "refraction";
inherit version;
src = filterSource ../.;
buildInputs = lib.optionals stdenv.hostPlatform.isDarwin [
CoreFoundation
Security
SystemConfiguration
];
RUSTFLAGS = lib.optionalString optimizeSize "-C codegen-units=1 -C strip=symbols -C opt-level=z";
meta = with lib; {
mainProgram = "refraction";
description = "Discord bot for Prism Launcher";
homepage = "https://github.com/PrismLauncher/refraction";
license = licenses.gpl3Plus;
platforms = with platforms; linux ++ darwin;
maintainers = with maintainers; [getchoo Scrumplex];
};
}

50
nix/dev.nix Normal file
View file

@ -0,0 +1,50 @@
{
perSystem = {
lib,
pkgs,
config,
...
}: {
pre-commit.settings.hooks = {
actionlint.enable = true;
alejandra.enable = true;
rustfmt.enable = true;
nil.enable = true;
prettier = {
enable = true;
excludes = ["flake.lock"];
};
};
proc.groups.daemons.processes = {
redis.command = "${lib.getExe' pkgs.redis "redis-server"}";
};
devShells.default = pkgs.mkShell {
shellHook = ''
${config.pre-commit.installationScript}
'';
packages = with pkgs; [
# general
actionlint
config.proc.groups.daemons.package
# rust
cargo
rustc
clippy
rustfmt
rust-analyzer
# nix
config.formatter
nil
];
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
};
formatter = pkgs.alejandra;
};
}

143
nix/module.nix Normal file
View file

@ -0,0 +1,143 @@
self: {
config,
lib,
pkgs,
...
}: let
cfg = config.services.refraction;
defaultUser = "refraction";
inherit
(lib)
getExe
literalExpression
mdDoc
mkEnableOption
mkIf
mkOption
mkPackageOption
optionals
types
;
in {
options.services.refraction = {
enable = mkEnableOption "refraction";
package = mkPackageOption self.packages.${pkgs.stdenv.hostPlatform.system} "refraction" {};
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/refraction"
'';
};
};
config = mkIf cfg.enable {
services.redis.servers.refraction = mkIf (cfg.redisUrl == "local") {
enable = true;
inherit (cfg) user;
port = 0; # disable tcp listener
};
systemd.services."refraction" = {
enable = true;
wantedBy = ["multi-user.target"];
after =
["network.target"]
++ optionals (cfg.redisUrl == "local") ["redis-refraction.service"];
script = ''
${getExe cfg.package}
'';
environment = {
REDIS_URL =
if cfg.redisUrl == "local"
then "unix:${config.services.redis.servers.refraction.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;
};
};
users = {
users = mkIf (cfg.user == defaultUser) {
${defaultUser} = {
isSystemUser = true;
inherit (cfg) group;
};
};
groups = mkIf (cfg.group == defaultUser) {
${defaultUser} = {};
};
};
};
}

29
nix/packages.nix Normal file
View file

@ -0,0 +1,29 @@
{
self,
inputs,
...
}: {
perSystem = {
pkgs,
system,
config,
...
}: {
packages = {
refraction = pkgs.callPackage ./derivation.nix {
version = builtins.substring 0 8 self.lastModifiedDate or "dirty";
inherit
(pkgs.darwin.apple_sdk.frameworks)
CoreFoundation
Security
SystemConfiguration
;
naersk = inputs.naersk.lib.${system};
};
default = config.packages.refraction;
};
};
}