smallest change

This commit is contained in:
zack 2025-03-22 16:03:07 -04:00
parent 4cca1dc327
commit 9c83ba6849
No known key found for this signature in database
GPG key ID: EE8A2B709E2401D1
77 changed files with 36828 additions and 1516 deletions

View file

@ -0,0 +1,87 @@
{
lib,
config,
pkgs,
...
}:
with lib;
with lib.custom; let
cfg = config.services.mail;
sec = config.age.secrets;
in {
options.services.mail = with types; {
enable = mkBoolOpt false "Enable Simple Nixos Mailserver";
};
config = mkIf cfg.enable {
age.secrets = {
webmaster-pw = {
file = ./sec/webmaster-pw.age;
};
zoeycomputer-pw = {
file = ./sec/zoey-zoeycomputer-pw.age;
};
zmio-pw = {
file = ./sec/zmio-pw.age;
};
zach-pw.file = ./sec/zach-pw.age;
emily-pw.file = ./sec/emily-piccat.age;
};
mailserver = {
enable = true;
fqdn = "mail.zoeys.email";
domains = ["zoeys.email" "zoeys.cloud" "zoeys.computer" "zackmyers.io" "zacharymyers.com" "pictureofcat.com"];
loginAccounts = {
"zoey@zoeys.email" = {
hashedPasswordFile = sec.webmaster-pw.path;
aliases = ["zoey@zoeys.cloud" "postmaster@zoeys.email" "abuse@zoeys.email"];
};
"hi@zoeys.computer" = {
hashedPasswordFile = sec.zoeycomputer-pw.path;
aliases = ["spam@zoeys.computer"];
};
"me@zackmyers.io" = {
hashedPasswordFile = sec.zmio-pw.path;
aliases = ["zach@zacharymyers.com" "zack@zacharymyers.com"];
};
"gf@zackmyers.io" = {
hashedPasswordFile = sec.emily-pw.path;
aliases = ["emily@pictureofcat.com"];
};
};
certificateScheme = "acme-nginx";
virusScanning = true;
};
# services.nginx = {
# virtualHosts = {
# "cal.zoeys.cloud" = {
# forceSSL = true;
# enableACME = true;
# locations."/" = {
# proxyPass = "http://localhost:5232/";
# extraConfig = ''
# proxy_set_header X-Script-Name /;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_pass_header Authorization;
# '';
# };
# };
# };
# };
services.roundcube = {
enable = true;
hostName = "zoeys.email";
extraConfig = ''
$config['smtp_server'] = "tls://${config.mailserver.fqdn}";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
'';
};
};
}

View file

@ -0,0 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 CtmR6w GByJvx+LFQ6yzgAl/liuJjfzjkwZMHC+R+aKNfKNAmY
S5csNYDpwtHvIWe5W0lEiKbVnR2FcOtRU5WQW2cALAA
-> ssh-ed25519 +be3hg 68FeHprHjQxUbxJj0ERz6HOM338g12EU/BmLCDjtz3Y
ydJ94RUuxLwuk0BedBk816wLMWjgOQd3/Eb7msud3mA
--- pM8bV+881Kh2Rpizrmaa/JzzvNXtKRTRU1KyFw9qtaQ
:Ã쀬ÿxÕþ,ʅ梞ÔYk0+1ÂZÏOIq@ÛY”¼Ô¡Ö±2T³Jũޤ*Í ýù!%¹…cüýcšò<C5A1>Yq<RÕF ²ù±^Ú+éf Ý

View file

@ -0,0 +1,8 @@
age-encryption.org/v1
-> ssh-ed25519 CtmR6w s2FYa/CFw32d95iUrKgwFbvMtNe+17vDYLzCRJaBumA
YgQyjn/bkEN6bH7VSlrN4xT/epITxj8NnPsalOz4ndU
-> ssh-ed25519 +be3hg BkNhJbmWJHREV54OnrDzA7ep8h2ZzVtzh+Ns6Es1jQ4
eepXxHwYgVZN56nuCisQuy+PHRjz+/NrJfVdqaAAMRE
--- wyDX4yv5LbYhCvxIiK+wzndFlBs5AdV/FgNC+MRHAO8
<EFBFBD>wVX=ó|¹éì @ß3ŒÜrÇ™sWl&ón»
¿Ù¿4“T&ÁÅJ"<Ë;רGYò-Dp@1Á<31>Î@ò»º_š9µÎ‡³ÌUû×™™ )•üb"

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,168 @@
{
config,
pkgs,
lib,
...
}: let
cfg = config.services.polaris2;
settingsFormat = pkgs.formats.toml {};
in {
options = {
services.polaris2 = {
enable = lib.mkEnableOption "Polaris Music Server";
package = lib.mkPackageOption pkgs "polaris" {};
user = lib.mkOption {
type = lib.types.str;
default = "polaris";
description = "User account under which Polaris runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "polaris";
description = "Group under which Polaris is run.";
};
extraGroups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Polaris' auxiliary groups.";
example = lib.literalExpression ''["media" "music"]'';
};
port = lib.mkOption {
type = lib.types.port;
default = 5050;
description = ''
The port which the Polaris REST api and web UI should listen to.
Note: polaris is hardcoded to listen to the hostname "0.0.0.0".
'';
};
settings = lib.mkOption {
type = settingsFormat.type;
default = {};
description = ''
Contents for the TOML Polaris config, applied each start.
Although poorly documented, an example may be found here:
[CONFIGURATION.md](https://github.com/agersant/polaris/blob/46aed8096ee9d8702b5a98e6f3b1ff5db2bfc32a/docs/CONFIGURATION.md#format)
[test-config.toml](https://github.com/agersant/polaris/blob/46aed8096ee9d8702b5a98e6f3b1ff5db2bfc32a/test-data/config.toml)
'';
example = lib.literalExpression ''
{
settings.reindex_every_n_seconds = 7*24*60*60; # weekly, default is 1800
settings.album_art_pattern =
"(cover|front|folder)\.(jpeg|jpg|png|bmp|gif)";
mount_dirs = [
{
name = "NAS";
source = "/mnt/nas/music";
}
{
name = "Local";
source = "/home/my_user/Music";
}
];
}
'';
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Open the configured port in the firewall.
'';
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.polaris = {
description = "Polaris Music Server";
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = rec {
User = cfg.user;
Group = cfg.group;
DynamicUser = true;
SupplementaryGroups = cfg.extraGroups;
StateDirectory = "polaris";
CacheDirectory = "polaris";
ExecStart = lib.escapeShellArgs (
[
"${cfg.package}/bin/polaris"
"--foreground"
"--port"
cfg.port
"--database"
"/var/lib/${StateDirectory}/db.sqlite"
"--data"
"/var/lib/${StateDirectory}/data"
"--cache"
"/var/cache/${CacheDirectory}"
]
++ lib.optionals (cfg.settings != {}) [
"--config"
(settingsFormat.generate "polaris-config.toml" cfg.settings)
]
);
Restart = "on-failure";
# Security options:
#NoNewPrivileges = true; # implied by DynamicUser
#RemoveIPC = true; # implied by DynamicUser
AmbientCapabilities = "";
CapabilityBoundingSet = "";
DeviceAllow = "";
LockPersonality = true;
#PrivateTmp = true; # implied by DynamicUser
PrivateDevices = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictNamespaces = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictRealtime = true;
#RestrictSUIDSGID = true; # implied by DynamicUser
SystemCallArchitectures = "native";
SystemCallErrorNumber = "EPERM";
SystemCallFilter = [
"@system-service"
"~@cpu-emulation"
"~@debug"
"~@keyring"
"~@memlock"
"~@obsolete"
"~@privileged"
"~@setuid"
];
};
};
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [cfg.port];
};
};
meta.maintainers = with lib.maintainers; [pbsds];
}

View file

@ -15,7 +15,29 @@ in {
};
config = mkIf cfg.enable {
services.mullvad-vpn.enable = cfg.mullvad;
services.mullvad-vpn = {
enable = cfg.mullvad;
package = nixos-stable.mullvad;
};
#
# # Create a specific network namespace for VPN traffic
# systemd.services.mullvad-daemon = {
# serviceConfig = {
# NetworkNamespacePath = "/run/netns/mullvad";
# };
# };
#
# # Configure transmission to use Mullvad's SOCKS5 proxy
# # Configure transmission to use the Mullvad network namespace
# systemd.services.transmission = mkIf config.services.transmission.enable {
# serviceConfig = {
# NetworkNamespacePath = "/run/netns/mullvad";
# };
# # Make sure Mullvad is running before transmission starts
# requires = ["mullvad-daemon.service"];
# after = ["mullvad-daemon.service"];
# };
services.openvpn = {
servers = {
work = {
@ -27,14 +49,21 @@ in {
systemd.services.openvpn-work.wantedBy = lib.mkForce [];
systemd.services."mullvad-daemon".postStart = let
mullvad = config.services.mullvad-vpn.package;
in
mkIf cfg.mullvad ''
while ! ${mullvad}/bin/mullvad status >/dev/null; do sleep 1; done
${mullvad}/bin/mullvad auto-connect set on
${mullvad}/bin/mullvad tunnel set ipv6 on
${mullvad}/bin/mullvad connect
'';
# # Add necessary networking tools
# environment.systemPackages = with pkgs; [
# iproute2 # for ip netns commands
# ];
#
# # Setup network namespace
# systemd.services.setup-mullvad-netns = {
# description = "Setup Mullvad Network Namespace";
# before = ["mullvad-daemon.service"];
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = true;
# ExecStart = "${pkgs.iproute2}/bin/ip netns add mullvad";
# ExecStop = "${pkgs.iproute2}/bin/ip netns delete mullvad";
# };
# };
};
}

View file

@ -26,12 +26,22 @@ in {
recommendedOptimisation = true;
recommendedTlsSettings = true;
sslDhparam = config.security.dhparams.params.nginx.path;
virtualHosts = {
"node.nyc.zackmyers.io" = {
forceSSL = true;
enableACME = true;
};
};
appendHttpConfig = ''
limit_req_zone $binary_remote_addr zone=iso_ratelimit:10m rate=1r/m;
limit_conn_zone $binary_remote_addr zone=iso_connlimit:10m;
access_log /var/log/nginx/blocked.log combined if=$ratelimited;
map $request_uri $ratelimited {
default 0;
~\.iso$ $limit_req_status;
}
'';
};
security.acme = {
acceptTerms = true;
defaults.email = "zach@zacharymyers.com";
};
};
}

View file

@ -0,0 +1,60 @@
{
lib,
config,
pkgs,
...
}:
with lib;
with lib.custom; let
cfg = config.services.wg;
in {
options.services.wg = with types; {
enable = mkBoolOpt false "Enable wg service(s)";
};
config = mkIf cfg.enable {
networking.nat.enable = false;
networking.nat.externalInterface = "enp5s0";
networking.nat.internalInterfaces = ["wg0"];
networking.firewall = {
allowedUDPPorts = [51820];
extraCommands = ''
# Allow WireGuard peer to access only Jellyfin
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -s 10.100.0.2 -d 192.168.1.83 -j ACCEPT
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -s 10.100.0.3 -d 192.168.1.83 -j ACCEPT
'';
extraStopCommands = ''
# Clean up rules when stopping
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -s 10.100.0.2 -d 192.168.1.83 -j ACCEPT
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -s 10.100.0.3 -d 192.168.1.83 -j ACCEPT
'';
};
networking.wireguard.interfaces = {
wg0 = {
ips = ["10.100.0.1/24"];
listenPort = 51820;
privateKeyFile = "/home/zoey/wg-keys/private";
peers = [
# List of allowed peers.
{
# Feel free to give a meaning full name
# Public key of the peer (not a file path).
publicKey = "oxcliwRzjiYda7x90lv71R/PnnPxIWSVIjSjiv2DyBQ=";
# List of IPs assigned to this peer within the tunnel subnet. Used to configure routing.
allowedIPs = ["10.100.0.2/32" "192.168.1.83/32"];
}
{
publicKey = "+lWaMyRJOmijb3pSe8iufFO3lw2VW62uCn/ckJyAUxk=";
allowedIPs = ["10.100.0.3/32" "192.168.1.83/32"];
}
];
};
};
};
}