Linux desktop application sandbox.
Go to file
Ophestra 3c80fd2b0f
All checks were successful
Test / Create distribution (push) Successful in 19s
Test / Run NixOS test (push) Successful in 49s
app: defer system.I revert
Just returning an error after a successful call of commit will leave garbage behind with no way for the caller to clean them. This change ensures revert is always called after successful commit with at least per-process state enabled.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-02-19 21:12:11 +09:00
.gitea/workflows release: 0.2.14 2025-02-15 23:05:02 +09:00
acl acl: implement Update in C 2025-02-17 21:39:14 +09:00
cmd system: move out of internal 2025-02-17 19:00:43 +09:00
comp fortify: zsh complete show instance list 2024-12-21 21:13:53 +09:00
dbus dbus: remove BwrapStatic method 2025-02-14 18:09:59 +09:00
dist nix: configure target users via nixos 2025-01-23 17:04:19 +09:00
fst app: defer system.I revert 2025-02-19 21:12:11 +09:00
helper helper/bwrap: rename Write to WriteFile 2025-02-19 00:34:19 +09:00
internal app: defer system.I revert 2025-02-19 21:12:11 +09:00
ldd helper: use generic extra files interface 2025-02-13 23:34:15 +09:00
system acl: rename UpdatePerms to Update 2025-02-17 20:33:18 +09:00
wl app: improve WAYLAND_DISPLAY correctness 2025-02-15 14:45:09 +09:00
.gitignore nix: generate application package build script 2024-12-29 00:42:21 +09:00
bundle.nix cmd/fpkg: expose nixGL wrappers 2024-12-30 02:02:20 +09:00
error.go fmsg: export logBaseError function 2025-02-18 13:02:51 +09:00
flake.lock release: 0.2.13 2025-02-13 23:45:54 +09:00
flake.nix nix: run integration tests with race detector 2025-02-16 20:58:08 +09:00
go.mod migrate to git.gensokyo.uk/security/fortify 2024-12-20 00:20:02 +09:00
LICENSE apply MIT license 2024-07-16 20:49:00 +09:00
main.go app: defer system.I revert 2025-02-19 21:12:11 +09:00
nixos.nix nix: test direct_wayland behaviour 2025-02-15 10:45:27 +09:00
options.md release: 0.2.15 2025-02-17 00:13:04 +09:00
options.nix nix: test direct_wayland behaviour 2025-02-15 10:45:27 +09:00
package.nix release: 0.2.15 2025-02-17 00:13:04 +09:00
parse.go sys: rename from linux 2025-02-18 18:47:48 +09:00
print_test.go fortify: check print behaviour 2025-02-14 14:44:28 +09:00
print.go sys: rename from linux 2025-02-18 18:47:48 +09:00
README.md migrate to git.gensokyo.uk/security/fortify 2024-12-20 00:20:02 +09:00
test.nix linux: wrap fsu lookup error 2025-02-18 17:39:53 +09:00

Fortify

Go Reference Go Report Card

Lets you run graphical applications as another user in a confined environment with a nice NixOS module to configure target users and provide launchers and desktop files for your privileged user.

Why would you want this?

  • It protects the desktop environment from applications.

  • It protects applications from each other.

  • It provides UID isolation on top of the standard application sandbox.

If you have a flakes-enabled nix environment, you can try out the tool by running:

nix run git+https://git.gensokyo.uk/security/fortify -- help

Module usage

The NixOS module currently requires home-manager to function correctly.

Full module documentation can be found here.

To use the module, import it into your configuration with

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";

    fortify = {
      url = "git+https://git.gensokyo.uk/security/fortify";

      # Optional but recommended to limit the size of your system closure.
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, fortify, ... }:
  {
    nixosConfigurations.fortify = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        fortify.nixosModules.fortify
      ];
    };
  };
}

This adds the environment.fortify option:

{ pkgs, ... }:

{
  environment.fortify = {
    enable = true;
    stateDir = "/var/lib/persist/module/fortify";
    users = {
      alice = 0;
      nixos = 10;
    };

    apps = [
      {
        name = "chromium";
        id = "org.chromium.Chromium";
        packages = [ pkgs.chromium ];
        userns = true;
        mapRealUid = true;
        dbus = {
          system = {
            filter = true;
            talk = [
              "org.bluez"
              "org.freedesktop.Avahi"
              "org.freedesktop.UPower"
            ];
          };
          session =
            f:
            f {
              talk = [
                "org.freedesktop.FileManager1"
                "org.freedesktop.Notifications"
                "org.freedesktop.ScreenSaver"
                "org.freedesktop.secrets"
                "org.kde.kwalletd5"
                "org.kde.kwalletd6"
              ];
              own = [
                "org.chromium.Chromium.*"
                "org.mpris.MediaPlayer2.org.chromium.Chromium.*"
                "org.mpris.MediaPlayer2.chromium.*"
              ];
              call = { };
              broadcast = { };
            };
        };
      }
      {
        name = "claws-mail";
        id = "org.claws_mail.Claws-Mail";
        packages = [ pkgs.claws-mail ];
        gpu = false;
        capability.pulse = false;
      }
      {
        name = "weechat";
        packages = [ pkgs.weechat ];
        capability = {
          wayland = false;
          x11 = false;
          dbus = true;
          pulse = false;
        };
      }
      {
        name = "discord";
        id = "dev.vencord.Vesktop";
        packages = [ pkgs.vesktop ];
        share = pkgs.vesktop;
        command = "vesktop --ozone-platform-hint=wayland";
        userns = true;
        mapRealUid = true;
        capability.x11 = true;
        dbus = {
          session =
            f:
            f {
              talk = [ "org.kde.StatusNotifierWatcher" ];
              own = [ ];
              call = { };
              broadcast = { };
            };
          system.filter = true;
        };
      }
      {
        name = "looking-glass-client";
        groups = [ "plugdev" ];
        extraPaths = [
          {
            src = "/dev/shm/looking-glass";
            write = true;
          }
        ];
        extraConfig = {
          programs.looking-glass-client.enable = true;
        };
      }
    ];
  };
}