summaryrefslogtreecommitdiff
path: root/os/kay/modules/services
diff options
context:
space:
mode:
Diffstat (limited to 'os/kay/modules/services')
-rw-r--r--os/kay/modules/services/alina.nix30
-rw-r--r--os/kay/modules/services/cgit.nix34
-rw-r--r--os/kay/modules/services/github-runner.nix41
-rw-r--r--os/kay/modules/services/home-assistant.nix47
-rw-r--r--os/kay/modules/services/immich.nix23
-rw-r--r--os/kay/modules/services/iperf3.nix10
-rw-r--r--os/kay/modules/services/mail.nix173
-rw-r--r--os/kay/modules/services/matrix/default.nix22
-rw-r--r--os/kay/modules/services/matrix/dendrite.nix109
-rw-r--r--os/kay/modules/services/matrix/matrix-sliding-sync.nix123
-rw-r--r--os/kay/modules/services/minio.nix36
-rw-r--r--os/kay/modules/services/nix-cache.nix12
-rw-r--r--os/kay/modules/services/sftp.nix59
13 files changed, 719 insertions, 0 deletions
diff --git a/os/kay/modules/services/alina.nix b/os/kay/modules/services/alina.nix
new file mode 100644
index 0000000..c567953
--- /dev/null
+++ b/os/kay/modules/services/alina.nix
@@ -0,0 +1,30 @@
+{ config, alina, ... }:
+let
+ domain = "alinafs.com";
+in
+{
+ imports = [ alina.nixosModules.alina ];
+
+ sops.secrets."misc/alina" = { };
+
+ services.postgresql = {
+ ensureDatabases = [ "alina" ];
+ ensureUsers = [
+ {
+ name = "alina";
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
+ services.alina = {
+ enable = true;
+ port = 8006;
+ environmentFile = config.sops.secrets."misc/alina".path;
+ settings.server = {
+ data = "/hdd/alina";
+ file_size_limit = 1024 * 1024 * 1024; # 1GB
+ public_url = "https://${domain}";
+ };
+ };
+}
diff --git a/os/kay/modules/services/cgit.nix b/os/kay/modules/services/cgit.nix
new file mode 100644
index 0000000..254cc80
--- /dev/null
+++ b/os/kay/modules/services/cgit.nix
@@ -0,0 +1,34 @@
+{ config, pkgs, ... }:
+
+let
+ domain = config.global.userdata.domain;
+ user = config.global.userdata.name;
+in
+{
+ users.users.${user}.packages = with pkgs; [ git ];
+ environment.systemPackages = with pkgs; [
+ luajitPackages.luaossl
+ lua52Packages.luaossl
+ ];
+
+ services.cgit."git.${domain}" = {
+ enable = true;
+ nginx.virtualHost = "git.${domain}";
+ scanPath = "/var/lib/git";
+ settings = {
+ project-list = "/var/lib/git/project.list";
+ remove-suffix = 1;
+ enable-commit-graph = 1;
+ root-title = "${user}'s git repository";
+ root-desc = "how do i learn github anon";
+ source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py";
+ about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh";
+ readme = ":README.md";
+ footer = "";
+ enable-blame = 1;
+ clone-url = "https://git.${domain}/$CGIT_REPO_URL";
+ enable-log-filecount = 1;
+ enable-log-linecount = 1;
+ };
+ };
+}
diff --git a/os/kay/modules/services/github-runner.nix b/os/kay/modules/services/github-runner.nix
new file mode 100644
index 0000000..dd4d48d
--- /dev/null
+++ b/os/kay/modules/services/github-runner.nix
@@ -0,0 +1,41 @@
+{ config, ... }:
+let
+ repo = "nocodb/nocodb";
+ nocodbRunnerUser = "nocodbrunner";
+ user = config.global.userdata.name;
+in
+{
+ sops.secrets = {
+ "github-runner/nocodb-registration-token" = { };
+ "github-runner/age-master-key" = { };
+ };
+
+ # required by github:nocodb/nocodb docker builds
+ virtualisation.docker.enable = true;
+ users.groups.${nocodbRunnerUser} = { };
+ users.extraGroups.docker.members = [
+ user
+ nocodbRunnerUser
+ ];
+ users.users.nocodbrunner = {
+ name = nocodbRunnerUser;
+ group = nocodbRunnerUser;
+ isSystemUser = true;
+ };
+ services.github-runners.kay = {
+ user = nocodbRunnerUser;
+ group = nocodbRunnerUser;
+ enable = true;
+ noDefaultLabels = true;
+ extraLabels = [ "nix" ];
+ tokenFile = config.sops.secrets."github-runner/nocodb-registration-token".path;
+ url = "https://github.com/${repo}";
+ };
+
+ systemd.services."github-runner-kay" = {
+ environment.SOPS_AGE_KEY_FILE = "%d/age-master-key";
+ serviceConfig.LoadCredential = "age-master-key:${
+ config.sops.secrets."github-runner/age-master-key".path
+ }";
+ };
+}
diff --git a/os/kay/modules/services/home-assistant.nix b/os/kay/modules/services/home-assistant.nix
new file mode 100644
index 0000000..65807f7
--- /dev/null
+++ b/os/kay/modules/services/home-assistant.nix
@@ -0,0 +1,47 @@
+{ pkgs, ... }:
+{
+ services.postgresql = {
+ enable = true;
+
+ ensureDatabases = [ "hass" ];
+ ensureUsers = [
+ {
+ name = "hass";
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
+ services.home-assistant = {
+ enable = true;
+ package =
+ (pkgs.home-assistant.override {
+ extraPackages = py: with py; [ psycopg2 ];
+ }).overrideAttrs
+ (oldAttrs: {
+ doInstallCheck = false;
+ });
+
+ extraComponents = [
+ "analytics"
+ "google_translate"
+ "met"
+ "radio_browser"
+ "shopping_list"
+ "tplink"
+ "tuya"
+ "utility_meter"
+ ];
+
+ config = {
+ default_config = { };
+
+ recorder.db_url = "postgresql://@/hass";
+ http = {
+ server_host = "127.0.0.1";
+ trusted_proxies = [ "127.0.0.1" ];
+ use_x_forwarded_for = true;
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/services/immich.nix b/os/kay/modules/services/immich.nix
new file mode 100644
index 0000000..5e5eaf4
--- /dev/null
+++ b/os/kay/modules/services/immich.nix
@@ -0,0 +1,23 @@
+{ config, ... }:
+let
+ domain = config.global.userdata.domain;
+ mediaLocation = "/hdd/immich";
+in
+{
+ services.immich = {
+ enable = true;
+ inherit mediaLocation;
+ settings.server.externalDomain = "https://immich.${domain}";
+ };
+
+ systemd.tmpfiles.settings.immich.${mediaLocation}.d = {
+ group = config.services.immich.group;
+ user = config.services.immich.user;
+ mode = "0755";
+ };
+
+ users.users.immich.extraGroups = [
+ "video"
+ "render"
+ ];
+}
diff --git a/os/kay/modules/services/iperf3.nix b/os/kay/modules/services/iperf3.nix
new file mode 100644
index 0000000..2c8afef
--- /dev/null
+++ b/os/kay/modules/services/iperf3.nix
@@ -0,0 +1,10 @@
+{ ... }:
+
+{
+ services.iperf3 = {
+ enable = true;
+
+ bind = "192.168.43.1";
+ openFirewall = true;
+ };
+}
diff --git a/os/kay/modules/services/mail.nix b/os/kay/modules/services/mail.nix
new file mode 100644
index 0000000..685461f
--- /dev/null
+++ b/os/kay/modules/services/mail.nix
@@ -0,0 +1,173 @@
+{ config, pkgs, ... }:
+let
+ ipv6 = "2001:470:ee65::1337";
+ domain = config.global.userdata.domain;
+ username = config.global.userdata.name;
+ email = [
+ "${username}@${domain}"
+
+ # used by github automation
+ # https://github.com/nocodb/nocodb/blob/32826d4b24e9285b898bb3547fdf550f81c930bb/nix/bumper/bumper.sh#L5
+ "auto@${domain}"
+ # used by mail.sinanmohd.com
+ "postmaster@${domain}"
+ # used by ns1.sinanmohd.com
+ "hostmaster@${domain}"
+ ];
+
+ credentials_directory = "/run/credentials/stalwart-mail.service";
+in
+{
+ security.acme.certs.${domain}.postRun = "systemctl restart stalwart-mail.service";
+ sops.secrets = {
+ "mail.${domain}/dkim_rsa" = { };
+ "mail.${domain}/dkim_ed25519" = { };
+ "mail.${domain}/password" = { };
+ };
+
+ systemd.services.stalwart-mail.serviceConfig.LoadCredential = [
+ "password:${config.sops.secrets."mail.${domain}/password".path}"
+
+ "dkim_rsa:${config.sops.secrets."mail.${domain}/dkim_rsa".path}"
+ "dkim_ed25519:${config.sops.secrets."mail.${domain}/dkim_ed25519".path}"
+
+ "cert:${config.security.acme.certs.${domain}.directory}/fullchain.pem"
+ "key:${config.security.acme.certs.${domain}.directory}/key.pem"
+ ];
+
+ services.postgresql = {
+ ensureDatabases = [ "stalwart" ];
+ ensureUsers = [
+ {
+ name = "stalwart";
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
+ services.stalwart-mail = {
+ enable = true;
+ openFirewall = true;
+
+ settings = {
+ queue.outbound = {
+ ip-strategy = "ipv6_then_ipv4";
+ source-ip.v6 = "['${ipv6}']";
+ tls.starttls = "optional";
+ };
+ http.url = "'https://stalwart.${domain}'";
+
+ server = {
+ hostname = "mail.${domain}";
+ listener = {
+ smtp = {
+ bind = [
+ "[${ipv6}]:25"
+ "0.0.0.0:25"
+ ];
+ protocol = "smtp";
+ };
+ submission = {
+ bind = "[::]:587";
+ protocol = "smtp";
+ };
+ submissions = {
+ bind = "[::]:465";
+ protocol = "smtp";
+ tls.implicit = true;
+ };
+ imaptls = {
+ bind = "[::]:993";
+ protocol = "imap";
+ tls.implicit = true;
+ };
+ http = {
+ bind = "[::]:8085";
+ protocol = "http";
+ };
+ };
+ };
+
+ signature = {
+ rsa = {
+ private-key = "%{file:${credentials_directory}/dkim_rsa}%";
+ inherit domain;
+ selector = "rsa";
+ headers = [
+ "From"
+ "To"
+ "Date"
+ "Subject"
+ "Message-ID"
+ ];
+ algorithm = "rsa-sha-256";
+ canonicalization = "simple/simple";
+
+ set-body-length = true;
+ expire = "2d";
+ report = true;
+ };
+ ed25519 = {
+ private-key = "%{file:${credentials_directory}/dkim_ed25519}%";
+ inherit domain;
+ selector = "ed25519";
+ headers = [
+ "From"
+ "To"
+ "Date"
+ "Subject"
+ "Message-ID"
+ ];
+ algorithm = "ed25519-sha256";
+ canonicalization = "simple/simple";
+
+ set-body-length = true;
+ expire = "2d";
+ report = true;
+ };
+ };
+
+ certificate."default" = {
+ cert = "%{file:${credentials_directory}/cert}%";
+ private-key = "%{file:${credentials_directory}/key}%";
+ };
+
+ storage = {
+ data = "postgresql";
+ fts = "postgresql";
+ blob = "postgresql";
+ lookup = "postgresql";
+ directory = "memory";
+ };
+ store.postgresql = {
+ type = "postgresql";
+ host = "localhost";
+ database = "stalwart";
+ user = "stalwart";
+ timeout = "15s";
+ tls.enable = false;
+ pool.max-connections = 10;
+ };
+
+ directory."memory" = {
+ type = "memory";
+
+ principals = [
+ {
+ class = "admin";
+ name = "${username}@${domain}";
+ secret = "%{file:${credentials_directory}/password}%";
+ inherit email;
+ }
+ {
+ # for mta-sts & dmarc reports
+ class = "individual";
+ name = "reports@${domain}";
+ secret = "%{file:${credentials_directory}/password}%";
+ email = [ "reports@${domain}" ];
+ }
+ ];
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/services/matrix/default.nix b/os/kay/modules/services/matrix/default.nix
new file mode 100644
index 0000000..1b9564d
--- /dev/null
+++ b/os/kay/modules/services/matrix/default.nix
@@ -0,0 +1,22 @@
+{ config, ... }:
+let
+ domain = config.global.userdata.domain;
+in
+{
+ imports = [
+ ./dendrite.nix
+ ./matrix-sliding-sync.nix
+ ];
+
+ sops.secrets."matrix-${domain}/sliding_sync" = { };
+
+ services.matrix-sliding-sync-dirty = {
+ enable = true;
+ environmentFile = config.sops.secrets."matrix-${domain}/sliding_sync".path;
+
+ settings = {
+ SYNCV3_LOG_LEVEL = "warn";
+ SYNCV3_SERVER = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
+ };
+ };
+}
diff --git a/os/kay/modules/services/matrix/dendrite.nix b/os/kay/modules/services/matrix/dendrite.nix
new file mode 100644
index 0000000..e66c5a5
--- /dev/null
+++ b/os/kay/modules/services/matrix/dendrite.nix
@@ -0,0 +1,109 @@
+{ config, ... }:
+
+let
+ domain = config.global.userdata.domain;
+ database = {
+ connection_string = "postgres:///dendrite?host=/run/postgresql";
+ max_open_conns = 90;
+ max_idle_conns = 5;
+ conn_max_lifetime = -1;
+ };
+in
+{
+ sops.secrets."matrix-${domain}/key" = { };
+ systemd.services.dendrite.after = [ "postgresql.service" ];
+
+ services = {
+ postgresql = {
+ ensureDatabases = [ "dendrite" ];
+ ensureUsers = [
+ {
+ name = "dendrite";
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
+ dendrite = {
+ enable = true;
+ loadCredential = [
+ "private_key:${config.sops.secrets."matrix-${domain}/key".path}"
+ ];
+
+ settings = {
+ sync_api.search = {
+ enabled = true;
+ index_path = "/var/lib/dendrite/searchindex";
+ };
+ global = {
+ metrics.enabled = true;
+ server_name = domain;
+ private_key = "$CREDENTIALS_DIRECTORY/private_key";
+ trusted_third_party_id_servers = [
+ "matrix.org"
+ "vector.im"
+ ];
+ inherit database;
+ };
+ logging = [
+ {
+ type = "std";
+ level = "warn";
+ }
+ ];
+ mscs = {
+ inherit database;
+ mscs = [ "msc2836" ];
+ };
+ sync_api = {
+ inherit database;
+ real_ip_header = "X-Real-IP";
+ };
+ media_api = {
+ inherit database;
+ dynamic_thumbnails = true;
+ max_file_size_bytes = 12800000000;
+ };
+ federation_api = {
+ inherit database;
+ send_max_retries = 8;
+ key_perspectives = [
+ {
+ server_name = "matrix.org";
+ keys = [
+ {
+ key_id = "ed25519:auto";
+ public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
+ }
+ {
+ key_id = "ed25519:a_RXGa";
+ public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
+ }
+ ];
+ }
+ ];
+ };
+
+ app_service_api = {
+ inherit database;
+ };
+ room_server = {
+ inherit database;
+ };
+ push_server = {
+ inherit database;
+ };
+ relay_api = {
+ inherit database;
+ };
+ key_server = {
+ inherit database;
+ };
+ user_api = {
+ account_database = database;
+ device_database = database;
+ };
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/services/matrix/matrix-sliding-sync.nix b/os/kay/modules/services/matrix/matrix-sliding-sync.nix
new file mode 100644
index 0000000..63d95ad
--- /dev/null
+++ b/os/kay/modules/services/matrix/matrix-sliding-sync.nix
@@ -0,0 +1,123 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+
+let
+ cfg = config.services.matrix-sliding-sync-dirty;
+ matrix-sliding-sync = pkgs.callPackage ../../pkgs/matrix-sliding-sync.nix { };
+in
+{
+ imports = [
+ (lib.mkRenamedOptionModule
+ [ "services" "matrix-synapse" "sliding-sync" ]
+ [ "services" "matrix-sliding-sync" ]
+ )
+ ];
+
+ options.services.matrix-sliding-sync-dirty = {
+ enable = lib.mkEnableOption "sliding sync";
+
+ settings = lib.mkOption {
+ type = lib.types.submodule {
+ freeformType = with lib.types; attrsOf str;
+ options = {
+ SYNCV3_SERVER = lib.mkOption {
+ type = lib.types.str;
+ description = ''
+ The destination homeserver to talk to not including `/_matrix/` e.g `https://matrix.example.org`.
+ '';
+ };
+
+ SYNCV3_DB = lib.mkOption {
+ type = lib.types.str;
+ default = "postgresql:///matrix-sliding-sync?host=/run/postgresql";
+ description = ''
+ The postgres connection string.
+ Refer to <https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING>.
+ '';
+ };
+
+ SYNCV3_BINDADDR = lib.mkOption {
+ type = lib.types.str;
+ default = "127.0.0.1:8009";
+ example = "[::]:8008";
+ description = "The interface and port or path (for unix socket) to listen on.";
+ };
+
+ SYNCV3_LOG_LEVEL = lib.mkOption {
+ type = lib.types.enum [
+ "trace"
+ "debug"
+ "info"
+ "warn"
+ "error"
+ "fatal"
+ ];
+ default = "info";
+ description = "The level of verbosity for messages logged.";
+ };
+ };
+ };
+ default = { };
+ description = ''
+ Freeform environment variables passed to the sliding sync proxy.
+ Refer to <https://github.com/matrix-org/sliding-sync#setup> for all supported values.
+ '';
+ };
+
+ createDatabase = lib.mkOption {
+ type = lib.types.bool;
+ default = true;
+ description = ''
+ Whether to enable and configure `services.postgres` to ensure that the database user `matrix-sliding-sync`
+ and the database `matrix-sliding-sync` exist.
+ '';
+ };
+
+ environmentFile = lib.mkOption {
+ type = lib.types.str;
+ description = ''
+ Environment file as defined in {manpage}`systemd.exec(5)`.
+
+ This must contain the {env}`SYNCV3_SECRET` variable which should
+ be generated with {command}`openssl rand -hex 32`.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.postgresql = lib.optionalAttrs cfg.createDatabase {
+ enable = true;
+ ensureDatabases = [ "matrix-sliding-sync" ];
+ ensureUsers = [
+ {
+ name = "matrix-sliding-sync";
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
+ systemd.services.matrix-sliding-sync = rec {
+ after =
+ lib.optional cfg.createDatabase "postgresql.service"
+ ++ lib.optional config.services.dendrite.enable "dendrite.service"
+ ++ lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit;
+ wants = after;
+ wantedBy = [ "multi-user.target" ];
+ environment = cfg.settings;
+ serviceConfig = {
+ DynamicUser = true;
+ EnvironmentFile = cfg.environmentFile;
+ ExecStart = lib.getExe matrix-sliding-sync;
+ StateDirectory = "matrix-sliding-sync";
+ WorkingDirectory = "%S/matrix-sliding-sync";
+ RuntimeDirectory = "matrix-sliding-sync";
+ Restart = "on-failure";
+ RestartSec = "1s";
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/services/minio.nix b/os/kay/modules/services/minio.nix
new file mode 100644
index 0000000..d440e50
--- /dev/null
+++ b/os/kay/modules/services/minio.nix
@@ -0,0 +1,36 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ email = config.global.userdata.email;
+in
+{
+ sops.secrets."misc/default_password" = { };
+ systemd.services.minio.serviceConfig.LoadCredential = [
+ "password:${config.sops.secrets."misc/default_password".path}"
+ ];
+
+ services.minio = {
+ enable = true;
+ consoleAddress = ":9003";
+
+ package = pkgs.stdenv.mkDerivation {
+ name = "minio-with-secrets";
+ dontUnpack = true;
+ buildInputs = with pkgs; [
+ makeWrapper
+ minio
+ ];
+ installPhase = ''
+ mkdir -p $out/bin
+ makeWrapper ${lib.getExe pkgs.minio} $out/bin/minio \
+ --run 'echo "Seting Minio Secrets"' \
+ --set MINIO_ROOT_USER ${email} \
+ --run 'export MINIO_ROOT_PASSWORD="$(cat "$CREDENTIALS_DIRECTORY"/password)"'
+ '';
+ };
+ };
+}
diff --git a/os/kay/modules/services/nix-cache.nix b/os/kay/modules/services/nix-cache.nix
new file mode 100644
index 0000000..9c81b56
--- /dev/null
+++ b/os/kay/modules/services/nix-cache.nix
@@ -0,0 +1,12 @@
+{ config, ... }:
+let
+ keyname = "misc/nixbin.${config.global.userdata.domain}";
+in
+{
+ sops.secrets.${keyname} = { };
+
+ services.nix-serve = {
+ enable = true;
+ secretKeyFile = config.sops.secrets.${keyname}.path;
+ };
+}
diff --git a/os/kay/modules/services/sftp.nix b/os/kay/modules/services/sftp.nix
new file mode 100644
index 0000000..f75abc4
--- /dev/null
+++ b/os/kay/modules/services/sftp.nix
@@ -0,0 +1,59 @@
+{ config, ... }:
+
+let
+ storage = "/hdd/users";
+ user = config.global.userdata.name;
+ pubKeys = config.users.users.${user}.openssh.authorizedKeys.keys;
+in
+{
+ users = {
+ groups."sftp".members = [ ];
+
+ users."sftp" = {
+ group = "sftp";
+ shell = "/run/current-system/sw/bin/nologin";
+ isNormalUser = true;
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFmA1dyV+o9gfoxlbVG0Y+dn3lVqdFs5fMqfxyNc5/Lr sftp@cez"
+ # https://github.com/zhanghai/MaterialFiles
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILxKrIaWRACi0oKfJRv6m3uUWKjKNyd9edbbFR5pAONH sftp@paq"
+ # samsung files only support PEM, hence RSA key
+ # https://r1.community.samsung.com/t5/galaxy-s/unable-to-remotely-connect-to-sftp-server-through-my-files/m-p/16347552/highlight/true#M105871
+ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqe7CcXJw+dhXKUVeuj1iGOcV7KhyiJ55PxhGDXfQdu1YS5gi/pBnOk39pL22+QBFZX0trU/JNHpCMZWyFp/Fz9GBxp2LJERHwkANu0lk0PJ7QZdg79YN5lKpWTo2GpA3gHHC555Rm5V5BknwbZwVXWvGhSR93g/2b6AjcSZn4ZUwFF8soSb2EYsRa7blVbBv2njV2SGI9FezfHBF+N3CNOP7kxk63Pilk9NEUQuvYF1tmF7z/zIXbyLNaLT1MJE8KCbayM7E/WZuonSBqFf3fsmQge0La/LveRehQHb503uHNHzlFHXdMMZQrzOAHHyFQUHhYECvhLNDhGJb1KrjZcEiKmqCMmvHCG4JssRdJB5mq6J0g05ZmMrKt0srIT6lginkHy89AKkqt83xHHvXhZEw40zoGcq2rZD1dPN3toNZL/uGaIK0u1eMxFbuVKK3OjMg2UwzaHX1DDZyJdRes5huG/uXTgN7xamUu/TIBOK+WgibJeNf93i3GbsYezTs= sftp@paq"
+ ]
+ ++ pubKeys;
+ };
+
+ users."nazer" = {
+ group = "sftp";
+ shell = "/run/current-system/sw/bin/nologin";
+ isNormalUser = true;
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICV09w9Ovk9wk4Bhn/06iOn+Ss8lK3AmQAl8+lXHRycu nazu@pc"
+ ];
+ };
+ };
+
+ services.openssh = {
+ # support samsing files
+ settings = {
+ HostKeyAlgorithms = "+ssh-rsa";
+ PubkeyAcceptedAlgorithms = "+ssh-rsa";
+ Macs = [ "hmac-sha2-256" ];
+ };
+
+ # sandboxing
+ extraConfig = ''
+ Match Group sftp
+ # chroot dir should be owned by root
+ # and sub dirs by %u
+ ChrootDirectory ${storage}/%u
+ ForceCommand internal-sftp
+
+ PermitTunnel no
+ AllowAgentForwarding no
+ AllowTcpForwarding no
+ X11Forwarding no
+ '';
+ };
+}