Files
nix-config/hosts/idols-aquamarine/sftpgo.nix
T
ryan4yin | 二花 21d64e7add security: hardening pass 1 (AppArmor, firewall default, loopback metrics, k3s perms, SSH X11) (#266)
* security: make firewall secure-by-default, disable explicitly on servers

Flip the base firewall default to ON so new hosts are protected by default. Servers keep the firewall off (trusted internal LAN, WAN protected at the router) via explicit overrides in modules/nixos/server/{server,server-aarch64}.nix. Behavior-preserving for all 18 current hosts; adds a security-firewall eval test guarding the per-host state.

* test: fix security-firewall eval test to scalar per-host values

* security: enable AppArmor (complain) on all Linux hosts

* security: bind aquamarine metrics exporters to loopback

* security: restrict k3s kubeconfig file mode to 600

* security: disable SSH X11 forwarding on servers, keep on desktops

* security: add conservative systemd hardening to aquamarine services

* docs(apparmor): correct FHS-alias comment (nixpkgs has no broad FHS layer)

nixpkgs only creates /run/current-system, /usr/bin/env and /bin/sh; it does not
provide a broad FHS->store alias tree, so FHS-oriented abstractions are incomplete
on NixOS. They are safe only because the profiles run in complain mode.

* fix(aquamarine): scrape same-host exporters over loopback

The v2ray/postgres/sftpgo exporters were bound to 127.0.0.1 but VictoriaMetrics
scraped them via the host's routable IP, so those scrapes refused connections.
Point the three same-host scrape targets at 127.0.0.1 (VM runs on the same host).
node-exporter keeps the host IP since it binds 0.0.0.0.

* Revert "security: add conservative systemd hardening to aquamarine services"

This reverts commit f9cf99dadb.
2026-08-27 00:13:01 +08:00

120 lines
4.2 KiB
Nix

{ config, lib, ... }:
let
user = "sftpgo";
dataDir = "/data/apps/sftpgo";
in
{
# Read SFTPGO_DEFAULT_ADMIN_USERNAME and SFTPGO_DEFAULT_ADMIN_PASSWORD from a file
systemd.services.sftpgo.serviceConfig = {
EnvironmentFile = config.age.secrets."sftpgo.env".path;
};
# Join the shared fileshare group (defined globally in user-group.nix) so
# sftpgo can read/write files created by transmission, and vice versa.
users.users.${user}.extraGroups = [ "fileshare" ];
# Create Directories
# https://www.freedesktop.org/software/systemd/man/latest/tmpfiles.d.html#Type
# Mode 2775: setgid ensures new files/dirs inherit the 'fileshare' group
# regardless of the creating process's primary group.
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${user} ${user} -"
];
services.sftpgo = {
enable = true;
inherit user dataDir;
extraReadWriteDirs = [
"/data/fileshare"
];
extraArgs = [
"--log-level"
"info"
];
# https://github.com/drakkan/sftpgo/blob/2.5.x/docs/full-configuration.md
settings = {
common = {
# Auto-blocking policy for SFTPGo and thus helps to prevent DoS (Denial of Service) and brute force password guessing.
defender = {
enable = true;
};
};
# Where to store stfpgo's data
data_provider = {
driver = "sqlite";
name = "sftpgo.db";
password_hashing = {
algo = "argon2id";
# options for argon2id hashing algorithm.
# The memory and iterations parameters control the computational cost of hashing the password.
argon2_options = {
memory = 65536; # KiB
iterations = 2; # The number of iterations over the memory.
parallelism = 2; # The number of threads (or lanes) used by the algorithm.
};
};
password_validation = {
# What Entropy Value Should I Use?
# somewhere in the 50-70 range seems "reasonable".
# https://github.com/wagslane/go-password-validator#what-entropy-value-should-i-use
admins.min_entropy = 60;
users.min_entropy = 60;
};
# Cache passwords in memory to avoid hashing the same password multiple times(it costs).
password_caching = true;
# create the default admin user via environment variables
# SFTPGO_DEFAULT_ADMIN_USERNAME and SFTPGO_DEFAULT_ADMIN_PASSWORD
create_default_admin = true;
};
# WebDAV is a popular protocol for file sharing, better than CIFS/SMB, NFS, etc.
# it's save to use WebDAV over HTTPS on public networks.
webdavd.bindings = [
{
address = "127.0.0.1";
port = 3303;
}
];
# HTTP Server provides a simple web interface to manage the server.
httpd.bindings = [
{
address = "127.0.0.1";
enable_https = false;
port = 3302;
client_ip_proxy_header = "X-Forwarded-For";
# a basic built-in web interface that allows you to manage users,
# virtual folders, admins and connections.
# url: http://127.0.0.1:8080/web/admin
enable_web_admin = true;
# A basic front-end web interface for your users.
# It allows end-users to browse and manage their files and change their credentials.
enable_web_client = true;
enable_rest_api = true;
}
];
# prometheus metrics
telemetry = {
bind_port = 10000;
# loopback only: scraped by VictoriaMetrics on the same host
bind_address = "127.0.0.1";
# auth_user_file = "";
};
# multi-factor authentication settings
mfa.totp = [
{
# Unique configuration name, not visible to the authentication apps.
# Should not to be changed after the first user has been created.
name = "SFTPGo";
# Name of the issuing Organization/Company
issuer = "SFTPGo";
# Algorithm to use for HMAC
# Currently Google Authenticator app on iPhone seems to only support sha1
algo = "sha1";
}
];
# SMTP configuration enables SFTPGo email sending capabilities
# smtp = {};
};
};
}