split up hopper lab configuration into multiple files
This commit is contained in:
parent
f077fbe3fd
commit
b69fbbcde9
14 changed files with 435 additions and 404 deletions
|
@ -1,21 +1,20 @@
|
|||
## TODO look into sops-nix placeholders
|
||||
## reference: https://github.com/javigomezo/nixos/blob/b3ebe8d570ea9b37aea8bb3a343f6e16e054e322/services/network/authelia/user_database.nix
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
l = lib // builtins;
|
||||
domain = "xunuwu.xyz";
|
||||
caddyPort = 8336;
|
||||
slskdUiPort = 23488;
|
||||
adguardWebPort = 23489;
|
||||
in {
|
||||
imports = [
|
||||
./acme.nix
|
||||
./adguard.nix
|
||||
./caddy.nix
|
||||
./homepage.nix
|
||||
./jellyfin.nix
|
||||
./navidrome.nix
|
||||
./prometheus.nix
|
||||
./restic.nix
|
||||
./samba.nix
|
||||
inputs.authentik-nix.nixosModules.default
|
||||
./slskd.nix
|
||||
./transmission.nix
|
||||
./vaultwarden.nix
|
||||
./vpn-namespace.nix
|
||||
];
|
||||
|
||||
users.groups.media = {};
|
||||
|
@ -24,65 +23,6 @@ in {
|
|||
group = "media";
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "xunuwu@gmail.com";
|
||||
certs = {
|
||||
${domain} = {
|
||||
domain = "*.${domain}";
|
||||
dnsProvider = "cloudflare";
|
||||
reloadServices = ["caddy.service"];
|
||||
credentialFiles.CF_DNS_API_TOKEN_FILE = config.sops.secrets.cloudflare.path;
|
||||
extraDomainNames = [domain];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
vpnNamespaces."wg" = {
|
||||
enable = true;
|
||||
wireguardConfigFile = config.sops.secrets.wireguard.path;
|
||||
accessibleFrom = [
|
||||
"192.168.0.0/24"
|
||||
# "127.0.0.1"
|
||||
];
|
||||
|
||||
# Forwarded to my vpn, for making things accessible from outside
|
||||
openVPNPorts = [
|
||||
{
|
||||
port = caddyPort;
|
||||
protocol = "tcp";
|
||||
}
|
||||
{
|
||||
port = config.services.slskd.settings.soulseek.listen_port;
|
||||
protocol = "both";
|
||||
}
|
||||
{
|
||||
port = config.services.slskd.settings.soulseek.listen_port + 1;
|
||||
protocol = "both";
|
||||
}
|
||||
{
|
||||
port = config.services.transmission.settings.peer-port;
|
||||
protocol = "both";
|
||||
}
|
||||
];
|
||||
|
||||
# From inside of the vpn namespace to outside of it, for making things inside accessible to LAN
|
||||
portMappings = let
|
||||
passthrough = [
|
||||
caddyPort
|
||||
slskdUiPort
|
||||
80 # caddy
|
||||
443 # caddy
|
||||
1900 # jellyfin discovery
|
||||
7359 # jellyfin discovery
|
||||
];
|
||||
in (l.map (x: {
|
||||
from = x;
|
||||
to = x;
|
||||
})
|
||||
passthrough);
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedUDPPorts = [1900 7359]; # Jellyfin auto-discovery
|
||||
allowedTCPPorts = [
|
||||
|
@ -93,337 +33,5 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
systemd.services.caddy.vpnConfinement = {
|
||||
enable = true;
|
||||
vpnNamespace = "wg";
|
||||
};
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts = {
|
||||
jellyfin = {
|
||||
useACMEHost = domain;
|
||||
hostName = "jellyfin.${domain}:${toString caddyPort}";
|
||||
extraConfig = ''
|
||||
reverse_proxy {
|
||||
header_up X-Forwarded-For {http.request.header.CF-Connecting-IP}
|
||||
to localhost:8096
|
||||
}
|
||||
'';
|
||||
};
|
||||
navidrome = {
|
||||
useACMEHost = domain;
|
||||
hostName = "navidrome.${domain}:${toString caddyPort}";
|
||||
extraConfig = ''
|
||||
reverse_proxy unix//var/lib/navidrome/navidrome.sock
|
||||
'';
|
||||
};
|
||||
slskd = {
|
||||
hostName = "slskd.hopper.xun.host:80";
|
||||
extraConfig = ''
|
||||
reverse_proxy localhost:${toString config.services.slskd.settings.web.port}
|
||||
'';
|
||||
};
|
||||
transmission = {
|
||||
hostName = "transmission.hopper.xun.host:80";
|
||||
extraConfig = ''
|
||||
reverse_proxy localhost:${toString config.services.transmission.settings.rpc-port}
|
||||
'';
|
||||
};
|
||||
dash = {
|
||||
hostName = "dash.hopper.xun.host:80";
|
||||
extraConfig = ''
|
||||
reverse_proxy localhost:${toString config.services.homepage-dashboard.listenPort}
|
||||
'';
|
||||
};
|
||||
vw = {
|
||||
useACMEHost = domain;
|
||||
hostName = "vw.${domain}:${toString caddyPort}";
|
||||
extraConfig = ''
|
||||
reverse_proxy {
|
||||
header_up X-Real-Ip {http.request.header.CF-Connecting-IP}
|
||||
to localhost:${toString config.services.vaultwarden.config.ROCKET_PORT}
|
||||
}
|
||||
'';
|
||||
};
|
||||
other = {
|
||||
useACMEHost = domain;
|
||||
hostName = ":${toString caddyPort}";
|
||||
extraConfig = ''
|
||||
respond 404 {
|
||||
body "uhh that doesnt exist, i hope this isnt my fault.."
|
||||
}
|
||||
'';
|
||||
};
|
||||
otherPriv = {
|
||||
hostName = ":80";
|
||||
extraConfig = ''
|
||||
respond 404 {
|
||||
body "uhh that doesnt exist, i hope this isnt my fault.."
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.homepage-dashboard.vpnConfinement = {
|
||||
enable = true;
|
||||
vpnNamespace = "wg";
|
||||
};
|
||||
|
||||
services.homepage-dashboard = {
|
||||
enable = true;
|
||||
widgets = [
|
||||
{
|
||||
resources = {
|
||||
cpu = true;
|
||||
disk = "/";
|
||||
uptime = "";
|
||||
units = "metric";
|
||||
cputemp = true;
|
||||
memory = true;
|
||||
network = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
services = [
|
||||
{
|
||||
"Downloading" = [
|
||||
{
|
||||
"transmission" = {
|
||||
href = "http://transmission.hopper.xun.host";
|
||||
icon = "transmission";
|
||||
};
|
||||
}
|
||||
{
|
||||
"slskd" = {
|
||||
href = "http://slskd.hopper.xun.host";
|
||||
icon = "slskd";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
"Services" = [
|
||||
{
|
||||
"jellyfin" = {
|
||||
href = "https://jellyfin.${domain}";
|
||||
icon = "jellyfin";
|
||||
};
|
||||
}
|
||||
{
|
||||
"navidrome" = {
|
||||
href = "https://navidrome.${domain}";
|
||||
icon = "navidrome";
|
||||
};
|
||||
}
|
||||
{
|
||||
"adguard home" = {
|
||||
href = "http://${config.networking.hostName}:${toString config.services.adguardhome.port}";
|
||||
icon = "adguard-home";
|
||||
};
|
||||
}
|
||||
{
|
||||
"prometheus" = {
|
||||
href = "http://${config.networking.hostName}:${toString config.services.prometheus.port}";
|
||||
icon = "prometheus";
|
||||
};
|
||||
}
|
||||
{
|
||||
"vaultwarden" = {
|
||||
href = "https://vw.${domain}";
|
||||
icon = "vaultwarden";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.jellyfin.vpnConfinement = {
|
||||
enable = true;
|
||||
vpnNamespace = "wg";
|
||||
};
|
||||
|
||||
services.jellyfin.enable = true;
|
||||
|
||||
services.prometheus = {
|
||||
enable = true;
|
||||
port = 9001;
|
||||
extraFlags = ["--storage.tsdb.retention.time=30d"];
|
||||
scrapeConfigs = [
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = lib.singleton {
|
||||
targets = ["127.0.0.1:${toString config.services.prometheus.exporters.node.port}"];
|
||||
};
|
||||
}
|
||||
{
|
||||
job_name = "tailscale_client";
|
||||
static_configs = lib.singleton {
|
||||
targets = ["100.100.100.100"];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.prometheus.exporters = {
|
||||
node = {
|
||||
enable = true;
|
||||
enabledCollectors = ["systemd"];
|
||||
};
|
||||
systemd.enable = true;
|
||||
};
|
||||
|
||||
systemd.services.slskd.vpnConfinement = {
|
||||
enable = true;
|
||||
vpnNamespace = "wg";
|
||||
};
|
||||
|
||||
services.slskd = {
|
||||
enable = true;
|
||||
environmentFile = config.sops.secrets.slskd.path;
|
||||
domain = null; # why isnt this the default?
|
||||
settings = {
|
||||
metrics = {
|
||||
enabled = true;
|
||||
authentication.disabled = true;
|
||||
};
|
||||
remote_file_management = true;
|
||||
shares.directories = ["/media/library/music"];
|
||||
soulseek = {
|
||||
listen_port = 26449;
|
||||
description = "";
|
||||
};
|
||||
global = {
|
||||
upload = {
|
||||
slots = 50;
|
||||
speed_limit = 10000;
|
||||
};
|
||||
download.speed_limit = 10000;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.transmission.vpnConfinement = {
|
||||
enable = true;
|
||||
vpnNamespace = "wg";
|
||||
};
|
||||
|
||||
services.transmission = {
|
||||
enable = true;
|
||||
package = pkgs.transmission_4;
|
||||
performanceNetParameters = true;
|
||||
settings = let
|
||||
mbit = 125;
|
||||
in {
|
||||
speed-limit-up-enabled = true;
|
||||
speed-limit-up = 100 * mbit;
|
||||
speed-limit-down-enabled = true;
|
||||
speed-limit-down = 150 * mbit;
|
||||
rpc-authentication-required = true;
|
||||
peer-port = 11936;
|
||||
rpc-bind-address = "0.0.0.0";
|
||||
rpc-whitelist = "127.0.0.1,192.168.\*.\*";
|
||||
};
|
||||
credentialsFile = config.sops.secrets.transmission.path;
|
||||
};
|
||||
|
||||
boot.kernel.sysctl."fs.inotify.max_user_watches" = 99999999;
|
||||
|
||||
services.adguardhome = {
|
||||
enable = true;
|
||||
mutableSettings = false;
|
||||
port = adguardWebPort;
|
||||
settings = {
|
||||
dhcp.enabled = false;
|
||||
dns = {
|
||||
upstream_dns = [
|
||||
"quic://dns.nextdns.io"
|
||||
"https://cloudflare-dns.com/dns-query"
|
||||
"tls://unfiltered.adguard-dns.com"
|
||||
"https://dns10.quad9.net/dns-query"
|
||||
];
|
||||
bind_hosts = ["100.115.105.144"];
|
||||
bootstrap_dns = ["1.1.1.1" "8.8.8.8"];
|
||||
};
|
||||
filtering = {
|
||||
rewrites = [
|
||||
{
|
||||
domain = "*.hopper.xun.host";
|
||||
answer = "100.115.105.144";
|
||||
}
|
||||
{
|
||||
domain = "hopper.xun.host";
|
||||
answer = "100.115.105.144";
|
||||
}
|
||||
];
|
||||
};
|
||||
filters = [
|
||||
{
|
||||
name = "OISD (Big)";
|
||||
url = "https://big.oisd.nl";
|
||||
enabled = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.${config.services.navidrome.group}.members = ["caddy"]; # for caddy to access socket file
|
||||
services.navidrome = {
|
||||
enable = true;
|
||||
settings = {
|
||||
MusicFolder = "/media/library/music";
|
||||
Address = "unix:/var/lib/navidrome/navidrome.sock";
|
||||
EnableSharing = true;
|
||||
};
|
||||
};
|
||||
systemd.services.navidrome.serviceConfig.EnvironmentFile = config.sops.secrets.navidrome.path;
|
||||
|
||||
systemd.services.vaultwarden = {
|
||||
serviceConfig.EnvironmentFile = config.sops.secrets.vaultwarden-env.path;
|
||||
vpnConfinement = {
|
||||
enable = true;
|
||||
vpnNamespace = "wg";
|
||||
};
|
||||
};
|
||||
# NOTE send doesnt work, probably due to my cloudflare port rewriting rules
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
config = {
|
||||
DOMAIN = "https://${domain}:${toString caddyPort}";
|
||||
ROCKET_ADDRESS = "127.0.0.1";
|
||||
ROCKET_PORT = 35381;
|
||||
ROCKET_LOG = "critical";
|
||||
SIGNUPS_ALLOWED = false;
|
||||
};
|
||||
};
|
||||
|
||||
services.restic.backups.hopper = {
|
||||
initialize = true;
|
||||
inhibitsSleep = true;
|
||||
repository = "rest:http://nixdesk:8000/hopper";
|
||||
passwordFile = config.sops.secrets.restic-password.path;
|
||||
timerConfig = {
|
||||
OnCalendar = "18:00";
|
||||
Persistent = true;
|
||||
RandomizedDelaySec = "1h";
|
||||
};
|
||||
pruneOpts = [
|
||||
"--keep-daily 7"
|
||||
"--keep-weekly 5"
|
||||
"--keep-monthly 12"
|
||||
"--keep-yearly 2"
|
||||
];
|
||||
paths = [
|
||||
"/var/lib/navidrome"
|
||||
"/var/lib/jellyfin/data"
|
||||
"/var/lib/jellyfin/config"
|
||||
"/var/lib/bitwarden_rs"
|
||||
"/media/library/music"
|
||||
];
|
||||
exclude = [
|
||||
"/var/lib/navidrome/cache"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue