Initial commit

This commit is contained in:
2025-11-28 01:41:57 +01:00
commit 0be86c7284
113 changed files with 8498 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
# Adguard is a network-wide ad blocker
# When installed, open localhost:3000 to setup
{config, ...}: let
domain = "adguard.hadi.diy";
in {
services = {
adguardhome = {
enable = true;
port = 3000;
};
nginx.virtualHosts."${domain}" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.adguardhome.port}";
};
};
};
}

65
server-modules/arr.nix Normal file
View File

@@ -0,0 +1,65 @@
# *arr is a collection of media management applications.
# See https://github.com/rasmus-kirk/nixarr
# Setup guide: https://nixarr.com/wiki/setup/
{config, ...}: let
domain = "hadi.diy";
mkVirtualHost = port: {
useACMEHost = domain;
forceSSL = true;
locations."/" = {proxyPass = "http://127.0.0.1:${toString port}";};
};
username = config.var.username;
in {
# Add my secrets
sops.secrets = {
recyclarr = {
owner = "recyclarr";
mode = "0777";
};
wireguard-pia = {
group = "media";
mode = "0600";
};
};
nixarr = {
enable = true;
mediaUsers = [username];
mediaDir = "/mnt/data/media";
stateDir = "/mnt/data/.state/nixarr";
vpn = {
enable = true;
wgConf = config.sops.secrets.wireguard-pia.path;
};
jellyfin.enable = true;
jellyseerr.enable = true;
prowlarr.enable = true;
radarr.enable = true;
sonarr.enable = true;
bazarr.enable = true;
readarr.enable = true;
transmission = {
enable = true;
extraSettings = {trash-original-torrent-files = true;};
vpn.enable = true;
};
recyclarr = {
enable = true;
configFile = config.sops.secrets.recyclarr.path;
};
};
services.nginx.virtualHosts = {
"jellyfin.${domain}" = mkVirtualHost 8096;
"jellyseerr.${domain}" = mkVirtualHost 5055;
"bazarr.${domain}" = mkVirtualHost 6767;
"prowlarr.${domain}" = mkVirtualHost 9696;
"radarr.${domain}" = mkVirtualHost 7878;
"sonarr.${domain}" = mkVirtualHost 8989;
"transmission.${domain}" = mkVirtualHost 9091;
"readarr.${domain}" = mkVirtualHost 8787;
};
}

View File

@@ -0,0 +1,23 @@
# Bitwarden (or vaultwarden) is a self-hosted password manager.
{ config, ... }:
let
domain = "vault.jelles.net";
in
{
services = {
vaultwarden = {
enable = true;
backupDir = "/var/backup/vaultwarden";
config = {
DOMAIN = "https://" + domain;
SIGNUPS_ALLOWED = true;
ROCKET_PORT = 8100;
ROCKET_LOG = "critical";
};
};
caddy.virtualHosts."vault.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.vaultwarden.config.ROCKET_PORT}";
};
}

22
server-modules/caddy.nix Normal file
View File

@@ -0,0 +1,22 @@
{ inputs, pkgs, ... }:
{
services.caddy = {
enable = true;
virtualHosts."community.jelles.net".extraConfig = ''
root * ${inputs.community-website.packages.${pkgs.stdenv.hostPlatform.system}.default}
file_server
'';
virtualHosts."zentire.jelles.net".extraConfig = ''
root * ${inputs.zentire-website.packages.${pkgs.stdenv.hostPlatform.system}.default}
file_server
'';
email = "mail@jelles.net";
};
networking.firewall = {
allowedTCPPorts = [
80
443
];
};
}

View File

@@ -0,0 +1,14 @@
{
services = {
copyparty = {
enable = true;
settings = {
e2dsa = true;
no-cfg = true;
};
};
caddy.virtualHosts."files.jelles.net".extraConfig = "reverse_proxy :3923";
};
}

View File

@@ -0,0 +1,35 @@
{
config,
inputs,
pkgs,
...
}:
{
users.groups.eleakxir = { };
users.users.hadi.extraGroups = [ "eleakxir" ];
services.eleakxir = {
enable = true;
port = 9198;
user = "eleakxir";
group = "eleakxir";
limit = 1000;
folders = [
"/var/lib/eleakxir/leaks/"
"/mnt/data/clean-leak/"
];
debug = true;
};
environment.systemPackages = [
inputs.eleakxir.packages.${pkgs.stdenv.hostPlatform.system}.leak-utils
];
services.nginx.virtualHosts."eleakxir-back.hadi.diy" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.eleakxir.port}";
};
};
}

View File

@@ -0,0 +1,9 @@
# Firewall configuration for NixOS
{
networking.firewall = {
enable = true;
allowPing = false;
};
networking.nftables.enable = true;
}

View File

@@ -0,0 +1,353 @@
# Glance is a self-hosted homepage/dashboard service.
{
config,
lib,
...
}: let
domain = "start.hadi.diy";
rgb-to-hsl = color: let
r = ((lib.toInt config.lib.stylix.colors."${color}-rgb-r") * 100.0) / 255;
g = ((lib.toInt config.lib.stylix.colors."${color}-rgb-g") * 100.0) / 255;
b = ((lib.toInt config.lib.stylix.colors."${color}-rgb-b") * 100.0) / 255;
max = lib.max r (lib.max g b);
min = lib.min r (lib.min g b);
delta = max - min;
fmod = base: int: base - (int * builtins.floor (base / int));
h =
if delta == 0
then 0
else if max == r
then 60 * (fmod ((g - b) / delta) 6)
else if max == g
then 60 * (((b - r) / delta) + 2)
else if max == b
then 60 * (((r - g) / delta) + 4)
else 0;
l = (max + min) / 2;
s =
if delta == 0
then 0
else 100 * delta / (100 - lib.max (2 * l - 100) (100 - (2 * l)));
roundToString = value: toString (builtins.floor (value + 0.5));
in
lib.concatMapStringsSep " " roundToString [h s l];
in {
# TODO: Add tailscale custom widget
services = {
glance = {
enable = true;
settings = {
theme = {
contrast-multiplier = lib.mkForce 1.4;
};
pages = [
{
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{
type = "clock";
hour-format = "24h";
}
{
type = "weather";
location = "Paris, France";
}
{
type = "markets";
markets = [
{
symbol = "BTC-USD";
name = "Bitcoin";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:BTCUSD";
}
{
symbol = "SOL-USD";
name = "Solana";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:SOLUSD";
}
{
symbol = "ETH-USD";
name = "Ethereum";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:ETHUSD";
}
];
}
{
type = "dns-stats";
service = "adguard";
url = "https://adguard.hadi.diy";
username = "hadi";
password = "\${secret:adguard-pwd}";
}
];
}
{
size = "full";
widgets = [
{
type = "search";
search-engine = "duckduckgo";
}
{
type = "bookmarks";
groups = [
{
title = "";
same-tab = true;
color = "200 50 50";
links = [
{
title = "ProtonMail";
url = "https://proton.me/mail";
}
{
title = "Github";
url = "https://github.com";
}
{
title = "Youtube";
url = "https://youtube.com";
}
{
title = "Figma";
url = "https://figma.com";
}
];
}
{
title = "Docs";
same-tab = true;
color = "200 50 50";
links = [
{
title = "Nixpkgs repo";
url = "https://github.com/NixOS/nixpkgs";
}
{
title = "Nixvim";
url = "https://nix-community.github.io/nixvim/";
}
{
title = "Hyprland wiki";
url = "https://wiki.hyprland.org/";
}
{
title = "Search NixOS";
url = "https://search-nixos.hadi.diy";
}
];
}
{
title = "Homelab";
same-tab = true;
color = "100 50 50";
links = [
{
title = "Router";
url = "http://192.168.1.254/";
}
{
title = "Cloudflare";
url = "https://dash.cloudflare.com/";
}
];
}
{
title = "Work";
same-tab = true;
color = "50 50 50";
links = [
{
title = "Outlook";
url = "https://outlook.office.com/";
}
{
title = "Teams";
url = "https://teams.microsoft.com/";
}
{
title = "Office";
url = "https://www.office.com/";
}
];
}
{
title = "Cyber";
same-tab = true;
color = rgb-to-hsl "base09";
links = [
{
title = "CyberChef";
url = "https://cyberchef.org/";
}
{
title = "TryHackMe";
url = "https://tryhackme.com/";
}
{
title = "RootMe";
url = "https://www.root-me.org/";
}
{
title = "Exploit-DB";
url = "https://www.exploit-db.com/";
}
{
title = "CrackStation";
url = "https://crackstation.net/";
}
];
}
{
title = "Misc";
same-tab = true;
color = rgb-to-hsl "base01";
links = [
{
title = "Svgl";
url = "https://svgl.app/";
}
{
title = "Excalidraw";
url = "https://excalidraw.com/";
}
{
title = "Cobalt (Downloader)";
url = "https://cobalt.tools/";
}
{
title = "Mazanoke (Image optimizer)";
url = "https://mazanoke.com/";
}
{
title = "Vert (File converter)";
url = "https://vert.sh/";
}
];
}
];
}
{
type = "server-stats";
servers = [
{
type = "local";
name = "Jack";
}
];
}
{
type = "group";
widgets = [
{
type = "monitor";
title = "Services";
cache = "1m";
sites = [
{
title = "Vaultwarden";
url = "https://vault.hadi.diy";
icon = "si:bitwarden";
}
{
title = "Nextcloud";
url = "https://cloud.hadi.diy";
icon = "si:nextcloud";
}
{
title = "Adguard";
url = "https://adguard.hadi.diy";
icon = "si:adguard";
}
{
title = "Mealie";
url = "https://mealie.hadi.diy";
icon = "si:mealie";
}
];
}
{
type = "monitor";
title = "*arr";
cache = "1m";
sites = [
{
title = "Jellyfin";
url = "https://jellyfin.hadi.diy";
icon = "si:jellyfin";
}
{
title = "Jellyseerr";
url = "https://jellyseerr.hadi.diy";
icon = "si:odysee";
}
{
title = "Radarr";
url = "https://radarr.hadi.diy";
icon = "si:radarr";
}
{
title = "Sonarr";
url = "https://sonarr.hadi.diy";
icon = "si:sonarr";
}
{
title = "Prowlarr";
url = "https://prowlarr.hadi.diy";
icon = "si:podcastindex";
}
{
title = "Transmission";
url = "https://transmission.hadi.diy";
icon = "si:transmission";
}
];
}
];
}
];
}
];
name = "Home";
}
];
server = {port = 5678;};
};
};
nginx.virtualHosts."${domain}" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${
toString config.services.glance.settings.server.port
}";
};
};
};
systemd.services.glance = {
serviceConfig = {
DynamicUser = lib.mkForce false;
User = "glance";
Group = "glance";
};
};
users = {
groups.glance = {};
users.glance = {
isSystemUser = true;
description = "Glance user";
group = "glance";
};
};
sops.secrets.adguard-pwd = {
owner = "glance";
mode = "0600";
};
}

300
server-modules/glance.nix Normal file
View File

@@ -0,0 +1,300 @@
{ config, lib, ... }:
let
rgb-to-hsl =
color:
let
r = ((lib.toInt config.lib.stylix.colors."${color}-rgb-r") * 100.0) / 255;
g = ((lib.toInt config.lib.stylix.colors."${color}-rgb-g") * 100.0) / 255;
b = ((lib.toInt config.lib.stylix.colors."${color}-rgb-b") * 100.0) / 255;
max = lib.max r (lib.max g b);
min = lib.min r (lib.min g b);
delta = max - min;
fmod = base: int: base - (int * builtins.floor (base / int));
h =
if delta == 0 then
0
else if max == r then
60 * (fmod ((g - b) / delta) 6)
else if max == g then
60 * (((b - r) / delta) + 2)
else if max == b then
60 * (((r - g) / delta) + 4)
else
0;
l = (max + min) / 2;
s = if delta == 0 then 0 else 100 * delta / (100 - lib.max (2 * l - 100) (100 - (2 * l)));
roundToString = value: toString (builtins.floor (value + 0.5));
in
lib.concatMapStringsSep " " roundToString [
h
s
l
];
in
{
services = {
glance = {
enable = true;
settings = {
server.port = 8101;
pages = [
{
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{
type = "clock";
hour-format = "24h";
}
{
type = "weather";
location = "Paris, France";
}
{
type = "markets";
markets = [
{
symbol = "BTC-USD";
name = "Bitcoin";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:BTCUSD";
}
{
symbol = "SOL-USD";
name = "Solana";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:SOLUSD";
}
{
symbol = "ETH-USD";
name = "Ethereum";
chart-link = "https://www.tradingview.com/chart/?symbol=INDEX:ETHUSD";
}
];
}
];
}
{
size = "full";
widgets = [
{
type = "search";
search-engine = "google";
}
{
type = "bookmarks";
groups = [
{
title = "";
same-tab = true;
color = "200 50 50";
links = [
{
title = "Github";
url = "https://github.com";
}
{
title = "Youtube";
url = "https://youtube.com";
}
{
title = "Figma";
url = "https://figma.com";
}
];
}
{
title = "Docs";
same-tab = true;
color = "200 50 50";
links = [
{
title = "Nixpkgs repo";
url = "https://github.com/NixOS/nixpkgs";
}
{
title = "Nixvim";
url = "https://nix-community.github.io/nixvim/";
}
{
title = "Hyprland wiki";
url = "https://wiki.hyprland.org/";
}
{
title = "Search NixOS";
url = "https://search-nixos.hadi.diy";
}
];
}
{
title = "Homelab";
same-tab = true;
color = "100 50 50";
links = [
{
title = "Router";
url = "http://192.168.1.254/";
}
{
title = "Cloudflare";
url = "https://dash.cloudflare.com/";
}
];
}
{
title = "Work";
same-tab = true;
color = "50 50 50";
links = [
{
title = "Outlook";
url = "https://outlook.office.com/";
}
{
title = "Teams";
url = "https://teams.microsoft.com/";
}
{
title = "Office";
url = "https://www.office.com/";
}
];
}
{
title = "Cyber";
same-tab = true;
color = rgb-to-hsl "base09";
links = [
{
title = "CyberChef";
url = "https://cyberchef.org/";
}
{
title = "TryHackMe";
url = "https://tryhackme.com/";
}
{
title = "RootMe";
url = "https://www.root-me.org/";
}
{
title = "Exploit-DB";
url = "https://www.exploit-db.com/";
}
{
title = "CrackStation";
url = "https://crackstation.net/";
}
];
}
{
title = "Misc";
same-tab = true;
color = rgb-to-hsl "base01";
links = [
{
title = "Svgl";
url = "https://svgl.app/";
}
{
title = "Excalidraw";
url = "https://excalidraw.com/";
}
{
title = "Cobalt (Downloader)";
url = "https://cobalt.tools/";
}
{
title = "Mazanoke (Image optimizer)";
url = "https://mazanoke.com/";
}
{
title = "Vert (File converter)";
url = "https://vert.sh/";
}
];
}
];
}
{
type = "server-stats";
servers = [
{
type = "local";
name = "orion";
}
];
}
{
type = "group";
widgets = [
{
type = "monitor";
title = "Services";
cache = "1m";
sites = [
{
title = "Vaultwarden";
url = "https://vault.jelles.net";
icon = "si:bitwarden";
}
{
title = "Files";
url = "https://fiels.jelles.net";
icon = "si:nextcloud";
}
];
}
{
type = "monitor";
title = "*arr";
cache = "1m";
sites = [
{
title = "Jellyfin";
url = "https://jellyfin.hadi.diy";
icon = "si:jellyfin";
}
{
title = "Jellyseerr";
url = "https://jellyseerr.hadi.diy";
icon = "si:odysee";
}
{
title = "Radarr";
url = "https://radarr.hadi.diy";
icon = "si:radarr";
}
{
title = "Sonarr";
url = "https://sonarr.hadi.diy";
icon = "si:sonarr";
}
{
title = "Prowlarr";
url = "https://prowlarr.hadi.diy";
icon = "si:podcastindex";
}
{
title = "Transmission";
url = "https://transmission.hadi.diy";
icon = "si:transmission";
}
];
}
];
}
];
}
];
name = "Home";
}
];
};
};
caddy.virtualHosts."jelles.net".extraConfig =
"reverse_proxy :${toString config.services.glance.settings.server.port}";
};
}

View File

@@ -0,0 +1,48 @@
{ config, ... }:
{
services = {
home-assistant = {
enable = true;
openFirewall = false;
extraComponents = [
"evohome" # The Honeywell TCC (Europe) component
"met" # Default weather
"radio_browser" # Default radio
];
# Configuration for components that support YAML (like Evohome)
config = {
homeassistant = {
name = "My Home";
latitude = 51.5; # Update with your actual location
longitude = 5.9; # Update with your actual location
unit_system = "metric";
time_zone = config.var.timeZone;
};
# Honeywell TCC (Europe) / Evohome configuration
# https://www.home-assistant.io/integrations/evohome/
evohome = {
username = "!secret honeywell_username";
password = "!secret honeywell_password";
};
# Basic default setup
default_config = { };
http = {
server_port = 8123;
server_host = "127.0.0.1";
use_x_forwarded_for = true;
trusted_proxies = [
"127.0.0.1"
"::1"
];
};
};
};
caddy.virtualHosts."home.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.home-assistant.config.http.server_port}";
};
}

19
server-modules/mealie.nix Normal file
View File

@@ -0,0 +1,19 @@
# Mealie is a recipe management and meal planning application.
{config, ...}: let
domain = "mealie.hadi.diy";
in {
services = {
mealie = {
enable = true;
port = 8092;
};
nginx.virtualHosts."${domain}" = {
useACMEHost = "hadi.diy";
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.mealie.port}";
};
};
};
}

45
server-modules/nginx.nix Normal file
View File

@@ -0,0 +1,45 @@
# Nginx is a web server that can also be used as a reverse proxy, load balancer, and HTTP cache.
{config, ...}: let
domain = "hadi.diy";
in {
security.acme = {
acceptTerms = true;
defaults.email = config.var.git.email;
certs."${domain}" = {
domain = "${domain}";
extraDomainNames = ["*.${domain}"];
group = "nginx";
dnsProvider = "cloudflare";
dnsPropagationCheck = true;
credentialsFile = config.sops.secrets.cloudflare-dns-token.path;
};
};
# Return 444 for all requests not matching a used subdomain.
services.nginx = {
enable = true;
virtualHosts = {
"default" = {
default = true;
locations."/" = {return = 444;};
};
"*.${domain}" = {
useACMEHost = domain;
forceSSL = true;
locations."/" = {return = 444;};
};
"aaaaaa.${domain}" = {
useACMEHost = domain;
forceSSL = true;
locations."/" = {return = 444;};
};
};
};
networking.firewall = {
allowedTCPPorts = [80 443];
allowedUDPPorts = [80 443];
};
sops.secrets.cloudflare-dns-token = {path = "/etc/cloudflare/dnskey.txt";};
}

23
server-modules/ssh.nix Normal file
View File

@@ -0,0 +1,23 @@
# SSH configuration
{ config, ... }:
let
username = config.var.username;
in
{
services.openssh = {
enable = true;
ports = [ 22 ];
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
AllowUsers = [ username ];
};
};
# Add my public SSH key to my user
users.users."${username}" = {
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAU2LydkXRTtNFY7oyX8JQURwXLVhB71DeK8XzrXeFX1 openpgp:0xA490D93A"
];
};
}