2020-10-20 01:11:28 +02:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
{
|
|
|
|
imports = [
|
|
|
|
./hardware.nix
|
|
|
|
./variables.nix
|
|
|
|
./packages.nix
|
|
|
|
./jobs.nix
|
|
|
|
./matrix.nix
|
2021-02-17 18:06:00 +01:00
|
|
|
./email.nix
|
2020-10-20 01:11:28 +02:00
|
|
|
./magnetico.nix
|
|
|
|
./nameserver.nix
|
|
|
|
./custom
|
|
|
|
./secrets
|
|
|
|
];
|
|
|
|
|
|
|
|
### State
|
|
|
|
# Stateful things to do before updating:
|
|
|
|
# 1. Postgres migration
|
|
|
|
# 2. Matrix Synapse migration
|
|
|
|
system.stateVersion = "20.03";
|
|
|
|
|
|
|
|
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 = [
|
2020-11-13 08:49:13 +01:00
|
|
|
443 80 # reverse proxy
|
2021-02-17 18:06:00 +01:00
|
|
|
993 # imaps server
|
|
|
|
25 465 # smtp(s) server
|
2020-10-20 01:11:28 +02:00
|
|
|
8080 # hubot
|
|
|
|
5349 # turn server
|
|
|
|
5350 # turn server
|
|
|
|
3551 # apcups
|
|
|
|
5001 # iperf server
|
|
|
|
18080 # monero p2p
|
|
|
|
20000 # syncthing transfert
|
|
|
|
64738 # mumble server
|
|
|
|
];
|
|
|
|
firewall.allowedUDPPorts = [
|
|
|
|
53 # powerdns
|
|
|
|
1194 # dnscrypt
|
|
|
|
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];
|
|
|
|
};
|
|
|
|
|
|
|
|
# Runs two chatbots
|
|
|
|
meme = {
|
|
|
|
extraGroups = [ "ubino" "miguelbridge" ];
|
|
|
|
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 = {
|
|
|
|
description = "Git server user";
|
|
|
|
home = "/var/lib/gitea";
|
|
|
|
useDefaultShell = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
# 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;
|
|
|
|
extraConfig =
|
2020-11-13 08:49:13 +01:00
|
|
|
let
|
2020-10-20 01:11:28 +02:00
|
|
|
path = "/run/current-system/sw/bin";
|
|
|
|
journal = name: "${path}/journalctl -* ${name}";
|
|
|
|
services = lib.concatMapStringsSep "," (name: "${journal name}");
|
|
|
|
in ''
|
|
|
|
# Allow meme to see his logs.
|
|
|
|
Cmnd_Alias MEME_UNITS = ${services ["ubino" "miguelbridge"]}
|
|
|
|
meme ALL=(root) NOPASSWD: MEME_UNITS
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
security.polkit.extraConfig = ''
|
|
|
|
// Allow meme to manage his services.
|
|
|
|
polkit.addRule(function(action, subject) {
|
|
|
|
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
|
|
|
subject.user == "meme" &&
|
|
|
|
(action.lookup("unit") == "ubino.service" ||
|
|
|
|
action.lookup("unit") == "miguelbridge.service")) {
|
|
|
|
return polkit.Result.YES;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
'';
|
|
|
|
|
2020-11-13 08:49:13 +01:00
|
|
|
security.pam.loginLimits = [
|
2021-02-18 11:44:33 +01:00
|
|
|
# Limit user process to stop fork bombs
|
2020-10-20 01:11:28 +02:00
|
|
|
{ domain = "@users";
|
2020-11-13 08:49:13 +01:00
|
|
|
type = "hard";
|
2020-10-20 01:11:28 +02:00
|
|
|
item = "nproc";
|
|
|
|
value = "400";
|
|
|
|
}
|
2021-02-18 11:44:33 +01:00
|
|
|
# Disable core dumping
|
|
|
|
{ domain = "*";
|
|
|
|
type = "soft";
|
|
|
|
item = "core";
|
|
|
|
value = "0";
|
|
|
|
}
|
2020-10-20 01:11:28 +02:00
|
|
|
];
|
2020-11-13 08:49:13 +01:00
|
|
|
|
2020-10-20 01:11:28 +02:00
|
|
|
### ACME certificates
|
|
|
|
security.acme = with config.var; {
|
|
|
|
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.
|
2020-10-27 07:49:11 +01:00
|
|
|
users.groups."maxwell-ydns-eu".members = [ "murmur" "turnserver" "nginx" ];
|
2020-10-20 01:11:28 +02:00
|
|
|
users.groups."riot-maxwell-ydns-eu".members = [ "nginx" ];
|
|
|
|
|
|
|
|
|
|
|
|
services.openssh = {
|
|
|
|
enable = true;
|
|
|
|
permitRootLogin = "no";
|
|
|
|
passwordAuthentication = false;
|
|
|
|
challengeResponseAuthentication = 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;
|
|
|
|
password = "allwellthatmaxwell";
|
|
|
|
registerHostname = config.var.hostname;
|
|
|
|
registerName = "Maxwell Mumble";
|
|
|
|
registerPassword = config.secrets.murmur.password;
|
|
|
|
users = 10;
|
|
|
|
extraConfig = with config.var; ''
|
|
|
|
sslCert=/var/lib/acme/${hostname}/fullchain.pem
|
|
|
|
sslKey=/var/lib/acme/${hostname}/key.pem
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
### Syncthing node
|
|
|
|
services.syncthing = {
|
|
|
|
enable = true;
|
|
|
|
openDefaultPorts = 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
|
2020-10-26 00:47:39 +01:00
|
|
|
services.breve = with config.secrets; {
|
2020-10-20 01:11:28 +02:00
|
|
|
enable = true;
|
|
|
|
hostname = "localhost";
|
|
|
|
baseUrl = "https://brve.bit/";
|
|
|
|
port = 2000;
|
2020-10-26 00:47:39 +01:00
|
|
|
certificate = certs.breve.crt;
|
|
|
|
key = certs.breve.key;
|
2020-10-20 01:11:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
### 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 = {
|
|
|
|
security.LOGIN_REMEMBER_DAYS = 365;
|
|
|
|
attachment.MAX_SIZE = 10;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
### Searx instance
|
|
|
|
services.searx = {
|
|
|
|
enable = true;
|
2020-10-27 14:05:37 +01:00
|
|
|
environmentFile = config.secrets.searx.environment;
|
2020-11-13 08:49:29 +01:00
|
|
|
|
|
|
|
# Use nginx+uWSGI
|
|
|
|
runInUwsgi = true;
|
|
|
|
uwsgiConfig = {
|
|
|
|
disable-logging = true;
|
|
|
|
|
|
|
|
# serve via uwsgi unix socket
|
|
|
|
socket = "/run/searx/uwsgi.sock";
|
|
|
|
chmod-socket = "660";
|
|
|
|
|
|
|
|
# mount app on non-root url /srx
|
|
|
|
manage-script-name = true;
|
|
|
|
module = "";
|
|
|
|
mount = "/srx=searx.webapp:application";
|
|
|
|
};
|
|
|
|
|
2020-10-27 14:05:37 +01:00
|
|
|
settings =
|
|
|
|
{ general.instance_name = "searxwell";
|
|
|
|
server.base_url = "https://${config.var.hostname}/srx/";
|
|
|
|
|
|
|
|
# Replace DOI links with Sci-Hub
|
2020-11-01 15:48:35 +01:00
|
|
|
doi_resolvers."sci-hub.se" = "https://sci-hub.se/";
|
2020-10-27 14:05:37 +01:00
|
|
|
default_doi_resolver = "sci-hub.se";
|
|
|
|
|
|
|
|
# Use authenticated APIs for some services
|
2020-11-02 02:04:54 +01:00
|
|
|
engines = {
|
|
|
|
wolframalpha =
|
|
|
|
{ api_key = "@WOLFRAM_API_KEY@";
|
|
|
|
engine = "wolframalpha_api";
|
|
|
|
};
|
|
|
|
youtube =
|
|
|
|
{ api_key = "@YOUTUBE_API_KEY@";
|
|
|
|
engine = "youtube_api";
|
|
|
|
};
|
|
|
|
};
|
2020-10-27 14:05:37 +01:00
|
|
|
};
|
2020-10-20 01:11:28 +02:00
|
|
|
};
|
|
|
|
|
2020-11-13 08:49:29 +01:00
|
|
|
# Allow nginx access to the uwsgi socket
|
|
|
|
users.groups."searx".members = [ "nginx" ];
|
|
|
|
|
|
|
|
|
2020-10-20 01:11:28 +02:00
|
|
|
### 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
|
|
|
|
{
|
|
|
|
enable = true;
|
|
|
|
enableReload = true;
|
|
|
|
commonHttpConfig = ''
|
|
|
|
# recommendedTlsSettings = true;
|
|
|
|
# android doesn't like this one:
|
|
|
|
# ssl_ecdh_curve secp384r1;
|
|
|
|
ssl_session_cache shared:SSL:42m;
|
|
|
|
ssl_session_timeout 23m;
|
|
|
|
ssl_prefer_server_ciphers on;
|
|
|
|
ssl_stapling on;
|
2020-11-13 08:49:13 +01:00
|
|
|
ssl_stapling_verify on;
|
2020-10-20 01:11:28 +02:00
|
|
|
'';
|
|
|
|
recommendedGzipSettings = true;
|
|
|
|
recommendedProxySettings = true;
|
|
|
|
|
|
|
|
# Large enough to allow file uploads.
|
|
|
|
clientMaxBodySize = "1000M";
|
|
|
|
|
|
|
|
sslDhparam = "${config.security.dhparams.path}/nginx.pem";
|
|
|
|
|
|
|
|
# Maxwell
|
2020-11-13 08:49:13 +01:00
|
|
|
virtualHosts."${hostname}" = {
|
2020-10-20 01:11:28 +02:00
|
|
|
enableACME = true;
|
|
|
|
forceSSL = true;
|
|
|
|
default = true;
|
|
|
|
|
|
|
|
extraConfig = disableLog + enableSTS;
|
|
|
|
|
|
|
|
# Returns IP address
|
|
|
|
locations."/ip".extraConfig = "return 200 $remote_addr;";
|
|
|
|
|
2020-11-13 08:49:13 +01:00
|
|
|
# Asjon code coverage reports
|
2020-10-20 01:11:28 +02:00
|
|
|
locations."/asjon/report/" = {
|
|
|
|
index = "index.html";
|
|
|
|
alias = "/var/lib/asjon/tree/report/";
|
|
|
|
};
|
|
|
|
|
|
|
|
# Searx instance
|
2020-11-13 08:49:29 +01:00
|
|
|
locations."/srx/".extraConfig =
|
|
|
|
''
|
|
|
|
include ${pkgs.nginx}/conf/uwsgi_params;
|
|
|
|
uwsgi_pass unix:/run/searx/uwsgi.sock;
|
2020-10-20 01:11:28 +02:00
|
|
|
'';
|
2020-11-13 08:49:29 +01:00
|
|
|
locations."/srx/static/".alias = "${pkgs.searx}/share/static/";
|
|
|
|
|
2020-10-20 01:11:28 +02:00
|
|
|
# Git server
|
2020-11-13 08:49:13 +01:00
|
|
|
locations."/git/".proxyPass = "http://localhost:3000/";
|
2020-10-20 01:11:28 +02:00
|
|
|
|
|
|
|
# Syncthing
|
|
|
|
locations."/sync/".proxyPass = "http://localhost:8384/";
|
2021-02-17 18:06:00 +01:00
|
|
|
|
|
|
|
# User static files
|
|
|
|
locations."/~rnhmjoj/" = {
|
|
|
|
alias = "/home/rnhmjoj/www/";
|
|
|
|
extraConfig = "charset UTF-8;";
|
|
|
|
};
|
2020-10-20 01:11:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
# Breve URL shortner
|
2020-10-26 00:47:39 +01:00
|
|
|
virtualHosts."brve.bit" = with config.secrets; {
|
2020-10-20 01:11:28 +02:00
|
|
|
forceSSL = true;
|
2020-10-26 00:47:39 +01:00
|
|
|
sslCertificate = certs.breve.crt;
|
|
|
|
sslCertificateKey = certs.breve.key;
|
2020-10-20 01:11:28 +02:00
|
|
|
|
|
|
|
locations."/" = {
|
|
|
|
proxyPass = "https://localhost:2000";
|
|
|
|
extraConfig = "proxy_ssl_verify off;";
|
|
|
|
};
|
|
|
|
extraConfig = disableLog;
|
|
|
|
};
|
|
|
|
|
|
|
|
# The Cactalogue
|
|
|
|
virtualHosts."cacta.bit" = {
|
2020-11-13 08:49:29 +01:00
|
|
|
root = "/home/giu/cactalogue/";
|
2020-10-20 01:11:28 +02:00
|
|
|
extraConfig = disableLog;
|
|
|
|
};
|
|
|
|
};
|
2020-11-08 19:30:56 +01:00
|
|
|
# Allow nginx to see home directories for static files
|
|
|
|
# (conditional on having proper group permissions).
|
|
|
|
systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
|
2020-10-20 01:11:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
### Misc. services
|
|
|
|
services.ubino.enable = true;
|
|
|
|
services.miguelbridge.enable = true;
|
|
|
|
services.asjon.enable = true;
|
|
|
|
|
|
|
|
# Needed for the Asjon memory module
|
|
|
|
services.redis.enable = true;
|
|
|
|
|
|
|
|
|
|
|
|
### Program configuration
|
|
|
|
programs = {
|
|
|
|
fish.enable = true;
|
|
|
|
mosh.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.variables = {
|
|
|
|
PATH = "$HOME/.local/bin/:$PATH";
|
|
|
|
XDG_CONFIG_HOME = "$HOME/.config";
|
|
|
|
XDG_DATA_HOME = "$HOME/.local/share";
|
|
|
|
XDG_CACHE_HOME = "$HOME/.cache";
|
|
|
|
NIX_PROFILE = "$XDG_CONFIG_HOME/nix/profile";
|
|
|
|
};
|
|
|
|
|
|
|
|
# Needed to make the mosh server survive a
|
|
|
|
# user logout: systemd kills everything by default
|
|
|
|
environment.shellAliases = {
|
|
|
|
mosh-server = "systemd-run --user --scope mosh-server";
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|