aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-09-04 17:03:21 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-09-04 17:03:21 +0900
commit945cce2f5e487492730e06e13e920e08c55d8084 (patch)
treebbc0147dd26df2c1e950d7b2b8242223ee869e68
parent5c3e7cf6640721fc2cb5006c879bf570cedf1902 (diff)
nix: implement nixos module
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
-rw-r--r--flake.lock8
-rw-r--r--flake.nix59
-rw-r--r--nixos.nix220
-rw-r--r--package.nix25
4 files changed, 271 insertions, 41 deletions
diff --git a/flake.lock b/flake.lock
index 98f71cbe..06b3ed31 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,16 +2,16 @@
"nodes": {
"nixpkgs": {
"locked": {
- "lastModified": 1717179513,
- "narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=",
+ "lastModified": 1725361206,
+ "narHash": "sha256-/HTUg+kMaqBPGrcQBYboAMsQHIWIkuKRDldss/035Hc=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0",
+ "rev": "2830c7c930311397d94c0b86a359c865c081c875",
"type": "github"
},
"original": {
"owner": "NixOS",
- "ref": "24.05",
+ "ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
}
diff --git a/flake.nix b/flake.nix
index 1e31f3b5..aa10f3db 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,56 +1,41 @@
{
- description = "fortify development environment";
+ description = "fortify sandbox tool and nixos module";
inputs = {
- nixpkgs.url = "github:NixOS/nixpkgs/24.05";
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small";
};
outputs =
{ self, nixpkgs }:
let
- supportedSystems = [ "x86_64-linux" ];
- forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
+ supportedSystems = [
+ "aarch64-linux"
+ "i686-linux"
+ "x86_64-linux"
+ ];
+
+ forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
+ nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
in
{
- devShells = forAllSystems (
+ nixosModules.fortify = import ./nixos.nix;
+
+ packages = forAllSystems (
system:
let
- pkgs = import nixpkgs { inherit system; };
+ pkgs = nixpkgsFor.${system};
in
{
- default =
- let
- inherit (pkgs)
- mkShell
- buildGoModule
- acl
- xorg
- ;
- in
- mkShell {
- packages = [
- (buildGoModule rec {
- pname = "fortify";
- version = "0.0.0-flake";
-
- src = ./.;
- vendorHash = null; # we have no Go dependencies :3
+ default = self.packages.${system}.fortify;
- ldflags = [
- "-s"
- "-w"
- "-X"
- "main.Version=v${version}"
- ];
-
- buildInputs = [
- acl
- xorg.libxcb
- ];
- })
- ];
- };
+ fortify = pkgs.callPackage ./package.nix { };
}
);
+
+ devShells = forAllSystems (system: {
+ default = nixpkgsFor.${system}.mkShell {
+ buildInputs = with nixpkgsFor.${system}; [ self.packages.${system}.fortify ];
+ };
+ });
};
}
diff --git a/nixos.nix b/nixos.nix
new file mode 100644
index 00000000..0fe5b713
--- /dev/null
+++ b/nixos.nix
@@ -0,0 +1,220 @@
+{
+ lib,
+ pkgs,
+ config,
+ ...
+}:
+
+let
+ inherit (lib)
+ types
+ mkOption
+ mkEnableOption
+ mkIf
+ mapAttrs
+ mapAttrsToList
+ foldlAttrs
+ optional
+ ;
+
+ cfg = config.environment.fortify;
+in
+
+{
+ options = {
+ environment.fortify = {
+ enable = mkEnableOption "fortify";
+
+ target = mkOption {
+ default = { };
+ type =
+ let
+ inherit (types)
+ str
+ enum
+ bool
+ package
+ anything
+ submodule
+ listOf
+ attrsOf
+ nullOr
+ ;
+ in
+ attrsOf (submodule {
+ options = {
+ packages = mkOption {
+ type = listOf package;
+ default = [ ];
+ description = ''
+ List of extra packages to install via home-manager.
+ '';
+ };
+
+ launchers = mkOption {
+ type = attrsOf (submodule {
+ options = {
+ command = mkOption {
+ type = nullOr str;
+ default = null;
+ description = ''
+ Command to run as the target user.
+ Setting this to null will default command to wrapper name.
+ '';
+ };
+
+ pulse = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to share the PulseAudio socket and cookie.
+ '';
+ };
+
+ share = mkOption {
+ type = nullOr package;
+ default = null;
+ description = ''
+ Package containing share files.
+ Setting this to null will default package name to wrapper name.
+ '';
+ };
+
+ method = mkOption {
+ type = enum [
+ "fortify"
+ "fortify-sudo"
+ "sudo"
+ ];
+ default = "fortify";
+ description = ''
+ Launch method for the sandboxed program.
+ '';
+ };
+ };
+ });
+ default = { };
+ };
+
+ persistence = mkOption {
+ type = submodule {
+ options = {
+ directories = mkOption {
+ type = listOf anything;
+ default = [ ];
+ };
+
+ files = mkOption {
+ type = listOf anything;
+ default = [ ];
+ };
+ };
+ };
+ description = ''
+ Per-user state passed to github:nix-community/impermanence.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = anything;
+ default = { };
+ description = "Extra home-manager configuration.";
+ };
+ };
+ });
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.callPackage ./package.nix { };
+ description = "Package providing fortify.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ description = "Privileged user account.";
+ };
+
+ shell = mkOption {
+ type = types.str;
+ description = ''
+ Shell set up to source home-manager for the privileged user.
+ Required for setting up the environment of sandboxed programs.
+ '';
+ };
+
+ stateDir = mkOption {
+ type = types.str;
+ description = ''
+ The path to persistent storage where per-user state should be stored.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.persistence.${cfg.stateDir}.users = mapAttrs (_: target: target.persistence) cfg.target;
+
+ home-manager.users =
+ mapAttrs (_: target: target.extraConfig // { home.packages = target.packages; }) cfg.target
+ // {
+ ${cfg.user}.home.packages =
+ let
+ wrap =
+ user: launchers:
+ mapAttrsToList (
+ name: launcher:
+ let
+ command = if launcher.command == null then name else launcher.command;
+ in
+ pkgs.writeShellScriptBin name (
+ if launcher.method == "sudo" then
+ ''
+ exec sudo -u ${user} -i ${command} $@
+ ''
+ else
+ ''
+ exec fortify${if launcher.pulse then " -pulse" else ""} -u ${user}${
+ if launcher.method == "fortify-sudo" then " -sudo" else ""
+ } ${cfg.shell} -c "exec ${command} $@"
+ ''
+ )
+ ) launchers;
+ in
+ foldlAttrs (
+ acc: user: target:
+ acc
+ ++ (foldlAttrs (
+ shares: name: launcher:
+ let
+ pkg = if launcher.share != null then launcher.share else pkgs.${name};
+ link = source: "[ -d '${source}' ] && ln -sv '${source}' $out/share || true";
+ in
+ shares
+ ++ optional (launcher.method == "fortify") (
+ pkgs.runCommand "${name}-share" { } ''
+ mkdir -p $out/share
+ ${link "${pkg}/share/applications"}
+ ${link "${pkg}/share/icons"}
+ ${link "${pkg}/share/man"}
+ ''
+ )
+ ) (wrap user target.launchers) target.launchers)
+ ) [ cfg.package ] cfg.target;
+ };
+
+ security.polkit.extraConfig =
+ let
+ allowList = builtins.toJSON (mapAttrsToList (name: _: name) cfg.target);
+ in
+ ''
+ polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.machine1.host-shell" &&
+ ${allowList}.indexOf(action.lookup("user")) > -1 &&
+ subject.user == "${cfg.user}") {
+ return polkit.Result.YES;
+ }
+ });
+ '';
+ };
+}
diff --git a/package.nix b/package.nix
new file mode 100644
index 00000000..4445d2cb
--- /dev/null
+++ b/package.nix
@@ -0,0 +1,25 @@
+{
+ acl,
+ xorg,
+ buildGoModule,
+}:
+
+buildGoModule rec {
+ pname = "fortify";
+ version = "1.0.3";
+
+ src = ./.;
+ vendorHash = null;
+
+ ldflags = [
+ "-s"
+ "-w"
+ "-X"
+ "main.Version=v${version}"
+ ];
+
+ buildInputs = [
+ acl
+ xorg.libxcb
+ ];
+}