summaryrefslogtreecommitdiffstats
path: root/lass/3modules
diff options
context:
space:
mode:
Diffstat (limited to 'lass/3modules')
-rw-r--r--lass/3modules/default.nix2
-rw-r--r--lass/3modules/restic.nix119
-rw-r--r--lass/3modules/screenlock.nix4
-rw-r--r--lass/3modules/xjail.nix164
4 files changed, 287 insertions, 2 deletions
diff --git a/lass/3modules/default.nix b/lass/3modules/default.nix
index fd77b2262..5e7e6dff3 100644
--- a/lass/3modules/default.nix
+++ b/lass/3modules/default.nix
@@ -8,9 +8,11 @@ _:
./mysql-backup.nix
./news.nix
./pyload.nix
+ ./restic.nix
./screenlock.nix
./umts.nix
./usershadow.nix
+ ./xjail.nix
./xserver
];
}
diff --git a/lass/3modules/restic.nix b/lass/3modules/restic.nix
new file mode 100644
index 000000000..c720793b1
--- /dev/null
+++ b/lass/3modules/restic.nix
@@ -0,0 +1,119 @@
+{ config, lib, pkgs, ... }:
+
+with import <stockholm/lib>;
+
+{
+ options.lass.restic = mkOption {
+ type = types.attrsOf (types.submodule ({ config, ... }: {
+ options = {
+ name = mkOption {
+ type = types.str;
+ default = config._module.args.name;
+ };
+ passwordFile = mkOption {
+ type = types.str;
+ default = toString <secrets/restic-password>;
+ description = ''
+ read the repository password from a file.
+ '';
+ example = "/etc/nixos/restic-password";
+
+ };
+ repo = mkOption {
+ type = types.str;
+ default = "sftp:backup@prism.r:/backups/${config.name}";
+ description = ''
+ repository to backup to.
+ '';
+ example = "sftp:backup@192.168.1.100:/backups/${config.name}";
+ };
+ dirs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ which directories to backup.
+ '';
+ example = [
+ "/var/lib/postgresql"
+ "/home/user/backup"
+ ];
+ };
+ timerConfig = mkOption {
+ type = types.attrsOf types.str;
+ default = {
+ OnCalendar = "daily";
+ };
+ description = ''
+ When to run the backup. See man systemd.timer for details.
+ '';
+ example = {
+ OnCalendar = "00:05";
+ RandomizedDelaySec = "5h";
+ };
+ };
+ user = mkOption {
+ type = types.str;
+ default = "root";
+ description = ''
+ As which user the backup should run.
+ '';
+ example = "postgresql";
+ };
+ extraArguments = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Extra arguments to append to the restic command.
+ '';
+ example = [
+ "sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp"
+ ];
+ };
+ initialize = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Create the repository if it doesn't exist.
+ '';
+ };
+ };
+ }));
+ default = {};
+ };
+
+ config = {
+ systemd.services =
+ mapAttrs' (_: plan:
+ let
+ extraArguments = concatMapStringsSep " " (arg: "-o ${arg}") plan.extraArguments;
+ connectTo = elemAt (splitString ":" plan.repo) 1;
+ resticCmd = "${pkgs.restic}/bin/restic ${extraArguments}";
+ in nameValuePair "backup.${plan.name}" {
+ environment = {
+ RESTIC_PASSWORD_FILE = plan.passwordFile;
+ RESTIC_REPOSITORY = plan.repo;
+ };
+ path = with pkgs; [
+ openssh
+ ];
+ restartIfChanged = false;
+ serviceConfig = {
+ ExecStartPre = mkIf plan.initialize (pkgs.writeScript "rustic-${plan.name}-init" ''
+ #! ${pkgs.bash}/bin/bash
+ ${resticCmd} snapshots || ${resticCmd} init
+ '');
+ ExecStart = pkgs.writeDash "rustic-${plan.name}" (
+ "#! ${pkgs.bash}/bin/bash\n" +
+ concatMapStringsSep "\n" (dir: "${resticCmd} backup ${dir}") plan.dirs
+ );
+ User = plan.user;
+ };
+ }
+ ) config.lass.restic;
+ systemd.timers =
+ mapAttrs' (_: plan: nameValuePair "backup.${plan.name}" {
+ wantedBy = [ "timers.target" ];
+ timerConfig = plan.timerConfig;
+ }) config.lass.restic;
+ };
+}
diff --git a/lass/3modules/screenlock.nix b/lass/3modules/screenlock.nix
index e16ce9868..29c3861f2 100644
--- a/lass/3modules/screenlock.nix
+++ b/lass/3modules/screenlock.nix
@@ -14,7 +14,7 @@ let
enable = mkEnableOption "screenlock";
command = mkOption {
type = types.str;
- default = "${pkgs.i3lock}/bin/i3lock -i /var/lib/wallpaper/wallpaper -f";
+ default = "${pkgs.xlockmore}/bin/xlock -mode life1d -size 1";
};
};
@@ -28,7 +28,7 @@ let
serviceConfig = {
SyslogIdentifier = "screenlock";
ExecStart = cfg.command;
- Type = "forking";
+ Type = "simple";
User = "lass";
};
};
diff --git a/lass/3modules/xjail.nix b/lass/3modules/xjail.nix
new file mode 100644
index 000000000..325ebcc99
--- /dev/null
+++ b/lass/3modules/xjail.nix
@@ -0,0 +1,164 @@
+{ config, pkgs, lib, ... }:
+
+with import <stockholm/lib>;
+{
+ options.lass.xjail = mkOption {
+ type = types.attrsOf (types.submodule ({ config, ...}: {
+ options = {
+ name = mkOption {
+ type = types.string;
+ default = config._module.args.name;
+ };
+ user = mkOption {
+ type = types.string;
+ default = config.name;
+ };
+ groups = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ };
+ from = mkOption {
+ type = types.string;
+ default = "lass";
+ };
+ display = mkOption {
+ type = types.string;
+ default = toString (genid_signed config._module.args.name);
+ };
+ dpi = mkOption {
+ type = types.int;
+ default = 90;
+ };
+ extraXephyrArgs = mkOption {
+ type = types.str;
+ default = "";
+ };
+ extraVglrunArgs = mkOption {
+ type = types.str;
+ default = "";
+ };
+ script = mkOption {
+ type = types.path;
+ default = pkgs.writeScript "echo_lol" "echo lol";
+ };
+ wm = mkOption {
+ #TODO find type
+ type = types.string;
+ default = "${pkgs.writeHaskell "xephyrify-xmonad" {
+ executables.xmonad = {
+ extra-depends = [
+ "containers"
+ "unix"
+ "xmonad"
+ ];
+ text = /* haskell */ ''
+ module Main where
+ import XMonad
+ import Data.Monoid
+ import System.Posix.Process (executeFile)
+ import qualified Data.Map as Map
+
+ main :: IO ()
+ main = do
+ xmonad def
+ { workspaces = [ "1" ]
+ , layoutHook = myLayoutHook
+ , keys = myKeys
+ , normalBorderColor = "#000000"
+ , focusedBorderColor = "#000000"
+ , handleEventHook = myEventHook
+ }
+
+ myEventHook :: Event -> X All
+
+ myEventHook (ConfigureEvent { ev_event_type = 22 }) = do
+ spawn "${pkgs.xorg.xrandr}/bin/xrandr >/dev/null 2>&1"
+ return (All True)
+
+ myEventHook _ = do
+ return (All True)
+
+ myLayoutHook = Full
+ myKeys _ = Map.fromList []
+ '';
+ };
+ }}/bin/xmonad";
+ };
+ };
+ }));
+ default = {};
+ };
+
+ options.lass.xjail-bins = mkOption {
+ type = types.attrsOf types.path;
+ };
+
+ # implementation
+ config = let
+ scripts = mapAttrs' (name: cfg:
+ let
+ newOrExisting = pkgs.writeDash "${cfg.name}-existing" ''
+ DISPLAY=:${cfg.display} ${pkgs.xorg.xrandr}/bin/xrandr
+ if test $? -eq 0; then
+ echo using existing xephyr
+ ${sudo_} "$@"
+ else
+ echo starting new xephyr
+ ${xephyr_} "$@"
+ fi
+ '';
+ xephyr_ = pkgs.writeDash "${cfg.name}-xephyr" ''
+ ${pkgs.xorg.xorgserver}/bin/Xephyr -br -ac -reset -terminate -resizeable -nolisten local -dpi ${toString cfg.dpi} ${cfg.extraXephyrArgs} :${cfg.display} &
+ XEPHYR_PID=$!
+ DISPLAY=:${cfg.display} ${cfg.wm} &
+ WM_PID=$!
+ ${sudo_} "$@"
+ ${pkgs.coreutils}/bin/kill $WM_PID
+ ${pkgs.coreutils}/bin/kill $XEPHYR_PID
+ '';
+ sudo_ = pkgs.writeDash "${cfg.name}-sudo" ''
+ /var/run/wrappers/bin/sudo -u ${cfg.name} -i ${vglrun_} "$@"
+ '';
+ vglrun_ = pkgs.writeDash "${cfg.name}-vglrun" ''
+ DISPLAY=:${cfg.display} ${pkgs.virtualgl}/bin/vglrun ${cfg.extraVglrunArgs} ${cfg.script} "$@"
+ '';
+ in nameValuePair name {
+ existing = newOrExisting;
+ xephyr = xephyr_;
+ sudo = sudo_;
+ vglrun = vglrun_;
+ }
+ ) config.lass.xjail;
+ in {
+
+ users.users = mapAttrs' (_: cfg:
+ nameValuePair cfg.name {
+ uid = genid cfg.name;
+ home = "/home/${cfg.name}";
+ useDefaultShell = true;
+ createHome = true;
+ extraGroups = cfg.groups;
+ }
+ ) config.lass.xjail;
+
+ users.groups = mapAttrs' (_: cfg:
+ nameValuePair cfg.name {
+ members = [
+ cfg.name
+ cfg.from
+ ];
+ }
+ ) config.lass.xjail;
+
+ security.sudo.extraConfig = (concatStringsSep "\n" (mapAttrsToList (_: cfg:
+ # TODO allow just the right script with sudo
+ "${cfg.from} ALL=(${cfg.name}) NOPASSWD: ALL"
+ ) config.lass.xjail));
+
+ lass.xjail-bins = mapAttrs' (name: cfg:
+ nameValuePair name (pkgs.writeScriptBin cfg.name ''
+ ${scripts.${name}.existing} "$@"
+ '')
+ ) config.lass.xjail;
+ };
+}