diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..6931e02
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,93 @@
+{
+ "nodes": {
+ "nix-index-database": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1703387252,
+ "narHash": "sha256-XKJqGj0BaEn/zyctEnkgVIh6Ba1rgTRc+UBi9EU8Y54=",
+ "owner": "Mic92",
+ "repo": "nix-index-database",
+ "rev": "f4340c1a42c38d79293ba69bfd839fbd6268a538",
+ "type": "github"
+ },
+ "original": {
+ "owner": "Mic92",
+ "repo": "nix-index-database",
+ "type": "github"
+ }
+ },
+ "nixos-modules": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1703426109,
+ "narHash": "sha256-/ujCgLJUq+iMgrvMVj58uvXan/nKvG0SeNVVrsvzJHk=",
+ "owner": "SuperSandro2000",
+ "repo": "nixos-modules",
+ "rev": "caa008d22e663c6190ffe12286566b2e87f357e4",
+ "type": "github"
+ },
+ "original": {
+ "owner": "SuperSandro2000",
+ "repo": "nixos-modules",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1703255338,
+ "narHash": "sha256-Z6wfYJQKmDN9xciTwU3cOiOk+NElxdZwy/FiHctCzjU=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "6df37dc6a77654682fe9f071c62b4242b5342e04",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nix-index-database": "nix-index-database",
+ "nixos-modules": "nixos-modules",
+ "nixpkgs": "nixpkgs",
+ "sops-nix": "sops-nix"
+ }
+ },
+ "sops-nix": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "nixpkgs-stable": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1703387502,
+ "narHash": "sha256-JnWuQmyanPtF8c5yAEFXVWzaIlMxA3EAZCh8XNvnVqE=",
+ "owner": "Mic92",
+ "repo": "sops-nix",
+ "rev": "e523e89763ff45f0a6cf15bcb1092636b1da9ed3",
+ "type": "github"
+ },
+ "original": {
+ "owner": "Mic92",
+ "repo": "sops-nix",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
index 58c1766..9a35f2b 100644
--- a/flake.nix
+++ b/flake.nix
@@ -4,9 +4,17 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+ nixos-modules = {
+ url = "github:SuperSandro2000/nixos-modules";
+ inputs.nixpkgs-lib.follows = "nixpkgs";
+ };
+
sops-nix = {
url = "github:Mic92/sops-nix";
- inputs.nixpkgs.follows = "nixpkgs";
+ inputs = {
+ nixpkgs.follows = "nixpkgs";
+ nixpkgs-stable.follows = "nixpkgs";
+ };
};
nix-index-database = {
@@ -15,33 +23,36 @@
};
};
- outputs = { nixpkgs, nix-index-database, sops-nix, ... }: {
- src = builtins.filterSource (path: type: type == "directory" || lib.hasSuffix ".nix" (baseNameOf path)) ./.;
- ls = dir: lib.attrNames (builtins.readDir (src + "/${dir}"));
- fileList = dir: map (file: ./. + "/${dir}/${file}") (ls dir);
+ outputs = { nixpkgs, nixos-modules, nix-index-database, sops-nix, ... }:
+ let
+ inherit (nixpkgs) lib;
+ in {
nixosConfigurations = let
constructSystem = {
hostname,
system ? "x86_64-linux",
modules ? [],
users ? [],
- }: nixpkgs.lib.nixosSystem {
- inherit system hostname;
+ }: lib.nixosSystem {
+ inherit system;
+
modules = [
+ nixos-modules.nixosModule
sops-nix.nixosModules.sops
nix-index-database.nixosModules.nix-index
- ./system/programs.nix
- ./system/configuration.nix
- ./system/${hostname}/configuration.nix
- ] ++ fileList "modules" ++ modules ++ map (user: ./users/${user}/default.nix ) users;
+ ./systems/programs.nix
+ ./systems/configuration.nix
+ ./systems/${hostname}/configuration.nix
+ ] ++ modules ++ map(user: ./users/${user}) users;
+
};
in {
photon = constructSystem {
- hostname = "photon"
+ hostname = "photon";
};
palatine-hill = constructSystem {
- hostname = "palatine-hill"
+ hostname = "palatine-hill";
};
};
};
diff --git a/lib/ldap.nix b/lib/ldap.nix
deleted file mode 100644
index c954574..0000000
--- a/lib/ldap.nix
+++ /dev/null
@@ -1,9 +0,0 @@
-{ lib, ... }:
-
-{
- mkUserGroupOption = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- description = lib.mdDoc "Restrict logins to users in this group";
- };
-}
diff --git a/lib/modules.nix b/lib/modules.nix
deleted file mode 100644
index b74fbcc..0000000
--- a/lib/modules.nix
+++ /dev/null
@@ -1,11 +0,0 @@
-{ config, lib, ... }:
-
-{
- mkOpinionatedOption = text: lib.mkOption {
- type = lib.types.bool;
- default = config.opinionatedDefaults;
- description = lib.mdDoc "Whether to ${text}.";
- };
-
- mkRecursiveDefault = lib.mapAttrsRecursive (_: lib.mkDefault);
-}
diff --git a/lib/nix.nix b/lib/nix.nix
deleted file mode 100644
index c7f3455..0000000
--- a/lib/nix.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{ lib, ... }:
-
-{
- # taken from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/misc/nix-daemon.nix#L828-L832
- # a builder can run code for `gcc.arch` and inferior architectures
- gcc-system-features = arch: [ "gccarch-${arch}" ]
- ++ map (x: "gccarch-${x}") lib.systems.architectures.inferiors.${arch};
-}
diff --git a/lib/ssh.nix b/lib/ssh.nix
deleted file mode 100644
index e13b5a2..0000000
--- a/lib/ssh.nix
+++ /dev/null
@@ -1,10 +0,0 @@
-_:
-
-{
- mkPubKey = name: type: publicKey: {
- "${name}-${type}" = {
- extraHostNames = [ name ];
- publicKey = "${type} ${publicKey}";
- };
- };
-}
diff --git a/modules/acme.nix b/modules/acme.nix
deleted file mode 100644
index 28cdbc2..0000000
--- a/modules/acme.nix
+++ /dev/null
@@ -1,21 +0,0 @@
-{ config, lib, ... }:
-
-let
- cfg = config.security.acme;
-in
-{
- options.security.acme.staging = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc ''
- If set to true, use Let's Encrypt's staging environment instead of the production one.
- The staging environment has much higher rate limits but does not generate fully signed certificates.
- This is great for testing when the normla rate limit is hit fast and impacts other people on the same IP.
- See https://letsencrypt.org/docs/staging-environment for more detail.
- '';
- };
-
- config = lib.mkIf cfg.staging {
- security.acme.server = "https://acme-staging-v02.api.letsencrypt.org/directory";
- };
-}
diff --git a/modules/boot.nix b/modules/boot.nix
deleted file mode 100644
index 0b3d873..0000000
--- a/modules/boot.nix
+++ /dev/null
@@ -1,41 +0,0 @@
-{ config, lib, ... }:
-
-let
- cfg = config.boot;
-in
-{
- options = {
- boot = {
- default = lib.mkOpinionatedOption "enable the boot builder";
- };
- };
-
- cfg = lib.mkIf cfg.default {
- supportedFilesystems = [ "zfs" ];
- tmp.useTmpfs = true;
- kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
- kernelParams = [ "kvm-amd" "nordrand" ];
- zfs = {
- enableUnstable = true;
- devNodes = "/dev/disk/by-id/";
- forceImportRoot = true;
- };
- loader = {
- efi = {
- canTouchEfiVariables = false;
- efiSysMountPoint = "/boot/efis/nvme-Samsung_SSD_980_PRO_1TB_S5GXNF0W178262L-part1";
- };
- generationsDir.copyKernels = true;
- grub = {
- enable = true;
- copyKernels = true;
- zfsSupport = true;
- efiSupport = true;
- efiInstallAsRemovable = true;
- fsIdentifier = "uuid";
- device = "nodev";
- extraInstallCommands = "[ ! -e /boot/efis/nvme-Samsung_SSD_980_PRO_1TB_S5GXNF0W178262L-part1/EFI ] || cp -r /boot/efis/nvme-Samsung_SSD_980_PRO_1TB_S5GXNF0W178262L-part1/EFI/* /boot/efis/nvme-Samsung_SSD_980_PRO_1TB_S5GXNF0W178262L-part1";
- };
- };
- };
-}
\ No newline at end of file
diff --git a/modules/containers.nix b/modules/containers.nix
deleted file mode 100644
index 7f0d5f4..0000000
--- a/modules/containers.nix
+++ /dev/null
@@ -1,56 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.virtualisation;
- cfgd = cfg.docker;
- cfgp = cfg.podman;
-in
-{
- options.virtualisation = {
- docker = {
- aggresiveAutoPrune = libS.mkOpinionatedOption "configure aggresive auto prune which removes everything unreferenced by running containers. This includes named volumes and mounts should be used instead";
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended and maintenance reducing default settings";
- };
-
- podman.recommendedDefaults = libS.mkOpinionatedOption "set recommended and maintenance reducing default settings";
- };
-
- config = {
- virtualisation = {
- containers.registries.search = lib.mkIf cfgp.recommendedDefaults [
- "docker.io"
- "quay.io"
- "ghcr.io"
- "gcr.io"
- ];
-
- docker = {
- daemon.settings = let
- useIPTables = !config.networking.nftables.enable;
- in lib.mkIf cfgd.recommendedDefaults {
- fixed-cidr-v6 = "fd00::/80"; # TODO: is this a good idea for all networks?
- iptables = useIPTables;
- ip6tables = useIPTables;
- ipv6 = true;
- # userland proxy is slow, does not give back ports and if iptables/nftables is avaible just worsefgd.aggresiveAutoPrune
- userland-proxy = false;
- };
- autoPrune = lib.mkIf cfgd.aggresiveAutoPrune {
- enable = true;
- flags = [
- "--all"
- "--external"
- "--force"
- "--volumes"
- ];
- };
- };
-
- podman = {
- autoPrune.enable = lib.mkIf cfgp.recommendedDefaults true;
- defaultNetwork.settings.dns_enabled = lib.mkIf cfgp.recommendedDefaults true;
- };
- };
- };
-}
diff --git a/modules/gitea.nix b/modules/gitea.nix
deleted file mode 100644
index 1f3722c..0000000
--- a/modules/gitea.nix
+++ /dev/null
@@ -1,147 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.services.gitea;
- cfgl = cfg.ldap;
- inherit (config.security) ldap;
-in
-{
- options = {
- services.gitea = {
- # based on https://github.com/majewsky/nixos-modules/blob/master/gitea.nix
- ldap = {
- enable = lib.mkEnableOption (lib.mdDoc "login via ldap");
-
- adminGroup = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- example = "gitea-admins";
- description = lib.mdDoc "Name of the ldap group that grants admin access in gitea.";
- };
-
- bindPasswordFile = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- example = "/var/lib/secrets/bind-password";
- description = lib.mdDoc "Path to a file containing the bind password.";
- };
-
- userGroup = libS.ldap.mkUserGroupOption;
-
- options =
- let
- mkOptStr = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- };
- in
- {
- id = lib.mkOption {
- type = lib.types.ints.unsigned;
- default = 1;
- };
- name = mkOptStr;
- security-protocol = mkOptStr;
- host = mkOptStr;
- port = lib.mkOption {
- type = with lib.types; nullOr port;
- default = null;
- };
- bind-dn = mkOptStr;
- bind-password = mkOptStr;
- user-search-base = mkOptStr;
- user-filter = mkOptStr;
- admin-filter = mkOptStr;
- username-attribute = mkOptStr;
- firstname-attribute = mkOptStr;
- surname-attribute = mkOptStr;
- email-attribute = mkOptStr;
- public-ssh-key-attribute = mkOptStr;
- };
- };
- recommendedDefaults = libS.mkOpinionatedOption "set recommended, secure default settings";
- };
- };
-
- config.services.gitea = lib.mkIf (cfg.enable && cfgl.enable) {
- ldap.options = {
- name = "ldap";
- security-protocol = "LDAPS";
- host = ldap.domainName;
- inherit (ldap) port;
- bind-dn = ldap.bindDN;
- bind-password = "$(cat ${cfgl.bindPasswordFile})";
- user-search-base = ldap.userBaseDN;
- user-filter = ldap.searchFilterWithGroupFilter cfgl.userGroup (ldap.userFilter "%[1]s");
- admin-filter = ldap.groupFilter cfgl.adminGroup;
- username-attribute = ldap.userField;
- firstname-attribute = ldap.givenNameField;
- surname-attribute = ldap.surnameField;
- email-attribute = ldap.mailField;
- public-ssh-key-attribute = ldap.sshPublicKeyField;
- };
- settings = lib.mkIf cfg.recommendedDefaults (libS.modules.mkRecursiveDefault {
- cors = {
- ALLOW_DOMAIN = cfg.settings.server.DOMAIN;
- ENABLED = true;
- SCHEME = "https";
- };
- cron.ENABLED = true;
- "cron.resync_all_sshkeys".ENABLED = true;
- "cron.resync_all_hooks".ENABLED = true;
- other.SHOW_FOOTER_VERSION = false;
- repository.ACCESS_CONTROL_ALLOW_ORIGIN = cfg.settings.server.DOMAIN;
- "repository.signing".DEFAULT_TRUST_MODEL = "committer";
- security.DISABLE_GIT_HOOKS = true;
- server = {
- ENABLE_GZIP = true;
- ROOT_URL = "https://${cfg.settings.server.DOMAIN}/";
- SSH_SERVER_CIPHERS = "chacha20-poly1305@openssh.com, aes256-gcm@openssh.com, aes128-gcm@openssh.com";
- SSH_SERVER_KEY_EXCHANGES = "curve25519-sha256@libssh.org, ecdh-sha2-nistp521, ecdh-sha2-nistp384, ecdh-sha2-nistp256, diffie-hellman-group14-sha1";
- SSH_SERVER_MACS = "hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1";
- };
- session = {
- COOKIE_SECURE = true;
- PROVIDER = "db";
- SAME_SITE = "strict";
- SESSION_LIFE_TIME = 28 * 86400; # 28 days
- };
- "ssh.minimum_key_sizes" = {
- ECDSA = -1;
- RSA = 4095;
- };
- time.DEFAULT_UI_LOCATION = config.time.timeZone;
- });
- };
-
- config.systemd.services = lib.mkIf (cfg.enable && cfgl.enable) {
- gitea.preStart =
- let
- exe = lib.getExe cfg.package;
- # allow executing shell after the --bind-password argument to e.g. cat a password file
- formatOption = key: value: "--${key} ${if key == "bind-password" then value else lib.escapeShellArg value}";
- ldapOptionsStr = opt: lib.concatStringsSep " " (lib.mapAttrsToList formatOption opt);
- commonArgs = "--attributes-in-bind --synchronize-users";
- in
- lib.mkAfter ''
- if ${exe} admin auth list | grep -q ${cfgl.options.name}; then
- ${exe} admin auth update-ldap ${commonArgs} ${ldapOptionsStr cfgl.options}
- else
- ${exe} admin auth add-ldap ${commonArgs} ${ldapOptionsStr (lib.filterAttrs (name: _: name != "id") cfgl.options)}
- fi
- '';
- };
-
- config.services.portunus.seedSettings.groups = [
- (lib.mkIf (cfgl.adminGroup != null) {
- long_name = "Gitea Administrators";
- name = cfgl.adminGroup;
- permissions = { };
- })
- (lib.mkIf (cfgl.userGroup != null) {
- long_name = "Gitea Users";
- name = cfgl.userGroup;
- permissions = { };
- })
- ];
-}
diff --git a/modules/grafana.nix b/modules/grafana.nix
deleted file mode 100644
index 6a22126..0000000
--- a/modules/grafana.nix
+++ /dev/null
@@ -1,130 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.services.grafana;
-in
-{
- options = {
- services.grafana = {
- configureNginx = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc "Wether to configure Nginx.";
- };
-
- oauth = {
- enable = lib.mkEnableOption (lib.mdDoc ''login only via OAuth2'');
- enableViewerRole = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc "Wether to enable the fallback Viewer role when users do not have the user- or adminGroup.";
- };
- adminGroup = libS.ldap.mkUserGroupOption;
- userGroup = libS.ldap.mkUserGroupOption;
- };
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended and secure default settings";
- };
- };
-
- config = {
- # the default values are hardcoded instead of using options. because I couldn't figure out how to extract them from the freeform type
- assertions = lib.mkIf cfg.enable [
- {
- assertion = cfg.oauth.enable -> cfg.settings."auth.generic_oauth".client_secret != null;
- message = ''
- Setting services.grafana.oauth.enable to true requires to set services.grafana.settings."auth.generic_oauth".client_secret.
- Use this `$__file{/path/to/some/secret}` syntax to reference secrets securely.
- '';
- }
- {
- assertion = cfg.settings.security.secret_key != "SW2YcwTIb9zpOOhoPsMm";
- message = "services.grafana.settings.security.secret_key must be changed from it's insecure, default value!";
- }
- {
- assertion = cfg.settings.security.admin_password != "admin";
- message = "services.grafana.settings.security.admin_password must be changed from it's insecure, default value!";
- }
- ];
-
- services.grafana.settings = lib.mkMerge [
- (lib.mkIf (cfg.enable && cfg.recommendedDefaults) (libS.modules.mkRecursiveDefault {
- # no analytics, sorry, not sorry
- analytics = {
- # TODO: drop after https://github.com/NixOS/nixpkgs/pull/240323 is merged
- check_for_updates = false;
- feedback_links_enabled = false;
- reporting_enabled = false;
- };
- log.level = "warn";
- security = {
- cookie_secure = true;
- content_security_policy = true;
- strict_transport_security = true;
- };
- server = {
- enable_gzip = true;
- root_url = "https://${cfg.settings.server.domain}";
- };
- }))
-
- (lib.mkIf (cfg.enable && cfg.oauth.enable) {
- "auth.generic_oauth" = let
- inherit (config.services.dex.settings) issuer;
- in {
- enabled = true;
- allow_assign_grafana_admin = true; # required for grafana-admins
- allow_sign_up = true; # otherwise no new users can be created
- api_url = "${issuer}/userinfo";
- auth_url = "${issuer}/auth";
- client_id = "grafana";
- disable_login_form = true; # only allow OAuth
- icon = "signin";
- name = config.services.portunus.domain;
- oauth_allow_insecure_email_lookup = true; # otherwise updating the mail in ldap will break login
- oauth_auto_login = true; # redirect automatically to the only oauth provider
- use_refresh_token = true;
- role_attribute_path = "contains(groups[*], 'grafana-admins') && 'Admin' || contains(info.roles[*], 'grafana-user') && 'Editor'"
- + lib.optionalString cfg.oauth.enableViewerRole "|| 'Viewer'";
- role_attribute_strict = true;
- # https://dexidp.io/docs/custom-scopes-claims-clients/
- scopes = "openid email groups profile offline_access";
- token_url = "${issuer}/token";
- };
- server.protocol = "socket";
- })
- ];
- };
-
- config.services.nginx = lib.mkIf (cfg.enable && cfg.configureNginx) {
- upstreams.grafana.servers."unix:${cfg.settings.server.socket}" = {};
- virtualHosts = {
- "${cfg.settings.server.domain}".locations = {
- "/".proxyPass = "http://grafana";
- "/api/live/ws" = {
- proxyPass = "http://grafana";
- proxyWebsockets = true;
- };
- };
- };
- };
-
- config.services.portunus = {
- dex = lib.mkIf cfg.oauth.enable {
- enable = true;
- oidcClients = [{
- callbackURL = "https://${cfg.settings.server.domain}/login/generic_oauth";
- id = "grafana";
- }];
- };
- seedSettings.groups = lib.optional (cfg.oauth.adminGroup != null) {
- long_name = "Grafana Administrators";
- name = cfg.oauth.adminGroup;
- permissions = { };
- } ++ lib.optional (cfg.oauth.userGroup != null) {
- long_name = "Grafana Users";
- name = cfg.oauth.userGroup;
- permissions = { };
- };
- };
-}
diff --git a/modules/hedgedoc.nix b/modules/hedgedoc.nix
deleted file mode 100644
index 512d35b..0000000
--- a/modules/hedgedoc.nix
+++ /dev/null
@@ -1,34 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.services.hedgedoc.ldap;
- inherit (config.security) ldap;
-in
-{
- options = {
- services.hedgedoc.ldap = {
- enable = lib.mkEnableOption (lib.mdDoc ''
- login only via LDAP.
- Use `service.hedgedoc.environmentFile` in format `bindCredentials=password` to set the credentials used by the search user
- '');
-
- userGroup = libS.ldap.mkUserGroupOption;
- };
- };
-
- config.services.hedgedoc.settings.ldap = lib.mkIf cfg.enable {
- url = "ldaps://${ldap.domainName}:${toString ldap.port}";
- bindDn = ldap.bindDN;
- bindCredentials = "$bindCredentials";
- searchBase = ldap.userBaseDN;
- searchFilter = ldap.searchFilterWithGroupFilter cfg.userGroup (ldap.userFilter "{{username}}");
- tlsca = "/etc/ssl/certs/ca-certificates.crt";
- useridField = ldap.userField;
- };
-
- config.services.portunus.seedSettings.groups = lib.optional (cfg.userGroup != null) {
- long_name = "Hedgedoc Users";
- name = cfg.userGroup;
- permissions = {};
- };
-}
diff --git a/modules/home-assistant.nix b/modules/home-assistant.nix
deleted file mode 100644
index 7946d61..0000000
--- a/modules/home-assistant.nix
+++ /dev/null
@@ -1,103 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-let
- cfg = config.services.home-assistant;
- inherit (config.security) ldap;
-in
-{
- options = {
- services.home-assistant = {
- ldap = {
- enable = lib.mkEnableOption (lib.mdDoc ''login only via LDAP
-
- ::: {.note}
- Only enable this after completing the onboarding!
- :::
- '');
- userGroup = libS.ldap.mkUserGroupOption;
- };
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings";
- };
- };
-
- config.services.home-assistant = lib.mkMerge [
- (lib.mkIf (cfg.enable && cfg.recommendedDefaults) {
- config = {
- automation = "!include automations.yaml";
- default_config = { }; # yes, this is required...
- homeassistant = {
- auth_providers = lib.mkIf (!cfg.ldap.enable) [
- { type = "homeassistant"; }
- ];
- temperature_unit = "C";
- time_zone = config.time.timeZone;
- unit_system = "metric";
- };
- };
- })
-
- (lib.mkIf (cfg.enable && cfg.ldap.enable) {
- config.homeassistant.auth_providers = [{
- type = "command_line";
- # the script is not inheriting PATH from home-assistant
- command = pkgs.resholve.mkDerivation {
- pname = "ldap-auth-sh";
- version = "unstable-2019-02-23";
-
- src = pkgs.fetchFromGitHub {
- owner = "bob1de";
- repo = "ldap-auth-sh";
- rev = "819f9233116e68b5af5a5f45167bcbb4ed412ed4";
- hash = "sha256-+QjRP5SKUojaCv3lZX2Kv3wkaNvpWFd97phwsRlhroY=";
- };
-
- installPhase = ''
- install -Dm755 ldap-auth.sh -t $out/bin
- '';
-
- solutions.default = {
- fake.external = [ "on_auth_failure" "on_auth_success" ];
- inputs = with pkgs; [ coreutils curl gnugrep gnused openldap ];
- interpreter = "${pkgs.bash}/bin/bash";
- keep."source:$CONFIG_FILE" = true;
- scripts = [ "bin/ldap-auth.sh" ];
- };
- }+ "/bin/ldap-auth.sh";
- args = [
- # https://github.com/bob1de/ldap-auth-sh/blob/master/examples/home-assistant.cfg
- (pkgs.writeText "config.cfg" /* shell */ ''
- ATTRS="${ldap.userField}"
- CLIENT="ldapsearch"
- DEBUG=0
- FILTER="${ldap.groupFilter "home-assistant-users"}"
- NAME_ATTR="${ldap.userField}"
- SCOPE="base"
- SERVER="ldaps://${ldap.domainName}"
- USERDN="uid=$(ldap_dn_escape "$username"),${ldap.userBaseDN}"
- BASEDN="$USERDN"
-
- on_auth_success() {
- # print the meta entries for use in HA
- if [ ! -z "$NAME_ATTR" ]; then
- name=$(echo "$output" | ${lib.getExe pkgs.gnused} -nr "s/^\s*$NAME_ATTR:\s*(.+)\s*\$/\1/Ip")
- [ -z "$name" ] || echo "name=$name"
- fi
- }
- '')
- ];
- meta = true;
- }];
- })
- ];
-
- config.services.portunus.seedSettings.groups = lib.optional (cfg.ldap.userGroup != null) {
- long_name = "Home-Assistant Users";
- name = cfg.ldap.userGroup;
- permissions = { };
- };
-
- config.systemd.tmpfiles.rules = lib.mkIf (cfg.enable && cfg.recommendedDefaults) [
- "f ${cfg.configDir}/automations.yaml 0444 hass hass"
- ];
-}
diff --git a/modules/hydra.nix b/modules/hydra.nix
deleted file mode 100644
index 9e2ddb5..0000000
--- a/modules/hydra.nix
+++ /dev/null
@@ -1,91 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.services.hydra.ldap;
- inherit (config.security) ldap;
-in
-{
- options = {
- services.hydra.ldap = {
- enable = lib.mkEnableOption (lib.mdDoc ''
- login only via LDAP.
- The bind user password must be placed at `/var/lib/hydra/ldap-password.conf` in the format `bindpw = "PASSWORD"
- It is recommended to use a password without special characters because the perl config parser has weird escaping rule like that comment characters `#` must be escape with backslash
- '');
-
- roleMappings = lib.mkOption {
- type = with lib.types; listOf (attrsOf str);
- example = [{ hydra-admins = "admins"; }];
- default = [ ];
- description = lib.mdDoc "Map LDAP groups to hydra permissions. See upstream doc, especially role_mapping.";
- };
-
- userGroup = libS.ldap.mkUserGroupOption;
- };
- };
-
- config.services.hydra.extraConfig = lib.mkIf cfg.enable /* xml */ ''
- # https://hydra.nixos.org/build/196107287/download/1/hydra/configuration.html#using-ldap-as-authentication-backend-optional
-
-
-
- class = Password
- password_field = password
- password_type = self_check
-
-
- class = LDAP
- ldap_server = "${ldap.domainName}"
-
- scheme = ldaps
- timeout = 10
-
- binddn = "${ldap.bindDN}"
- include ldap-password.conf
- start_tls = 0
-
- ciphers = TLS_AES_256_GCM_SHA384
- sslversion = tlsv1_3
-
- user_basedn = "${ldap.userBaseDN}"
- user_filter = "${ldap.searchFilterWithGroupFilter cfg.userGroup (ldap.userFilter "%s")}"
- user_scope = one
- user_field = ${ldap.userField}
-
- deref = always
-
- # Important for role mappings to work:
- use_roles = 1
- role_basedn = "${ldap.roleBaseDN}"
- role_filter = "${ldap.roleFilter}"
- role_scope = one
- role_field = ${ldap.roleField}
- role_value = ${ldap.roleValue}
-
- deref = always
-
-
-
-
- # Make all users in the hydra-admin group Hydra admins
- # hydra-admins = admin
- # Allow all users in the dev group to restart jobs and cancel builds
- # dev = restart-jobs
- # dev = cancel-build
- ${lib.concatStringsSep "\n" (lib.concatMap (lib.mapAttrsToList (name: value: "${name} = ${value}")) cfg.roleMappings)}
-
-
- '';
-
- config.services.portunus.seedSettings.groups = [
- (lib.mkIf (cfg.userGroup != null) {
- long_name = "Hydra Users";
- name = cfg.userGroup;
- permissions = { };
- })
- ] ++ lib.flatten (map lib.attrValues (map (lib.mapAttrs (ldapGroup: _: {
- long_name = "Hydra Role ${ldapGroup}";
- name = ldapGroup;
- permissions = { };
- })) cfg.roleMappings));
-}
diff --git a/modules/intel.nix b/modules/intel.nix
deleted file mode 100644
index f5c61a8..0000000
--- a/modules/intel.nix
+++ /dev/null
@@ -1,23 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-{
- options.hardware = {
- intelGPU = lib.mkEnableOption "" // { description = "Whether to add drivers for intel hardware acceleration."; };
- };
-
- config = {
- hardware.opengl = {
- extraPackages = with pkgs; lib.mkIf config.hardware.intelGPU [
- intel-compute-runtime # OpenCL library for iGPU
- # video encoding/decoding hardware acceleration
- intel-media-driver # broadwell or newer
- intel-vaapi-driver # older hardware like haswell
- ];
- extraPackages32 = with pkgs.pkgsi686Linux; lib.mkIf config.hardware.intelGPU [
- # video encoding/decoding hardware acceleration
- intel-media-driver # broadwell or newer
- intel-vaapi-driver # older hardware like haswell
- ];
- };
- };
-}
diff --git a/modules/ldap.nix b/modules/ldap.nix
deleted file mode 100644
index 117e776..0000000
--- a/modules/ldap.nix
+++ /dev/null
@@ -1,146 +0,0 @@
-{ config, lib, ... }:
-
-let
- cfg = config.security.ldap;
-in
-{
- options.security.ldap = lib.mkOption {
- type = lib.types.submodule {
- options = {
- bindDN = lib.mkOption {
- type = lib.types.str;
- example = "uid=search";
- default = "uid=${cfg.searchUID}";
- apply = s: s + "," + cfg.userBaseDN;
- description = lib.mdDoc ''
- The DN of the service user used by services.
- The user base dn will be automatically appended.
- '';
- };
-
- domainComponent = lib.mkOption {
- type = with lib.types; listOf str;
- example = [ "example" "com" ];
- apply = dc: lib.removeSuffix "," (lib.concatMapStrings (x: "dc=${x},") dc);
- description = lib.mdDoc ''
- Domain component(s) (dc) represented as a list of strings.
-
- Each entry will be prefixed with `dc=` and all are concatinated with `,`, except the last one.
- The example would be concatinated to `dc=example,dc=com`
- '';
- };
-
- domainName = lib.mkOption {
- type = lib.types.str;
- example = "auth.example.com";
- description = lib.mdDoc "The domain name to connect to the ldap server.";
- };
-
- givenNameField = lib.mkOption {
- type = lib.types.str;
- example = "givenName";
- description = lib.mdDoc "The attribute of the user object where to find its given name.";
- };
-
- groupFilter = lib.mkOption {
- type = with lib.types; functionTo str;
- example = lib.literalExpression ''group: "(&(objectclass=person)(isMemberOf=cn=''${group},''${config.security.ldap.roleBaseDN}"'';
- description = lib.mdDoc "A function that returns a group filter that matches the first argument against the names of the groups the user is part of.";
- };
-
- mailField = lib.mkOption {
- type = lib.types.str;
- example = "mail";
- description = lib.mdDoc "The attribute of the user object where to find its email.";
- };
-
- port = lib.mkOption {
- type = lib.types.port;
- example = "636";
- description = lib.mdDoc "The port the ldap server listens on. Usually this is 389 for ldap and 636 for ldaps.";
- };
-
- roleBaseDN = lib.mkOption {
- type = lib.types.str;
- example = "ou=groups";
- apply = s: s + "," + cfg.domainComponent;
- description = lib.mdDoc ''
- The directory path where applications should search for users.
- Domain component will be automatically appended.
- '';
- };
-
- roleField = lib.mkOption {
- type = lib.types.str;
- example = "cn";
- description = lib.mdDoc "The attribute where the user account is listed in a group.";
- };
-
- roleFilter = lib.mkOption {
- type = lib.types.str;
- example = "(&(objectclass=groupOfNames)(member=%s))";
- description = lib.mdDoc "Filter to get the groups of an user object.";
- };
-
- roleValue = lib.mkOption {
- type = lib.types.str;
- example = "dn";
- description = lib.mdDoc "The attribute of the user object where to find its distinguished name.";
- };
-
- searchUID = lib.mkOption {
- type = lib.types.str;
- example = "search";
- description = lib.mdDoc "The uid of the service user used by services, often referred as search user.";
- };
-
- searchFilterWithGroupFilter = lib.mkOption {
- type = with lib.types; functionTo (functionTo str);
- example = lib.literalExpression ''userFilterGroup: userFilter: if (userFilterGroup != null) then "(&''${config.security.ldap.groupFilter userFilterGroup})" else userFilter'';
- description = lib.mdDoc ''
- A function that returns a search filter that may include a group filter.
- The first argument may be the group that is filtered upon or null.
- If set to null no additional filtering is done. If set the supplied filter is combined with the user filter.
- The second argument must be the user filter including the applications placeholders or ideally the userFilter option.
- '';
- };
-
- sshPublicKeyField = lib.mkOption {
- type = lib.types.str;
- example = "sshPublicKey";
- description = lib.mdDoc "The attribute of the user object where to find its ssh public key.";
- };
-
- surnameField = lib.mkOption {
- type = lib.types.str;
- example = "sn";
- description = lib.mdDoc "The attribute of the user object where to find its surname.";
- };
-
- userBaseDN = lib.mkOption {
- type = lib.types.str;
- example = "ou=users";
- apply = s: s + "," + cfg.domainComponent;
- description = lib.mdDoc ''
- The directory path where applications should search for users.
- Domain component will be automatically appended.
- '';
- };
-
- userField = lib.mkOption {
- type = lib.types.str;
- example = "uid";
- description = lib.mdDoc "The attribute of the user object where to find its username.";
- };
-
- userFilter = lib.mkOption {
- type = with lib.types; functionTo str;
- example = ''param: "(&(objectclass=person)(|(uid=''${param})(mail=''${param})))"'';
- description = lib.mdDoc "A function that returns a user search filter that uses the first argument as the placeholder.";
- };
- };
- };
- default = { };
- description = "LDAP options used in other services.";
- };
-}
diff --git a/modules/mastodon.nix b/modules/mastodon.nix
deleted file mode 100644
index 58496b6..0000000
--- a/modules/mastodon.nix
+++ /dev/null
@@ -1,75 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-let
- cfg = config.services.mastodon;
- cfgl = cfg.ldap;
- inherit (config.security) ldap;
-in
-{
- options.services.mastodon = {
- ldap = {
- enable = lib.mkEnableOption (lib.mdDoc "login only via LDAP");
-
- userGroup = libS.ldap.mkUserGroupOption;
- };
-
- enableBirdUITheme = lib.mkEnableOption (lib.mdDoc "Bird UI Theme");
- };
-
- config.services.mastodon = {
- package = lib.mkIf cfg.enableBirdUITheme (pkgs.mastodon.overrideAttrs (_: with pkgs; let
- src = pkgs.applyPatches {
- src = fetchFromGitHub {
- owner = "mstdn";
- repo = "Bird-UI-Theme-Admins";
- rev = "2f9921db746593f393c13f9b79e5b4c2e19b03bd";
- hash = "sha256-+7FUm5GNXRWyS9Oiow6kwX+pWh11wO3stm5iOTY3sYY=";
- };
-
- patches = [
- # fix compose box background
- (fetchpatch {
- url = "https://github.com/mstdn/Bird-UI-Theme-Admins/commit/d5a07d653680fba0ad8dd941405e2d0272ff9cd1.patch";
- hash = "sha256-1gnQNCSSuTE/pkPCf49lJQbmeLAbaiPD9u/q8KiFvlU=";
- })
- ];
- };
- in {
- mastodonModules = mastodon.mastodonModules.overrideAttrs (oldAttrs: {
- pname = "mastodon-birdui-theme";
-
- nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [
- rsync
- xorg.lndir
- ];
-
- postPatch = ''
- rsync -r ${src}/mastodon/ .
- '';
- });
-
- postBuild = ''
- cp ${src}/mastodon/config/themes.yml config/themes.yml
- '';
- }));
-
- extraConfig = lib.mkIf cfgl.enable {
- LDAP_ENABLED = "true";
- LDAP_BASE = ldap.userBaseDN;
- LDAP_BIND_DN = ldap.bindDN;
- LDAP_HOST = ldap.domainName;
- LDAP_METHOD = "simple_tls";
- LDAP_PORT = toString ldap.port;
- LDAP_UID = ldap.userField;
- # convert .,- (space) in LDAP usernames to underscore, otherwise those users cannot log in
- LDAP_UID_CONVERSION_ENABLED = "true";
- LDAP_SEARCH_FILTER = ldap.searchFilterWithGroupFilter cfgl.userGroup "(|(%{uid}=%{email})(%{mail}=%{email}))";
- };
- };
-
- config.services.portunus.seedSettings.groups = lib.optional (cfgl.userGroup != null) {
- long_name = "Mastodon Users";
- name = cfgl.userGroup;
- permissions = { };
- };
-}
diff --git a/modules/matrix.nix b/modules/matrix.nix
deleted file mode 100644
index d487888..0000000
--- a/modules/matrix.nix
+++ /dev/null
@@ -1,158 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-let
- cfg = config.services.matrix-synapse;
- cfge = cfg.element-web;
- inherit (config.security) ldap;
-in
-{
- options = {
- services.matrix-synapse = {
- addAdditionalOembedProvider = libS.mkOpinionatedOption "add additional oembed providers from oembed.com";
-
- element-web = {
- enable = lib.mkEnableOption (lib.mdDoc "the element-web client");
-
- domain = lib.mkOption {
- type = lib.types.str;
- example = "element.example.org";
- description = lib.mdDoc "The domain that element-web will use.";
- };
-
- package = lib.mkPackageOptionMD pkgs "Element-Web" {
- default = [ "element-web" ];
- };
-
- enableConfigFeatures = libS.mkOpinionatedOption "enable most features available via config.json";
- };
-
- ldap = {
- enable = lib.mkEnableOption (lib.mdDoc "login via ldap");
-
- userGroup = libS.ldap.mkUserGroupOption;
-
- bindPasswordFile = lib.mkOption {
- type = lib.types.str;
- example = "/var/lib/secrets/bind-password";
- description = lib.mdDoc "Path to a file containing the bind password.";
- };
- };
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended and secure default settings";
- };
- };
-
- config.environment.etc = lib.mkIf cfg.enable {
- "matrix-synapse/config.yaml".source = cfg.configFile;
- };
-
- config.services.nginx = lib.mkIf cfge.enable {
- enable = true;
- virtualHosts."${cfge.domain}" = {
- forceSSL = true;
- enableACME = lib.mkDefault true;
- root = (cfge.package.override {
- conf = with config.services.matrix-synapse.settings; {
- default_server_config."m.homeserver" = {
- "base_url" = public_baseurl;
- "server_name" = server_name;
- };
- default_theme = "dark";
- room_directory.servers = [ server_name ];
- } // lib.optionalAttrs cfge.enableConfigFeatures {
- features = {
- # https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.tsx
- # https://github.com/vector-im/element-web/blob/develop/docs/labs.md
- feature_ask_to_join = true;
- feature_bridge_state = true;
- feature_exploring_public_spaces = true;
- feature_jump_to_date = true;
- feature_mjolnir = true;
- feature_pinning = true;
- feature_presence_in_room_list = true;
- feature_report_to_moderators = true;
- feature_qr_signin_reciprocate_show = true;
- };
- show_labs_settings = true;
- };
- }).overrideAttrs ({ postInstall ? "", ... }: {
- # prevent 404 spam in nginx log
- postInstall = postInstall + ''
- ln -rs $out/config.json $out/config.${cfge.domain}.json
- '';
- });
- };
- };
-
- config.services.matrix-synapse = lib.mkMerge [
- {
- settings = lib.mkIf cfge.enable rec {
- email.client_base_url = web_client_location;
- web_client_location = "https://${cfge.domain}";
- };
- }
-
- (lib.mkIf cfg.ldap.enable {
- plugins = with config.services.matrix-synapse.package.plugins; [
- matrix-synapse-ldap3
- ];
-
- settings.modules = [{
- module = "ldap_auth_provider.LdapAuthProviderModule";
- config = {
- enabled = true;
- mode = "search";
- uri = "ldaps://${ldap.domainName}:${toString ldap.port}";
- base = ldap.userBaseDN;
- attributes = {
- uid = ldap.userField;
- mail = ldap.mailField;
- name = ldap.givenNameField;
- };
- bind_dn = ldap.bindDN;
- bind_password_file = cfg.ldap.bindPasswordFile;
- tls_options.validate = true;
- } // lib.optionalAttrs (cfg.ldap.userGroup != null) {
- filter = ldap.groupFilter cfg.ldap.userGroup;
- };
- }];
- })
-
- {
- settings.oembed.additional_providers = lib.mkIf cfg.addAdditionalOembedProvider [
- (
- let
- providers = pkgs.fetchurl {
- url = "https://oembed.com/providers.json?2023-03-23";
- sha256 = "sha256-OdgBgkLbtNMn84ixKuC1gGzpyr+X+ORiLl6TAK3lYuQ=";
- };
- in
- pkgs.runCommand "providers.json"
- {
- nativeBuildInputs = with pkgs; [ jq ];
- } ''
- # filter out entries that do not contain a schemes entry
- # Error in configuration at 'oembed.additional_providers.- .
- .endpoints.
- ': 'schemes' is a required property
- # and have none http protocols: Unsupported oEmbed scheme (spotify) for pattern: spotify:*
- jq '[ ..|objects| select(.endpoints[0]|has("schemes")) | .endpoints[0].schemes=([ .endpoints[0].schemes[]|select(.|contains("http")) ]) ]' ${providers} > $out
- ''
- )
- ];
- }
-
- (lib.mkIf cfg.recommendedDefaults {
- settings = {
- federation_client_minimum_tls_version = "1.2";
- suppress_key_server_warning = true;
- user_directory.prefer_local_users = true;
- };
- withJemalloc = true;
- })
- ];
-
- config.services.portunus.seedSettings.groups = lib.optional (cfg.ldap.userGroup != null) {
- long_name = "Matrix Users";
- name = cfg.ldap.userGroup;
- permissions = { };
- };
-}
diff --git a/modules/nextcloud.nix b/modules/nextcloud.nix
deleted file mode 100644
index 01a753c..0000000
--- a/modules/nextcloud.nix
+++ /dev/null
@@ -1,218 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-let
- cfg = config.services.nextcloud;
-in
-{
- options = {
- services.nextcloud = {
- recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings";
-
- configureImaginary = libS.mkOpinionatedOption "configure and use Imaginary for preview generation";
-
- configureMemories = libS.mkOpinionatedOption "configure dependencies for Memories App";
-
- configureMemoriesVaapi = lib.mkOption {
- type = lib.types.bool;
- default = config.hardware.intelGPU;
- defaultText = "config.hardware.intelGPU";
- description = lib.mdDoc ''
- Wether to configure Memories App to use an Intel iGPU for hardware acceleration.
- '';
- };
-
- configurePreviewSettings = lib.mkOption {
- type = lib.types.bool;
- default = cfg.configureImaginary;
- defaultText = "config.services.nextcloud.configureImaginary";
- description = lib.mdDoc ''
- Wether to configure the preview settings to be more optimised for real world usage.
- By default this is enabled, when Imaginary is configured.
- '';
- };
-
- configureRecognize = libS.mkOpinionatedOption "configure dependencies for Recognize App";
- };
- };
-
- config = lib.mkIf cfg.enable {
- services = {
- imaginary = lib.mkIf cfg.configureImaginary {
- enable = true;
- address = "127.0.0.1";
- settings.return-size = true;
- };
-
- nextcloud = {
- # otherwise the Logging App does not function
- logType = lib.mkIf cfg.recommendedDefaults "file";
-
- phpOptions = lib.mkIf cfg.recommendedDefaults {
- # https://docs.nextcloud.com/server/latest/admin_manual/installation/server_tuning.html#:~:text=opcache.jit%20%3D%201255%20opcache.jit_buffer_size%20%3D%20128m
- "opcache.jit" = 1255;
- "opcache.jit_buffer_size" = "128M";
- };
-
- extraOptions = lib.mkMerge [
- (lib.mkIf cfg.configureImaginary {
- enabledPreviewProviders = [
- # default from https://github.com/nextcloud/server/blob/master/config/config.sample.php#L1295-L1304
- ''OC\Preview\BMP''
- ''OC\Preview\GIF''
- ''OC\Preview\JPEG''
- ''OC\Preview\Krita''
- ''OC\Preview\MarkDown''
- ''OC\Preview\MP3''
- ''OC\Preview\OpenDocument''
- ''OC\Preview\PNG''
- ''OC\Preview\TXT''
- ''OC\Preview\XBitmap''
- # https://docs.nextcloud.com/server/24/admin_manual/installation/server_tuning.html#previews
- ''OC\Preview\Imaginary''
- ];
- })
-
- (lib.mkIf cfg.configureMemories {
- enabledPreviewProviders = [
- # https://github.com/pulsejet/memories/wiki/File-Type-Support
- # TODO: not sure if this should be under configurePreviewSettings instead or both
- ''OC\Preview\Image'' # alias for png,jpeg,gif,bmp
- ''OC\Preview\HEIC''
- ''OC\Preview\TIFF''
- ''OC\Preview\Movie''
- ];
-
- "memories.exiftool" = "${pkgs.exiftool}/bin/exiftool";
- "memories.vod.vaapi" = lib.mkIf cfg.configureMemoriesVaapi true;
- "memories.vod.ffmpeg" = "${pkgs.ffmpeg-headless}/bin/ffmpeg";
- "memories.vod.ffprobe" = "${pkgs.ffmpeg-headless}/bin/ffprobe";
- })
-
- (lib.mkIf cfg.configurePreviewSettings {
- enabledPreviewProviders = [
- # https://github.com/nextcloud/server/tree/master/lib/private/Preview
- ''OC\Preview\Font''
- ''OC\Preview\PDF''
- ''OC\Preview\SVG''
- ''OC\Preview\WebP''
- ];
-
- jpeg_quality = 60;
- preview_max_filesize_image = 128; # MB
- preview_max_memory = 512; # MB
- preview_max_x = 2048; # px
- preview_max_y = 2048; # px
- })
- ];
- };
-
- phpfpm.pools = lib.mkIf cfg.configurePreviewSettings {
- # add user packages to phpfpm process PATHs, required to find ffmpeg for preview generator
- # beginning taken from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/web-apps/nextcloud.nix#L985
- nextcloud.phpEnv.PATH = lib.mkForce "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin:/etc/profiles/per-user/nextcloud/bin";
- };
- };
-
- systemd = {
- services = {
- nextcloud-cron = lib.mkIf cfg.configureMemories {
- # required for memories
- # see https://github.com/pulsejet/memories/blob/master/docs/troubleshooting.md#issues-with-nixos
- path = with pkgs; [ perl ];
- # fix memories app being unpacked without the x-bit on binaries
- # could be done in nextcloud-update-plugins but then manually updates would be broken until the next auto update
- preStart = "${pkgs.coreutils}/bin/chmod +x /var/lib/nextcloud/store-apps/memories/bin-ext/*";
- };
-
- nextcloud-cron-preview-generator = lib.mkIf cfg.configurePreviewSettings {
- environment.NEXTCLOUD_CONFIG_DIR = "${config.services.nextcloud.datadir}/config";
- serviceConfig = {
- ExecStart = "/run/current-system/sw/bin/nextcloud-occ preview:pre-generate";
- Type = "oneshot";
- User = "nextcloud";
- };
- };
-
- nextcloud-preview-generator-setup = lib.mkIf cfg.configurePreviewSettings {
- wantedBy = [ "multi-user.target" ];
- requires = [ "phpfpm-nextcloud.service" ];
- after = [ "phpfpm-nextcloud.service" ];
- environment.NEXTCLOUD_CONFIG_DIR = "${config.services.nextcloud.datadir}/config";
- script =
- let
- occ = "/run/current-system/sw/bin/nextcloud-occ";
- in
- /* bash */ ''
- # check with:
- # for size in squareSizes widthSizes heightSizes; do echo -n "$size: "; nextcloud-occ config:app:get previewgenerator $size; done
-
- # extra commands run for preview generator:
- # 32 icon file list
- # 64 icon file list android app, photos app
- # 96 nextcloud client VFS windows file preview
- # 256 file app grid view, many requests
- # 512 photos app tags
- ${occ} config:app:set --value="32 64 96 256 512" previewgenerator squareSizes
-
- # 341 hover in maps app
- # 1920 files/photos app when viewing picture
- ${occ} config:app:set --value="341 1920" previewgenerator widthSizes
-
- # 256 hover in maps app
- # 1080 files/photos app when viewing picture
- ${occ} config:app:set --value="256 1080" previewgenerator heightSizes
- '';
- serviceConfig = {
- Type = "oneshot";
- User = "nextcloud";
- };
- };
-
- nextcloud-setup = lib.mkIf cfg.configureRecognize {
- script = /* bash */ ''
- export PATH=$PATH:/etc/profiles/per-user/nextcloud/bin:/run/current-system/sw/bin
-
- if [[ ! -e /var/lib/nextcloud/store-apps/recognize/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node ]]; then
- if [[ -d /var/lib/nextcloud/store-apps/recognize/node_modules/ ]]; then
- cd /var/lib/nextcloud/store-apps/recognize/node_modules/
- npm rebuild @tensorflow/tfjs-node --build-addon-from-source
- fi
- fi
- '';
- };
-
- phpfpm-nextcloud.serviceConfig = lib.mkIf cfg.configureMemoriesVaapi {
- DeviceAllow = [ "/dev/dri/renderD128 rwm" ];
- PrivateDevices = lib.mkForce false;
- };
- };
-
- timers.nextcloud-cron-preview-generator = lib.mkIf cfg.configurePreviewSettings {
- timerConfig = {
- OnUnitActiveSec = "5m";
- Unit = "nextcloud-cron-preview-generator.service";
- };
- wantedBy = [ "timers.target" ];
- };
- };
-
- users.users.nextcloud = {
- extraGroups = lib.mkIf cfg.configureMemoriesVaapi [
- "render" # access /dev/dri/renderD128
- ];
- packages = with pkgs;
- # generate video thumbnails with preview generator
- lib.optional cfg.configurePreviewSettings ffmpeg-headless
- # required for memories, duplicated with nextcloud-cron to better debug
- ++ lib.optional cfg.configureMemories perl
- # required for recognize app
- ++ lib.optionals cfg.configureRecognize [
- gnumake # installation requirement
- nodejs_16 # runtime and installation requirement
- nodejs_16.pkgs.node-pre-gyp # installation requirement
- python3 # requirement for node-pre-gyp otherwise fails with exit code 236
- util-linux # runtime requirement for taskset
- ];
- };
- };
-}
diff --git a/modules/nginx.nix b/modules/nginx.nix
deleted file mode 100644
index 49d8904..0000000
--- a/modules/nginx.nix
+++ /dev/null
@@ -1,176 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-let
- cfg = config.services.nginx;
-in
-{
- options.services.nginx = {
- allCompression = libS.mkOpinionatedOption "set all recommended compression options";
-
- default404Server = {
- enable = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc ''
- Wether to add a default server which always responds with 404.
- This is useful when using a wildcard cname with a wildcard certitificate to not return the first server entry in the config on unknown subdomains
- or to do the same for an old and not fully removed domain.
- '';
- };
-
- acmeHost = lib.mkOption {
- type = lib.types.str;
- description = lib.mdDoc ''
- The acme host to use for the default 404 server.
- '';
- };
- };
-
- generateDhparams = libS.mkOpinionatedOption "generate more secure, 2048 bits dhparams replacing the default 1024 bits";
-
- openFirewall = libS.mkOpinionatedOption "open the firewall port for the http (80) and https (443) default ports";
-
- quic = {
- enable = lib.mkEnableOption (lib.mdDoc "quic support in nginx");
-
- bpf = libS.mkOpinionatedOption "configure nginx' bpf support which routes quic packets from the same source to the same worker";
- };
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended performance options not grouped into other settings";
-
- resolverAddrFromNameserver = libS.mkOpinionatedOption "set resolver address to environment.nameservers";
-
- rotateLogsFaster = libS.mkOpinionatedOption "keep logs only for 7 days and rotate them daily";
-
- setHSTSHeader = libS.mkOpinionatedOption "add the HSTS header to all virtual hosts";
-
- tcpFastOpen = libS.mkOpinionatedOption "enable tcp fast open";
- };
-
- config = lib.mkIf cfg.enable {
- assertions = [
- {
- assertion = cfg.quic.enable && cfg.quic.bpf -> !lib.versionOlder cfg.package.version "1.25.0";
- message = "Setting services.nginx.quic.bpf to true requires nginx version 1.25.0 or newer, but currently \"${cfg.package.version}\" is used!";
- }
- ];
-
- boot.kernel.sysctl = lib.mkIf cfg.tcpFastOpen {
- # enable tcp fastopen for outgoing and incoming connections
- "net.ipv4.tcp_fastopen" = 3;
- };
-
- networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ 80 443 ];
-
- nixpkgs.overlays = lib.mkIf cfg.tcpFastOpen [
- (final: prev:
- let
- configureFlags = [ "-DTCP_FASTOPEN=23" ];
- in
- {
- nginx = prev.nginx.override { inherit configureFlags; };
- nginxQuic = prev.nginxQuic.override { inherit configureFlags; };
- nginxStable = prev.nginxStable.override { inherit configureFlags; };
- nginxMainline = prev.nginxMainline.override { inherit configureFlags; };
- })
- ];
-
- services = {
- logrotate.settings.nginx = lib.mkIf cfg.rotateLogsFaster {
- frequency = "daily";
- rotate = 7;
- };
-
- # NOTE: do not use mkMerge here to prevent infinite recursions
- nginx = {
- appendConfig = lib.optionalString (cfg.quic.enable && cfg.quic.bpf) /* nginx */ ''
- quic_bpf on;
- '' + lib.optionalString cfg.recommendedDefaults /* nginx */ ''
- worker_processes auto;
- worker_cpu_affinity auto;
- '';
-
- commonHttpConfig = lib.optionalString cfg.recommendedDefaults /* nginx */ ''
- error_log syslog:server=unix:/dev/log;
- '' + lib.optionalString cfg.quic.enable /* nginx */''
- quic_retry on;
- '' + lib.optionalString cfg.recommendedZstdSettings /* nginx */ ''
- # TODO: upstream this?
- zstd_types application/x-nix-archive;
- '';
-
- commonServerConfig = lib.mkIf cfg.setHSTSHeader /* nginx */ ''
- more_set_headers "Strict-Transport-Security: max-age=63072000; includeSubDomains; preload";
- '';
-
- package = lib.mkIf cfg.quic.enable pkgs.nginxQuic; # based on pkgs.nginxMainline
-
- recommendedBrotliSettings = lib.mkIf cfg.allCompression true;
- recommendedGzipSettings = lib.mkIf cfg.allCompression true;
- recommendedOptimisation = lib.mkIf cfg.allCompression true;
- recommendedProxySettings = lib.mkIf cfg.allCompression true;
- recommendedTlsSettings = lib.mkIf cfg.allCompression true;
- recommendedZstdSettings = lib.mkIf cfg.allCompression true;
-
- resolver.addresses =
- let
- isIPv6 = addr: builtins.match ".*:.*:.*" addr != null;
- escapeIPv6 = addr:
- if isIPv6 addr then
- "[${addr}]"
- else
- addr;
- in
- lib.optionals (cfg.resolverAddrFromNameserver && config.networking.nameservers != [ ]) (map escapeIPv6 config.networking.nameservers);
- sslDhparam = lib.mkIf cfg.generateDhparams config.security.dhparams.params.nginx.path;
-
- # NOTE: do not use mkMerge here to prevent infinite recursions
- virtualHosts =
- let
- extraParameters = [
- # net.core.somaxconn is set to 4096
- # see https://www.nginx.com/blog/tuning-nginx/#:~:text=to%20a%20value-,greater%20than%20512,-%2C%20change%20the%20backlog
- "backlog=1024"
-
- "deferred"
- "fastopen=256" # requires nginx to be compiled with -DTCP_FASTOPEN=23
- ];
- in
- lib.mkIf (cfg.recommendedDefaults || cfg.default404Server.enable || cfg.quic.enable) {
- "_" = {
- kTLS = lib.mkIf cfg.recommendedDefaults true;
- reuseport = lib.mkIf (cfg.recommendedDefaults || cfg.quic.enable) true;
-
- default = lib.mkIf cfg.default404Server.enable true;
- forceSSL = lib.mkIf cfg.default404Server.enable true;
- useACMEHost = lib.mkIf cfg.default404Server.enable cfg.default404Server.acmeHost;
- extraConfig = lib.mkIf cfg.default404Server.enable /* nginx */ ''
- return 404;
- '';
-
- listen = lib.mkIf cfg.tcpFastOpen (lib.mkDefault [
- { addr = "0.0.0.0"; port = 80; inherit extraParameters; }
- { addr = "0.0.0.0"; port = 443; ssl = true; inherit extraParameters; }
- { addr = "[::]"; port = 80; inherit extraParameters; }
- { addr = "[::]"; port = 443; ssl = true; inherit extraParameters; }
- ]);
-
- quic = lib.mkIf cfg.quic.enable true;
- };
- };
- };
- };
-
- security.dhparams = lib.mkIf cfg.generateDhparams {
- enable = cfg.generateDhparams;
- params.nginx = { };
- };
-
- systemd.services.nginx.serviceConfig = lib.mkIf (cfg.quic.enable && cfg.quic.bpf) {
- # NOTE: CAP_BPF is included in CAP_SYS_ADMIN but it is not enough alone
- AmbientCapabilities = [ "CAP_BPF" "CAP_NET_ADMIN" "CAP_SYS_ADMIN" ];
- CapabilityBoundingSet = [ "CAP_BPF" "CAP_NET_ADMIN" "CAP_SYS_ADMIN" ];
- SystemCallFilter = [ "bpf" ];
- };
- };
-}
diff --git a/modules/nix.nix b/modules/nix.nix
deleted file mode 100644
index 9c7fc71..0000000
--- a/modules/nix.nix
+++ /dev/null
@@ -1,91 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-let
- cfg = config.nix;
-in
-{
- options.nix = {
- deleteChannels = lib.mkEnableOption "" // { description = "Whether to delete all channels on a system switch."; };
-
- deleteUserProfiles = lib.mkEnableOption "" // { description = "Whether to delete all user profiles on a system switch."; };
-
- diffSystem = libS.mkOpinionatedOption "system closure diffing on updates";
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings";
-
- remoteBuilder = {
- enable = lib.mkEnableOption "restricted nix remote builder";
-
- sshPublicKeys = lib.mkOption {
- description = "SSH public keys accepted by the remote build user.";
- type = lib.types.listOf lib.types.str;
- };
-
- name = lib.mkOption {
- description = "Name of the user used for remote building.";
- type = lib.types.str;
- readOnly = true;
- default = "nix-remote-builder";
- };
- };
- };
-
- config = {
- # based on https://github.com/numtide/srvos/blob/main/nixos/roles/nix-remote-builder.nix
- # and https://discourse.nixos.org/t/wrapper-to-restrict-builder-access-through-ssh-worth-upstreaming/25834
- nix.settings = {
- builders-use-substitutes = lib.mkIf cfg.recommendedDefaults true;
- connect-timeout = lib.mkIf cfg.recommendedDefaults 20;
- experimental-features = lib.mkIf cfg.recommendedDefaults [ "nix-command" "flakes" ];
- trusted-users = lib.mkIf cfg.remoteBuilder.enable [ cfg.remoteBuilder.name ];
- };
-
- users.users.${cfg.remoteBuilder.name} = lib.mkIf cfg.remoteBuilder.enable {
- group = "nogroup";
- isNormalUser = true;
- openssh.authorizedKeys.keys = map
- (key:
- let
- wrapper-dispatch-ssh-nix = pkgs.writeShellScriptBin "wrapper-dispatch-ssh-nix" /* bash */ ''
- case $SSH_ORIGINAL_COMMAND in
- "nix-daemon --stdio")
- exec ${config.nix.package}/bin/nix-daemon --stdio
- ;;
- "nix-store --serve --write")
- exec ${config.nix.package}/bin/nix-store --serve --write
- ;;
- *)
- echo "Access is only allowed for the nix remote builder" 1>&2
- exit 1
- esac
- '';
-
- in
- "restrict,pty,command=\"${wrapper-dispatch-ssh-nix}/bin/wrapper-dispatch-ssh-nix\" ${key}"
- )
- config.nix.remoteBuilder.sshPublicKeys;
- };
-
- system.activationScripts = {
- deleteChannels = lib.mkIf cfg.deleteChannels ''
- echo "Deleting all channels..."
- rm -rf /root/.nix-channels /home/*/.nix-channels /nix/var/nix/profiles/per-user/*/channels* || true
- '';
-
- deleteUserProfiles = lib.mkIf cfg.deleteUserProfiles ''
- echo "Deleting all user profiles..."
- rm -rf /root/.nix-profile /home/*/.nix-profile /nix/var/nix/profiles/per-user/*/profile* || true
- '';
-
- diff-system = lib.mkIf cfg.diffSystem {
- supportsDryActivation = true;
- text = ''
- if [[ -e /run/current-system && -e $systemConfig ]]; then
- echo System package diff:
- ${lib.getExe config.nix.package} --extra-experimental-features nix-command store diff-closures /run/current-system $systemConfig || true
- fi
- '';
- };
- };
- };
-}
diff --git a/modules/openvpn.nix b/modules/openvpn.nix
deleted file mode 100644
index 4f77041..0000000
--- a/modules/openvpn.nix
+++ /dev/null
@@ -1,9 +0,0 @@
-
-{ config, lib, ... }:
-
-let
- cfg = config.services.openvpn;
-in
-{
- # TODO: OpenVPN
-}
diff --git a/modules/portunus-remove-add-group.diff b/modules/portunus-remove-add-group.diff
deleted file mode 100644
index e3c210a..0000000
--- a/modules/portunus-remove-add-group.diff
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git a/internal/frontend/core.go b/internal/frontend/core.go
-index 5976377..7c67991 100644
---- a/internal/frontend/core.go
-+++ b/internal/frontend/core.go
-@@ -43,8 +43,6 @@ func HTTPHandler(nexus core.Nexus, isBehindTLSProxy bool) http.Handler {
- r.Methods("POST").Path(`/users/{uid}/delete`).Handler(postUserDeleteHandler(nexus))
-
- r.Methods("GET").Path(`/groups`).Handler(getGroupsHandler(nexus))
-- r.Methods("GET").Path(`/groups/new`).Handler(getGroupsNewHandler(nexus))
-- r.Methods("POST").Path(`/groups/new`).Handler(postGroupsNewHandler(nexus))
- r.Methods("GET").Path(`/groups/{name}/edit`).Handler(getGroupEditHandler(nexus))
- r.Methods("POST").Path(`/groups/{name}/edit`).Handler(postGroupEditHandler(nexus))
- r.Methods("GET").Path(`/groups/{name}/delete`).Handler(getGroupDeleteHandler(nexus))
-diff --git a/internal/frontend/groups.go b/internal/frontend/groups.go
-index 5ac6a75..ac59f4f 100644
---- a/internal/frontend/groups.go
-+++ b/internal/frontend/groups.go
-@@ -38,7 +38,6 @@ func getGroupsHandler(n core.Nexus) http.Handler {
-
Members |
- Permissions granted |
-
-- New group
- |
-
-
diff --git a/modules/portunus.nix b/modules/portunus.nix
deleted file mode 100644
index dca6c5a..0000000
--- a/modules/portunus.nix
+++ /dev/null
@@ -1,183 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-let
- cfg = config.services.portunus;
- inherit (config.security) ldap;
-in
-{
- options.services.portunus = {
- # TODO: how to automatically set this?
- # maybe based on $service.ldap.enable && services.portunus.enable?
- addToHosts = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc "Whether to add a hosts entry for the portunus domain pointing to externalIp";
- };
-
- configureOAuth2Proxy = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc ''
- Wether to configure OAuth2 Proxy with Portunus' Dex.
-
- Use `services.oauth2_proxy.nginx.virtualHosts` to configure the nginx virtual hosts that should require authentication.
- '';
- };
-
- internalIp4 = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- description = lib.mdDoc "Internal IPv4 of portunus instance. This is used in the addToHosts option.";
- };
-
- internalIp6 = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- description = lib.mdDoc "Internal IPv6 of portunus instance. This is used in the addToHosts option.";
- };
-
- ldapPreset = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc "Whether to set config.security.ldap to portunus specific settings.";
- };
-
- removeAddGroup = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc "When enabled, remove the function to add new Groups via the web ui, to enforce seeding usage.";
- };
-
- seedGroups = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = lib.mdDoc "Wether to seed groups configured in services as not member managed groups.";
- };
-
- # TODO: upstream to nixos
- seedSettings = lib.mkOption {
- type = with lib.types; nullOr (attrsOf (listOf (attrsOf anything)));
- default = null;
- description = lib.mdDoc ''
- Seed settings for users and grousp.
- See upstream for format
- '';
- };
- };
-
- config = {
- assertions = [
- {
- assertion = cfg.configureOAuth2Proxy -> config.services.oauth2_proxy.keyFile != null;
- message = ''
- Setting services.portunus.configureOAuth2Proxy to true requires to set service.oauth2_proxy.keyFile
- to a file that contains `OAUTH2_PROXY_CLIENT_SECRET` and `OAUTH2_PROXY_COOKIE_SECRET`.
- '';
- }
- ];
-
- networking.hosts = lib.mkIf cfg.addToHosts {
- ${cfg.internalIp4} = [ cfg.domain ];
- ${cfg.internalIp6} = [ cfg.domain ];
- };
-
- nixpkgs.overlays = lib.mkIf cfg.enable [
- (final: prev: with final; {
- dex-oidc = prev.dex-oidc.override {
- buildGoModule = args: buildGoModule (args // {
- patches = args.patches or [ ] ++ [
- # remember session
- (fetchpatch {
- url = "https://github.com/SuperSandro2000/dex/commit/d2fb6cdf8188e6973721ddac657a7c5d3daf6955.patch";
- hash = "sha256-PKC7jsNyFN28qFZ7SLYgnd0s09G2cb+vBeFvRzyyLGQ=";
- })
- # Complain if the env set in SecretEnv cannot be found
- (fetchpatch {
- url = "https://github.com/dexidp/dex/commit/f25f72053c9282cfe22521cd508698a07dc5190f.patch";
- hash = "sha256-dyo+UPpceHxL3gcBQaGaDAHJqmysDJw051gMG1aeh5o=";
- })
- ];
-
- vendorHash = "sha256-YIi67pPIcVndIjWk94ckv6X4WLELUe/J/03e+XWIdHE=";
- });
- };
-
- portunus = (prev.portunus.override { buildGoModule = buildGo121Module; }).overrideAttrs ({ patches ? [ ], buildInputs ? [ ], ... }: let
- version = "2.0.0-beta.2";
- in {
- inherit version;
-
- # TODO: upstream
- src = fetchFromGitHub {
- owner = "majewsky";
- repo = "portunus";
- rev = "v${version}";
- hash = "sha256-1OU3bepvqriGCW1qDszPnUDJ6eqBzNTiBZ2J4KF4ynw=";
- };
-
- patches = patches
- ++ lib.optional cfg.removeAddGroup ./portunus-remove-add-group.diff;
-
- # TODO: upstream
- buildInputs = buildInputs ++ [
- libxcrypt-legacy
- ];
- });
- })
- ];
-
- services = let
- callbackURL = "https://${cfg.domain}/oauth2/callback";
- clientID = "oauth2_proxy"; # - is not allowed in environment variables
- in {
- dex = {
- enable = lib.mkIf cfg.configureOAuth2Proxy true;
- # the user has no other option to accept this and all clients are internal anyway
- settings.oauth2.skipApprovalScreen = true;
- };
-
- oauth2_proxy = lib.mkIf cfg.configureOAuth2Proxy {
- enable = true;
- inherit clientID;
- nginx = {
- inherit (config.services.portunus) domain;
- };
- provider = "oidc";
- redirectURL = callbackURL;
- reverseProxy = true;
- upstream = "http://127.0.0.1:4181";
- extraConfig = {
- oidc-issuer-url = config.services.dex.settings.issuer;
- provider-display-name = "Portunus";
- };
- };
-
- portunus = {
- dex.oidcClients = lib.mkIf cfg.configureOAuth2Proxy [{
- inherit callbackURL;
- id = clientID;
- }];
- seedPath = pkgs.writeText "seed.json" (builtins.toJSON cfg.seedSettings);
- };
- };
-
- security.ldap = lib.mkIf cfg.ldapPreset {
- domainName = cfg.domain;
- givenNameField = "givenName";
- groupFilter = group: "(&(objectclass=person)(isMemberOf=cn=${group},${ldap.roleBaseDN}))";
- mailField = "mail";
- port = 636;
- roleBaseDN = "ou=groups";
- roleField = "cn";
- roleFilter = "(&(objectclass=groupOfNames)(member=%s))";
- roleValue = "dn";
- searchFilterWithGroupFilter = userFilterGroup: userFilter: if (userFilterGroup != null) then "(&${ldap.groupFilter userFilterGroup}${userFilter})" else userFilter;
- sshPublicKeyField = "sshPublicKey";
- searchUID = "search";
- surnameField = "sn";
- userField = "uid";
- userFilter = replaceStr: "(&(objectclass=person)(|(uid=${replaceStr})(mail=${replaceStr})))";
- userBaseDN = "ou=users";
- };
- };
-}
diff --git a/modules/postgres.nix b/modules/postgres.nix
deleted file mode 100644
index 17d860c..0000000
--- a/modules/postgres.nix
+++ /dev/null
@@ -1,96 +0,0 @@
-{ config, lib, libS, pkgs, ... }:
-
-# NOTE: requires https://github.com/NixOS/nixpkgs/pull/257503 because of new usage of extraPlugins
-
-let
- cfg = config.services.postgresql;
- cfgu = config.services.postgresql.upgrade;
-in
-{
- options.services.postgresql = {
- upgrade = {
- enable = libS.mkOpinionatedOption "install the upgrade-pg-cluster script to update postgres.";
-
- extraArgs = lib.mkOption {
- type = with lib.types; listOf str;
- default = [ "--link" "--jobs=$(nproc)" ];
- description = lib.mdDoc "Extra arguments to pass to pg_upgrade. See https://www.postgresql.org/docs/current/pgupgrade.html for doc.";
- };
-
- newPackage = (lib.mkPackageOptionMD pkgs "postgresql" {
- default = [ "postgresql_16" ];
- }) // {
- description = lib.mdDoc ''
- The postgres package to which should be updated.
- After running upgrade-pg-cluster this must be set to services.postgresql.package to complete the update.
- '';
- };
-
- stopServices = lib.mkOption {
- type = with lib.types; listOf str;
- default = [ ];
- example = [ "hedgedoc" "hydra" "nginx" ];
- description = lib.mdDoc "Systemd services to stop when upgrade is started.";
- };
- };
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings";
- };
-
- config = lib.mkIf cfg.enable {
- environment.systemPackages = lib.optional cfgu.enable (
- let
- # conditions copied from nixos/modules/services/databases/postgresql.nix
- newPackage = if cfg.enableJIT && !cfgu.newPackage.jitSupport then cfgu.newPackage.withJIT else cfg.newPackage;
- newData = "/var/lib/postgresql/${cfgu.newPackage.psqlSchema}";
- newBin = "${if cfg.extraPlugins == [] then cfgu.newPackage else cfgu.newPackage.withPackages cfg.extraPlugins}/bin";
-
- oldPackage = if cfg.enableJIT && !cfg.package.jitSupport then cfg.package.withJIT else cfg.package;
- oldData = config.services.postgresql.dataDir;
- oldBin = "${if cfg.extraPlugins == [] then oldPackage else oldPackage.withPackages cfg.extraPlugins}/bin";
- in
- pkgs.writeScriptBin "upgrade-pg-cluster" /* bash */ ''
- set -eu
-
- echo "Current version: ${cfg.package.version}"
- echo "Update version: ${cfgu.newPackage.version}"
-
- if [[ ${cfgu.newPackage.version} == ${cfg.package.version} ]]; then
- echo "There is no major postgres update available."
- exit 2
- fi
-
- systemctl stop postgresql ${lib.concatStringsSep " " cfgu.stopServices}
-
- install -d -m 0700 -o postgres -g postgres "${newData}"
- cd "${newData}"
- sudo -u postgres "${newBin}/initdb" -D "${newData}"
-
- sudo -u postgres "${newBin}/pg_upgrade" \
- --old-datadir "${oldData}" --new-datadir "${newData}" \
- --old-bindir ${oldBin} --new-bindir ${newBin} \
- ${lib.concatStringsSep " " cfgu.extraArgs} \
- "$@"
-
- echo "
-
-
- Run the following commands after setting:
- services.postgresql.package = pkgs.postgresql_${lib.versions.major cfgu.newPackage.version}
- sudo -u postgres vacuumdb --all --analyze-in-stages
- ${newData}/delete_old_cluster.sh
- "
- ''
- );
-
- services = {
- postgresql.enableJIT = lib.mkIf cfg.recommendedDefaults true;
-
- postgresqlBackup = lib.mkIf cfg.recommendedDefaults {
- compression = "zstd";
- compressionLevel = 9;
- pgdumpOptions = "--create --clean";
- };
- };
- };
-}
diff --git a/modules/simd.nix b/modules/simd.nix
deleted file mode 100644
index cd81630..0000000
--- a/modules/simd.nix
+++ /dev/null
@@ -1,27 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.simd;
-in
-{
- options.simd = {
- enable = lib.mkEnableOption "optimized builds with simd instructions";
- arch = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- description = ''
- Microarchitecture string for nixpkgs.hostPlatform.gcc.march and to generate system-features.
- Can be determined with: ``nix shell nixpkgs#gcc -c gcc -march=native -Q --help=target | grep march``
- '';
- };
- };
-
- config = {
- nix.settings.system-features = lib.mkIf (cfg.arch != null) (libS.nix.gcc-system-features config.simd.arch);
-
- nixpkgs.hostPlatform = lib.mkIf cfg.enable {
- gcc.arch = config.simd.arch;
- inherit (config.nixpkgs) system;
- };
- };
-}
diff --git a/modules/slim.nix b/modules/slim.nix
deleted file mode 100644
index c16f949..0000000
--- a/modules/slim.nix
+++ /dev/null
@@ -1,23 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.slim;
-in
-{
- options.slim = {
- enable = libS.mkOpinionatedOption "disable some usual rarely used things to slim down the system";
- };
-
- config = lib.mkIf cfg.enable {
- documentation = {
- # html docs and info are not required, man pages are enough
- doc.enable = false;
- info.enable = false;
- };
-
- environment.defaultPackages = lib.mkForce [ ];
-
- # durring testing only 550K-650K of the tmpfs where used
- security.wrapperDirSize = "10M";
- };
-}
diff --git a/modules/ssh.nix b/modules/ssh.nix
deleted file mode 100644
index 501eeeb..0000000
--- a/modules/ssh.nix
+++ /dev/null
@@ -1,66 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfgP = config.programs.ssh;
- cfgS = config.services.openssh;
-in
-{
- options = {
- programs.ssh = {
- addPopularKnownHosts = libS.mkOpinionatedOption "add ssh public keys of popular websites to known_hosts";
- recommendedDefaults = libS.mkOpinionatedOption "set recommend and secure default settings";
- };
-
- services.openssh = {
- fixPermissions = libS.mkOpinionatedOption "fix host key permissions to prevent lock outs";
- };
- };
-
- config = lib.mkIf cfgP.addPopularKnownHosts {
- programs.ssh = {
- extraConfig = lib.mkIf cfgP.recommendedDefaults ''
- # hard complain about wrong knownHosts
- StrictHostKeyChecking accept-new
- # make automated host key rotation possible
- UpdateHostKeys yes
- # fetch host keys via DNS and trust them
- VerifyHostKeyDNS yes
- '';
- knownHosts = lib.mkMerge [
- (libS.mkPubKey "github.com" "ssh-rsa" "AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=")
- (libS.mkPubKey "github.com" "ecdsa-sha2-nistp256" "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=")
- (libS.mkPubKey "github.com" "ssh-ed25519" "AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl")
- (libS.mkPubKey "gitlab.com" "ssh-rsa" "AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9")
- (libS.mkPubKey "gitlab.com" "ecdsa-sha2-nistp256" "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=")
- (libS.mkPubKey "gitlab.com" "ssh-ed25519" "AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf")
- (libS.mkPubKey "git.openwrt.org" "ssh-rsa" "AAAAB3NzaC1yc2EAAAABIwAAAQEAtnM1w/A1uRZqZuYHhw4ASOe9mr3J2qKAa9K9zR8jG+B+NQVtYlIBSkmCFyP6OuydCmoRZ5Gs1I9pl/hEyi7ieEi6g9yww/JbV322cw04Tli46enIYDG1bnSxF6Qt4aXqvPhcObI3z/1Z3XR6weS1fiLDzLvzq+w1gNM77xExD4Mh27LTPkdwOWjkGa5joNx3EQUC3rzwxUqE4fhOT2Ii93h8FSAUXY9C32jkJj9x7vfaJEsCacs6YTiUKKxyzEB+TvFZdUtGtoRThX7UVICUCD2th/r3UeSp8ItWPg/KqzSg2pRfWeYszlVoD59JZ6YCupSjjRqZddghQc94Hev7oQ==")
- (libS.mkPubKey "git.openwrt.org" "ecdsa-sha2-nistp256" "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBASOHg+tghASiZF0ClxYb/HEhUcqnD43I86YatRZSUsXNWLEd8yOzjOJExDHHaKtmZtQ/jfEMmoYbCjdEDOYm5g=")
- (libS.mkPubKey "git.openwrt.org" "ssh-ed25519" "AAAAC3NzaC1lZDI1NTE5AAAAIJZFpKQMaLM8bG9lAPfEpTBExrzuiTKMni7PgktmDbJe")
- (libS.mkPubKey "git.sr.ht" "ssh-rsa" "AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ+l/lvYmaeOAPeijHL8d4794Am0MOvmXPyvHTtrqvgmvCJB8pen/qkQX2S1fgl9VkMGSNxbp7NF7HmKgs5ajTGV9mB5A5zq+161lcp5+f1qmn3Dp1MWKp/AzejWXKW+dwPBd3kkudDBA1fa3uK6g1gK5nLw3qcuv/V4emX9zv3P2ZNlq9XRvBxGY2KzaCyCXVkL48RVTTJJnYbVdRuq8/jQkDRA8lHvGvKI+jqnljmZi2aIrK9OGT2gkCtfyTw2GvNDV6aZ0bEza7nDLU/I+xmByAOO79R1Uk4EYCvSc1WXDZqhiuO2sZRmVxa0pQSBDn1DB3rpvqPYW+UvKB3SOz")
- (libS.mkPubKey "git.sr.ht" "ecdsa-sha2-nistp256" "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCj6y+cJlqK3BHZRLZuM+KP2zGPrh4H66DacfliU1E2DHAd1GGwF4g1jwu3L8gOZUTIvUptqWTkmglpYhFp4Iy4=")
- (libS.mkPubKey "git.sr.ht" "ssh-ed25519" "AAAAC3NzaC1lZDI1NTE5AAAAIMZvRd4EtM7R+IHVMWmDkVU3VLQTSwQDSAvW0t2Tkj60")
- ];
- };
-
- systemd.tmpfiles.rules = lib.mkIf cfgS.fixPermissions [
- "d /etc 0755 root root -"
- "d /etc/ssh 0755 root root -"
- "f /etc/ssh/ssh_host_ed25519_key 0700 root root -"
- "f /etc/ssh/ssh_host_ed25519_key.pub 0744 root root -"
- "f /etc/ssh/ssh_host_rsa_key 0700 root root -"
- "f /etc/ssh/ssh_host_rsa_key.pub 0744 root root -"
- ];
-
- services.openssh.banner = ''
- Welcome to another
- ░██╗░░░░░░░██╗░█████╗░██╗░░░██╗███████╗██╗░░░░░███████╗███╗░░██╗░██████╗
- ░██║░░██╗░░██║██╔══██╗██║░░░██║██╔════╝██║░░░░░██╔════╝████╗░██║██╔════╝
- ░╚██╗████╗██╔╝███████║╚██╗░██╔╝█████╗░░██║░░░░░█████╗░░██╔██╗██║╚█████╗░
- ░░████╔═████║░██╔══██║░╚████╔╝░██╔══╝░░██║░░░░░██╔══╝░░██║╚████║░╚═══██╗
- ░░╚██╔╝░╚██╔╝░██║░░██║░░╚██╔╝░░███████╗███████╗███████╗██║░╚███║██████╔╝
- ░░░╚═╝░░░╚═╝░░╚═╝░░╚═╝░░░╚═╝░░░╚══════╝╚══════╝╚══════╝╚═╝░░╚══╝╚═════╝░
- Server :o
-
- '';
- };
-}
diff --git a/modules/tmux.nix b/modules/tmux.nix
deleted file mode 100644
index 4f5c9c1..0000000
--- a/modules/tmux.nix
+++ /dev/null
@@ -1,31 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.programs.tmux;
-in
-{
- options = {
- programs.tmux.recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings";
- };
-
- config = lib.mkIf cfg.recommendedDefaults {
- programs.tmux = {
- keyMode = "vi";
- shortcut = "Space";
- aggressiveResize = true;
- baseIndex = 1;
- clock24 = true;
- escapeTime = 100;
- terminal = "xterm-256color";
- extraConfig = ''
- # focus events enabled for terminals that support them
- set -g focus-events on
-
- # open new tab in PWD
- bind '"' split-window -c "#{pane_current_path}"
- bind % split-window -h -c "#{pane_current_path}"
- bind c new-window -c "#{pane_current_path}"
- '';
- };
- };
-}
diff --git a/modules/vaultwarden.nix b/modules/vaultwarden.nix
deleted file mode 100644
index 899f604..0000000
--- a/modules/vaultwarden.nix
+++ /dev/null
@@ -1,97 +0,0 @@
-{ config, lib, libS, ... }:
-
-let
- cfg = config.services.vaultwarden;
- usingPostgres = cfg.dbBackend == "postgresql";
-in
-{
- options = {
- services.vaultwarden = {
- configureNginx = libS.mkOpinionatedOption "configure nginx for the configured domain";
-
- domain = lib.mkOption {
- type = with lib.types; nullOr str;
- default = null;
- description = lib.mdDoc ''
- The domain under which vaultwarden will be reachable.
- '';
- };
-
- recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings";
- };
- };
-
- config = lib.mkIf cfg.enable {
- assertions = [ {
- assertion = cfg.configureNginx -> cfg.domain != null;
- message = ''
- Setting services.vaultwarden.configureNginx to true requires configuring services.vaultwarden.domain!
- '';
- } ];
-
- nixpkgs.overlays = lib.mkIf cfg.recommendedDefaults [
- (final: prev: {
- vaultwarden = prev.vaultwarden.overrideAttrs ({ patches ? [], ... }: {
- patches = patches ++ [
- # add eu region push support
- (final.fetchpatch {
- url = "https://github.com/dani-garcia/vaultwarden/pull/3752.diff";
- hash = "sha256-QWbuUotNss1TkIIW6c54Y7U7u2yLg2xHopEngtNawcc=";
- })
- ];
- });
- })
- ];
-
- services = {
- nginx = lib.mkIf cfg.configureNginx {
- upstreams.vaultwarden.servers."127.0.0.1:${toString config.services.vaultwarden.config.ROCKET_PORT}" = { };
- virtualHosts.${cfg.domain}.locations = {
- "/".proxyPass = "http://vaultwarden";
- "/notifications/hub" = {
- proxyPass = "http://vaultwarden";
- proxyWebsockets = true;
- };
- };
- };
-
- postgresql = lib.mkIf usingPostgres {
- enable = true;
- ensureDatabases = [ "vaultwarden" ];
- ensureUsers = [{
- name = "vaultwarden";
- ensureDBOwnership = true;
- }];
- };
-
- vaultwarden.config = lib.mkMerge [
- {
- DATABASE_URL = lib.mkIf usingPostgres "postgresql:///vaultwarden?host=/run/postgresql";
- DOMAIN = lib.mkIf (cfg.domain != null) "https://${cfg.domain}";
- }
- (lib.mkIf cfg.recommendedDefaults {
- DATA_FOLDER = "/var/lib/vaultwarden"; # changes data directory
- # TODO: change with 1.31.0 update
- # ENABLE_WEBSOCKET = true;
- LOG_LEVEL = "warn";
- PASSWORD_ITERATIONS = 600000;
- ROCKET_ADDRESS = "127.0.0.1";
- ROCKET_PORT = lib.mkDefault 8222;
- SIGNUPS_VERIFY = true;
- TRASH_AUTO_DELETE_DAYS = 30;
- WEBSOCKET_ADDRESS = "127.0.0.1";
- WEBSOCKET_ENABLED = true;
- WEBSOCKET_PORT = lib.mkDefault 8223;
- })
- ];
- };
-
- systemd.services.vaultwarden = {
- after = lib.mkIf usingPostgres [ "postgresql.service" ];
- requires = lib.mkIf usingPostgres [ "postgresql.service" ];
- serviceConfig = lib.mkIf cfg.recommendedDefaults {
- StateDirectory = lib.mkForce "vaultwarden"; # modules defaults to bitwarden_rs
- };
- };
- };
-}
diff --git a/modules/zfs.nix b/modules/zfs.nix
deleted file mode 100644
index 457913d..0000000
--- a/modules/zfs.nix
+++ /dev/null
@@ -1,34 +0,0 @@
-{ config, lib, libS, options, pkgs, ... }:
-
-let
- cfg = config.boot.zfs;
-in
-{
- options = {
- boot.zfs = {
- recommendedDefaults = libS.mkOpinionatedOption "enable recommended ZFS settings";
- latestCompatibleKernel = libS.mkOpinionatedOption "use the latest ZFS compatible kernel";
- };
- };
-
- config = lib.mkIf cfg.enabled {
- boot.kernelPackages =
- let
- ver = config.boot.zfs.package.latestCompatibleLinuxPackages.kernel.version;
- in
- # 6.0 has a bug in the bind syscall and does not error correct when the port is already in use
- # https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/7VPNMC77YC3SI5LFYKUA4B5MTFPLTLVB/
- # https://lore.kernel.org/stable/CAFsF8vL4CGFzWMb38_XviiEgxoKX0GYup=JiUFXUOmagdk9CRg@mail.gmail.com/
- lib.mkIf (cfg.latestCompatibleKernel && lib.versions.majorMinor ver != "6.0") (lib.mkDefault config.boot.zfs.package.latestCompatibleLinuxPackages);
-
- services.zfs = lib.mkIf cfg.recommendedDefaults {
- autoScrub.enable = true;
- trim.enable = true;
- };
-
- virtualisation.containers.storage.settings = lib.mkIf cfg.recommendedDefaults (lib.recursiveUpdate options.virtualisation.containers.storage.settings.default {
- # fixes: Error: 'overlay' is not supported over zfs, a mount_program is required: backing file system is unsupported for this graph driver
- storage.options.mount_program = "${pkgs.fuse-overlayfs}/bin/fuse-overlayfs";
- });
- };
-}
diff --git a/systems/configuration.nix b/systems/configuration.nix
index c7b750b..d1ce548 100644
--- a/systems/configuration.nix
+++ b/systems/configuration.nix
@@ -1,7 +1,5 @@
-{ pkgs, lib, config, ... }:
-let
-in {
-
+{ pkgs, ... }:
+{
i18n = {
defaultLocale = "en_US.utf8";
supportedLocales = [
@@ -10,7 +8,6 @@ in {
];
};
-
networking.firewall.allowedTCPPorts = [ 22 ];
services = {
@@ -26,13 +23,6 @@ in {
};
};
- users.users.brain = {
- isNormalUser = true;
- description = "Administrator";
- extraGroups = [ "networkmanager" "wheel" ];
- shell = pkgs.zsh;
- };
-
nixpkgs.config.allowUnfree = true;
programs = {
@@ -180,7 +170,7 @@ in {
options = "--delete-oder-than 14d";
};
- diff-system = true;
+ diffSystem = true;
};
system = {
diff --git a/systems/palatine-hill/configuration.nix b/systems/palatine-hill/configuration.nix
index e47646d..c6e4baf 100644
--- a/systems/palatine-hill/configuration.nix
+++ b/systems/palatine-hill/configuration.nix
@@ -1,6 +1,5 @@
-{ pkgs, lib, config, ... }:
-let
-in {
+{ pkgs, ... }:
+{
time.timeZone = "America/New_York";
console.keyMap = "us";
diff --git a/users/alice/default.nix b/users/alice/default.nix
index 2125303..b74829f 100644
--- a/users/alice/default.nix
+++ b/users/alice/default.nix
@@ -1,27 +1,8 @@
-{
- pkgs,
- lib,
- config,
-}: let
- pubKeys = import ./keys/default.nix;
-in {
- isNormalUser = true;
- description = "AmethystAndroid";
- uid = 1000;
- extraGroups = [
- "wheel"
- "media"
- (lib.mkIf config.networking.networkmanager.enable "networkmanager")
- (lib.mkIf config.programs.adb.enable "adbusers")
- (lib.mkIf config.programs.wireshark.enable "wireshark")
- (lib.mkIf config.programs.virtualisation.docker.enable "docker")
- "libvirtd"
- "dialout"
- "plugdev"
- "uaccess"
- ];
- shell = pkgs.fish;
- openssh.authorizedKeys.keys = [
- (lib.mkIf (pubKeys ? ${config.networking.hostName}) pubKeys.${config.networking.hostName})
- ];
+{ pkgs, lib, config }:
+import ../default.nix {
+ inherit pkgs lib config;
+ userName = "AmethystAndroid";
+ pubKeys = {
+ palatine-hill = "ed25516-AAAAAAA";
+ };
}
\ No newline at end of file
diff --git a/users/alice/keys/default.nix b/users/alice/keys/default.nix
deleted file mode 100644
index 6de9970..0000000
--- a/users/alice/keys/default.nix
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- palatine-hill = "ed25516-AAAAAAA";
-}
\ No newline at end of file
diff --git a/users/default.nix b/users/default.nix
new file mode 100644
index 0000000..d25005c
--- /dev/null
+++ b/users/default.nix
@@ -0,0 +1,21 @@
+{ lib, config, pkgs, userName, pubKeys }:
+{
+ isNormalUser = true;
+ uid = 1000;
+ extraGroups = [
+ "wheel"
+ "media"
+ (lib.mkIf config.networking.networkmanager.enable "networkmanager")
+ (lib.mkIf config.programs.adb.enable "adbusers")
+ (lib.mkIf config.programs.wireshark.enable "wireshark")
+ (lib.mkIf config.programs.virtualisation.docker.enable "docker")
+ "libvirtd"
+ "dialout"
+ "plugdev"
+ "uaccess"
+ ];
+ shell = pkgs.zsh;
+ openssh.authorizedKeys.keys = [
+ (lib.mkIf (pubKeys ? ${config.networking.hostName}) pubKeys.${config.networking.hostName})
+ ];
+}
\ No newline at end of file
diff --git a/users/user.nix b/users/user.nix
deleted file mode 100644
index e69de29..0000000