nixos-config/modules/programs/browser.nix
2019-10-24 02:24:33 +02:00

248 lines
6.7 KiB
Nix

{ config, lib, pkgs, ... }:
# todo : this needs to be cleaned up
with lib;
let
cfg = config.programs.custom.browser;
library = import <library> { inherit pkgs lib; };
chromiumBin = "${pkgs.chromium}/bin/chromium";
chromeBin = "${pkgs.google-chrome}/bin/google-chrome-stable";
firefoxBin = "${pkgs.firefox}/bin/firefox";
tarBin = "${pkgs.gnutar}/bin/tar";
# desktop file
# ------------
# makes it possible to be used by other programs
desktopFile = bin: let
browserName = bin.name;
in pkgs.writeTextFile {
name = "${browserName}.desktop" ;
destination = "/share/applications/${browserName}.desktop";
text = ''
[Desktop Entry]
Type=Application
Exec=${bin}/bin/${browserName} %U
Icon=chromium
Comment=An open source web browser from Google
Terminal=false
Name=${browserName}
GenericName=Web browser
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/webcal;x-scheme-handler/about
Categories=Network;WebBrowser
StartupWMClass=${browserName}
'';
};
cleanBrowser = name: browser: home: homeBackup:
let
backupFile = "${homeBackup}.tar.lzma";
rolloutFile = "${home}.tar.lzma";
lockFile = "${home}-lock";
in
pkgs.writeShellScriptBin "${name}-clean" /* sh */ ''
sudo killall -9 -u ${name}
sudo rm ${lockFile}
sudo rm -rf ${home}
'';
createBrowser = name: user: browser: home: homeBackup:
let
backupFile = "${homeBackup}.tar.lzma";
rolloutFile = "${home}.tar.lzma";
lockFile = "${home}-lock";
in
pkgs.writeShellScriptBin "${name}" /* sh */ ''
# set -x
if [[ ! -e ${lockFile} ]]
then
# rollout backup
if [[ -e ${backupFile} ]]
then
if [[ ! -d ${home} ]]
then
# todo : use make user
sudo mkdir -p ${home}
sudo chown -R ${user}:users ${home}
fi
cp ${backupFile} ${rolloutFile}
sudo -u ${user} ${tarBin} xf ${rolloutFile} --directory ${home}
rm ${rolloutFile}
touch ${lockFile}
fi
fi
sudo -u ${user} ${browser}
'';
browserExecutableList =
let
allBrowser = flip mapAttrsToList cfg.configList (
name: config:
let
browser = if config.browserType == "chrome"
then "${chromiumBin} \"$@\""
else if config.browserType == "google"
then "${chromeBin} \"$@\""
else "${firefoxBin} \"$@\"";
in
createBrowser name config.user browser config.home config.homeBackup
);
xclipBrowser = [
(pkgs.writeShellScriptBin "copy-to-xclip" /* sh */''
echo "$*" | ${pkgs.xclip}/bin/xclip
'')
];
in
allBrowser ++ xclipBrowser;
createBackupScript = name: home: backupHome:
pkgs.writeShellScriptBin "${name}-backup" /* sh */ ''
sudo -u ${name} \
${tarBin} \
--exclude=.cache \
--exclude=Downloads \
--create \
--verbos \
--lzma \
--file ${home}.tar.lzma \
--directory ${home} \
.
cp ${home}.tar.lzma ${backupHome}.tar.lzma
'';
allBackupScripts =
let
filteredConfigs =
filterAttrs
(name: browserConfig: browserConfig.homeBackup != null)
cfg.configList;
in
mapAttrsToList
(name: browserConfig: createBackupScript name browserConfig.home browserConfig.homeBackup)
filteredConfigs;
allCleanScripts =
let
filteredConfigs =
filterAttrs
(name: browserConfig: browserConfig.homeBackup != null)
cfg.configList;
in
mapAttrsToList
(name: browserConfig: cleanBrowser name name browserConfig.home browserConfig.homeBackup)
filteredConfigs;
# browser chooser
# ---------------
browserSelect = pkgs.writeScriptBin "browser-select" ''
# select a browser using dmenu
# ----------------------------
BROWSER=$( echo -e "${lib.concatMapStringsSep "\\n" (bin: bin.name) browserExecutableList}" \
| ${pkgs.rofi}/bin/rofi -dmenu )
# start selected browser
# ----------------------
case $BROWSER in
${lib.concatStringsSep "\n"
(flip map browserExecutableList (bin: "${bin.name}) export BIN=${bin}/bin/${bin.name} ;;"))
}
esac
$BIN "$@"
'';
in {
options.programs.custom.browser = {
enable = mkEnableOption "enable browsers";
configList = mkOption {
type = with types; attrsOf (submodule ({ name , ... }: {
options = {
browserType = mkOption {
type = with types; enum ["firefox" "chrome" "google"];
default = "chrome";
description = ''
the type of browser which is simulated
'';
};
home = mkOption {
type = with types; str;
description = ''
Home of the browser.
'';
};
user = mkOption {
default = name;
type = with types; str;
description = ''
user to run the browser as
'';
};
sudoUsers = mkOption {
default = [ config.users.users.mainUser.name ];
type = with types; listOf str;
description = ''
user allowed to run sudo without password to start the browser
'';
};
homeBackup = mkOption {
type = with types; nullOr str;
default = null;
example = "~/.my-browser-backup";
description = ''
backup of the home, which gets rolled out if the
home does not exists. usefull for homes in tmpfs.
dont use file endings!
'';
};
};
}));
};
};
config = mkIf cfg.enable {
# add sudo rights
security.sudo.extraConfig =
let
extraRules = flip mapAttrsToList cfg.configList (name: values:
concatStringsSep "\n" (map (sudoUser: "${sudoUser} ALL=(${values.user}) NOPASSWD: ALL") values.sudoUsers)) ;
in
lib.concatStringsSep "\n" extraRules;
# create users
users.users = flip mapAttrs cfg.configList (name: config:
{
home = config.home;
createHome = true;
initialPassword = "${name}-browser";
shell = pkgs.bashInteractive;
isNormalUser = true;
group = "users";
# enable video usage
extraGroups = [ "video" "audio" ];
}
);
# add groups to mainUser
system.custom.mainUser.extraGroups = builtins.attrNames cfg.configList;
environment.systemPackages = [
browserSelect
( desktopFile browserSelect )
]
++ browserExecutableList
++ (map (bin: desktopFile bin) browserExecutableList)
++ allBackupScripts
++ allCleanScripts;
};
}