2024-01-09 08:34:03 +03:00
|
|
|
{ lib, abs, pkgs, ... }@inputs:
|
|
|
|
|
|
|
|
let
|
|
|
|
sqlite = import (abs "lib/sqlite.nix") inputs;
|
|
|
|
|
|
|
|
defaultFilesystem = {
|
|
|
|
provider = 0;
|
|
|
|
osconfig = { };
|
|
|
|
s3config = { };
|
|
|
|
gcsconfig = { };
|
|
|
|
azblobconfig = { };
|
|
|
|
cryptconfig = { };
|
|
|
|
sftpconfig = { };
|
|
|
|
httpconfig = { };
|
|
|
|
};
|
|
|
|
|
|
|
|
insertFolder = name: folder: sqlite.insert {
|
|
|
|
into = "folders";
|
|
|
|
value = {
|
|
|
|
name = name;
|
|
|
|
description = folder.description or "";
|
|
|
|
path = folder.path;
|
|
|
|
used_quota_size = "0";
|
|
|
|
used_quota_files = "0";
|
|
|
|
last_quota_update = "0";
|
|
|
|
filesystem = defaultFilesystem;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
insertUser = username: user: sqlite.insert {
|
|
|
|
into = "users";
|
|
|
|
orReplace = true;
|
|
|
|
value = {
|
|
|
|
username = username;
|
|
|
|
status = "1";
|
|
|
|
expiration_date = "0";
|
|
|
|
description = user.description or "";
|
|
|
|
password = user.password or "";
|
|
|
|
public_keys = builtins.toJSON (user.publicKeys or [ ]);
|
|
|
|
home_dir = user.home or "/tmp/${username}";
|
|
|
|
uid = "0";
|
|
|
|
gid = "0";
|
|
|
|
max_sessions = "0";
|
|
|
|
quota_size = "0";
|
|
|
|
quota_files = "0";
|
|
|
|
last_login = "0";
|
|
|
|
permissions."/" = [ "*" ];
|
|
|
|
used_quota_size = "0";
|
|
|
|
used_quota_files = "0";
|
|
|
|
last_quota_update = "0";
|
|
|
|
upload_bandwidth = "0";
|
|
|
|
download_bandwidth = "0";
|
|
|
|
filters = {
|
|
|
|
hooks = {
|
|
|
|
external_auth_disabled = false;
|
|
|
|
pre_login_disabled = false;
|
|
|
|
check_password_disabled = false;
|
|
|
|
};
|
|
|
|
totp_config = {
|
|
|
|
secret = { };
|
|
|
|
};
|
|
|
|
};
|
|
|
|
filesystem = defaultFilesystem;
|
|
|
|
additional_info = "";
|
|
|
|
created_at = "0";
|
|
|
|
updated_at = "0";
|
|
|
|
email = "";
|
|
|
|
upload_data_transfer = "0";
|
|
|
|
download_data_transfer = "0";
|
|
|
|
total_data_transfer = "0";
|
|
|
|
used_upload_data_transfer = "0";
|
|
|
|
used_download_data_transfer = "0";
|
|
|
|
deleted_at = "0";
|
|
|
|
first_download = "0";
|
|
|
|
first_upload = "0";
|
|
|
|
role_id = null;
|
|
|
|
last_password_change = "0";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
insertUserFolder = userFolder: sqlite.insert {
|
|
|
|
into = "users_folders_mapping";
|
|
|
|
orReplace = true;
|
|
|
|
value = {
|
|
|
|
user_id = sqlite.sql (
|
|
|
|
sqlite.select {
|
|
|
|
from = "users";
|
|
|
|
columns = [ "id" ];
|
|
|
|
where.username = userFolder.username;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
folder_id = sqlite.sql (
|
|
|
|
sqlite.select {
|
|
|
|
from = "folders";
|
|
|
|
columns = [ "id" ];
|
|
|
|
where.name = userFolder.folder;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
virtual_path = userFolder.path or "/${userFolder.folder}";
|
|
|
|
quota_size = -1;
|
|
|
|
quota_files = -1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
insertAdmin = username: admin: sqlite.insert {
|
|
|
|
into = "admins";
|
|
|
|
value = {
|
|
|
|
username = username;
|
|
|
|
description = admin.description or "";
|
|
|
|
password = admin.password;
|
|
|
|
email = admin.email or "";
|
|
|
|
status = "1";
|
|
|
|
permissions = "[\"*\"]";
|
|
|
|
filters = {
|
|
|
|
totp_config = { secret = { }; };
|
|
|
|
preferences = { };
|
|
|
|
};
|
|
|
|
additional_info = "";
|
|
|
|
last_login = "0";
|
|
|
|
created_at = "0";
|
|
|
|
updated_at = "0";
|
|
|
|
role_id = null;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
in
|
|
|
|
{
|
|
|
|
setup =
|
|
|
|
{
|
|
|
|
# paths to private keys for sftp server
|
|
|
|
# all required with default config, but can be omitted if you change the config to not require them
|
|
|
|
# { ecdsa?: string, ed25519?: string, rsa?: string }
|
|
|
|
keys ? { }
|
|
|
|
# https://github.com/drakkan/sftpgo/blob/main/docs/full-configuration.md
|
|
|
|
, config ? null
|
|
|
|
# username => {
|
|
|
|
# home?: string, # defaults to /tmp/username
|
|
|
|
# description?: string,
|
2024-01-09 10:06:17 +03:00
|
|
|
# password?: string, # bcrypt hashed
|
2024-01-09 08:34:03 +03:00
|
|
|
# publicKeys?: string[]
|
|
|
|
# permisisons?: Record<string, string>, e.g,
|
|
|
|
# }
|
|
|
|
, users ? { }
|
|
|
|
# name => { description?: string, path: string }
|
|
|
|
, folders ? { }
|
|
|
|
# username => {
|
2024-01-09 10:06:17 +03:00
|
|
|
# password: string, # bcrypt hashed
|
2024-01-09 08:34:03 +03:00
|
|
|
# description?: string,
|
|
|
|
# email?: string,
|
|
|
|
# }
|
|
|
|
, admins ? {
|
2024-01-09 10:06:17 +03:00
|
|
|
# bcrypt hash of password "admin"
|
2024-01-09 08:34:03 +03:00
|
|
|
admin.password = "$2a$10$7QZqmQNWwfbgIwc5Jskkgea7s8dffkbwPUW30MEShpDpZWxMVrFaa";
|
|
|
|
}
|
|
|
|
# array of {
|
|
|
|
# username: string,
|
|
|
|
# folder: string, # name of folder
|
|
|
|
# path?: string # virtual path, e.g. /Folder (defaults to /${folder})
|
|
|
|
# }
|
|
|
|
, usersFolders ? null
|
|
|
|
, package ? pkgs.sftpgo
|
|
|
|
, sqlitePackage ? pkgs.sqlite
|
|
|
|
, serviceName ? "sftpgo"
|
|
|
|
}:
|
|
|
|
let
|
|
|
|
configFile = if config != null then pkgs.writeText "sftpgo.json" (builtins.toJSON config) else null;
|
|
|
|
|
|
|
|
sqliteStatements = [ ] ++
|
|
|
|
lib.optionals (users != null) (lib.attrsets.mapAttrsToList insertUser users) ++
|
|
|
|
lib.optionals (folders != null) (lib.attrsets.mapAttrsToList insertFolder folders) ++
|
|
|
|
lib.optionals (admins != null) (lib.attrsets.mapAttrsToList insertAdmin admins) ++
|
|
|
|
lib.optionals (usersFolders != null) (builtins.map insertUserFolder usersFolders);
|
|
|
|
sqliteScript = pkgs.writeText "sftpgo-init.sql" (sqlite.script sqliteStatements);
|
|
|
|
in
|
|
|
|
{
|
|
|
|
systemd.services.${serviceName} = {
|
|
|
|
description = "${serviceName} Daemon";
|
|
|
|
after = [ "network.target" ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
path = [ package sqlitePackage ];
|
|
|
|
serviceConfig.PrivateTmp = true;
|
|
|
|
script = ''
|
|
|
|
sftpgo initprovider
|
|
|
|
sqlite3 sftpgo.db < ${sqliteScript}
|
|
|
|
|
|
|
|
${lib.optionalString (keys ? ecdsa) "cp ${keys.ecdsa} id_ecdsa"}
|
|
|
|
${lib.optionalString (keys ? ed25519) "cp ${keys.ed25519} id_ed25519"}
|
|
|
|
${lib.optionalString (keys ? rsa) "cp ${keys.rsa} id_rsa"}
|
|
|
|
${lib.optionalString (configFile != null) "cp ${configFile} sftpgo.json"}
|
|
|
|
|
|
|
|
sftpgo serve
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|