aboutsummaryrefslogtreecommitdiff
path: root/modules/system
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2016-09-29 13:51:44 +0300
committerIgor Pashev <pashev.igor@gmail.com>2016-09-29 13:51:44 +0300
commit62f28d30a069135f9c48678507203958adfc334f (patch)
tree7f38af0c8d3f445ee8cc50906a639baec7011127 /modules/system
parent1af9e6589bdd18e6ba7eeabf073aa7d710020cdd (diff)
downloadnixsap-62f28d30a069135f9c48678507203958adfc334f.tar.gz
Moved everything into ./modules
Diffstat (limited to 'modules/system')
-rw-r--r--modules/system/default.nix11
-rw-r--r--modules/system/firewall.nix52
-rw-r--r--modules/system/raid0.nix134
-rw-r--r--modules/system/sysops.nix35
-rw-r--r--modules/system/users.nix83
-rw-r--r--modules/system/worldWritableDirs.nix25
6 files changed, 340 insertions, 0 deletions
diff --git a/modules/system/default.nix b/modules/system/default.nix
new file mode 100644
index 0000000..240d970
--- /dev/null
+++ b/modules/system/default.nix
@@ -0,0 +1,11 @@
+{lib, ... }:
+
+let
+ all = lib.filterAttrs
+ ( n: _: n != "default.nix" && ! lib.hasPrefix "." n )
+ (builtins.readDir ./.);
+
+in {
+ imports = map (p: ./. + "/${p}") ( builtins.attrNames all );
+}
+
diff --git a/modules/system/firewall.nix b/modules/system/firewall.nix
new file mode 100644
index 0000000..289f635
--- /dev/null
+++ b/modules/system/firewall.nix
@@ -0,0 +1,52 @@
+{ config, lib, ... }:
+
+let
+ inherit (builtins) length toString replaceStrings;
+ inherit (lib) flatten concatMapStringsSep optionalString splitString mkOption;
+ inherit (lib.types) listOf int either submodule enum str;
+
+ inherit (config.nixsap.system.firewall) whitelist;
+
+ iptablesAllow = { dport, protocol, source, comment, ... }:
+ let
+ ports = concatMapStringsSep "," toString (flatten [dport]);
+ iptables = if 1 < length (splitString ":" source)
+ then "ip6tables" else "iptables";
+ in "${iptables} -w -A nixos-fw -m multiport "
+ + "-p ${protocol} --dport ${ports} -s ${source} -j nixos-fw-accept"
+ + optionalString (comment != "")
+ " -m comment --comment '${replaceStrings ["'"] ["'\\''"] comment} '";
+
+in {
+ options.nixsap.system.firewall.whitelist = mkOption {
+ description = "Inbound connection rules (whitelist)";
+ default = [];
+ type = listOf (submodule {
+ options = {
+ dport = mkOption {
+ description = "Destination port or list of ports";
+ type = either int (listOf int);
+ };
+ source = mkOption {
+ description = "Source specification: a network IP address (with optional /mask)";
+ type = str;
+ };
+ protocol = mkOption {
+ description = "The network protocol";
+ type = enum [ "tcp" "udp" ];
+ default = "tcp";
+ };
+ comment = mkOption {
+ description = "Free-form comment";
+ type = str;
+ default = "";
+ };
+ };
+ });
+ };
+
+ config = {
+ networking.firewall.extraCommands =
+ concatMapStringsSep "\n" iptablesAllow whitelist;
+ };
+}
diff --git a/modules/system/raid0.nix b/modules/system/raid0.nix
new file mode 100644
index 0000000..d260e29
--- /dev/null
+++ b/modules/system/raid0.nix
@@ -0,0 +1,134 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+with lib.types;
+with builtins;
+
+let
+ groups = filterAttrs (n: _: n != "_module") config.nixsap.system.lvm.raid0;
+
+ createLV = vg: lv: s: opts:
+ let
+ new = toString s;
+ stripes = toString opts.stripes;
+ sizeSpec = if opts.units == "%"
+ then "--extents ${new}%VG"
+ else "--size ${new}${opts.units}";
+ scale = {
+ "%" = "* 100 / $(vgs --unit b --noheadings --nosuffix --options vg_size ${vg})";
+ "M" = "/ ${toString (1000 * 1000)}";
+ "m" = "/ ${toString (1024 * 1024)}";
+ "G" = "/ ${toString (1000 * 1000 * 1000)}";
+ "g" = "/ ${toString (1024 * 1024 * 1024)}";
+ "T" = "/ ${toString (1000 * 1000 * 1000 * 1000)}";
+ "t" = "/ ${toString (1024 * 1024 * 1024 * 1024)}";
+ };
+ in pkgs.writeBashScript "raid0-create-${vg}-${lv}" ''
+ set -eu
+ device=/dev/${vg}/${lv}
+
+ lv_size=$(lvs --unit b --noheadings --nosuffix --options lv_size "$device" || echo 0)
+ old=$(( lv_size ${scale."${opts.units}"} ))
+
+ if (( ${new} == old )) ; then
+ exit 0
+ elif (( old == 0 )); then
+ lvcreate ${vg} --name ${lv} ${sizeSpec} --stripes ${stripes}
+ elif (( ${new} < old )) ; then
+ echo "Cannot shrink volume $device from $old ${opts.units} to ${new} ${opts.units}" >&2
+ exit 1
+ else
+ lvextend "$device" ${sizeSpec}
+ resize2fs "$device"
+ fi
+ '';
+
+ createVG = vg: pv: pkgs.writeBashScript "raid0-create-vg-${vg}" ''
+ set -eu
+ for pv in ${toString pv}; do
+ type=$(blkid -p -s TYPE -o value "$pv" || true)
+ if [ "$type" != LVM2_member ]; then
+ pvcreate "$pv"
+ if ! vgs ${vg}; then
+ vgcreate ${vg} "$pv"
+ else
+ vgextend ${vg} "$pv"
+ fi
+ fi
+ done
+ '';
+
+ mkRaidService = vg: opts:
+ let
+ ExecStart = pkgs.writeBashScript "raid0-${vg}" ''
+ set -eu
+ ${createVG vg opts.physical}
+ ${concatStringsSep "\n" (
+ mapAttrsToList (v: s:
+ "${createLV vg (baseNameOf v) s opts}")
+ opts.fileSystems
+ )}
+ vgchange -ay ${vg}
+ udevadm trigger --action=add
+ '';
+
+ in nameValuePair "raid0-${vg}" rec {
+ wantedBy = map (v: "dev-${vg}-${baseNameOf v}.device") (attrNames opts.fileSystems);
+ requires = map (pv: replaceStrings ["/"] ["-"] (removePrefix "/" pv) + ".device") opts.physical;
+ after = requires;
+ before = wantedBy;
+ unitConfig.DefaultDependencies = false;
+ path = with pkgs; [ utillinux lvm2 e2fsprogs ];
+ serviceConfig = {
+ inherit ExecStart;
+ RemainAfterExit = true;
+ Type = "oneshot";
+ };
+ };
+
+in {
+ options.nixsap.system = {
+ lvm.raid0 = mkOption {
+ description = "Set of LVM2 volume groups";
+ default = {};
+ type = attrsOf (submodule {
+ options = {
+ stripes = mkOption {
+ description = "Number of stripes";
+ type = int;
+ example = 2;
+ };
+ physical = mkOption {
+ description = "List of physical devices (must be even for stripes)";
+ example = [ "/dev/sdb" "/dev/sdc" ];
+ type = listOf path;
+ };
+ fileSystems = mkOption {
+ description = "Filesystems and their sizes";
+ type = attrsOf int;
+ example = { "/mariadb/db" = 100; };
+ };
+ units = mkOption {
+ description = "Units of size";
+ type = enum [ "%" "m" "g" "t" "M" "G" "T"];
+ };
+ };
+ });
+ };
+ };
+
+ config = {
+ systemd.services = mapAttrs' mkRaidService groups;
+
+ fileSystems = foldl (a: b: a//b) {} (
+ mapAttrsToList (vg: opts: genAttrs (attrNames opts.fileSystems)
+ (fs: {
+ fsType = "ext4";
+ autoFormat = true;
+ device = "/dev/${vg}/${baseNameOf fs}";
+ })
+ ) groups
+ );
+ };
+}
+
diff --git a/modules/system/sysops.nix b/modules/system/sysops.nix
new file mode 100644
index 0000000..ccf6d0b
--- /dev/null
+++ b/modules/system/sysops.nix
@@ -0,0 +1,35 @@
+{ config, lib, ...}:
+let
+
+ inherit (lib) concatMapStringsSep concatStringsSep mkOption types;
+ inherit (types) str listOf;
+
+ bindir = "/run/current-system/sw/bin";
+
+ commands = concatStringsSep ", " (
+ [
+ "${bindir}/du *"
+ "${bindir}/iftop"
+ "${bindir}/iotop"
+ "${bindir}/ip6tables -L*"
+ "${bindir}/ipsec *"
+ "${bindir}/iptables -L*"
+ "${bindir}/journalctl *"
+ "${bindir}/lsof *"
+ "${bindir}/mtr *"
+ "${bindir}/nix-collect-garbage *"
+ "${bindir}/nmap *"
+ "${bindir}/tcpdump *"
+ "${bindir}/traceroute *"
+ ] ++ map (c: "${bindir}/systemctl ${c} *")
+ [ "kill" "reload" "restart" "start" "status" "stop" ]
+ );
+
+in {
+
+ config = {
+ security.sudo.extraConfig = ''
+ %wheel ALL=(ALL) NOPASSWD: ${commands}
+ '';
+ };
+}
diff --git a/modules/system/users.nix b/modules/system/users.nix
new file mode 100644
index 0000000..022a7e7
--- /dev/null
+++ b/modules/system/users.nix
@@ -0,0 +1,83 @@
+{ config, pkgs, lib, ... }:
+
+let
+
+ inherit (builtins)
+ genList hashString mul substring ;
+
+ inherit (lib)
+ foldl genAttrs imap mkOption stringToCharacters toLower
+ types unique ;
+
+ inherit (types)
+ listOf str ;
+
+ uid = name:
+ let
+ dec = {
+ "0" = 0; "1" = 1; "2" = 2; "3" = 3;
+ "4" = 4; "5" = 5; "6" = 6; "7" = 7;
+ "8" = 8; "9" = 9; "a" = 10; "b" = 11;
+ "c" = 12; "d" = 13; "e" = 14; "f" = 15;
+ };
+ base = 1000000000; # 2^32 > base + 16^7
+ hex = toLower (substring 0 7 (hashString "sha1" name));
+ pow = b: n: foldl mul 1 (genList (_: b) n);
+ digits = imap (i: d: {m = pow 16 (i - 1); d = d;}) (stringToCharacters hex);
+ f = a: {m, d}: a + m * dec.${d};
+
+ in foldl f base digits;
+
+ daemons = config.nixsap.system.users.daemons;
+ normal = config.nixsap.system.users.normal;
+ groups = config.nixsap.system.groups;
+
+ mkGroup = name: { gid = uid name; };
+ mkDaemonUser = name:
+ {
+ isNormalUser = false;
+ uid = uid name;
+ group = name;
+ };
+
+ mkNormalUser = name:
+ {
+ isNormalUser = true;
+ uid = uid name;
+ };
+
+in {
+ options.nixsap.system = {
+ users.daemons = mkOption {
+ type = listOf str;
+ description = "List of system users with automatic UID and group";
+ default = [];
+ };
+ users.normal = mkOption {
+ type = listOf str;
+ description = "List of regular users with automatic UID";
+ default = [];
+ };
+ users.sysops = mkOption {
+ description = ''
+ List of local users with special roles in applications or system-wide.
+ The users in this list are not create automatically.
+ '';
+ type = listOf str;
+ default = [];
+ };
+ groups = mkOption {
+ type = listOf str;
+ description = "List of groups with automatic GID";
+ default = [];
+ };
+ };
+
+ # XXX: Modules for automatic unicity of user names:
+ imports = [
+ { users.groups = genAttrs (unique (daemons ++ groups)) mkGroup; }
+ { users.users = genAttrs daemons mkDaemonUser; }
+ { users.users = genAttrs normal mkNormalUser; }
+ ];
+}
+
diff --git a/modules/system/worldWritableDirs.nix b/modules/system/worldWritableDirs.nix
new file mode 100644
index 0000000..9899696
--- /dev/null
+++ b/modules/system/worldWritableDirs.nix
@@ -0,0 +1,25 @@
+{ config, pkgs, lib, ... }:
+let
+ dirs = config.nixsap.system.worldWritableDirs;
+
+in {
+ options.nixsap.system.worldWritableDirs = lib.mkOption {
+ type = lib.types.listOf lib.types.path;
+ description = "These dirs will be chmod'ed 1777";
+ default = [ "/tmp" "/var/tmp" ];
+ };
+
+ config = lib.mkIf (dirs != []) {
+ systemd.services.chmod1777 = {
+ description = "Make some dirs world-writable";
+ unitConfig.RequiresMountsFor = dirs;
+ before = [ "local-fs.target" ];
+ wantedBy = [ "local-fs.target" ];
+ serviceConfig = {
+ ExecStart = "${pkgs.coreutils}/bin/chmod -c 1777 ${lib.concatStringsSep " " dirs}";
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+ };
+ };
+}