{ config, lib, pkgs, ... }: let cfg = config.modules.rustfs; rustfsPkg = pkgs.stdenv.mkDerivation { pname = "rustfs"; version = "1.0.1"; src = pkgs.fetchurl { url = "https://github.com/rustfs/rustfs/releases/download/1.0.1/rustfs-linux-x86_64-musl-v1.0.1.zip"; hash = "sha256-qDQJba+h8aVYJaLNr0nQBqGTl400Ty1QjCvkdRM3OKM="; }; nativeBuildInputs = [ pkgs.unzip ]; unpackPhase = "unzip $src"; installPhase = '' mkdir -p $out/bin cp rustfs rustfs-cli $out/bin/ chmod +x $out/bin/* ''; }; in { options.modules.rustfs = { enable = lib.mkEnableOption "RustFS S3 object storage server"; package = lib.mkOption { type = lib.types.package; default = rustfsPkg; description = "The rustfs package to use."; }; dataDir = lib.mkOption { type = lib.types.path; default = "/rustfs/data"; description = "Path to store RustFS data."; }; address = lib.mkOption { type = lib.types.str; default = "0.0.0.0:9000"; description = "S3 API listen address."; }; consoleAddress = lib.mkOption { type = lib.types.str; default = "0.0.0.0:9001"; description = "Console listen address."; }; environmentFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = "Environment file containing RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY."; }; accessKey = lib.mkOption { type = lib.types.str; default = "rustfsadmin"; description = "Root access key if not using environmentFile."; }; secretKey = lib.mkOption { type = lib.types.str; default = "rustfsadmin"; description = "Root secret key if not using environmentFile."; }; allowedNetworks = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ "127.0.0.0/8" "10.0.0.0/8" "100.64.0.0/10" "172.16.0.0/12" "192.168.0.0/16" "fd00::/8" "fe80::/10" "::1" ]; description = "Networks allowed to reach RustFS (enforced via systemd IPAddressAllow)."; }; }; config = lib.mkIf cfg.enable { users.users.rustfs = { isSystemUser = true; group = "rustfs"; home = cfg.dataDir; createHome = false; }; users.groups.rustfs = { }; systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0750 rustfs rustfs -" ]; systemd.services.rustfs = { description = "RustFS Object Storage Server"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" "zfs-mount.service" ]; wants = [ "network-online.target" ]; requires = [ "zfs-mount.service" ]; unitConfig.AssertPathIsMountPoint = "/rustfs"; environment = { RUSTFS_VOLUMES = cfg.dataDir; RUSTFS_ADDRESS = cfg.address; RUSTFS_CONSOLE_ENABLE = "true"; RUSTFS_CONSOLE_ADDRESS = cfg.consoleAddress; } // lib.optionalAttrs (cfg.environmentFile == null) { RUSTFS_ACCESS_KEY = cfg.accessKey; RUSTFS_SECRET_KEY = cfg.secretKey; }; serviceConfig = { User = "rustfs"; Group = "rustfs"; EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; ExecStart = "${cfg.package}/bin/rustfs server ${cfg.dataDir}"; Restart = "always"; RestartSec = "5s"; LimitNOFILE = 65536; IPAddressAllow = cfg.allowedNetworks; IPAddressDeny = [ "any" ]; }; }; }; }