chore(koi): moved sftpgo to a docker container

This commit is contained in:
alina 🌸 2024-09-18 01:04:59 +03:00
parent 26a33620bc
commit e5897c194b
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
8 changed files with 186 additions and 263 deletions

View file

@ -21,8 +21,8 @@
./services/landing
./containers/torrent.nix
./containers/puffer.nix
./containers/vaultwarden.nix
./containers/sftpgo
./containers/verdaccio
./containers/sharkey
./containers/pds

View file

@ -1,210 +0,0 @@
{ abs, lib, config, pkgs, ... }@inputs:
let
containers = import (abs "lib/containers.nix") inputs;
avahi = import (abs "lib/avahi.nix") inputs;
systemd = import (abs "lib/systemd.nix") inputs;
sftpgo = import (abs "services/sftpgo.nix") inputs;
secrets = import (abs "lib/secrets.nix");
sftpKey = secrets.mount config "sftpgo-ed25519";
sambaConfig = {
imports = [
(systemd.mkOneshot {
name = "smb-guest-setup";
# for whatever reason smbd refuses to write unless we set the password
script = "${pkgs.samba}/bin/smbpasswd -a smb-guest -n";
})
];
services.samba = {
enable = true;
openFirewall = true;
securityType = "user";
extraConfig = ''
workgroup = WORKGROUP
server string = puffer
netbios name = puffer
security = user
hosts allow = 10.0.0.0/8
hosts deny = 0.0.0.0/0
guest account = smb-guest
map to guest = bad user
inherit permissions = yes
# Performance
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
read raw = yes
write raw = yes
server signing = no
strict locking = no
min receivefile size = 16384
use sendfile = Yes
aio read size = 16384
aio write size = 16384
# Fruit global config
fruit:aapl = yes
fruit:nfs_aces = no
fruit:copyfile = no
fruit:model = MacSamba
'';
shares =
let
publicShare = {
browseable = "yes";
"read only" = "no";
"guest ok" = "yes";
"create mask" = "2775";
"directory mask" = "2775";
"force user" = "smb-guest";
"force group" = "puffer";
};
in
{
Downloads = {
path = "/mnt/puffer/Downloads";
browseable = "yes";
"read only" = "yes";
"guest ok" = "yes";
};
Public = publicShare // {
path = "/mnt/puffer/Public";
};
# its ok for this to be local-public, since Time Machine
# backups are to be encrypted anyway
# (and also im too lazy to set up users here)
Backups = publicShare // {
path = "/mnt/puffer/Backups";
# whatever this means
"vfs objects" = "catia fruit streams_xattr";
"fruit:time machine" = "yes";
"fruit:time machine max size" = "100G";
};
};
};
};
avahiConfig = avahi.setup {
name = "puffer";
services = [
{ type = "_smb._tcp"; port = 445; }
# cancer stuff for macs to see this disk as a time machine-compatible disk
[
{ type = "_adisk._tcp"; port = 9; }
{ txt-record = "sys=waMa=0,adVF=0x100"; }
{ txt-record = "dk0=adVN=Puffer TimeMachine,adVF=0x82"; }
]
{ type = "_device-info._tcp"; port = 0; txt-record = "model=TimeCapsule8,119"; }
];
};
sftpgoConfig = sftpgo.setup {
package = pkgs.callPackage (abs "packages/sftpgo.nix") {
tags = [ "nogcs" "nos3" "noazblob" "nobolt" "nomysql" "nopgsql" "nometrics" "bundle" ];
};
config = {
sftpd = {
bindings = [
{ port = 22; }
];
host_keys = [ "id_ed25519" ];
};
};
keys.ed25519 = sftpKey.path;
users.guest = {
# bcrypt-hashed 0
password = "$2a$10$IcGdNtx10ycmPRD6lA4c0uNfRXTEchFRzCZEDkngTjzForn6pd0Wa";
};
folders.Public.path = "/mnt/puffer/Public";
folders.Downloads.path = "/mnt/puffer/Downloads";
usersFolders = [
{ username = "guest"; folder = "Public"; }
{ username = "guest"; folder = "Downloads"; }
];
};
container = containers.mkNixosContainer {
name = "puffer";
ip = "10.42.0.5";
private = false;
config = { ... }: {
imports = [
sambaConfig
avahiConfig
sftpgoConfig
];
environment.systemPackages = with pkgs; [
uxplay
];
users.groups.puffer = { };
users.users.smb-guest = {
isNormalUser = true;
description = "Guest account for Samba";
extraGroups = [ "puffer" ];
createHome = false;
shell = pkgs.shadow;
};
systemd.tmpfiles.rules = [
"d /mnt/puffer/Public 0755 smb-guest puffer - -"
"d /mnt/puffer/Backups 0755 smb-guest puffer - -"
];
networking.firewall.allowedTCPPorts = [ 22 7000 7001 7002 ];
networking.firewall.allowedUDPPorts = [ 22 7000 7001 7002 ];
};
mounts = {
"/mnt/puffer" = {
hostPath = "/mnt/puffer";
isReadOnly = false;
};
} // (sftpKey.mounts);
};
in
{
imports = [
(secrets.declare [ "sftpgo-ed25519" ])
container
];
services.nginx.virtualHosts."puffer.stupid.fish" = {
forceSSL = true;
useACMEHost = "stupid.fish";
locations."/public/" = {
extraConfig = ''
alias /mnt/puffer/Public/;
autoindex on;
'';
};
locations."/downloads/" = {
extraConfig = ''
alias /mnt/puffer/Downloads/;
autoindex on;
'';
};
locations."= /" = {
extraConfig = ''
add_header 'Content-Type' 'text/html; charset=utf-8';
return 200 '<html><body><h1>🐡 puffer</h1><a href="/public/">public</a><br><a href="/downloads/">downloads</a></body></html>';
'';
};
};
}

View file

@ -0,0 +1,68 @@
{ pkgs, abs, config, ... }@inputs:
let
secrets = import (abs "lib/secrets.nix");
UID = 1112;
in {
imports = [
(secrets.declare [{
name = "sftpgo-env";
owner = "sftpgo";
}])
./samba.nix
];
users.users.sftpgo = {
isNormalUser = true;
uid = UID;
};
virtualisation.oci-containers.containers.sftpgo = {
image = "drakkan/sftpgo:v2.6.2";
volumes = [
"/srv/sftpgo/data:/srv/sftpgo"
"/srv/sftpgo/config:/var/lib/sftpgo"
"/mnt/puffer:/mnt/puffer"
];
user = builtins.toString UID;
environment = {
SFTPGO_SFTPD__BINDINGS__0__PORT = "22";
SFTPGO_WEBDAVD__BINDINGS__0__PORT = "80";
SFTPGO_WEBDAVD__BINDINGS__0__PROXY_ALLOWED = "172.17.0.1";
SFTPGO_WEBDAVD__BINDINGS__0__CLIENT_IP_PROXY_HEADER = "X-Forwarded-For";
SFTPGO_WEBDAVD__BINDINGS__0__PREFIX = "/dav/";
SFTPGO_HTTPD__BINDINGS__0__PORT = "8080";
SFTPGO_HTTPD__BINDINGS__0__ENABLED_LOGIN_METHODS = "3";
SFTPGO_HTTPD__BINDINGS__0__SECURITY__ENABLED = "true";
SFTPGO_HTTPD__BINDINGS__0__SECURITY__ALLOWED_HOSTS = "puffer.stupid.fish";
SFTPGO_HTTPD__BINDINGS__0__BRANDING__NAME = "puffer";
SFTPGO_HTTPD__BINDINGS__0__BRANDING__SHORT_NAME = "puffer";
SFTPGO_HTTPD__BINDINGS__0__OIDC__REDIRECT_BASE_URL = "https://puffer.stupid.fish/";
SFTPGO_HTTPD__BINDINGS__0__OIDC__USERNAME_FIELD = "preferred_username";
SFTPGO_HTTPD__BINDINGS__0__OIDC__IMPLICIT_ROLES = "true";
};
environmentFiles = [
(secrets.file config "sftpgo-env")
];
};
systemd.tmpfiles.rules = [
"d /srv/sftpgo/data 0700 ${builtins.toString UID} ${builtins.toString UID} -"
"d /srv/sftpgo/config 0700 ${builtins.toString UID} ${builtins.toString UID} -"
];
services.nginx.virtualHosts."puffer.stupid.fish" = {
forceSSL = true;
useACMEHost = "stupid.fish";
locations."/" = {
proxyPass = "http://sftpgo.docker:8080$request_uri";
proxyWebsockets = true;
};
locations."/dav/" = {
proxyPass = "http://sftpgo.docker:80$request_uri";
};
};
}

View file

@ -0,0 +1,116 @@
{ abs, lib, config, pkgs, ... }@inputs:
let
containers = import (abs "lib/containers.nix") inputs;
in
{
imports = [
(containers.mkNixosContainer {
name = "puffer";
ip = "10.42.0.5";
private = false;
config = { ... }: {
users.users.smb-guest.isNormalUser = true;
services.avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
publish = {
enable = true;
userServices = true;
};
extraServiceFiles.puffer = ''
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name>puffer</name>
<service>
<port>445</port>
<type>_smb._tcp</type>
</service>
<service>
<port>9</port>
<type>_adisk._tcp</type>
<txt-record>sys=waMa=0,adVF=0x100</txt-record>
<txt-record>dk0=adVN=Puffer TimeMachine,adVF=0x82</txt-record>
</service>
<service>
<port>0</port>
<type>_device-info._tcp</type>
<txt-record>model=TimeCapsule8,119</txt-record>
</service>
</service-group>
'';
};
services.samba = {
enable = true;
openFirewall = true;
securityType = "user";
extraConfig = ''
workgroup = WORKGROUP
server string = puffer
netbios name = puffer
security = user
guest account = smb-guest
map to guest = bad user
hosts allow = 10.0.0.0/8
hosts deny = 0.0.0.0/0
inherit permissions = yes
# Performance
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
read raw = yes
write raw = yes
server signing = no
strict locking = no
min receivefile size = 16384
use sendfile = Yes
aio read size = 16384
aio write size = 16384
# Fruit global config
fruit:aapl = yes
fruit:nfs_aces = no
fruit:copyfile = no
fruit:model = MacSamba
'';
shares =
let
common = {
browseable = "yes";
"read only" = "yes";
"guest ok" = "yes";
};
in
{
Downloads = common // {
path = "/mnt/puffer/Downloads";
};
Public = common // {
path = "/mnt/puffer/Public";
};
};
};
};
mounts = {
"/mnt/puffer/Downloads" = {
hostPath = "/mnt/puffer/Downloads";
isReadOnly = true;
};
"/mnt/puffer/Public" = {
hostPath = "/mnt/puffer/Public";
isReadOnly = true;
};
};
})
];
}

View file

@ -11,6 +11,7 @@ let
10.42.0.2 very.stupid.fish
10.42.0.8 bnuuy.stupid.fish
10.42.0.2 puffer.stupid.fish
10.42.0.2 puffer-webdav.stupid.fish
'';
package = coredns.override {

View file

@ -1,47 +0,0 @@
{ ... }@inputs:
let
xml = import ./xml.nix;
in
rec {
mkConfig = config:
let
configs = if builtins.isList config then config else [ config ];
data = map
(cfg: {
service-group =
[{ name = cfg.name; }] ++
map (service: { inherit service; }) cfg.services ++
[ cfg.extra or { } ];
})
configs;
in
''
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
${xml.generateXMLInner { obj = data; }}
'';
setup = services:
let
servicesList = if builtins.isList services then services else [ services ];
in
{
services.avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
publish = {
enable = true;
userServices = true;
};
extraServiceFiles = (builtins.listToAttrs (map
(service: {
name = service.name;
value = mkConfig service;
})
servicesList));
};
};
}

View file

@ -1,5 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 sj88Xw 2YLa2A0IPI5OYU1pACLEZmIXse0w3rwthY/0IhUfITE
W3fHzNoxCouKZXeEZpfZTAfIAKIF07rCDvvnNHgF23Y
--- dIuhxlxaabb+kOpULhF3wcj6CaDpjnLCdog9dTnsWyo
%Å0ÕÛE~G öZ^UFR”ji©w/ÖÄCM~þv©«AŠdá>[h´ëA ÁÊÆãÊ¿œV>D>[m?€y£CZ©Ù^yĹ˜TP§“Ó<ÖDL¡Î£âFÞ©³Ld<4C>éÏ j1(¸(êõ7ë-î§ <0A>}“°JQ4¦EÝÍ ›î%'ìªí/

BIN
secrets/sftpgo-env.age Normal file

Binary file not shown.