Files
sp-config/configuration.nix

252 lines
6.8 KiB
Nix
Raw Normal View History

2025-06-18 19:53:44 +03:00
{
config,
pkgs,
lib,
2025-05-20 15:31:35 +03:00
modulesPath,
2025-06-18 19:53:44 +03:00
...
}:
2024-05-30 04:09:20 +04:00
let
redis-sp-api-srv-name = "sp-api";
sp-print-api-token = pkgs.writeShellApplication {
name = "sp-print-api-token";
runtimeInputs = with pkgs; [ redis ];
text = ''
hash_token="$(redis-cli -s /run/redis-${redis-sp-api-srv-name}/redis.sock keys "token_repo:tokens:*" | head -n 1)"
hash_token="''${hash_token#"token_repo:tokens:"}"
token="$(redis-cli -s /run/redis-${redis-sp-api-srv-name}/redis.sock HGETALL "token_repo:tokens:$hash_token")"
token="$(echo "$token" | sed -n '2p')"
echo "$token"
'';
};
2024-12-18 15:40:15 +03:00
# TODO: We need this in the API's environmet, not here.
sp-fetch-remote-module = pkgs.writeShellApplication {
name = "sp-fetch-remote-module";
runtimeInputs = [ config.nix.package.out ];
text = ''
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <URL>"
exit 1
fi
URL="$1"
2024-12-24 17:39:34 +03:00
nix eval --file /etc/sp-fetch-remote-module.nix --raw --apply "f: f { flakeURL = \"$URL\"; }" | jq .
2024-12-18 15:40:15 +03:00
'';
};
2024-05-30 04:09:20 +04:00
in
2021-11-15 13:02:05 +03:00
{
imports = [
./selfprivacy-module.nix
./auth/auth-module.nix
./volumes.nix
2021-11-15 13:02:05 +03:00
./users.nix
./letsencrypt/acme.nix
./letsencrypt/resolve.nix
./webserver/nginx.nix
./webserver/memcached.nix
2024-12-22 13:19:10 +03:00
./postgresql/postgresql.nix
# ./resources/limits.nix
2025-05-20 15:31:35 +03:00
"${modulesPath}/profiles/hardened.nix"
2021-11-15 13:02:05 +03:00
];
2024-12-18 15:40:15 +03:00
environment.etc."sp-fetch-remote-module.nix" = {
text = ''
{ flakeURL }: let
sp-module = builtins.getFlake flakeURL;
pkgs = import ${pkgs.path} {};
in (import ${./lib/meta.nix}) { inherit pkgs sp-module; }
'';
};
2023-11-21 01:23:28 +04:00
fileSystems."/".options = [ "noatime" ];
services.selfprivacy-api.enable = true;
services.redis.package = pkgs.valkey;
2024-05-30 04:09:20 +04:00
services.redis.servers.${redis-sp-api-srv-name} = {
enable = true;
save = [
[
30
1
]
[
10
10
]
];
port = 0;
settings = {
notify-keyspace-events = "KEA";
};
};
2025-06-18 19:53:44 +03:00
services.do-agent.enable =
if config.selfprivacy.server.provider == "DIGITALOCEAN" then true else false;
nix.package = pkgs.selfprivacy_nix_2_26;
2023-12-18 18:13:57 +04:00
boot.tmp.cleanOnBoot = true;
2021-11-15 13:02:05 +03:00
networking = {
hostName = config.selfprivacy.hostname;
domain = config.selfprivacy.domain;
usePredictableInterfaceNames = false;
2021-11-15 13:02:05 +03:00
firewall = {
2025-06-18 19:53:44 +03:00
allowedTCPPorts = [
22
25
80
143
443
465
587
993
4443
8443
];
allowedUDPPorts = [
8443
10000
];
extraCommands = ''
iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
iptables --append FORWARD --in-interface vpn00 -j ACCEPT
'';
2021-11-15 13:02:05 +03:00
};
2025-06-18 19:53:44 +03:00
nameservers = [
"1.1.1.1"
"1.0.0.1"
];
2021-11-15 13:02:05 +03:00
};
time.timeZone = config.selfprivacy.timezone;
2021-11-15 13:02:05 +03:00
i18n.defaultLocale = "en_GB.UTF-8";
users.users.root.openssh.authorizedKeys.keys = config.selfprivacy.ssh.rootKeys;
2021-11-15 13:02:05 +03:00
services.openssh = {
enable = config.selfprivacy.ssh.enable;
2023-12-18 18:13:57 +04:00
settings = {
PasswordAuthentication = false;
2025-03-20 12:48:41 +03:00
PermitRootLogin = "prohibit-password";
2023-12-18 18:13:57 +04:00
};
2021-11-15 13:02:05 +03:00
openFirewall = false;
2024-07-01 19:14:28 +04:00
2021-11-15 13:02:05 +03:00
};
2024-10-02 16:52:56 +03:00
services.fail2ban.enable = true;
2021-11-15 13:02:05 +03:00
programs.ssh = {
2025-06-18 19:53:44 +03:00
pubkeyAcceptedKeyTypes = [
"ssh-ed25519"
"ssh-rsa"
"ecdsa-sha2-nistp256"
];
hostKeyAlgorithms = [
"ssh-ed25519"
"ssh-rsa"
];
2021-11-15 13:02:05 +03:00
};
environment.systemPackages = with pkgs; [
git
jq
2024-05-30 04:09:20 +04:00
sp-print-api-token
2024-12-18 15:40:15 +03:00
sp-fetch-remote-module
2021-11-15 13:02:05 +03:00
];
2023-11-18 05:53:08 +04:00
# consider environment.defaultPackages = lib.mkForce [];
documentation.enable = false; # no {man,info}-pages & docs, etc to save space
2023-12-27 11:37:59 +04:00
# (or create a systemd service with `ConditionFirstBoot=yes`?)
systemd.tmpfiles.rules = [
"# Completely remove remnants of NIXOS_LUSTRATE."
"R! /old-root"
2024-10-04 11:56:54 +00:00
"d /etc/selfprivacy/dump 0700 0700 selfprivacy-api selfprivacy-api"
];
2025-06-18 19:53:44 +03:00
system.stateVersion = lib.mkIf (
config.selfprivacy.stateVersion != null
) config.selfprivacy.stateVersion;
system.autoUpgrade = {
enable = config.selfprivacy.autoUpgrade.enable;
allowReboot = config.selfprivacy.autoUpgrade.allowReboot;
# TODO get attribute name from selfprivacy options
flake = "/etc/nixos#default";
};
systemd.services.nixos-upgrade.serviceConfig.WorkingDirectory = "/etc/nixos";
# TODO parameterize URL somehow; run nix flake update as non-root user
systemd.services.nixos-upgrade.serviceConfig.ExecCondition =
pkgs.writeShellScript "flake-update-script" ''
set -o xtrace
if ${config.nix.package.out}/bin/nix flake update \
2025-04-25 15:08:38 +03:00
--override-input selfprivacy-nixos-config git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-config.git?ref=flakes
then
if ${pkgs.diffutils}/bin/diff -u -r /etc/selfprivacy/nixos-config-source/ /etc/nixos/
then
set +o xtrace
echo "No configuration changes detected. Nothing to upgrade."
exit 1
fi
else
# ExecStart must not start after 255 exit code, service must fail.
exit 255
fi
'';
2021-11-15 13:02:05 +03:00
nix = {
2025-05-02 16:52:16 +03:00
package = pkgs.nixVersions.nix_2_18;
channel.enable = false;
2023-11-18 05:53:08 +04:00
# daemonCPUSchedPolicy = "idle";
# daemonIOSchedClass = "idle";
# daemonIOSchedPriority = 7;
# this is superseded by nix.settings.auto-optimise-store.
# optimise.automatic = true;
2021-11-15 13:02:05 +03:00
gc = {
automatic = true; # TODO it's debatable, because of IO&CPU load
2021-11-15 13:02:05 +03:00
options = "--delete-older-than 7d";
};
};
2023-11-18 05:53:08 +04:00
nix.settings = {
sandbox = true;
2025-06-18 19:53:44 +03:00
experimental-features = [
"nix-command"
"flakes"
];
2023-11-18 05:53:08 +04:00
# auto-optimise-store = true;
# evaluation restrictions:
# restrict-eval = true;
# allowed-uris = [];
allow-dirty = false;
};
nixpkgs.overlays = [
(import ./overlay.nix config.nixpkgs.hostPlatform.system)
];
services.journald.extraConfig = "SystemMaxUse=500M";
# TODO must be configurable and determined at nixos-infect stage
2021-11-15 13:02:05 +03:00
swapDevices = [
{
device = "/swapfile";
priority = 0;
size = 2048;
}
];
2025-05-20 15:31:35 +03:00
systemd.enableEmergencyMode = false;
systemd.coredump.enable = false;
2025-05-20 15:31:35 +03:00
environment.memoryAllocator.provider = "libc"; # Scudo has problems with PHP, which may cause PHP to segfault...
2025-05-20 16:24:12 +03:00
security.sudo.enable = false;
2025-05-20 15:31:35 +03:00
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1; # TODO why is it here by default, for VPN only?
"kernel.core_pattern" = "|${pkgs.coreutils}/bin/false"; # Ignore coredumps
"kernel.yama.ptrace_scope" = "3"; # Disable ptrace()
"kernel.io_uring_disabled" = "2"; # io_uring has huge attack surface and is not used by any module in SelfPrivacy.
"dev.tty.ldisc_autoload" = "0";
"kernel.kexec_load_disabled" = "1";
"kernel.unprivileged_bpf_disabled" = "1"; # Only systemd uses eBPF.
"kernel.kptr_restrict" = "2"; # Hide kernel pointer locations.
"vm.unprivileged_userfaultfd" = "0"; # Reduce attack surface
};
}