Compare commits

...

5 Commits

11 changed files with 279 additions and 114 deletions

View File

@ -41,12 +41,16 @@
sublime-music sublime-music
anki anki
gnome-podcasts gnome-podcasts
gimp
#psst #psst
evolution evolution
# Proprietary stuff (yikes) # Proprietary stuff (yikes)
discord-wrapped discord-app-wrapped spotify-wrapped discord-wrapped #discord-app-wrapped
spotify-wrapped
vortex-wrapped
zoom-vm
]; ];
ptw = { ptw = {
@ -68,6 +72,7 @@
}; };
#xournalpp.enable = true; #xournalpp.enable = true;
zsh.enable = true; zsh.enable = true;
direnv.enable = true;
office.enable = true; office.enable = true;
plasma.enable = true; plasma.enable = true;
gaming.enable = true; gaming.enable = true;

View File

@ -5,38 +5,38 @@
}: }:
{ {
name name # Name of the sandboxed package, e.g. "package-wrapped"
, package , launchScriptName # Name of the script that will be placed in $out/bin
, binaryName , binary # The binary to execute inside the sandbox
, version ? "1.0.0" , extraArgs ? [] # Extra arguments to add to the argv
, desktopFileArgs ? null , desktopFileAttributes ? {} # Arguments to apply to the desktop file
, copyIntoSandbox ? null , preDesktopFilePhase ? "" # Code to run during the install phase before building the desktop file
, enableDesktopFile ? false # Whether to build a desktop file
, copyIntoSandbox ? {} # Source -> destination relative to $out
, unshareUser ? true , unshareUser ? true
, unshareIpc ? true , unshareIpc ? true
, unsharePid ? true , unsharePid ? true
, unshareNet ? false , unshareNet ? false
, unshareUts ? true , unshareUts ? true
, unshareCgroup ? true , unshareCgroup ? true
, dieWithParent ? true , dieWithParent ? true # Should bubblewrap exit when the parents exits
, mountInHome ? [] , mountInHome ? [] # Files, directories to mount inside the sandbox
, chdirTo ? "\"$(pwd)\"" , chdirTo ? "\"$(pwd)\"" # What should be the CWD when entering the sandbox
, additionalBlacklist ? [] , additionalBlacklist ? [] # Root directories that should not be mounted
, additionalMounts ? [] , additionalMounts ? [] # Files, directories outside the home directory to mount inside the sandbox
, extraEnv ? {} , extraEnv ? {} # Extra environment variables to set inside the sandbox
, enableAlsa ? true # Mount ALSA files from /etc/
, enableSudo ? true # Mount sudo files from /etc/
, enableShells ? true # Mount shell related files from /etc/
, enableNix ? true # Mount nix related files from /etc/
, enableOsInfo ? true # Mount /etc/{machine-id,os-release}
}: }:
let let
mountHome = mountInHome == [];
etcBindFlags = let etcBindFlags = let
files = [ files = [
# NixOS Compatibility
"static"
"nix" # mainly for nixUnstable users, but also for access to nix/netrc
# Shells
"bashrc"
"zshenv"
"zshrc"
"zinputrc"
"zprofile"
# Users, Groups, NSS # Users, Groups, NSS
"passwd" "passwd"
"group" "group"
@ -46,29 +46,22 @@ let
"nsswitch.conf" "nsswitch.conf"
# User profiles # User profiles
"profiles" "profiles"
# Sudo & Su
"login.defs"
"sudoers"
"sudoers.d"
# Time # Time
"localtime" "localtime"
"zoneinfo" "zoneinfo"
# Other Core Stuff
"machine-id"
"os-release"
# PAM # PAM
"pam.d" "pam.d"
# Fonts # Fonts
"fonts" "fonts"
# ALSA ]
"alsa" ++ (lib.optionals enableNix [ "static" "nix" ])
"asound.conf" ++ (lib.optionals enableShells [ "bashrc" "zshenv" "zshrc" "zinputrc" "zprofile" ])
# SSL ++ (lib.optionals enableSudo [ "login.defs" "sudoers" "sudoers.d" ])
"ssl/certs" ++ (lib.optionals enableAlsa [ "alsa" "asound.conf" ])
"pki" ++ (lib.optionals enableOsInfo [ "machine-id" "os-release" ])
]; # Only add SSL stuff when we have networking enabled
in builtins.concatStringsSep "\n " ++ (lib.optionals (!unshareNet) [ "ssl/certs" "pki" ]);
(map (file: "--ro-bind-try /etc/${file} /etc/${file}") files); in builtins.concatStringsSep "\n " (map (file: "--ro-bind-try /etc/${file} /etc/${file}") files);
# Create this on the fly instead of linking from /nix # Create this on the fly instead of linking from /nix
# The container might have to modify it and re-run ldconfig if there are # The container might have to modify it and re-run ldconfig if there are
@ -88,15 +81,21 @@ let
EOF EOF
ldconfig &> /dev/null ldconfig &> /dev/null
''; '';
init = run: writeShellScriptBin "${binaryName}-init" '' sandboxInitScriptName = "${name}-wrapped-init.sh";
sandboxInitScript = writeShellScriptBin sandboxInitScriptName ''
source /etc/profile source /etc/profile
${createLdConfCache} ${createLdConfCache}
exec ${run} "$@" exec ${binary} "$@"
''; '';
sandboxScriptName = "${name}-wrapped.sh";
sandboxScript = let
extraEnvString = lib.foldl (acc: val: acc + val + "\n") "" (lib.mapAttrsToList (name: value: "--setenv ${name} \"${value}\"") extraEnv); extraEnvString = lib.foldl (acc: val: acc + val + "\n") "" (lib.mapAttrsToList (name: value: "--setenv ${name} \"${value}\"") extraEnv);
mountHome = mountInHome == []; stringify = x: "\"${x}\"";
initStr = init "${package}/bin/${binaryName}"; safeAdditionalMounts = map stringify additionalMounts;
bwrapCmd = { initArgs ? "" }: '' safeMountInHome = map stringify mountInHome;
in writeShellScriptBin sandboxScriptName ''
blacklist=(/nix /dev /proc /etc ${lib.optionalString (!mountHome) "/home"} ${builtins.toString additionalBlacklist}) blacklist=(/nix /dev /proc /etc ${lib.optionalString (!mountHome) "/home"} ${builtins.toString additionalBlacklist})
ro_mounts=() ro_mounts=()
symlinks=() symlinks=()
@ -112,13 +111,13 @@ let
done done
if [[ "${lib.optionalString (!mountHome) "1"}" = "1" ]]; then if [[ "${lib.optionalString (!mountHome) "1"}" = "1" ]]; then
for entry in ${builtins.toString mountInHome}; do for entry in ${builtins.toString safeMountInHome}; do
auto_mounts+=(--bind "/home/$USER/$entry" "/home/$USER/$entry") auto_mounts+=(--bind "/home/$USER/$entry" "/home/$USER/$entry")
done done
fi fi
if [[ ! -z "${builtins.toString additionalMounts}" ]]; then if [[ ! -z "${builtins.toString additionalMounts}" ]]; then
for entry in ${builtins.toString additionalMounts}; do for entry in ${builtins.toString safeAdditionalMounts}; do
auto_mounts+=(--bind "$entry" "$entry") auto_mounts+=(--bind "$entry" "$entry")
done done
fi fi
@ -158,27 +157,40 @@ let
"''${symlinks[@]}" "''${symlinks[@]}"
"''${auto_mounts[@]}" "''${auto_mounts[@]}"
${extraEnvString} ${extraEnvString}
${initStr}/bin/${name}-init ${initArgs} ${sandboxInitScript}/bin/${sandboxInitScriptName}
) )
exec "''${cmd[@]}" exec "''${cmd[@]}" $@
''; '';
bin = writeShellScriptBin name (bwrapCmd { initArgs = ''"$@"''; });
desktopItem = makeDesktopItem (desktopFileArgs // {
exec = "${bin}/bin/${name}";
});
copyIntoSandboxString = lib.concatStrings (map (x: "cp -Lr ${package}/${x} $out/${x}\n") copyIntoSandbox);
in stdenv.mkDerivation { in stdenv.mkDerivation {
pname = "${name}-sandboxed"; pname = name;
version = version; version = "1.0.0";
unpackPhase = ":"; unpackPhase = ":";
dontBuild = true; dontBuild = true;
installPhase = '' installPhase = let
desktopFilePhase = let
desktopFile = makeDesktopItem (desktopFileAttributes // {
exec = "${sandboxScript}/bin/${sandboxScriptName}";
});
in ''
cp -r ${desktopFile}/share/applications $out/share
'';
copyIntoSandboxPhase = let
attrs = builtins.attrNames copyIntoSandbox;
cps = map (x: "cp -Lr ${x} $out/${copyIntoSandbox."${x}"}\n") attrs;
in lib.concatStrings cps;
in ''
mkdir -p $out/bin mkdir -p $out/bin
ln -s ${bin}/bin/${name} $out/bin/${name} ln -s ${sandboxScript}/bin/${sandboxScriptName} $out/bin/${launchScriptName}
'' + lib.strings.optionalString (!(builtins.isNull desktopFileArgs)) ''
mkdir -p $out/share/
cp -r ${desktopItem}/share/applications $out/share # Generate the desktop file, if enabled
'' + lib.strings.optionalString (!(builtins.isNull copyIntoSandbox)) copyIntoSandboxString; ${lib.optionalString enableDesktopFile "mkdir -p $out/share"}
${lib.optionalString enableDesktopFile preDesktopFilePhase}
${lib.optionalString enableDesktopFile desktopFilePhase}
# Copy extra files if they are specified
${lib.optionalString (copyIntoSandbox != {}) copyIntoSandboxPhase}
'';
} }

View File

@ -24,6 +24,7 @@
./programs/office ./programs/office
./programs/gaming ./programs/gaming
./programs/bluray ./programs/bluray
./programs/direnv
# Services # Services
./services/kanshi ./services/kanshi

View File

@ -0,0 +1,19 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ptw.programs.direnv;
in {
options.ptw.programs.direnv = {
enable = lib.mkEnableOption "Enable direnv";
};
config = lib.mkIf cfg.enable {
home-manager.users."${config.ptw.system.singleUser}".programs.direnv = {
enable = true;
enableZshIntegration = true;
nix-direnv = {
enable = true;
};
};
};
}

View File

@ -22,7 +22,7 @@ in {
home-manager.users."${config.ptw.system.singleUser}" = { home-manager.users."${config.ptw.system.singleUser}" = {
home.file = { home.file = {
#".emacs".text = builtins.replaceStrings [ "%%DARTLANG_ANALYSIS_SERVER_PATH%%" "" ] (builtins.readFile ./dotemacs); #".emacs".text = builtins.replaceStrings [ "%%DARTLANG_ANALYSIS_SERVER_PATH%%" "" ] (builtins.readFile ./dotemacs);
".emace".source = ./dotemacs; ".emacs".source = ./dotemacs;
".emacs.d/mu4e.el".source = ./mu4e.el; ".emacs.d/mu4e.el".source = ./mu4e.el;
".emacs.d/themes/weyland-yutani-theme.el".source = "${weyland-yutani}/weyland-yutani-theme.el"; ".emacs.d/themes/weyland-yutani-theme.el".source = "${weyland-yutani}/weyland-yutani-theme.el";
}; };

View File

@ -8,7 +8,7 @@ in {
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
winePackages.stagingFull winetricks lutris-free-wrapped wineWowPackages.staging winetricks lutris-free-wrapped
(pkgs.callPackage ./wrapper.nix { (pkgs.callPackage ./wrapper.nix {
inherit (pkgs) retroarch; inherit (pkgs) retroarch;

View File

@ -10,7 +10,11 @@ in {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment = { environment = {
systemPackages = with pkgs; [ systemPackages = with pkgs; [
# Themes
arc-theme arc-theme
libsForQt5.qtstyleplugin-kvantum
# Gnome Shell Extensions
gnomeExtensions.appindicator gnomeExtensions.appindicator
gnomeExtensions.caffeine gnomeExtensions.caffeine
gnomeExtensions.gnome-40-ui-improvements gnomeExtensions.gnome-40-ui-improvements
@ -23,14 +27,17 @@ in {
gnomeExtensions.gsconnect gnomeExtensions.gsconnect
gnomeExtensions.blur-my-shell gnomeExtensions.blur-my-shell
gnomeExtensions.forge gnomeExtensions.forge
# Programs
gnome.eog gnome.eog
gnome.nautilus gnome.nautilus
gnome.evince gnome.evince
unstable.gnome.gnome-shell
gnome.gnome-terminal gnome.gnome-terminal
pinentry-gnome pinentry-gnome
mousai
# For config
dconf # For home-manager dconf # For home-manager
libsForQt5.qtstyleplugin-kvantum
]; ];
gnome.excludePackages = pkgs.gnome.optionalPackages; gnome.excludePackages = pkgs.gnome.optionalPackages;
}; };

View File

@ -47,8 +47,14 @@ in {
bindkey "\e[3~" delete-char bindkey "\e[3~" delete-char
''; '';
history.share = true; history.share = true;
initExtraFirst = let
enableDirenv = lib.optionalString
config.ptw.programs.direnv.enable
"eval \"$(${pkgs.direnv}/bin/direnv hook zsh)\"";
in ''
${enableDirenv}
# TODO: Maybe move this somewhere else # TODO: Maybe move this somewhere else
initExtraFirst = ''
wcurl() { wcurl() {
[[ -z "$1" ]] && echo "Error: No URL specified" && exit 1 [[ -z "$1" ]] && echo "Error: No URL specified" && exit 1

View File

@ -3,27 +3,7 @@ final: prev:
let let
wrapInSandbox = prev.callPackage ../lib/sandbox.nix {}; wrapInSandbox = prev.callPackage ../lib/sandbox.nix {};
in { in {
discord-wrapped = wrapInSandbox { /*
name = "discord";
package = prev.discord;
#package = discord-system-electron;
binaryName = "discord";
mountInHome = [ ".config/discord" ".config/BetterDiscord" ];
additionalBlacklist = [ "/mnt" ];
chdirTo = "/home/$USER";
version = "1.0.1";
copyIntoSandbox = [ "share/pixmaps" ];
desktopFileArgs = {
name = "discord-wrapped";
#exec = "discord";
icon = "discord";
desktopName = "Discord (wrapped)";
genericName = "Instant Messenger";
categories = [ "Network" "InstantMessaging" ];
};
};
discord-app-wrapped = wrapInSandbox { discord-app-wrapped = wrapInSandbox {
name = "discord-app"; name = "discord-app";
package = prev.discord-app; package = prev.discord-app;
@ -50,48 +30,135 @@ in {
mountInHome = [ ".local/share/minecraft" ".minecraft" ]; mountInHome = [ ".local/share/minecraft" ".minecraft" ];
additionalBlacklist = [ "/mnt" ]; additionalBlacklist = [ "/mnt" ];
chdirTo = "/home/$USER"; chdirTo = "/home/$USER";
}; };*/
steam-wrapped = wrapInSandbox { steam-wrapped = wrapInSandbox {
name = "steam"; name = "steam-wrapped";
package = prev.steam; binary = "${prev.steam}/bin/steam";
binaryName = "steam"; launchScriptName = "steam";
mountInHome = [ ".steam" ".local/share/Steam" ]; mountInHome = [ ".steam" ".local/share/Steam" ];
additionalBlacklist = [ "/mnt" ]; additionalBlacklist = [ "/mnt" ];
additionalMounts = [ "/mnt/Storage/Games/SteamLibrary" ]; additionalMounts = [ "/mnt/Storage/Games/SteamLibrary" ];
chdirTo = "/home/$USER"; chdirTo = "/home/$USER";
extraEnv = {
DRI_PRIME = "1";
};
copyIntoSandbox = [ "/share" ]; preDesktopFilePhase = ''
cp -Lr ${prev.steam}/share/icons $out/share/icons
'';
desktopFileAttributes = {
name = "steam-wrapped";
icon = "steam";
desktopName = "Steam (wrapped)";
}; };
enableDesktopFile = true;
android-studio-wrapped = wrapInSandbox {
name = "android-studio";
package = prev.android-studio;
binaryName = "android-studio";
additionalBlacklist = [ "/mnt" ];
mountInHome = [ "Development/Personal/Android" ".android" ];
chdirTo = "/home/$USER";
}; };
spotify-wrapped = wrapInSandbox { spotify-wrapped = wrapInSandbox {
name = "spotify"; name = "spotify-wrapped";
package = prev.spotify; launchScriptName = "spotify";
binaryName = "spotify"; binary = "${prev.spotify}/bin/spotify";
additionalBlacklist = [ "/mnt" ]; additionalBlacklist = [ "/mnt" ];
mountInHome = [ ".config/spotify" ]; mountInHome = [ ".config/spotify" ];
chdirTo = "/home/$USER"; chdirTo = "/home/$USER";
preDesktopFilePhase = ''
cp -Lr ${prev.spotify}/share/icons $out/share/icons
'';
desktopFileAttributes = {
name = "spotify-wrapped";
icon = "spotify";
desktopName = "Spotify (wrapped)";
};
enableDesktopFile = true;
}; };
lutris-free-wrapped = wrapInSandbox { lutris-free-wrapped = wrapInSandbox {
name = "lutris-free"; name = "lutris-free-wrapped";
package = prev.lutris-free; launchScriptName = "lutris";
binaryName = "lutris"; binary = "${prev.lutris-free}/bin/lutris";
additionalBlacklist = [ "/mnt" ]; additionalBlacklist = [ "/mnt" ];
additionalMounts = [ "/mnt/Storage/Games/UPlay" ]; additionalMounts = [ "/mnt/Storage/Games/" ];
mountInHome = [ ".local/share/lutris" ".config/lutris" ]; mountInHome = [ ".local/share/lutris" ".config/lutris" "Games" ];
chdirTo = "/home/$USER"; chdirTo = "/home/$USER";
preDesktopFilePhase = ''
mkdir -p $out/share/
cp -Lr ${prev.lutris-free}/share/icons $out/share/icons/
'';
desktopFileAttributes = {
name = "lutris-wrapped";
icon = "lutris";
desktopName = "Lutris (wrapped)";
};
enableDesktopFile = true;
};
discord-wrapped = let
discordPkg = prev.discord;
in wrapInSandbox {
name = "discord-wrapped";
launchScriptName = "discord";
binary = "${discordPkg}/bin/discord";
mountInHome = [ ".config/discord" ".config/BetterDiscord" ];
additionalBlacklist = [ "/mnt" ];
chdirTo = "/home/$USER";
preDesktopFilePhase = ''
mkdir -p $out/share/icons
cp -L ${discordPkg}/share/pixmaps/discord.png $out/share/icons/discord.png
'';
desktopFileAttributes = {
name = "discord-wrapped";
#exec = "discord";
icon = "discord";
desktopName = "Discord (wrapped)";
genericName = "Instant Messenger";
#categories = [ "Network" "InstantMessaging" ];
};
enableDesktopFile = true;
};
vortex-wrapped = let
# The path to the wine prefix Vortex is installed in
prefixPath = "/mnt/Storage/Games/NewVortex";
vortexStartScript = prev.writeShellScriptBin "start-vortex.sh" ''
WINEARCH=win64 \
WINEPREFIX=${prefixPath} \
${prev.wineWowPackages.staging}/bin/wine "C:\Program Files\Black Tree Gaming Ltd\Vortex\Vortex.exe"
'';
vortexIcon = builtins.fetchurl {
url = "https://www.nexusmods.com/bootstrap/images/vortex/vortex-logomark.svg";
sha256 = "0237wbbyvgapmmjsq5xab0izzaciqjx1si163r75wa2g7xvz4s22";
};
in wrapInSandbox {
name = "vortex-wrapped";
launchScriptName = "vortex";
binary = "${vortexStartScript}/bin/start-vortex.sh";
chdirTo = "/mnt/Storage/Games/";
additionalBlacklist = [ "/mnt" ];
additionalMounts = [
# Wine prefix
"/mnt/Storage/Games/NewVortex"
# Mod cache
"/mnt/Storage/Vortex Mods"
# Only access Skyrim: SE
"/mnt/Storage/Games/SteamLibrary/SteamLibrary/steamapps/common/Skyrim\ Special\ Edition/"
];
mountInHome = [
# Mod downloads
"Downloads/Skyrim Mods"
];
preDesktopFilePhase = ''
mkdir -p $out/share/icons
cp ${vortexIcon} $out/share/icons/vortex.svg
'';
desktopFileAttributes = {
name = "vortex-wrapped";
icon = "vortex";
desktopName = "Vortex Mod Manager (wrapped)";
};
enableDesktopFile = true;
}; };
} }

View File

@ -66,4 +66,6 @@ in {
discord-app = prev.callPackage applications/networking/instant-messengers/discord-app { discord-app = prev.callPackage applications/networking/instant-messengers/discord-app {
chromium = prev.ungoogled-chromium; chromium = prev.ungoogled-chromium;
}; };
zoom-vm = prev.callPackage scripts/zoom-vm {};
} }

View File

@ -0,0 +1,46 @@
{
stdenv, lib
, makeDesktopItem, writeShellScriptBin
, virt-manager, libvirt, notify-desktop
}:
let
zoomVmScript = writeShellScriptBin "start-zoom-vm.sh" ''
${notify-desktop}/bin/notify-desktop "Zoom VM" "Starting VM..."
output=$(/run/wrappers/bin/pkexec virsh start zoom 2>&1)
if [[ ! "$?" = "0" ]]; then
${notify-desktop}/bin/notify-desktop -u critical "Zoom VM" "$output"
exit 1
fi
${virt-manager}/bin/virt-manager --connect qemu:///system --show-domain-console zoom
'';
zoomIcon = builtins.fetchurl {
url = "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/us.zoom.Zoom.png";
sha256 = "0d94vhjna2196s4wnq0vkga345ad5lpb7b5qp6cymwf1hnpg9lyh";
};
in stdenv.mkDerivation rec {
pname = "zoom-vm";
version = "1.0.0";
unpackPhase = ":";
dontBuild = true;
desktopItem = makeDesktopItem {
name = "zoom-vm";
desktopName = "Zoom (VM)";
exec = "start-zoom-vm";
icon = "us.zoom.Zoom";
};
installPhase = ''
# Install the script
mkdir -p $out/bin
cp ${zoomVmScript}/bin/start-zoom-vm.sh $out/bin/start-zoom-vm
# Install the desktop file
mkdir -p $out/share/icons
cp ${zoomIcon} $out/share/icons/us.zoom.Zoom.png
cp -r ${desktopItem}/share/applications $out/share
'';
}