refactoring vps

This commit is contained in:
Ivan Kirilov Dimitrov 2024-08-03 20:16:58 +02:00
parent b432efdd0f
commit e2e10b3f0a
No known key found for this signature in database
GPG Key ID: 0BDAD4B211C49294
13 changed files with 280 additions and 396 deletions

View File

@ -1,103 +0,0 @@
{ pkgs, ... }:
{
time.timeZone = "Europe/Prague";
fileSystems."/mnt/export1981" = {
device = "172.16.128.47:/nas/5490";
fsType = "nfs";
options = [ "nofail" ];
};
nix = {
extraOptions = ''
experimental-features = nix-command flakes
'';
};
security = {
acme = {
acceptTerms = true;
defaults.email = "security@idimitrov.dev";
};
};
networking = {
firewall = pkgs.lib.mkForce {
enable = true;
allowedTCPPorts = [
25 # smtp
465 # smtps
80 # http
443 # https
];
allowedUDPPorts = [
25
465
80
443
51820 # wireguard
];
extraCommands = ''
iptables -N vpn # create a new chain named vpn
iptables -A vpn --src 10.0.0.2 -j ACCEPT # allow
iptables -A vpn --src 10.0.0.3 -j ACCEPT # allow
iptables -A vpn --src 10.0.0.4 -j ACCEPT # allow
iptables -A vpn -j DROP # drop everyone else
iptables -I INPUT -m tcp -p tcp --dport 22 -j vpn
'';
extraStopCommands = ''
iptables -F vpn
iptables -D INPUT -m tcp -p tcp --dport 22 -j vpn
iptables -X vpn
'';
};
};
users = {
users.ivand = {
isNormalUser = true;
hashedPassword =
"$2b$05$hPrPcewxj4qjLCRQpKBAu.FKvKZdIVlnyn4uYsWE8lc21Jhvc9jWG";
extraGroups = [ "wheel" "adm" "mlocate" ];
openssh.authorizedKeys.keys = [
''
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCyW157tNiQdeoQsoo5AEzhyi6BvPeqEvChCxCHf3hikmFDqb6bvvlKYb9grW+fqE0HzALRwpXvPKnuUwHKPVG8HZ7NC9bT5RPMO0rFviNoxWF2PNDWG0ivPmLrQGKtCPM3aUIhSdUdlJ7ImYl34KBkUIrSmL7WlLJUvh1PtyyuVfrhpFzFxHwYwVCNO33L89lfl5PY/G9qrjlH64urt/6aWqMdHD8bZ4MHBPcnSwLMd7f0nNa0aTAJMabsfmndZhV24y7T1FUWG0dl27Q4rnpnZJWBDD1IyWIX/aN+DD6eVVWa4tRVJs6ycfw48hft0zs9zLn9mU4a2hxQ6VvfwpqZHOO8XqqOSai9Yw9Ba60iVQokQQiL91KidoSF7zD0U0szdEmylANyAntUcJ1kdu496s21IU2hjYfN/3seH5a9hBk8iPHp/eTeVUXFKh27rRWn0gc+rba1LF0BWfTjRYR7e1uvPEau0I61sNsp3lnMULdkgkZ9rap1sRM6ULlaRXM= ivand@nixos
''
];
};
extraGroups = { mlocate = { }; };
};
environment = {
enableAllTerminfo = true;
};
services = {
openssh = {
enable = true;
settings = {
PermitRootLogin = "prohibit-password";
};
};
};
systemd = {
timers = {
bingwp = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*-*-* 10:00:00";
Persistent = true;
};
};
};
services = {
bingwp = {
description = "Download bing image of the day";
script = ''
${pkgs.nushell}/bin/nu -c "http get ('https://bing.com' + ((http get https://www.bing.com/HPImageArchive.aspx?format=js&n=1).images.0.url)) | save ('/var/pic' | path join ( [ (date now | format date '%Y-%m-%d'), '.png' ] | str join ))"
${pkgs.nushell}/bin/nu -c "${pkgs.toybox}/bin/ln -sf (ls /var/pic | where type == file | get name | sort | last) /var/pic/latest.png"
'';
};
};
};
}

View File

@ -1,3 +1,279 @@
{
imports = [ ./configuration.nix ./mailserver ./roundcube ./postgres ./wireguard ./nginx ./tor ./i2pd ./gitea ./dnscrypt ./monero ];
{ config, pkgs, ... }: {
fileSystems."/mnt/export1981" = {
device = "172.16.128.47:/nas/5490";
fsType = "nfs";
options = [ "nofail" ];
};
security = {
acme = {
acceptTerms = true;
defaults.email = "security@idimitrov.dev";
};
};
networking = {
nameservers = [ "127.0.0.1" "::1" ];
dhcpcd.extraConfig = "nohook resolv.conf";
firewall = pkgs.lib.mkForce {
enable = true;
allowedTCPPorts = [
25 # smtp
465 # smtps
80 # http
443 # https
];
allowedUDPPorts = [
25
465
80
443
51820 # wireguard
];
extraCommands = ''
iptables -N vpn # create a new chain named vpn
iptables -A vpn --src 10.0.0.2 -j ACCEPT # allow
iptables -A vpn --src 10.0.0.3 -j ACCEPT # allow
iptables -A vpn --src 10.0.0.4 -j ACCEPT # allow
iptables -A vpn -j DROP # drop everyone else
iptables -I INPUT -m tcp -p tcp --dport 22 -j vpn
'';
extraStopCommands = ''
iptables -F vpn
iptables -D INPUT -m tcp -p tcp --dport 22 -j vpn
iptables -X vpn
'';
};
nat = {
enable = true;
enableIPv6 = true;
externalInterface = "venet0";
internalInterfaces = [ "wg0" ];
};
wg-quick.interfaces = {
wg0 = {
address = [ "10.0.0.1/32" ];
listenPort = 51820;
privateKeyFile = "/etc/wireguard/privatekey";
postUp = ''
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o venet0 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -A POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o venet0 -j MASQUERADE
'';
preDown = ''
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.0.0.1/24 -o venet0 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -D POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o venet0 -j MASQUERADE
'';
peers = [
{
publicKey = "kI93V0dVKSqX8hxMJHK5C0c1hEDPQTgPQDU8TKocVgo=";
allowedIPs = [ "10.0.0.2/32" ];
}
{
publicKey = "RqTsFxFCcgYsytcDr+jfEoOA5UNxa1ZzGlpx6iuTpXY=";
allowedIPs = [ "10.0.0.3/32" ];
}
];
};
};
};
users = {
users.ivand = {
isNormalUser = true;
hashedPassword =
"$2b$05$hPrPcewxj4qjLCRQpKBAu.FKvKZdIVlnyn4uYsWE8lc21Jhvc9jWG";
extraGroups = [ "wheel" "adm" "mlocate" ];
openssh.authorizedKeys.keys = [
''
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICcLkzuCoBEg+wq/H+hkrv6pLJ8J5BejaNJVNnymlnlo ivan@idimitrov.dev
''
];
};
extraGroups = { mlocate = { }; };
};
services = {
dovecot2.sieve.extensions = [ "fileinto" ];
openssh = {
enable = true;
settings = {
PermitRootLogin = "prohibit-password";
};
};
roundcube = {
enable = true;
package = pkgs.roundcube.withPlugins (plugins: [ plugins.persistent_login ]);
plugins = [
"persistent_login"
];
hostName = "${config.mailserver.fqdn}";
extraConfig = ''
$config['smtp_host'] = "tls://${config.mailserver.fqdn}";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
'';
};
postgresql = {
enable = true;
ensureUsers = [
{
name = "root";
ensureClauses = {
superuser = true;
createrole = true;
createdb = true;
};
}
];
};
gitea = {
enable = true;
appName = "src";
database = {
type = "postgres";
};
settings = {
server = {
DOMAIN = "src.idimitrov.dev";
ROOT_URL = "https://src.idimitrov.dev/";
HTTP_PORT = 3001;
};
repository = {
DEFAULT_BRANCH = "master";
};
service = {
DISABLE_REGISTRATION = true;
};
};
};
dnscrypt-proxy2 = {
enable = true;
settings = {
ipv4_servers = true;
ipv6_servers = true;
dnscrypt_servers = true;
doh_servers = false;
odoh_servers = false;
require_dnssec = true;
require_nolog = true;
require_nofilter = true;
sources.public-resolvers = {
urls = [
"https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md"
"https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md"
];
cache_file = "/var/lib/dnscrypt-proxy/public-resolvers.md";
minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
};
};
};
nginx =
let
webshiteConfig = ''
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Content-Type-Options nosniff;
'';
restrictToVpn = ''
allow 10.0.0.2/32;
allow 10.0.0.3/32;
allow 10.0.0.4/32;
deny all;
'';
extensions = [ "html" "txt" "png" "jpg" "jpeg" ];
serveStatic = exts: ''
try_files $uri $uri/ ${pkgs.lib.strings.concatStringsSep " " (builtins.map (x: "$uri." + "${x}") exts)} =404;
'';
in
{
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
virtualHosts = {
"idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = "${pkgs.webshite}";
extraConfig = serveStatic extensions;
};
extraConfig = webshiteConfig;
};
"www.idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = "${pkgs.webshite}";
extraConfig = serveStatic extensions;
};
extraConfig = webshiteConfig;
};
"${config.mailserver.fqdn}" = {
extraConfig = restrictToVpn;
};
"src.idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3001";
};
};
"pic.idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = "/var/pic";
extraConfig = ''
autoindex on;
${serveStatic ["png"]}
'';
};
};
};
};
};
systemd = {
timers = {
bingwp = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*-*-* 10:00:00";
Persistent = true;
};
};
};
services = {
bingwp = {
description = "Download bing image of the day";
script = ''
${pkgs.nushell}/bin/nu -c "http get ('https://bing.com' + ((http get https://www.bing.com/HPImageArchive.aspx?format=js&n=1).images.0.url)) | save ('/var/pic' | path join ( [ (date now | format date '%Y-%m-%d'), '.png' ] | str join ))"
${pkgs.nushell}/bin/nu -c "${pkgs.toybox}/bin/ln -sf (ls /var/pic | where type == file | get name | sort | last) /var/pic/latest.png"
'';
};
};
};
mailserver = {
enable = true;
localDnsResolver = false;
fqdn = "mail.idimitrov.dev";
domains = [ "idimitrov.dev" "mail.idimitrov.dev" ];
loginAccounts = {
"ivan@idimitrov.dev" = {
hashedPassword = "$2b$05$rTVIQD98ogXeCBKdk/YufulWHqpMCAlb7SHDPlh5y8Xbukoa/uQLm";
aliases = [ "admin@idimitrov.dev" ];
};
"security@idimitrov.dev" = {
hashedPassword = "$2b$05$rTVIQD98ogXeCBKdk/YufulWHqpMCAlb7SHDPlh5y8Xbukoa/uQLm";
};
};
certificateScheme = "acme-nginx";
hierarchySeparator = "/";
};
}

View File

@ -1,33 +0,0 @@
{
networking = {
nameservers = [ "127.0.0.1" "::1" ];
dhcpcd.extraConfig = "nohook resolv.conf";
};
services.dnscrypt-proxy2 = {
enable = true;
settings = {
ipv4_servers = true;
ipv6_servers = true;
dnscrypt_servers = true;
doh_servers = false;
odoh_servers = false;
require_dnssec = true;
require_nolog = true;
require_nofilter = true;
sources.public-resolvers = {
urls = [
"https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md"
"https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md"
];
cache_file = "/var/lib/dnscrypt-proxy/public-resolvers.md";
minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
};
};
};
systemd.services.dnscrypt-proxy2.serviceConfig = {
StateDirectory = "dnscrypt-proxy";
};
}

View File

@ -1,23 +0,0 @@
{ ... }:
{
services.gitea = {
enable = true;
appName = "src";
database = {
type = "postgres";
};
settings = {
server = {
DOMAIN = "src.idimitrov.dev";
ROOT_URL = "https://src.idimitrov.dev/";
HTTP_PORT = 3001;
};
repository = {
DEFAULT_BRANCH = "master";
};
service = {
DISABLE_REGISTRATION = true;
};
};
};
}

View File

@ -1,14 +0,0 @@
{
services.i2pd = {
enable = true;
inTunnels = {
idimitrov = {
enable = true;
keys = "idimitrov-keys.dat";
inPort = 80;
destination = "127.0.0.1";
port = 3000;
};
};
};
}

View File

@ -1,21 +0,0 @@
{ config, pkgs, ... }:
{
mailserver = {
enable = true;
localDnsResolver = false;
fqdn = "mail.idimitrov.dev";
domains = [ "idimitrov.dev" "mail.idimitrov.dev" ];
loginAccounts = {
"ivan@idimitrov.dev" = {
hashedPassword = "$2b$05$rTVIQD98ogXeCBKdk/YufulWHqpMCAlb7SHDPlh5y8Xbukoa/uQLm";
aliases = [ "admin@idimitrov.dev" ];
};
"security@idimitrov.dev" = {
hashedPassword = "$2b$05$rTVIQD98ogXeCBKdk/YufulWHqpMCAlb7SHDPlh5y8Xbukoa/uQLm";
};
};
certificateScheme = "acme-nginx";
hierarchySeparator = "/";
};
services.dovecot2.sieve.extensions = [ "fileinto" ];
}

View File

@ -1,6 +0,0 @@
{
services.monero = {
enable = false;
dataDir = "/mnt/export1981/monero";
};
}

View File

@ -1,72 +0,0 @@
{ config, pkgs, ... }:
let
webshiteConfig = ''
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Content-Type-Options nosniff;
add_header Onion-Location http://sxfx23zafag4lixkb4s6zwih7ga5jnzfgtgykcerd354bvb6u7alnkid.onion;
'';
restrictToVpn = ''
allow 10.0.0.2/32;
allow fdc9:281f:04d7:9ee9::2/128;
allow 10.0.0.3/32;
allow 10.0.0.4/32;
deny all;
'';
extensions = [ "html" "txt" "png" "jpg" "jpeg" ];
serveStatic = exts: ''
try_files $uri $uri/ ${pkgs.lib.strings.concatStringsSep " " (builtins.map (x: "$uri." + "${x}") exts)} =404;
'';
in
{
services = {
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
virtualHosts = {
"idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = "${pkgs.webshite}";
extraConfig = serveStatic extensions;
};
extraConfig = webshiteConfig;
};
"www.idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = "${pkgs.webshite}";
extraConfig = serveStatic extensions;
};
extraConfig = webshiteConfig;
};
"${config.mailserver.fqdn}" = {
extraConfig = restrictToVpn;
};
"src.idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3001";
};
};
"pic.idimitrov.dev" = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = "/var/pic";
extraConfig = ''
autoindex on;
${serveStatic ["png"]}
'';
};
};
};
};
};
}

View File

@ -1,39 +0,0 @@
{ config, pkgs, ... }:
{
services = {
postgresql = {
enable = true;
ensureDatabases = [ "roundcube" "gitea" ];
ensureUsers = [
{
name = "roundcube";
ensureDBOwnership = true;
}
{
name = "gitea";
ensureDBOwnership = true;
}
{
name = "root";
ensureClauses = {
superuser = true;
createrole = true;
createdb = true;
};
}
];
authentication = ''
local gitea all ident map=gitea-users
'';
identMap = ''
gitea-users gitea gitea
'';
initialScript = pkgs.writeText "init" ''
GRANT ALL PRIVILEGES ON DATABASE roundcube TO roundcube;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO roundcube;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO roundcube;
GRANT ALL PRIVILEGES ON SCHEMA public TO roundcube;
'';
};
};
}

View File

@ -1,18 +0,0 @@
{ config, pkgs, ... }:
{
services = {
roundcube = {
enable = true;
package = pkgs.roundcube.withPlugins (plugins: [ plugins.persistent_login ]);
plugins = [
"persistent_login"
];
hostName = "${config.mailserver.fqdn}";
extraConfig = ''
$config['smtp_host'] = "tls://${config.mailserver.fqdn}";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
'';
};
};
}

View File

@ -1,21 +0,0 @@
{
services.tor = {
enable = true;
client.enable = true;
relay = {
enable = true;
role = "relay";
onionServices = {
idimitrov = {
map = [{
port = 80;
target = {
addr = "127.0.0.1";
port = 3000;
};
}];
};
};
};
};
}

View File

@ -1,43 +0,0 @@
{ pkgs, ... }: {
networking.nat = {
enable = true;
enableIPv6 = true;
externalInterface = "venet0";
internalInterfaces = [ "wg0" ];
};
networking.wg-quick.interfaces = {
wg0 = {
address = [ "10.0.0.1/24" "fdc9:281f:04d7:9ee9::1/64" ];
listenPort = 51820;
privateKeyFile = "/etc/wireguard/privatekey";
postUp = ''
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o venet0 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -A POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o venet0 -j MASQUERADE
'';
preDown = ''
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.0.0.1/24 -o venet0 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -D POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o venet0 -j MASQUERADE
'';
peers = [
{
publicKey = "28yXYLk4U0r6MdWFEZzk6apI8uhg962wMprF47wUJyI=";
allowedIPs = [ "10.0.0.2/32" "fdc9:281f:04d7:9ee9::2/128" ];
}
{
publicKey = "RqTsFxFCcgYsytcDr+jfEoOA5UNxa1ZzGlpx6iuTpXY=";
allowedIPs = [ "10.0.0.3/32" ];
}
{
publicKey = "kI93V0dVKSqX8hxMJHK5C0c1hEDPQTgPQDU8TKocVgo=";
allowedIPs = [ "10.0.0.4/32" ];
}
];
};
};
}

View File

@ -22,6 +22,7 @@ top@{ inputs, moduleWithSystem, ... }: {
systemPackages = with pkgs; [ cmatrix uutils-coreutils-noprefix cryptsetup fd file git glibc gnumake mlocate openssh openssl procs ripgrep srm unzip vim zip just nixos-install-tools ];
sessionVariables = { MAKEFLAGS = "-j 4"; };
shells = with pkgs; [ bash zsh nushell ];
enableAllTerminfo = true;
};
users.defaultUserShell = pkgs.zsh;
programs = { zsh.enable = true; nix-ld.enable = true; };
@ -98,7 +99,7 @@ top@{ inputs, moduleWithSystem, ... }: {
wireguard = {
networking.wg-quick.interfaces = {
wg0 = {
address = [ "10.0.0.4/32" ];
address = [ "10.0.0.2/32" ];
privateKeyFile = "/etc/wireguard/privatekey";
peers = [
{