summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/installer/sd-card/sd-image.nix9
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/programs/feedbackd.nix32
-rw-r--r--nixos/modules/programs/phosh.nix167
-rw-r--r--nixos/modules/services/continuous-integration/buildkite-agents.nix10
-rw-r--r--nixos/modules/services/hardware/pcscd.nix1
-rw-r--r--nixos/modules/services/security/fail2ban.nix20
7 files changed, 235 insertions, 6 deletions
diff --git a/nixos/modules/installer/sd-card/sd-image.nix b/nixos/modules/installer/sd-card/sd-image.nix
index b811ae07eb033..45c8c67169b82 100644
--- a/nixos/modules/installer/sd-card/sd-image.nix
+++ b/nixos/modules/installer/sd-card/sd-image.nix
@@ -126,6 +126,13 @@ in
       '';
     };
 
+    expandOnBoot = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to configure the sd image to expand it's partition on boot.
+      '';
+    };
   };
 
   config = {
@@ -215,7 +222,7 @@ in
       '';
     }) {};
 
-    boot.postBootCommands = ''
+    boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot ''
       # On the first boot do some maintenance tasks
       if [ -f /nix-path-registration ]; then
         set -euo pipefail
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 62dfac0857d83..9bd8e4caa0e58 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -130,6 +130,7 @@
   ./programs/droidcam.nix
   ./programs/environment.nix
   ./programs/evince.nix
+  ./programs/feedbackd.nix
   ./programs/file-roller.nix
   ./programs/firejail.nix
   ./programs/fish.nix
@@ -163,6 +164,7 @@
   ./programs/partition-manager.nix
   ./programs/plotinus.nix
   ./programs/proxychains.nix
+  ./programs/phosh.nix
   ./programs/qt5ct.nix
   ./programs/screen.nix
   ./programs/sedutil.nix
diff --git a/nixos/modules/programs/feedbackd.nix b/nixos/modules/programs/feedbackd.nix
new file mode 100644
index 0000000000000..bb14489a6f4dc
--- /dev/null
+++ b/nixos/modules/programs/feedbackd.nix
@@ -0,0 +1,32 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.feedbackd;
+in {
+  options = {
+    programs.feedbackd = {
+      enable = mkEnableOption ''
+        Whether to enable the feedbackd D-BUS service and udev rules.
+
+        Your user needs to be in the `feedbackd` group to trigger effects.
+      '';
+      package = mkOption {
+        description = ''
+          Which feedbackd package to use.
+        '';
+        type = types.package;
+        default = pkgs.feedbackd;
+      };
+    };
+  };
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+
+    services.dbus.packages = [ cfg.package ];
+    services.udev.packages = [ cfg.package ];
+
+    users.groups.feedbackd = {};
+  };
+}
diff --git a/nixos/modules/programs/phosh.nix b/nixos/modules/programs/phosh.nix
new file mode 100644
index 0000000000000..f6faf7990dd1e
--- /dev/null
+++ b/nixos/modules/programs/phosh.nix
@@ -0,0 +1,167 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.phosh;
+
+  # Based on https://source.puri.sm/Librem5/librem5-base/-/blob/4596c1056dd75ac7f043aede07887990fd46f572/default/sm.puri.OSK0.desktop
+  oskItem = pkgs.makeDesktopItem {
+    name = "sm.puri.OSK0";
+    type = "Application";
+    desktopName = "On-screen keyboard";
+    exec = "${pkgs.squeekboard}/bin/squeekboard";
+    categories = "GNOME;Core;";
+    extraEntries = ''
+      OnlyShowIn=GNOME;
+      NoDisplay=true
+      X-GNOME-Autostart-Phase=Panel
+      X-GNOME-Provides=inputmethod
+      X-GNOME-Autostart-Notify=true
+      X-GNOME-AutoRestart=true
+    '';
+  };
+
+  phocConfigType = types.submodule {
+    options = {
+      xwayland = mkOption {
+        description = ''
+          Whether to enable XWayland support.
+
+          To start XWayland immediately, use `immediate`.
+        '';
+        type = types.enum [ "true" "false" "immediate" ];
+        default = "false";
+      };
+      cursorTheme = mkOption {
+        description = ''
+          Cursor theme to use in Phosh.
+        '';
+        type = types.str;
+        default = "default";
+      };
+      outputs = mkOption {
+        description = ''
+          Output configurations.
+        '';
+        type = types.attrsOf phocOutputType;
+        default = {
+          DSI-1 = {
+            scale = 2;
+          };
+        };
+      };
+    };
+  };
+
+  phocOutputType = types.submodule {
+    options = {
+      modeline = mkOption {
+        description = ''
+          One or more modelines.
+        '';
+        type = types.either types.str (types.listOf types.str);
+        default = [];
+        example = [
+          "87.25 720 776 848  976 1440 1443 1453 1493 -hsync +vsync"
+          "65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync"
+        ];
+      };
+      mode = mkOption {
+        description = ''
+          Default video mode.
+        '';
+        type = types.nullOr types.str;
+        default = null;
+        example = "768x1024";
+      };
+      scale = mkOption {
+        description = ''
+          Display scaling factor.
+        '';
+        type = types.nullOr types.ints.unsigned;
+        default = null;
+        example = 2;
+      };
+      rotate = mkOption {
+        description = ''
+          Screen transformation.
+        '';
+        type = types.enum [
+          "90" "180" "270" "flipped" "flipped-90" "flipped-180" "flipped-270" null
+        ];
+        default = null;
+      };
+    };
+  };
+
+  optionalKV = k: v: if v == null then "" else "${k} = ${builtins.toString v}";
+
+  renderPhocOutput = name: output: let
+    modelines = if builtins.isList output.modeline
+      then output.modeline
+      else [ output.modeline ];
+    renderModeline = l: "modeline = ${l}";
+  in ''
+    [output:${name}]
+    ${concatStringsSep "\n" (map renderModeline modelines)}
+    ${optionalKV "mode" output.mode}
+    ${optionalKV "scale" output.scale}
+    ${optionalKV "rotate" output.rotate}
+  '';
+
+  renderPhocConfig = phoc: let
+    outputs = mapAttrsToList renderPhocOutput phoc.outputs;
+  in ''
+    [core]
+    xwayland = ${phoc.xwayland}
+    ${concatStringsSep "\n" outputs}
+    [cursor]
+    theme = ${phoc.cursorTheme}
+  '';
+in {
+  options = {
+    programs.phosh = {
+      enable = mkEnableOption ''
+        Whether to enable, Phosh, related packages and default configurations.
+      '';
+      phocConfig = mkOption {
+        description = ''
+          Configurations for the Phoc compositor.
+        '';
+        type = types.oneOf [ types.lines types.path phocConfigType ];
+        default = {};
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [
+      pkgs.phoc
+      pkgs.phosh
+      pkgs.squeekboard
+      oskItem
+    ];
+
+    programs.feedbackd.enable = true;
+
+    # https://source.puri.sm/Librem5/phosh/-/issues/303
+    security.pam.services.phosh = {
+      text = ''
+        auth    requisite       pam_nologin.so
+        auth    required        pam_succeed_if.so user != root quiet_success
+        auth    required        pam_securetty.so
+        auth    requisite       pam_nologin.so
+      '';
+    };
+
+    services.gnome3.core-shell.enable = true;
+    services.gnome3.core-os-services.enable = true;
+    services.xserver.displayManager.sessionPackages = [ pkgs.phosh ];
+
+    environment.etc."phosh/phoc.ini".source =
+      if builtins.isPath cfg.phocConfig then cfg.phocConfig
+      else if builtins.isString cfg.phocConfig then pkgs.writeText "phoc.ini" cfg.phocConfig
+      else pkgs.writeText "phoc.ini" (renderPhocConfig cfg.phocConfig);
+  };
+}
diff --git a/nixos/modules/services/continuous-integration/buildkite-agents.nix b/nixos/modules/services/continuous-integration/buildkite-agents.nix
index b0045409ae609..3dd1c40aaa4b2 100644
--- a/nixos/modules/services/continuous-integration/buildkite-agents.nix
+++ b/nixos/modules/services/continuous-integration/buildkite-agents.nix
@@ -76,7 +76,7 @@ let
       };
 
       tags = mkOption {
-        type = types.attrsOf types.str;
+        type = types.attrsOf (types.either types.str (types.listOf types.str));
         default = {};
         example = { queue = "default"; docker = "true"; ruby2 ="true"; };
         description = ''
@@ -230,7 +230,11 @@ in
         ##     don't end up in the Nix store.
         preStart = let
           sshDir = "${cfg.dataDir}/.ssh";
-          tagStr = lib.concatStringsSep "," (lib.mapAttrsToList (name: value: "${name}=${value}") cfg.tags);
+          tagStr = name: value:
+            if lib.isList value
+            then lib.concatStringsSep "," (builtins.map (v: "${name}=${v}") value)
+            else "${name}=${value}";
+          tagsStr = lib.concatStringsSep "," (lib.mapAttrsToList tagStr cfg.tags);
         in
           optionalString (cfg.privateSshKeyPath != null) ''
             mkdir -m 0700 -p "${sshDir}"
@@ -241,7 +245,7 @@ in
             token="$(cat ${toString cfg.tokenPath})"
             name="${cfg.name}"
             shell="${cfg.shell}"
-            tags="${tagStr}"
+            tags="${tagsStr}"
             build-path="${cfg.dataDir}/builds"
             hooks-path="${cfg.hooksPath}"
             ${cfg.extraConfig}
diff --git a/nixos/modules/services/hardware/pcscd.nix b/nixos/modules/services/hardware/pcscd.nix
index 59c12ee12ca59..4fc1e351f5037 100644
--- a/nixos/modules/services/hardware/pcscd.nix
+++ b/nixos/modules/services/hardware/pcscd.nix
@@ -50,6 +50,7 @@ in
 
     environment.etc."reader.conf".source = cfgFile;
 
+    environment.systemPackages = [ pkgs.pcsclite ];
     systemd.packages = [ (getBin pkgs.pcsclite) ];
 
     systemd.sockets.pcscd.wantedBy = [ "sockets.target" ];
diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix
index b901b19cf3187..0c24972823dd4 100644
--- a/nixos/modules/services/security/fail2ban.nix
+++ b/nixos/modules/services/security/fail2ban.nix
@@ -62,6 +62,22 @@ in
         description = "The firewall package used by fail2ban service.";
       };
 
+      extraPackages = mkOption {
+        default = [];
+        type = types.listOf types.package;
+        example = lib.literalExample "[ pkgs.ipset ]";
+        description = ''
+          Extra packages to be made available to the fail2ban service. The example contains
+          the packages needed by the `iptables-ipset-proto6` action.
+        '';
+      };
+
+      maxretry = mkOption {
+        default = 3;
+        type = types.ints.unsigned;
+        description = "Number of failures before a host gets banned.";
+      };
+
       banaction = mkOption {
         default = "iptables-multiport";
         type = types.str;
@@ -243,7 +259,7 @@ in
       restartTriggers = [ fail2banConf jailConf pathsConf ];
       reloadIfChanged = true;
 
-      path = [ cfg.package cfg.packageFirewall pkgs.iproute2 ];
+      path = [ cfg.package cfg.packageFirewall pkgs.iproute2 ] ++ cfg.extraPackages;
 
       unitConfig.Documentation = "man:fail2ban(1)";
 
@@ -291,7 +307,7 @@ in
       ''}
       # Miscellaneous options
       ignoreip    = 127.0.0.1/8 ${optionalString config.networking.enableIPv6 "::1"} ${concatStringsSep " " cfg.ignoreIP}
-      maxretry    = 3
+      maxretry    = ${toString cfg.maxretry}
       backend     = systemd
       # Actions
       banaction   = ${cfg.banaction}