diff options
40 files changed, 1019 insertions, 389 deletions
@@ -1 +1,2 @@ !**/.keep +result diff --git a/config.nix b/config.nix deleted file mode 100644 index 8d78534..0000000 --- a/config.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - android_sdk.accept_license = true; -} diff --git a/env/acme/default.nix b/env/acme/default.nix new file mode 100644 index 0000000..779b4e2 --- /dev/null +++ b/env/acme/default.nix @@ -0,0 +1,44 @@ +{ config, lib, ... }: +with lib; let + cfg = config.local; +in +{ + options.local = with types; { + domains = mkOption { + type = attrsOf (attrsOf str); + }; + + certs = mapAttrs + (_: _: { + enable = mkEnableOption "TLS cert for ${name}"; + }) + cfg.domains; + }; + + config = { + security.acme = { + acceptTerms = true; + + defaults = { + email = "security@${config.networking.domain}"; + renewInterval = "weekly"; + }; + + certs = + let + domainSort = sort (a: b: splitString "." a < splitString "." b); + + certConfig = domains: { + domain = domains.main; + extraDomainNames = domainSort (attrValues (filterAttrs (k: _: k != "main") domains)); + webroot = "/var/lib/acme/acme-challenge"; + }; + in + mapAttrs' + (_: value: nameValuePair value.main (certConfig value)) + (filterAttrs (name: _: cfg.certs.${name}.enable) cfg.domains); + }; + + local.domains = import ./domains.nix; + }; +} diff --git a/env/acme/domains.nix b/env/acme/domains.nix new file mode 100644 index 0000000..0412391 --- /dev/null +++ b/env/acme/domains.nix @@ -0,0 +1,12 @@ +{ + host = { + main = "34project.org"; + www = "www.34project.org"; + mail = "mail.34project.org"; + }; + + smtp.main = "smtp.34project.org"; + imap.main = "imap.34project.org"; + + git.main = "git.cluster451.org"; +} diff --git a/env/default.nix b/env/default.nix new file mode 100644 index 0000000..d9b85ab --- /dev/null +++ b/env/default.nix @@ -0,0 +1,8 @@ +{ lib, ... }: +with lib; { + imports = [ + ./acme + ./dhe.nix + ./users + ]; +} diff --git a/env/dhe.nix b/env/dhe.nix new file mode 100644 index 0000000..7a95f2d --- /dev/null +++ b/env/dhe.nix @@ -0,0 +1,6 @@ +{ ... }: { + config.security.dhparams = { + enable = true; + defaultBitSize = 2048; + }; +} diff --git a/env/users/default.nix b/env/users/default.nix new file mode 100644 index 0000000..3602630 --- /dev/null +++ b/env/users/default.nix @@ -0,0 +1,126 @@ +{ config, lib, ... }: +with lib; let + cfg = config.local; + inherit (config.networking) domain; +in +{ + imports = [ + ./mailbox.nix + ]; + + options.local = with types; { + sysadmin = mkOption { + type = str; + }; + + users = mkOption { + default = { }; + + type = attrsOf (submodule ({ config, ... }: { + options = { + uid = mkOption { + type = int; + }; + + gid = mkOption { + type = int; + }; + + gecos = mkOption { + type = str; + default = ""; + }; + + sysadmin = mkOption { + type = bool; + default = false; + }; + + groups = mkOption { + type = listOf str; + default = [ ]; + }; + + allowLogin = mkOption { + type = bool; + default = true; + }; + + hardAliases = mkOption { + type = listOf str; + default = [ ]; + }; + }; + + config.groups = mkBefore (optional config.sysadmin "wheel"); + })); + }; + + virtual = mkOption { + default = { }; + + type = attrsOf (submodule ({ name, ... }: { + options = { + aliases = mkOption { + type = attrsOf (listOf str); + default = { }; + }; + + rules = mkOption { + default = [ ]; + + type = listOf (submodule { + options = { + pattern = mkOption { + type = str; + }; + + targets = mkOption { + type = listOf str; + }; + }; + }); + }; + + users = mkOption { + type = attrsOf (submodule { }); + default = { }; + }; + }; + + config.aliases = + let + sysadmin = mkDefault [ "sysadmin@${name}" ]; + in + { + abuse = sysadmin; + security = sysadmin; + webmaster = sysadmin; + hostmaster = sysadmin; + postmaster = sysadmin; + + sysadmin = mkDefault [ "sysadmin@${domain}" ]; + }; + })); + }; + }; + + config.local = mkMerge [ + { + users = import ./users.nix; + virtual = import ./virtual.nix; + + sysadmin = + (findSingle + (user: user.value.sysadmin) + (throw "no user is declared as sysadmin") + (throw "more than one user is declared as sysadmin") + (mapAttrsToList nameValuePair cfg.users) + ).name; + } + + { + virtual.${domain}.aliases.sysadmin = [ cfg.sysadmin ]; + } + ]; +} diff --git a/env/users/mailbox.nix b/env/users/mailbox.nix new file mode 100644 index 0000000..e603214 --- /dev/null +++ b/env/users/mailbox.nix @@ -0,0 +1,163 @@ +{ config, lib, pkgs, ... }: +with lib; let + cfg = config.local; +in +{ + options.local.mailHost = with types; { + enable = mkEnableOption "mailbox host service"; + + mdaListen = mkOption { + type = str; + }; + + saslPort = mkOption { + type = port; + }; + + lmtpPort = mkOption { + type = port; + }; + }; + + config = + let + imapHostname = cfg.domains.imap.main; + in + mkIf cfg.mailHost.enable { + services.dovecot2 = + let + cert = config.security.acme.certs.${imapHostname}.directory; + in + { + enable = true; + enablePAM = false; + enableLmtp = true; + + #sslServerKey = "${cert}/key.pem"; + #sslServerCert = "${cert}/fullchain.pem"; + + modules = [ pkgs.dovecot_pigeonhole ]; + + mailUser = "vmail"; + mailGroup = "vmail"; + mailLocation = "maildir:~/mail"; + mailPlugins.perProtocol.lmtp.enable = [ "sieve" ]; + + extraConfig = + let + inherit (config.networking) domain; + + # https://dovecot.org/list/dovecot/2019-March/115250.html + # Otra solución posible (https://serverfault.com/a/1062274/980378): + # auth_username_format = %{if;%d;eq;${domain};%Ln;%Lu} + localEntry = canonical: username: '' + ${username}:::::::user=${canonical} nopassword userdb_user=${canonical} + ''; + + localEntries = concatStrings + (flatten (mapAttrsToList + (canonical: user: + map (localEntry canonical) ([ canonical ] ++ user.hardAliases)) + cfg.users)); + + localMailboxes = pkgs.writeText "local-mailboxes" localEntries; + + vmailPath = "/var/lib/vmail/%{if;%d;ne;;%Ld;${domain}}"; + in + '' + auth_mechanisms = plain login external + + # TODO: los defaults de nixpkgs dejan los sockets bajo + # /run/dovecot2 con demasiados permisos rwx, arreglar + + service auth { + inet_listener mta-sasl { + port = ${toString cfg.mailHost.saslPort} + address = ${cfg.mailHost.mdaListen} + } + } + + service lmtp { + inet_listener mta-lmtp { + port = ${toString cfg.mailHost.lmtpPort} + address = ${cfg.mailHost.mdaListen} + } + } + + # Esto enfuerza user@domain.tld + auth_username_format = %{if;%Ld;eq;${domain};%Ln;%{if;%d;ne;;%Lu;%Ln@invalid}} + + # FIXME: Esta cadena de passdbs hace que 'doveadm user lookup' + # falle para usuarios locales, pero todo lo demás sirve. Parece + # ser debido a que pam no puede enumerar. + + passdb { + driver = passwd-file + args = username_format=%Ln ${vmailPath}/passwd + } + + passdb { + driver = passwd-file + args = ${localMailboxes} + + # Esta es una forma de determinar si se encontró el usuario en + # el passwd-file por medio de nopassword sin realmente + # autenticarlo. Cuidado con result_success, porque si eso se + # configura mal se permite inicio de sesión con cualquier + # contraseña (!!!). + result_success = continue + result_failure = return-fail + result_internalfail = return-fail + + username_filter = !*@* + } + + passdb { + driver = pam + args = dovecot2 + username_filter = !*@* + #TODO: algo como 'override_fields = allow_nets=...' + } + + userdb { + driver = passwd-file + args = username_format=%Ln ${vmailPath}/passwd + override_fields = uid=vmail gid=vmail home=${vmailPath}/home/%Ln + } + + userdb { + driver = passwd-file + args = ${localMailboxes} + + result_success = continue-ok + result_internalfail = return-fail + skip = found + } + + userdb { + driver = passwd + args = blocking=no + skip = notfound + } + ''; + }; + + security = { + # Necesario debido a 'enablePAM = false' + pam.services.dovecot2 = { }; + + #acme.certs.${imapHostname} = { + # inherit (config.services.dovecot2) group; + #}; + }; + + users = { + users.${config.services.dovecot2.mailUser}.uid = 995; + groups.${config.services.dovecot2.mailGroup}.gid = 993; + }; + + #networking.firewall.allowedTCPPorts = [ 143 993 ]; + + #local.certs.imap.enable = true; + }; +} diff --git a/env/users/users.nix b/env/users/users.nix new file mode 100644 index 0000000..1bb3788 --- /dev/null +++ b/env/users/users.nix @@ -0,0 +1 @@ +# This file has been lustrated. diff --git a/env/users/virtual.nix b/env/users/virtual.nix new file mode 100644 index 0000000..1bb3788 --- /dev/null +++ b/env/users/virtual.nix @@ -0,0 +1 @@ +# This file has been lustrated. @@ -1,10 +1,10 @@ { inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; - nixpkgsUnstable.url = "github:nixos/nixpkgs"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11"; + unstable.url = "github:nixos/nixpkgs"; home-manager = { - url = "github:nix-community/home-manager/release-22.05"; + url = "github:nix-community/home-manager/release-22.11"; inputs.nixpkgs.follows = "nixpkgs"; }; @@ -14,58 +14,79 @@ }; outputs = - { self, nixpkgs, nixpkgsUnstable, home-manager - , nur, impermanence, hm-isolation, ... }: - with nixpkgs.lib; let - util = import ./util; - inherit (util nixpkgs.lib) importAll; + { self, nixpkgs, unstable, home-manager, nur, impermanence, hm-isolation, ... }: + let + system = "x86_64-linux"; + + pkgs = pkgsNoLocal.extend self.overlays.default; + pkgsNoLocal = importPkgs nixpkgs; - pkgSet = pkgs: import ./pkgs pkgs; - in { - packages."x86_64-linux" = pkgSet nixpkgs.legacyPackages."x86_64-linux"; + importPkgs = flake: import flake { + inherit system; - overlay = self: super: { - local = pkgSet super; - unstable = import nixpkgsUnstable { inherit (super) config system; }; + config = import ./pkgs/config nixpkgs.lib; + overlays = [ nur.overlay ]; }; - nixosConfigurations = let - hostConfig = host: (makeOverridable nixosSystem) { - system = "x86_64-linux"; - modules = [ (import ./sys { inherit self impermanence; }) host ]; - }; - in mapAttrs (_: hostConfig) (importAll { root = ./sys/platform; }); + util = import ./util; + inherit (util pkgs.lib) importAll; - homeConfigurations = let - configuration = import ./home { - inherit self nixpkgs nixpkgsUnstable nur hm-isolation; - }; + local = import ./pkgs; + in + with pkgs.lib; { + formatter.${system} = pkgs.nixpkgs-fmt; + packages.${system} = local pkgs pkgsNoLocal; - username = "ale"; + overlays.default = final: prev: { + local = local final prev; + unstable = (importPkgs unstable).extend self.overlays.default; + }; - home = platform: home-manager.lib.homeManagerConfiguration { - system = "x86_64-linux"; + nixosConfigurations = + let + hostConfig = host: (makeOverridable nixpkgs.lib.nixosSystem) { + inherit pkgs system; - inherit configuration; - extraModules = [ platform ]; + modules = [ + ./sys + host + nixpkgs.nixosModules.notDetected + impermanence.nixosModule + ]; + }; + in + mapAttrs (_: hostConfig) (importAll { root = ./sys/platform; }); - inherit username; - homeDirectory = "/home/${username}"; + homeConfigurations = + let + registry = { ... }: { + config.nix.registry = { + "nixpkgs".flake = nixpkgs; + "unstable".flake = unstable; + "nur".flake = nur; + }; + }; - # Update the state version as needed. - # See the changelog here: - # https://nix-community.github.io/home-manager/release-notes.html#sec-release-21.05 - stateVersion = "21.11"; + home = platform: home-manager.lib.homeManagerConfiguration { + inherit pkgs; - # Optionally use extraSpecialArgs - # to pass through arguments to home.nix - extraSpecialArgs = {}; - }; + modules = [ + ./home + platform + registry + hm-isolation.homeManagerModule + ]; + }; - platformHome = name: platform: { - name = "${username}@${name}"; - value = home platform; - }; - in mapAttrs' platformHome (importAll { root = ./home/platform; }); + platformHome = name: platform: + let + value = home platform; + in + { + inherit value; + name = "${value.config.home.username}@${name}"; + }; + in + mapAttrs' platformHome (importAll { root = ./home/platform; }); }; } diff --git a/home/default.nix b/home/default.nix index d6e8a81..0afdc7c 100644 --- a/home/default.nix +++ b/home/default.nix @@ -1,12 +1,11 @@ -{ self, nixpkgs, nixpkgsUnstable, nur, hm-isolation }: { lib, config, pkgs, ... }: with lib; { imports = [ - hm-isolation.homeManagerModule ./desktop.nix ./environ.nix ./graphics.nix ./isolation.nix + ./mail ./path.nix ]; @@ -15,17 +14,9 @@ with lib; { }; config = { - nixpkgs.overlays = [ nur.overlay self.overlay ]; - - nix.registry = { - "nixpkgs".flake = nixpkgs; - "nixpkgsUnstable".flake = nixpkgsUnstable; - "nur".flake = nur; - - "system".to = { - type = "path"; - path = "/home/ale/nix"; - }; + nix.registry."system".to = { + type = "path"; + path = "${config.home.homeDirectory}/nix"; }; home = { @@ -40,7 +31,7 @@ with lib; { stateVersion = "21.11"; username = "ale"; - homeDirectory = "/home/ale"; + homeDirectory = "/home/${config.home.username}"; sessionVariables = { EDITOR = "nvim"; diff --git a/home/environ.nix b/home/environ.nix index 5b20f51..b12093e 100644 --- a/home/environ.nix +++ b/home/environ.nix @@ -7,15 +7,17 @@ with lib; { "d %t/vtmp 0700" ]; - home.file = let - symlink = path: { source = config.lib.file.mkOutOfStoreSymlink path; }; - #TODO: No sirve, creo que por readline - devNull = symlink "/dev/null"; - in { - "vtmp" = symlink "/run/user/1000/vtmp"; - ".calc_history" = devNull; - ".units_history" = devNull; - }; + home.file = + let + symlink = path: { source = config.lib.file.mkOutOfStoreSymlink path; }; + #TODO: No sirve, creo que por readline + devNull = symlink "/dev/null"; + in + { + "vtmp" = symlink "/run/user/1000/vtmp"; + ".units_history" = devNull; + #TODO: .calc_history + }; programs = { zsh = { diff --git a/home/i3-config.nix b/home/i3-config.nix index 18e94ce..999745b 100644 --- a/home/i3-config.nix +++ b/home/i3-config.nix @@ -171,6 +171,9 @@ # (No) Title Bars for_window [class="^.*"] border pixel 5 + # i3-msg exec --no-startup-id --class floating + for_window [class="floating"] floating enabled + exec --no-startup-id ${xautolock}/bin/xautolock -time 10 -locker '${i3lock-color}/bin/i3lock-color -fe -c222222' #exec --no-startup-id /usr/local/bin/platform-graphical-login.sh '' diff --git a/home/mail/.gitignore b/home/mail/.gitignore new file mode 100644 index 0000000..1d9a3a0 --- /dev/null +++ b/home/mail/.gitignore @@ -0,0 +1 @@ +*.svbin diff --git a/home/mail/default.nix b/home/mail/default.nix new file mode 100644 index 0000000..a6fe8ff --- /dev/null +++ b/home/mail/default.nix @@ -0,0 +1,72 @@ +{ config, lib, pkgs, ... }: +with lib; { + config = mkIf (!config.home.isolation.active) { + accounts.email = { + maildirBasePath = "mail"; + + accounts.local = { + address = "alejandro@34project.org"; + userName = "alejandro@34project.org"; + realName = "Alejandro Soto"; + + primary = true; + + # ${maildirBasePath}/${maildir.path} + maildir.path = ""; + folders.inbox = ""; + + msmtp.enable = true; + neomutt.enable = true; + + smtp = { + host = "smtp.34project.org"; + + tls = { + enable = true; + useStartTls = true; + }; + }; + }; + }; + + programs = { + msmtp.enable = true; + + neomutt = { + enable = true; + vimKeys = true; + + settings = { + record = "+.Sent"; + postponed = "+.Drafts"; + + use_threads = "flat"; + index_format = "'%4C %Z %<[y?%<[m?%<[d?%[%H:%M ]&%[%a %d]>&%[%b %d]>&%[%m/%y ]> %-15.15L (%?l?%4l&%4c?) %s'"; + }; + }; + }; + + # .dovecot.sieve tiene que ser un symlink tal que el readlink -f de su + # dirname (no del symlink en sí) sea la misma cadena que el readlink -f + # de ~/sieve. Dovecot verifica eso y tira "Invalid/unknown path to + # storage" si este check frágil falla. Ni siquiera + # mkOutOfStoreSymlink funciona. Ver código fuente de Dovecot: + # pigeonhole/src/lib-sieve/storage/file/sieve-file-storage-active.c + home = + let + sieve = pkgs.runCommandNoCCLocal "sieve" { src = ./sieve; } '' + cp -r $src $out + chmod -R u+w $out + find $out -name '*.sieve' -exec ${pkgs.dovecot_pigeonhole}/bin/sievec -c /dev/null {} \; + ''; + in + { + file."sieve".source = sieve; + + activation.sieve = hm.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' + $DRY_RUN_CMD ln -Tsf ${sieve}/mail.sieve .dovecot.sieve + $DRY_RUN_CMD ln -Tsf ${sieve}/mail.svbin .dovecot.svbin + ''; + }; + }; +} diff --git a/home/mail/sieve/mail.sieve b/home/mail/sieve/mail.sieve new file mode 100644 index 0000000..1bb3788 --- /dev/null +++ b/home/mail/sieve/mail.sieve @@ -0,0 +1 @@ +# This file has been lustrated. diff --git a/home/path.nix b/home/path.nix index 56678bb..2199b3e 100644 --- a/home/path.nix +++ b/home/path.nix @@ -1,53 +1,51 @@ { config, lib, pkgs, ... }: with lib; { - home.packages = let - py = pkgs.python39Packages; - in [ - pkgs.file - pkgs.killall - pkgs.man-pages - pkgs.man-pages-posix - pkgs.tree - pkgs.unzip - pkgs.wget - pkgs.zip - ] ++ optionals (!config.home.isolation.active) [ - pkgs.calc - pkgs.cloc - pkgs.gcc - pkgs.gnome.gnome-screenshot - pkgs.gpicview - pkgs.gruvbox-dark-icons-gtk - pkgs.hack-font - pkgs.i3-gaps - py.ipython - pkgs.jq - pkgs.keepassxc - pkgs.libreoffice-fresh - pkgs.mosh - pkgs.mpv - pkgs.nmap - pkgs.libsForQt5.okular - pkgs.pavucontrol - pkgs.pciutils - py.python - pkgs.rustup - pkgs.local.scripts - pkgs.socat - pkgs.local.st - pkgs.local.tmux-lift - pkgs.units - pkgs.usbutils - pkgs.xclip # keepassxc-cli clip - pkgs.xsel - pkgs.xournalpp - ]; - - nixpkgs.config.allowUnfreePredicate = pkg: elem (getName pkg) [ - "anydesk" - "mssql-tools" - "quartus-prime-lite-unwrapped" - "teams" - "zoom" - ]; + home.packages = + let + py = pkgs.python39Packages; + in + [ + pkgs.file + pkgs.killall + pkgs.man-pages + pkgs.man-pages-posix + pkgs.tree + pkgs.unzip + pkgs.wget + pkgs.zip + ] ++ optionals (!config.home.isolation.active) [ + pkgs.calc + pkgs.cloc + pkgs.gcc + pkgs.gnome.gnome-screenshot + pkgs.gpicview + pkgs.gruvbox-dark-icons-gtk + pkgs.hack-font + pkgs.i3-gaps + py.ipython + pkgs.jq + pkgs.keepassxc + pkgs.libreoffice-fresh + pkgs.mosh + pkgs.mpv + pkgs.nmap + pkgs.libsForQt5.okular + pkgs.pavucontrol + pkgs.pciutils + py.python + pkgs.rustup + pkgs.local.scripts + pkgs.signal-desktop + pkgs.socat + pkgs.local.st + pkgs.tdesktop + pkgs.local.tmux-lift + pkgs.teams + pkgs.units + pkgs.usbutils + pkgs.xclip # keepassxc-cli clip + pkgs.xsel + pkgs.xournalpp + pkgs.zoom-us + ]; } diff --git a/pkgs/config/default.nix b/pkgs/config/default.nix new file mode 100644 index 0000000..6787b5e --- /dev/null +++ b/pkgs/config/default.nix @@ -0,0 +1,4 @@ +lib: with lib; { + android_sdk.accept_license = true; + allowUnfreePredicate = pkg: import ./unfree.nix lib (getName pkg); +} diff --git a/pkgs/config/unfree.nix b/pkgs/config/unfree.nix new file mode 100644 index 0000000..1bb3788 --- /dev/null +++ b/pkgs/config/unfree.nix @@ -0,0 +1 @@ +# This file has been lustrated. diff --git a/pkgs/default.nix b/pkgs/default.nix index 21d9686..a0fc1c7 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,28 +1,25 @@ -pkgs: -with pkgs.lib; let - inherit (pkgs) buildEnv callPackage writeTextDir; +final: prev: +let + inherit (final) callPackage fetchpatch; +in +{ + btclone = callPackage ./btclone { }; + git-aliases = callPackage ./git-aliases.nix { }; + mssql-tools = callPackage ./mssql-tools.nix { }; + oregano = callPackage ./oregano { }; + rqlite = callPackage ./rqlite.nix { }; + rv8 = callPackage ./rv8.nix { }; + scripts = callPackage ./scripts { }; + tmux-lift = callPackage ./tmux-lift { }; - combined = pkgs // { inherit local; }; + st = prev.st.override { + conf = import ./st.nix { }; - local = { - btclone = callPackage ./btclone {}; - git-aliases = callPackage ./git-aliases.nix {}; - mssql-tools = callPackage ./mssql-tools.nix {}; - oregano = callPackage ./oregano {}; - rqlite = callPackage ./rqlite.nix {}; - rv8 = callPackage ./rv8.nix {}; - scripts = callPackage ./scripts {}; - tmux-lift = callPackage ./tmux-lift {}; - - st = pkgs.st.override { - conf = import ./st.nix {}; - - patches = [ - (pkgs.fetchpatch { - url = "https://st.suckless.org/patches/clipboard/st-clipboard-0.8.3.diff"; - sha256 = "cbb37675e9b4986836c19aadacc616a006df81c9bf394e9e3573e164fa1867cf"; - }) - ]; - }; + patches = [ + (fetchpatch { + url = "https://st.suckless.org/patches/clipboard/st-clipboard-0.8.3.diff"; + sha256 = "cbb37675e9b4986836c19aadacc616a006df81c9bf394e9e3573e164fa1867cf"; + }) + ]; }; -in local +} diff --git a/pkgs/mssql-tools.nix b/pkgs/mssql-tools.nix index a2de629..9213c16 100644 --- a/pkgs/mssql-tools.nix +++ b/pkgs/mssql-tools.nix @@ -5,7 +5,8 @@ let version = "17.9.1.1-1"; ubuntuRelease = "21.10"; -in stdenv.mkDerivation { +in +stdenv.mkDerivation { pname = "mssql-tools"; inherit version; @@ -13,10 +14,11 @@ in stdenv.mkDerivation { src = if stdenv.hostPlatform.system == "x86_64-linux" then - fetchurl { - url = "https://packages.microsoft.com/ubuntu/${ubuntuRelease}/prod/pool/main/m/mssql-tools/mssql-tools_${version}_amd64.deb"; - sha256 = "0ya9643assr80yh6g0nd3i6iw819frhbb1m421khwplk9iq793kk"; - } + fetchurl + { + url = "https://packages.microsoft.com/ubuntu/${ubuntuRelease}/prod/pool/main/m/mssql-tools/mssql-tools_${version}_amd64.deb"; + sha256 = "0ya9643assr80yh6g0nd3i6iw819frhbb1m421khwplk9iq793kk"; + } else throw "mssql-tools is not supported on ${stdenv.hostPlatform.system}"; @@ -32,14 +34,16 @@ in stdenv.mkDerivation { rm -r $out/opt $out/usr ''; - postFixup = let - rpath = lib.makeLibraryPath [ glibc stdenv.cc.cc unixODBC ]; - in '' - for file in $(find $out/bin -type f); do - patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" - patchelf --set-rpath ${rpath} $file - done - ''; + postFixup = + let + rpath = lib.makeLibraryPath [ glibc stdenv.cc.cc unixODBC ]; + in + '' + for file in $(find $out/bin -type f); do + patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" "$file" + patchelf --set-rpath ${rpath} $file + done + ''; meta = with lib; { license = licenses.unfree; diff --git a/pkgs/oregano/default.nix b/pkgs/oregano/default.nix index e85dded..82303f4 100644 --- a/pkgs/oregano/default.nix +++ b/pkgs/oregano/default.nix @@ -1,9 +1,23 @@ -{ lib, fetchFromGitHub, glib, goocanvas2, groff -, gtk3, gtksourceview, intltool, libxml2, perl -, pkg-config, python, stdenv, wafHook, wrapGAppsHook }: +{ lib +, fetchFromGitHub +, glib +, goocanvas2 +, groff +, gtk3 +, gtksourceview +, intltool +, libxml2 +, perl +, pkg-config +, python +, stdenv +, wafHook +, wrapGAppsHook +}: let version = "0.84.43"; -in stdenv.mkDerivation { +in +stdenv.mkDerivation { pname = "oregano"; inherit version; @@ -18,7 +32,15 @@ in stdenv.mkDerivation { patches = [ ./gio-unix.patch ]; buildInputs = [ - intltool glib goocanvas2 groff gtk3 gtksourceview - libxml2 perl pkg-config python + intltool + glib + goocanvas2 + groff + gtk3 + gtksourceview + libxml2 + perl + pkg-config + python ]; } diff --git a/pkgs/rqlite.nix b/pkgs/rqlite.nix index a56d288..19d0fa3 100644 --- a/pkgs/rqlite.nix +++ b/pkgs/rqlite.nix @@ -1,7 +1,8 @@ { lib, buildGoModule, fetchFromGitHub }: let version = "7.5.0"; -in buildGoModule { +in +buildGoModule { pname = "rqlite"; inherit version; diff --git a/pkgs/rv8.nix b/pkgs/rv8.nix index 61cb91f..8527601 100644 --- a/pkgs/rv8.nix +++ b/pkgs/rv8.nix @@ -17,30 +17,32 @@ stdenv.mkDerivation { mkdir -p $out/bin $out/lib ''; - patches = [ (writeText "rv8-include-limits.patch" '' - diff --git a/src/gen/gen-cc.cc b/src/gen/gen-cc.cc - index fd9f948..44c8bf7 100644 - --- a/src/gen/gen-cc.cc - +++ b/src/gen/gen-cc.cc - @@ -12,6 +12,7 @@ - #include <deque> - #include <map> - #include <set> - +#include <limits> + patches = [ + (writeText "rv8-include-limits.patch" '' + diff --git a/src/gen/gen-cc.cc b/src/gen/gen-cc.cc + index fd9f948..44c8bf7 100644 + --- a/src/gen/gen-cc.cc + +++ b/src/gen/gen-cc.cc + @@ -12,6 +12,7 @@ + #include <deque> + #include <map> + #include <set> + +#include <limits> - #include "util.h" - #include "cmdline.h" - diff --git a/src/gen/gen-fpu-test.cc b/src/gen/gen-fpu-test.cc - index f1b8f84..d0a2f32 100644 - --- a/src/gen/gen-fpu-test.cc - +++ b/src/gen/gen-fpu-test.cc - @@ -12,6 +12,7 @@ - #include <deque> - #include <map> - #include <set> - +#include <limits> + #include "util.h" + #include "cmdline.h" + diff --git a/src/gen/gen-fpu-test.cc b/src/gen/gen-fpu-test.cc + index f1b8f84..d0a2f32 100644 + --- a/src/gen/gen-fpu-test.cc + +++ b/src/gen/gen-fpu-test.cc + @@ -12,6 +12,7 @@ + #include <deque> + #include <map> + #include <set> + +#include <limits> - #include "util.h" - #include "cmdline.h" - '') ]; + #include "util.h" + #include "cmdline.h" + '') + ]; } diff --git a/pkgs/scripts/clip.nix b/pkgs/scripts/clip.nix index 862d82e..501bb3b 100644 --- a/pkgs/scripts/clip.nix +++ b/pkgs/scripts/clip.nix @@ -1,5 +1,12 @@ -{ lib ,writeShellScriptBin, gnome, xclip -, file, imagemagick, toPDF, ... }: +{ lib +, writeShellScriptBin +, gnome +, xclip +, file +, imagemagick +, toPDF +, ... +}: with lib; let name = if toPDF then "clip-pdf" else "clip"; @@ -13,13 +20,15 @@ with lib; let shift ''; - copyOut = if toPDF then '' - ${imagemagick}/bin/convert "$CLIP" "$OUT" - '' else '' - ${xclip}/bin/xclip -selection clipboard \ - -t $(${file}/bin/file -b --mime-type $CLIP) <"$CLIP" - ''; -in writeShellScriptBin name '' + copyOut = + if toPDF then '' + ${imagemagick}/bin/convert "$CLIP" "$OUT" + '' else '' + ${xclip}/bin/xclip -selection clipboard \ + -t $(${file}/bin/file -b --mime-type $CLIP) <"$CLIP" + ''; +in +writeShellScriptBin name '' ${pdfCmdline} OPTIONS=-a diff --git a/pkgs/scripts/default.nix b/pkgs/scripts/default.nix index 18900f6..43eae89 100644 --- a/pkgs/scripts/default.nix +++ b/pkgs/scripts/default.nix @@ -4,6 +4,6 @@ symlinkJoin { paths = [ (callPackage ./clip.nix { toPDF = false; }) (callPackage ./clip.nix { toPDF = true; }) - (callPackage ./merge-pdfs.nix {}) + (callPackage ./merge-pdfs.nix { }) ]; } diff --git a/pkgs/st.nix b/pkgs/st.nix index a19bcea..117b94c 100644 --- a/pkgs/st.nix +++ b/pkgs/st.nix @@ -1,4 +1,4 @@ -{ }: +{}: '' /* See LICENSE file for copyright and license details. */ diff --git a/pkgs/tmux-lift/default.nix b/pkgs/tmux-lift/default.nix index 9d1adf2..e353494 100644 --- a/pkgs/tmux-lift/default.nix +++ b/pkgs/tmux-lift/default.nix @@ -5,7 +5,7 @@ src = ./.; installPhase = '' - mkdir -p $out/bin - cp lift unlift $out/bin + mkdir -p $out/bin + cp lift unlift $out/bin ''; } diff --git a/sys/auth.nix b/sys/auth.nix index e6e156d..e85543e 100644 --- a/sys/auth.nix +++ b/sys/auth.nix @@ -1,7 +1,8 @@ { lib, config, ... }: with lib; let cfg = config.local; -in { +in +{ config = { security.pam = { oath = { diff --git a/sys/boot.nix b/sys/boot.nix index 9e1ef85..5d37b25 100644 --- a/sys/boot.nix +++ b/sys/boot.nix @@ -1,7 +1,8 @@ { lib, config, ... }: with lib; let cfg = config.local; -in { +in +{ options.local = with lib.types; { loader = mkOption { type = enum [ "grub" "systemd-boot" ]; @@ -40,64 +41,70 @@ in { }; }; - initrd = let - crypt = cfg.crypt.toplevel; - headerPathEscaped = escapeShellArg "/initrd-boot/${crypt.headerFromBoot}"; - in { - availableKernelModules = cfg.initrdModules; - supportedFilesystems = [ "vfat" ]; + initrd = + let + crypt = cfg.crypt.toplevel; + headerPathEscaped = escapeShellArg "/initrd-boot/${crypt.headerFromBoot}"; + in + { + availableKernelModules = cfg.initrdModules; + supportedFilesystems = [ "vfat" ]; - preDeviceCommands = optionalString (crypt != null) '' - mkdir -p `dirname ${headerPathEscaped}` - touch ${headerPathEscaped} - ''; - - preLVMCommands = optionalString cfg.portable '' - sleep 2 #TODO - ''; + preDeviceCommands = optionalString (crypt != null) '' + mkdir -p `dirname ${headerPathEscaped}` + touch ${headerPathEscaped} + ''; - postMountCommands = let - fromRoot = path: escapeShellArg "/mnt-root/${path}"; - auxOpen = aux: '' - cryptsetup -v open \ - --header ${fromRoot aux.header} \ - --key-file ${fromRoot aux.keyfile} \ - ${aux.device} ${aux.target} + preLVMCommands = optionalString cfg.portable '' + sleep 2 #TODO ''; - in concatStringsSep "\n" (map auxOpen cfg.crypt.aux); - luks.devices = mkIf (crypt != null) { - "${crypt.target}" = { - inherit (crypt) device; - header = "/initrd-boot/${crypt.headerFromBoot}"; - preLVM = false; + postMountCommands = + let + fromRoot = path: escapeShellArg "/mnt-root/${path}"; + auxOpen = aux: '' + cryptsetup -v open \ + --header ${fromRoot aux.header} \ + --key-file ${fromRoot aux.keyfile} \ + ${aux.device} ${aux.target} + ''; + in + concatStringsSep "\n" (map auxOpen cfg.crypt.aux); + + luks.devices = mkIf (crypt != null) { + "${crypt.target}" = { + inherit (crypt) device; + header = "/initrd-boot/${crypt.headerFromBoot}"; + preLVM = false; - preOpenCommands = '' - mount -o ro -t vfat ${escapeShellArg cfg.fs.boot.device} /initrd-boot - ''; + preOpenCommands = '' + mount -o ro -t vfat ${escapeShellArg cfg.fs.boot.device} /initrd-boot + ''; - postOpenCommands = '' - umount /initrd-boot - ''; + postOpenCommands = '' + umount /initrd-boot + ''; + }; }; - }; - #network = { - # enable = true; + #network = { + # enable = true; - # ssh = { - # enable = true; - # port = 2234; - # }; - #}; - }; + # ssh = { + # enable = true; + # port = 2234; + # }; + #}; + }; }; - hardware.cpu = let - ucode.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - in { - amd = mkIf (cfg.cpuVendor == "amd") ucode; - intel = mkIf (cfg.cpuVendor == "intel") ucode; - }; + hardware.cpu = + let + ucode.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + in + { + amd = mkIf (cfg.cpuVendor == "amd") ucode; + intel = mkIf (cfg.cpuVendor == "intel") ucode; + }; }; } diff --git a/sys/default.nix b/sys/default.nix index ef60f43..f19bc0a 100644 --- a/sys/default.nix +++ b/sys/default.nix @@ -1,21 +1,17 @@ -{ self, impermanence }: -{ lib, config, pkgs, modulesPath, ... }: +{ lib, config, pkgs, ... }: with lib; { imports = [ - "${modulesPath}/installer/scan/not-detected.nix" - impermanence.nixosModule - + ../env ./auth.nix ./boot.nix ./fs ./net.nix + ./nspawn.nix ./options.nix ./users.nix ]; config = { - nixpkgs.overlays = [ self.overlay ]; - # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions # on your system were taken. It‘s perfectly fine and recommended to leave @@ -27,11 +23,11 @@ with lib; { nix = { package = pkgs.nixFlakes; extraOptions = '' - experimental-features = nix-command flakes + experimental-features = nix-command flakes repl-flake ''; }; - # shenvs necesita systemd 251 + # hm-isolation necesita systemd 251 systemd = mkIf (config.system.nixos.release == "22.05") { package = pkgs.unstable.systemd; }; diff --git a/sys/fs/btrfs.nix b/sys/fs/btrfs.nix index 87c9fca..809d35e 100644 --- a/sys/fs/btrfs.nix +++ b/sys/fs/btrfs.nix @@ -1,15 +1,16 @@ { lib, config, pkgs, ... }: with lib; let cfg = config.local; -in { +in +{ options.local = with lib.types; { snapperSubvols = mkOption { type = attrsOf str; - default = {}; + default = { }; }; fs.btrfs = mkOption { - default = []; + default = [ ]; type = attrsOf (submodule { options = { @@ -35,77 +36,83 @@ in { }; config = { - environment.systemPackages = optional (cfg.snapperSubvols != {}) pkgs.local.btclone; - - fileSystems = let - inherit (cfg) fs; - btrfs = { device, subvol, ssd, ... }: { - inherit device; - fsType = "btrfs"; - options = [ "noatime" "compress=zstd" "subvol=${subvol}" ] ++ optional ssd "ssd"; - }; - in mapAttrs (_: btrfs) cfg.fs.btrfs; - - local.snapperSubvols = let - snapperEntry = path: opts: { name = opts.snapper; value = path; }; - validEntry = _: opts: opts.snapper != null; - in mapAttrs' snapperEntry (filterAttrs validEntry cfg.fs.btrfs); - - services.snapper.configs = let - snapperConfig = _: subvolume: { - inherit subvolume; - - extraConfig = '' - # btrfs qgroup for space aware cleanup algorithms - QGROUP="" - - # fraction of the filesystems space the snapshots may use - SPACE_LIMIT="0.5" - - # fraction of the filesystems space that should be free - FREE_LIMIT="0.2" - - # users and groups allowed to work with config - ALLOW_USERS="" - ALLOW_GROUPS="" - - # sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots - # directory - SYNC_ACL="no" - - # start comparing pre- and post-snapshot in background after creating - # post-snapshot - BACKGROUND_COMPARISON="yes" - - # run daily number cleanup - NUMBER_CLEANUP="yes" - - # limit for number cleanup - NUMBER_MIN_AGE="1800" - NUMBER_LIMIT="100" - NUMBER_LIMIT_IMPORTANT="10" - - # create hourly snapshots - TIMELINE_CREATE="yes" - - # cleanup hourly snapshots after some time - TIMELINE_CLEANUP="yes" - - # limits for timeline cleanup - TIMELINE_MIN_AGE="1800" - TIMELINE_LIMIT_HOURLY="24" - TIMELINE_LIMIT_DAILY="7" - TIMELINE_LIMIT_WEEKLY="4" - TIMELINE_LIMIT_MONTHLY="12" - TIMELINE_LIMIT_YEARLY="10" - - # cleanup empty pre-post-pairs - EMPTY_PRE_POST_CLEANUP="yes" - - # limits for empty pre-post-pair cleanup - EMPTY_PRE_POST_MIN_AGE="1800" - ''; - }; - in mapAttrs snapperConfig cfg.snapperSubvols; + environment.systemPackages = optional (cfg.snapperSubvols != { }) pkgs.local.btclone; + + fileSystems = + let + inherit (cfg) fs; + btrfs = { device, subvol, ssd, ... }: { + inherit device; + fsType = "btrfs"; + options = [ "noatime" "compress=zstd" "subvol=${subvol}" ] ++ optional ssd "ssd"; + }; + in + mapAttrs (_: btrfs) cfg.fs.btrfs; + + local.snapperSubvols = + let + snapperEntry = path: opts: { name = opts.snapper; value = path; }; + validEntry = _: opts: opts.snapper != null; + in + mapAttrs' snapperEntry (filterAttrs validEntry cfg.fs.btrfs); + + services.snapper.configs = + let + snapperConfig = _: subvolume: { + inherit subvolume; + + extraConfig = '' + # btrfs qgroup for space aware cleanup algorithms + QGROUP="" + + # fraction of the filesystems space the snapshots may use + SPACE_LIMIT="0.5" + + # fraction of the filesystems space that should be free + FREE_LIMIT="0.2" + + # users and groups allowed to work with config + ALLOW_USERS="" + ALLOW_GROUPS="" + + # sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots + # directory + SYNC_ACL="no" + + # start comparing pre- and post-snapshot in background after creating + # post-snapshot + BACKGROUND_COMPARISON="yes" + + # run daily number cleanup + NUMBER_CLEANUP="yes" + + # limit for number cleanup + NUMBER_MIN_AGE="1800" + NUMBER_LIMIT="100" + NUMBER_LIMIT_IMPORTANT="10" + + # create hourly snapshots + TIMELINE_CREATE="yes" + + # cleanup hourly snapshots after some time + TIMELINE_CLEANUP="yes" + + # limits for timeline cleanup + TIMELINE_MIN_AGE="1800" + TIMELINE_LIMIT_HOURLY="24" + TIMELINE_LIMIT_DAILY="7" + TIMELINE_LIMIT_WEEKLY="4" + TIMELINE_LIMIT_MONTHLY="12" + TIMELINE_LIMIT_YEARLY="10" + + # cleanup empty pre-post-pairs + EMPTY_PRE_POST_CLEANUP="yes" + + # limits for empty pre-post-pair cleanup + EMPTY_PRE_POST_MIN_AGE="1800" + ''; + }; + in + mapAttrs snapperConfig cfg.snapperSubvols; }; } diff --git a/sys/fs/default.nix b/sys/fs/default.nix index d24e357..04b8acb 100644 --- a/sys/fs/default.nix +++ b/sys/fs/default.nix @@ -1,7 +1,8 @@ { lib, config, ... }: with lib; let cfg = config.local.fs; -in { +in +{ imports = [ ./btrfs.nix ./layout.nix ]; options.local.fs = with lib.types; { diff --git a/sys/fs/layout.nix b/sys/fs/layout.nix index 897cffe..7e1ac2e 100644 --- a/sys/fs/layout.nix +++ b/sys/fs/layout.nix @@ -1,7 +1,8 @@ { lib, config, ... }: with lib; let cfg = config.local; -in { +in +{ options.local.fs.layout = with lib.types; { sysHddBtrfs = mkOption { default = null; @@ -41,38 +42,40 @@ in { }; config = { - local.fs.btrfs = let - sysHddBtrfs = layout: { - "/" = { - inherit (layout.sys) device ssd; - subvol = layout.sys.root; - }; + local.fs.btrfs = + let + sysHddBtrfs = layout: { + "/" = { + inherit (layout.sys) device ssd; + subvol = layout.sys.root; + }; - "/toplevel" = { - inherit (layout.sys) device ssd; - subvol = layout.sys.toplevel; - }; + "/toplevel" = { + inherit (layout.sys) device ssd; + subvol = layout.sys.toplevel; + }; - "/hdd" = { - inherit (layout.hdd) device; - subvol = "/"; - ssd = false; - }; + "/hdd" = { + inherit (layout.hdd) device; + subvol = "/"; + ssd = false; + }; - "/home" = { - inherit (layout.hdd) device; - subvol = layout.hdd.home; - ssd = false; - snapper = "home"; + "/home" = { + inherit (layout.hdd) device; + subvol = layout.hdd.home; + ssd = false; + snapper = "home"; + }; }; - }; - inherit (cfg.fs) layout; + inherit (cfg.fs) layout; - layoutMaps = [ sysHddBtrfs ]; - layoutOpts = [ layout.sysHddBtrfs ]; - valid = filter ({ snd, ... }: snd != null) (zipLists layoutMaps layoutOpts); - in optionalAttrs (valid != []) ((head valid).fst (head valid).snd); + layoutMaps = [ sysHddBtrfs ]; + layoutOpts = [ layout.sysHddBtrfs ]; + valid = filter ({ snd, ... }: snd != null) (zipLists layoutMaps layoutOpts); + in + optionalAttrs (valid != [ ]) ((head valid).fst (head valid).snd); assertions = [ { diff --git a/sys/net.nix b/sys/net.nix index 30675e0..4075a12 100644 --- a/sys/net.nix +++ b/sys/net.nix @@ -1,7 +1,8 @@ { lib, config, pkgs, ... }: with lib; let cfg = config.local; -in { +in +{ options.local = with lib.types; { hostname = mkOption { type = str; diff --git a/sys/nspawn.nix b/sys/nspawn.nix new file mode 100644 index 0000000..6f1558c --- /dev/null +++ b/sys/nspawn.nix @@ -0,0 +1,130 @@ +{ lib, config, pkgs, ... }: +with lib; let + cfg = config.local; +in +{ + options.local.nspawn.dmz = with types; { + enable = mkEnableOption "DMZ services in a container"; + + net = mkOption { + type = str; + }; + + netBits = mkOption { + type = int; + }; + + hostAddr = mkOption { + type = str; + }; + + system = mkOption { + type = attrs; + }; + }; + + # Situación con os-release + # + # La idea aquí es poder hacer 'btrfs subvol create /var/lib/machines/foo' y + # dejar que systemd-nspawn y el activation script creen todo lo demás. Esto + # no sirve bien debido a la prueba barata que hace systemd para revisar si el + # árbol parece contener una imagen de sistema operativo. Esta prueba falla en + # dos momentos distintos: + # + # 1. Inmediatamente tras crear un árbol vacío, puesto que os-release no existe. + # La solución naive es 'mkdir rootfs/etc && touch rootfs/etc/os-release'. + # + # 2. Luego de reiniciar el contenedor una vez que NixOS ha preparado /etc, ya que + # systemd espera un archivo regular y no telera el symlink a la store. + # + # Resulta ser que systemd revisa tanto /etc/os-release como /usr/lib/os-release. + # NixOS evidentemente no usa la segunda ruta por ser FHS, así que la duct tape + # final es 'mkdir rootfs/usr/lib && touch rootfs/usr/lib/os-release'. + + config = mkIf cfg.nspawn.dmz.enable { + local = { + mailHost = { + mdaListen = cfg.nspawn.dmz.hostAddr; + saslPort = 11000; + lmtpPort = 11001; + }; + + nspawn.dmz = { + system = + let + containerModule = { ... }: { + #TODO: urgente: bloquear puertos de dovecot a non-postfix con iptables + config = { + boot.isContainer = true; + + local.mta = { + mdaAddr = cfg.mailHost.mdaListen; + inherit (cfg.mailHost) saslPort lmtpPort; + }; + }; + }; + in + pkgs.nixos [ ../dmz containerModule ]; + + net = "10.34.3.0"; + netBits = 28; + hostAddr = "10.34.3.1"; + }; + }; + + systemd = { + nspawn.dmz = { + execConfig.PrivateUsers = "pick"; + + filesConfig.BindReadOnly = [ + # idmap porque algunos hacks en nixpkgs (postfix-setup.service) + # asumen que la store es de root + "/nix/store:/nix/store:idmap" + "${cfg.nspawn.dmz.system.toplevel}/init:/sbin/init" + ]; + + networkConfig.Port = [ "tcp:25" "tcp:80" "tcp:443" "tcp:587" ]; + }; + + network.networks."40-ve-dmz" = { + matchConfig = { + Name = "ve-dmz"; + Driver = "veth"; + }; + + networkConfig = { + Address = "${cfg.nspawn.dmz.hostAddr}/${toString cfg.nspawn.dmz.netBits}"; + LinkLocalAddressing = "yes"; + DHCPServer = "yes"; + IPMasquerade = "both"; + LLDP = "yes"; + EmitLLDP = "customer-bridge"; + IPv6SendRA = "yes"; + }; + + # IP de contenedor fijada en hostAddr + 1 + dhcpServerConfig = { + PoolOffset = 2; + PoolSize = 1; + }; + }; + + services = { + dovecot2.after = [ "systemd-nspawn@dmz.service" ]; + + "systemd-nspawn@dmz" = { + overrideStrategy = "asDropin"; + + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + wantedBy = [ "machines.target" ]; + }; + }; + }; + + networking.firewall.interfaces.ve-dmz = { + allowedTCPPorts = [ cfg.mailHost.saslPort cfg.mailHost.lmtpPort ]; + allowedUDPPorts = [ 67 ]; # DHCP + }; + }; +} diff --git a/sys/options.nix b/sys/options.nix index f719522..cfb2827 100644 --- a/sys/options.nix +++ b/sys/options.nix @@ -1,7 +1,8 @@ { lib, ... }: with lib.types; let inherit (lib) mkOption; -in { +in +{ options.local = { portable = mkOption { type = bool; @@ -29,7 +30,7 @@ in { }; aux = mkOption { - default = []; + default = [ ]; type = listOf (submodule { options = { device = mkOption { diff --git a/sys/users.nix b/sys/users.nix index 8c8be6b..b84d1c0 100644 --- a/sys/users.nix +++ b/sys/users.nix @@ -1,7 +1,8 @@ { lib, config, pkgs, ... }: with lib; let cfg = config.local; -in { +in +{ config = { sound.enable = true; hardware.pulseaudio.enable = true; @@ -24,27 +25,21 @@ in { environment.pathsToLink = [ "/share/zsh" ]; - users.users = { - ale = { + users.users = mapAttrs + (username: user: { isNormalUser = true; - uid = 1000; - group = "ale"; - extraGroups = [ "users" "wheel" "adbusers" ]; - shell = pkgs.zsh; - }; - tutorias = { - isNormalUser = true; - uid = 1004; - group = "tutorias"; - extraGroups = [ "users" ]; - shell = pkgs.zsh; - }; - }; + inherit (user) uid; + description = user.gecos; + + group = username; + extraGroups = [ "users" ] ++ user.groups; + + shell = if user.allowLogin then pkgs.zsh else null; + }) + cfg.users; - users.groups = { - ale.gid = 1001; - tutorias.gid = 1007; + users.groups = mapAttrs (_: user: { inherit (user) gid; }) cfg.users // { adbusers.gid = 1008; }; }; diff --git a/util/importAll.nix b/util/importAll.nix index 678cf06..cc18640 100644 --- a/util/importAll.nix +++ b/util/importAll.nix @@ -1,5 +1,5 @@ lib: -{ root, exclude ? [] }: +{ root, exclude ? [ ] }: with builtins; with lib; # http://chriswarbo.net/projects/nixos/useful_hacks.html @@ -7,11 +7,11 @@ let basename = removeSuffix ".nix"; isMatch = name: type: (hasSuffix ".nix" name || type == "directory") - && ! elem name (map basename exclude); + && ! elem name (map basename exclude); entry = name: _: { name = basename name; value = import (root + "/${name}"); }; in - mapAttrs' entry (filterAttrs isMatch (readDir root)) +mapAttrs' entry (filterAttrs isMatch (readDir root)) |
