maxwell/configuration.nix
rnhmjoj 50daabb203
use sessionVariables for setting XDG directories
environment.sessionVariables are set before the shell starts, so the
wont't pollute the default value before switch to the one set using
the environment.variables.
2022-10-21 17:31:18 +02:00

498 lines
12 KiB
Nix

{ config, lib, pkgs, ... }:
{
imports = [
./hardware.nix
./variables.nix
./packages.nix
./jobs.nix
./matrix.nix
./email.nix
./magnetico.nix
./nameserver.nix
./custom
./secrets
];
### State
# Stateful things to do before updating:
# 1. Postgres migration (https://www.postgresql.org/docs/current/upgrading.html)
# 2. Matrix Synapse migration (https://matrix-org.github.io/synapse/latest/upgrade.html)
system.stateVersion = "22.05";
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.tmpOnTmpfs = true;
boot.kernel.sysctl = {
# avoid OOM hangs
"vm.admin_reserve_kbytes" = 262144;
};
time.timeZone = "Europe/Rome";
i18n.defaultLocale = "en_US.UTF-8";
systemd.enableEmergencyMode = false;
networking = {
hostName = "maxwell";
firewall.allowedTCPPorts = [
443 80 # reverse proxy
993 # imaps server
25 465 # smtp(s) server
3478 # turn server
5349 # turn server
3551 # apcups
18080 # monero p2p
22000 # syncthing transfer
64738 # mumble server
];
firewall.allowedUDPPorts = [
53 # powerdns
1194 # dnscrypt
3478 # turn server
21027 # syncthing discovery
64738 # mumble server
];
firewall.allowedUDPPortRanges = [
{ from=49152; to=49999; } # turn relay
];
usePredictableInterfaceNames = false;
nameservers = [ "127.0.0.1" ];
hosts."127.0.0.1" = [ config.var.hostname ];
};
# Only declarative users and no password logins
users.mutableUsers = false;
users.users ={
# Only needed for local (read emergency) shell access
root.passwordFile = config.secrets.passwords.root;
# Admin
rnhmjoj = {
uid = 1000;
extraGroups = [ "wheel" ];
isNormalUser = true;
shell = pkgs.fish;
openssh.authorizedKeys.keyFiles = [ config.secrets.publicKeys.rnhmjoj ];
};
# Admin
fazo = {
extraGroups = [ "wheel" ];
isNormalUser = true;
openssh.authorizedKeys.keyFiles = [ config.secrets.publicKeys.fazo ];
};
# User
meme = {
isNormalUser = true;
shell = pkgs.fish;
openssh.authorizedKeys.keyFiles = [ config.secrets.publicKeys.meme ];
};
# Hosts the cactalogo
giu = {
isNormalUser = true;
shell = pkgs.fish;
openssh.authorizedKeys.keyFiles = with config.secrets.publicKeys;
[ rnhmjoj giu ];
};
# Needed to perform remote builds on Maxwell
builder = {
description = "Remote Nix builds user";
isNormalUser = true;
openssh.authorizedKeys.keyFiles = [ config.secrets.publicKeys.rnhmjoj-builder ];
};
# Use "git" instead of the default name to make
# SSH operation handier, example:
# git clone git@maxwell:user/repo
git = {
group = "git";
description = "Git server user";
home = "/var/lib/gitea";
isSystemUser = true;
useDefaultShell = true;
};
};
users.groups.git = { };
# Generate Diffie-Hellman parameters
# for TLS applications, like nginx.
security.dhparams = {
enable = true;
params.nginx = 2048; # prime modulus bits
};
security.sudo = {
enable = true;
# Users don't have a password
wheelNeedsPassword = false;
};
security.pam.loginLimits = [
# Limit user process to stop fork bombs
{ domain = "@users";
type = "hard";
item = "nproc";
value = "400";
}
# Disable core dumping
{ domain = "*";
type = "soft";
item = "core";
value = "0";
}
];
### ACME certificates
security.acme = with config.var; {
defaults.email = "rnhmjoj@inventati.org";
acceptTerms = true;
certs."${hostname}" = {
group = "maxwell-ydns-eu";
};
certs."riot.${hostname}" = {
group = "riot-maxwell-ydns-eu";
};
};
# Allow read access to ACME certificate
# to specific (service) users.
users.groups."maxwell-ydns-eu".members = [ "murmur" "turnserver" "nginx" ];
users.groups."riot-maxwell-ydns-eu".members = [ "nginx" ];
services.openssh = {
enable = true;
permitRootLogin = "no";
passwordAuthentication = false;
kbdInteractiveAuthentication = false;
};
# Traceroute easter egg
services.fakeroute = {
enable = true;
route = [
"89.111.117.32" "99.97.110.110" "111.116.32.104" "105.100.101.46"
"32.73.32.115" "101.101.32.121" "111.117.46.32" "84.104.101.114"
"101.32.105.115" "32.110.111.32" "108.105.102.101" "32.105.110.32"
"116.104.101.32" "118.111.105.100" "46.32.79.110" "108.121.32.100"
"101.97.116.104" ];
};
### Mumble server
services.murmur = {
enable = true;
registerHostname = config.var.hostname;
registerName = "Maxwell Mumble";
registerPassword = "$REG_PASSWORD";
password = "$JOIN_PASSWORD";
users = 10;
environmentFile = config.secrets.environments.murmur;
sslCert = "/var/lib/acme/${config.var.hostname}/fullchain.pem";
sslKey = "/var/lib/acme/${config.var.hostname}/key.pem";
};
### Syncthing node
services.syncthing = {
enable = true;
};
### Monero node with local RPC
services.monero = {
enable = true;
mining = {
enable = false;
threads = 4;
address = config.secrets.monero.address;
};
limits = {
upload = 250;
download = 625;
threads = 4;
};
rpc.user = config.secrets.monero.user;
rpc.password = config.secrets.monero.password;
};
### URL shortner
services.breve = with config.secrets; {
enable = true;
hostname = "localhost";
baseUrl = "https://brve.bit/";
port = 2000;
certificate = certs.breve.crt;
key = certs.breve.key;
};
### Git server
services.gitea = with config.var; {
enable = true;
domain = hostname;
appName = "Maxwell git server";
rootUrl = "https://${hostname}/git/";
user = "git";
database.user = "git";
log.level = "Error";
cookieSecure = true;
disableRegistration = false;
settings = {
# increase cookie expiration time
security.LOGIN_REMEMBER_DAYS = 365;
# file upload size (MB)
attachment.MAX_SIZE = 10;
# new users can only create PR/issues
service.DEFAULT_ALLOW_CREATE_ORGANIZATION = false;
repository.MAX_CREATION_LIMIT = 0;
# somewhat limit spam
service.EMAIL_DOMAIN_BLOCKLIST = "gmail.com";
# allow the notify webhook to use matrix
webhook.ALLOWED_HOST_LIST = "maxwell.ydns.eu";
};
};
### Searx instance
services.searx = {
enable = true;
environmentFile = config.secrets.environments.searx;
# Use nginx+uWSGI
runInUwsgi = true;
uwsgiConfig = {
disable-logging = true;
# serve using the uwsgi protocol
socket = "/run/searx/uwsgi.sock";
chmod-socket = "660";
# use /searx as url "mountpoint"
mount = "/srx=searx.webapp:application";
module = "";
manage-script-name = true;
# caching
cache2 = lib.concatStringsSep ","
[ "name=searxcache"
"items=2000"
"blocks=2000"
"blocksize=4096"
"bitmap=1"
];
};
settings =
{ general.instance_name = "searxwell";
server.base_url = "https://${config.var.hostname}/";
server.secret_key = "@SEARX_SECRET@";
# Replace DOI links with Sci-Hub
default_doi_resolver = "sci-hub.st";
## Use authenticated APIs for some services
engines = [
{ name = "wolframalpha";
api_key = "@WOLFRAM_API_KEY@";
}
{ name = "youtube";
api_key = "@YOUTUBE_API_KEY@";
}
];
};
};
# Allow nginx access to the uwsgi socket
users.groups."searx".members = [ "nginx" ];
### Reverse Proxy
services.nginx =
with config.var;
let
disableLog = ''
error_log syslog:server=unix:/dev/log crit;
access_log off;
'';
enableSTS = ''
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
'';
in
rec {
enable = true;
enableReload = true;
recommendedTlsSettings = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
# Large enough to allow file uploads.
clientMaxBodySize = "1000M";
sslDhparam = "${config.security.dhparams.path}/nginx.pem";
# Maxwell
virtualHosts."${hostname}" = {
enableACME = true;
forceSSL = true;
default = true;
extraConfig = disableLog + enableSTS;
# Returns IP address
locations."/ip".extraConfig = ''
default_type text/plain;
return 200 $remote_addr;
'';
# Asjon code coverage reports
locations."/asjon/report/" = {
index = "index.html";
alias = "/run/nginx/static/asjon/";
};
# Searx instance
locations."/srx/".extraConfig =
''
include ${pkgs.nginx}/conf/uwsgi_params;
uwsgi_pass unix:/run/searx/uwsgi.sock;
'';
locations."/srx/static/".alias = "${pkgs.searx}/share/static/";
# Git server
locations."/git/".proxyPass = "http://localhost:3000/";
# Syncthing
locations."/sync/".proxyPass = "http://localhost:8384/";
# User static files
locations."/~rnhmjoj/" = {
alias = "/run/nginx/static/rnhmjoj/";
extraConfig = "charset UTF-8;";
};
locations."/~giu/" = {
alias = "/run/nginx/static/giu/";
extraConfig = "charset UTF-8;";
};
};
# Breve URL shortner
virtualHosts."brve.bit" = with config.secrets; {
forceSSL = true;
sslCertificate = certs.breve.crt;
sslCertificateKey = certs.breve.key;
locations."/" = {
proxyPass = "https://localhost:2000";
extraConfig = "proxy_ssl_verify off;";
};
extraConfig = disableLog;
};
# The Cactalogue
virtualHosts."cacta.bit" = {
root = "/run/nginx/static/cactalogue";
extraConfig = disableLog;
};
virtualHosts."cacta.eurofusion.eu" = virtualHosts."cacta.bit";
};
# Bind mount directories for Nginx
# This avoids giving nginx traversal permission
systemd.mounts =
let bindNginx = from: to:
{ what = from;
where = "/run/nginx/static/" + to;
type = "none";
options = "bind";
wantedBy = [ "nginx.service" ];
};
in [ (bindNginx "/home/rnhmjoj/www" "rnhmjoj")
(bindNginx "/home/giu/www" "giu")
(bindNginx "/home/giu/cactalogue" "cactalogue")
(bindNginx "/var/lib/asjon/tree/report" "asjon")
];
### Misc. services
services.asjon.enable = true;
# Needed for the Asjon memory module
services.redis.servers."asjon" =
{ enable = true;
user = "asjon";
};
### Program configuration
programs = {
fuse.userAllowOther = true;
fish.enable = true;
tmux = {
enable = true;
newSession = true;
baseIndex = 1;
escapeTime = 0;
historyLimit = 4096;
keyMode = "vi";
terminal = "screen-256color";
customPaneNavigationAndResize = true;
extraConfig = ''
set -g mouse on
# bindings
bind | split-window -h
bind - split-window -v
bind : command-prompt
bind -n C-k clear-history
# colors
set -g pane-border-style fg=brightblack
set -g pane-active-border fg=green
set -g message-style fg=white,bg=black
set -g status-style fg=brightblue,bg=black
setw -g mode-style fg=black,bg=cyan
# status line
set -g status on
set -g status-justify left
set -g status-left ""
set -g status-right-length 60
set -g status-right '#[fg=yellow]#(cut -d\ -f 1-3 /proc/loadavg) | #[fg=brightgreen]%a %H:%M'
setw -g window-status-format "#[fg=black#,bg=brightblack] #I #[fg=blue#,bg=black] #W "
setw -g window-status-current-format "#[fg=white#,bg=cyan] #I #[fg=black#,bg=brightblack] #W "
'';
};
};
nix = {
useSandbox = true;
# Can connect to the Nix daemon
# and upload/run code as root!
trustedUsers = [ "builder" "rnhmjoj" ];
# Use at most half the cores
buildCores = 8;
extraOptions = ''
# Always keep at least 256MiB free
min-free = 268435456
'';
};
environment.sessionVariables = {
PATH = [ "$HOME/.local/bin/" ];
XDG_CONFIG_HOME = "$HOME/.config";
XDG_DATA_HOME = "$HOME/.local/share";
XDG_CACHE_HOME = "$HOME/.cache";
SYSTEMD_COLORS = "16";
};
}