From 28b7923e4740abc6b14d637f32a38dd7604f08bc Mon Sep 17 00:00:00 2001 From: Hadi <112569860+anotherhadi@users.noreply.github.com> Date: Sat, 11 Apr 2026 02:26:00 +0200 Subject: [PATCH] New way to deploy apps in my server Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com> --- docs/SERVER.md | 2 - flake.lock | 237 +++++++++++++++++--------- flake.nix | 2 +- hosts/server/configuration.nix | 2 + hosts/server/secrets/secrets.yaml | 8 +- hosts/server/variables.nix | 1 + server-modules/adguardhome.nix | 7 + server-modules/awesome-wallpapers.nix | 53 +++--- server-modules/blog.nix | 84 +++++---- server-modules/cyberchef.nix | 41 +++-- server-modules/default-creds.nix | 37 +++- server-modules/eleakxir.nix | 26 --- server-modules/gitea.nix | 125 +++++++------- server-modules/glance/default.nix | 142 +++++++++------ server-modules/glance/home.nix | 10 +- server-modules/glance/server.nix | 70 +++++--- server-modules/iknowyou.nix | 64 +++++++ server-modules/mazanoke.nix | 78 +++++---- server-modules/mealie.nix | 29 +++- server-modules/mk-container.nix | 61 +++++++ server-modules/stirling-pdf.nix | 28 ++- server-modules/umami.nix | 59 ++++--- 22 files changed, 759 insertions(+), 407 deletions(-) delete mode 100644 server-modules/eleakxir.nix create mode 100644 server-modules/iknowyou.nix create mode 100644 server-modules/mk-container.nix diff --git a/docs/SERVER.md b/docs/SERVER.md index e3fdbcf..4d4e817 100644 --- a/docs/SERVER.md +++ b/docs/SERVER.md @@ -24,8 +24,6 @@ The server hosts several key applications: - **Mealie**: A self-hosted recipe manager and meal planner with a clean user interface. - **Stirling-PDF**: A powerful, locally hosted web application for editing, merging, and converting PDF files. - **CyberChef**: The "Cyber Swiss Army Knife" for data analysis, decoding, and encryption tasks. -- **Linkding**: A simple, fast, and minimalist bookmark manager. - **Mazanoke**: A utility service for image processing, specialized in format conversion and downgrading/optimization. -- **Eleakxir**: A private search engine for exploring data wells (parquet files) with a modern web interface. - **SSH**: Secure remote access configuration for server management. (via browser too) - **Security related stuff**: Cloudflared, Fail2Ban, Firewall diff --git a/flake.lock b/flake.lock index 15006c2..848f6d9 100644 --- a/flake.lock +++ b/flake.lock @@ -38,11 +38,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1775546492, - "narHash": "sha256-nPYrrr9IRCO+4bZu7W/YZ5VknoaNpNI6s2yoSJDzzWM=", + "lastModified": 1775854941, + "narHash": "sha256-N0vdKbQdCsAQux+7aTYHqzIqQ89Xtjpq8CTnq0Mu+gg=", "owner": "anotherhadi", "repo": "awesome-wallpapers", - "rev": "810825e86cc33e5cb1e65b7bdc3468e53187bb1d", + "rev": "c96227e49b858e1ae81c5b887bccf01be4ee5b13", "type": "github" }, "original": { @@ -125,11 +125,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1775241811, - "narHash": "sha256-4Ml38s0ZcFz8Z8OhNbTbjPwjRJEbi6LRopkjKtZ/UPA=", + "lastModified": 1775859534, + "narHash": "sha256-kZ4QFWOaSC8FuMsrEva7jB0Ofj85t8+Fc8zYaH6rCxw=", "owner": "anotherhadi", "repo": "blog", - "rev": "18837d814d4cb103933a9f0cae832b3dbabfbf65", + "rev": "9d928c62186d4f986cdedd200daf6c40a55fe9b4", "type": "github" }, "original": { @@ -210,6 +210,31 @@ "type": "github" } }, + "bun2nix_4": { + "inputs": { + "flake-parts": "flake-parts_4", + "import-tree": "import-tree_4", + "nixpkgs": [ + "iknowyou", + "nixpkgs" + ], + "systems": "systems_5", + "treefmt-nix": "treefmt-nix_4" + }, + "locked": { + "lastModified": 1770895533, + "narHash": "sha256-v3QaK9ugy9bN9RXDnjw0i2OifKmz2NnKM82agtqm/UY=", + "owner": "nix-community", + "repo": "bun2nix", + "rev": "c843f477b15f51151f8c6bcc886954699440a6e1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "bun2nix", + "type": "github" + } + }, "caelestia-cli": { "inputs": { "caelestia-shell": "caelestia-shell", @@ -354,20 +379,6 @@ } }, "flake-compat_2": { - "locked": { - "lastModified": 1733328505, - "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", - "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", - "revCount": 69, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_3": { "flake": false, "locked": { "lastModified": 1751685974, @@ -442,11 +453,11 @@ "nixpkgs-lib": "nixpkgs-lib_4" }, "locked": { - "lastModified": 1772408722, - "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "lastModified": 1769996383, + "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", "type": "github" }, "original": { @@ -893,6 +904,26 @@ "type": "github" } }, + "iknowyou": { + "inputs": { + "bun2nix": "bun2nix_4", + "nixpkgs": "nixpkgs_6", + "nur-osint": "nur-osint" + }, + "locked": { + "lastModified": 1775857107, + "narHash": "sha256-kdXDHdwKrpol9c2Z7l/s47a8P9hGrToWQlKGNKfe3Qo=", + "owner": "anotherhadi", + "repo": "iknowyou", + "rev": "f30c386fbf37013150588678c0ec13f02c354f8d", + "type": "github" + }, + "original": { + "owner": "anotherhadi", + "repo": "iknowyou", + "type": "github" + } + }, "import-tree": { "locked": { "lastModified": 1763762820, @@ -938,6 +969,21 @@ "type": "github" } }, + "import-tree_4": { + "locked": { + "lastModified": 1763762820, + "narHash": "sha256-ZvYKbFib3AEwiNMLsejb/CWs/OL/srFQ8AogkebEPF0=", + "owner": "vic", + "repo": "import-tree", + "rev": "3c23749d8013ec6daa1d7255057590e9ca726646", + "type": "github" + }, + "original": { + "owner": "vic", + "repo": "import-tree", + "type": "github" + } + }, "mnw": { "locked": { "lastModified": 1770419553, @@ -997,7 +1043,7 @@ }, "nixarr": { "inputs": { - "nixpkgs": "nixpkgs_6", + "nixpkgs": "nixpkgs_7", "vpnconfinement": "vpnconfinement", "website-builder": "website-builder" }, @@ -1015,27 +1061,6 @@ "type": "github" } }, - "nixcord": { - "inputs": { - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts_4", - "nixpkgs": "nixpkgs_7", - "nixpkgs-nixcord": "nixpkgs-nixcord" - }, - "locked": { - "lastModified": 1775579520, - "narHash": "sha256-RNp45gx7mlP/udPeYALAF1qYqVlvZwcP/xzrR8H/kTQ=", - "owner": "kaylorben", - "repo": "nixcord", - "rev": "096f9f5b4f83c762fbdbf58a51da82a22615f0f3", - "type": "github" - }, - "original": { - "owner": "kaylorben", - "repo": "nixcord", - "type": "github" - } - }, "nixos-hardware": { "locked": { "lastModified": 1775490113, @@ -1115,11 +1140,11 @@ }, "nixpkgs-lib_4": { "locked": { - "lastModified": 1772328832, - "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=", + "lastModified": 1769909678, + "narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742", + "rev": "72716169fe93074c333e8d0173151350670b824c", "type": "github" }, "original": { @@ -1128,22 +1153,6 @@ "type": "github" } }, - "nixpkgs-nixcord": { - "locked": { - "lastModified": 1773222311, - "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "0590cd39f728e129122770c029970378a79d076a", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-25.11", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs-stable": { "locked": { "lastModified": 1767313136, @@ -1257,6 +1266,22 @@ } }, "nixpkgs_6": { + "locked": { + "lastModified": 1775036866, + "narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6201e203d09599479a3b3450ed24fa81537ebc4e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { "locked": { "lastModified": 1765608474, "narHash": "sha256-9Wx53UK0z8Di5iesJID0tS1dRKwGxI4i7tsSanOHhF0=", @@ -1272,22 +1297,6 @@ "type": "github" } }, - "nixpkgs_7": { - "locked": { - "lastModified": 1773222311, - "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "0590cd39f728e129122770c029970378a79d076a", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-25.11", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs_8": { "locked": { "lastModified": 1775423009, @@ -1345,14 +1354,35 @@ "type": "github" } }, + "nur-osint": { + "inputs": { + "nixpkgs": [ + "iknowyou", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1774035694, + "narHash": "sha256-PtORnAJ/SKeOwrPAjZ0LR00Pu8aDIzXO8H8v9CoM7zk=", + "owner": "anotherhadi", + "repo": "nur-osint", + "rev": "813351d47721d411441bb6221faf2c6163846946", + "type": "github" + }, + "original": { + "owner": "anotherhadi", + "repo": "nur-osint", + "type": "github" + } + }, "nvf": { "inputs": { - "flake-compat": "flake-compat_3", + "flake-compat": "flake-compat_2", "flake-parts": "flake-parts_5", "mnw": "mnw", "ndg": "ndg", "nixpkgs": "nixpkgs_9", - "systems": "systems_5" + "systems": "systems_6" }, "locked": { "lastModified": 1775567832, @@ -1444,9 +1474,9 @@ "default-creds": "default-creds", "home-manager": "home-manager", "hyprland": "hyprland", + "iknowyou": "iknowyou", "nix-index-database": "nix-index-database", "nixarr": "nixarr", - "nixcord": "nixcord", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs_8", "nixpkgs-stable": "nixpkgs-stable", @@ -1479,7 +1509,7 @@ "nixpkgs": [ "nixpkgs" ], - "systems": "systems_6" + "systems": "systems_7" }, "locked": { "lastModified": 1775421933, @@ -1506,7 +1536,7 @@ "gnome-shell": "gnome-shell", "nixpkgs": "nixpkgs_11", "nur": "nur", - "systems": "systems_7", + "systems": "systems_8", "tinted-kitty": "tinted-kitty", "tinted-schemes": "tinted-schemes", "tinted-tmux": "tinted-tmux", @@ -1631,6 +1661,21 @@ "type": "github" } }, + "systems_8": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "tinted-kitty": { "flake": false, "locked": { @@ -1760,6 +1805,28 @@ "type": "github" } }, + "treefmt-nix_4": { + "inputs": { + "nixpkgs": [ + "iknowyou", + "bun2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770228511, + "narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "337a4fe074be1042a35086f15481d763b8ddc0e7", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, "vpnconfinement": { "locked": { "lastModified": 1765634578, diff --git a/flake.nix b/flake.nix index 4310726..918820a 100644 --- a/flake.nix +++ b/flake.nix @@ -11,7 +11,6 @@ nixos-hardware.url = "github:NixOS/nixos-hardware/master"; hyprland.url = "git+https://github.com/hyprwm/Hyprland?submodules=1"; stylix.url = "github:danth/stylix"; - nixcord.url = "github:kaylorben/nixcord"; sops-nix.url = "github:Mic92/sops-nix"; nvf.url = "github:notashelf/nvf"; bun2nix.url = "github:nix-community/bun2nix"; @@ -43,6 +42,7 @@ default-creds.url = "github:anotherhadi/default-creds"; blog.url = "github:anotherhadi/blog"; awesome-wallpapers.url = "github:anotherhadi/awesome-wallpapers"; + iknowyou.url = "github:anotherhadi/iknowyou"; }; outputs = inputs @ {nixpkgs, ...}: { diff --git a/hosts/server/configuration.nix b/hosts/server/configuration.nix index 911d61c..a028893 100644 --- a/hosts/server/configuration.nix +++ b/hosts/server/configuration.nix @@ -19,6 +19,7 @@ # ../../server-modules/eleakxir.nix ../../server-modules/blog.nix ../../server-modules/awesome-wallpapers.nix + ../../server-modules/iknowyou.nix ../../server-modules/stirling-pdf.nix ../../server-modules/cyberchef.nix ../../server-modules/mazanoke.nix @@ -27,6 +28,7 @@ ../../server-modules/default-creds.nix ../../server-modules/umami.nix ../../server-modules/gitea.nix + ../../server-modules/mealie.nix # You should let those lines as is ./hardware-configuration.nix diff --git a/hosts/server/secrets/secrets.yaml b/hosts/server/secrets/secrets.yaml index 39ad5f2..6206863 100644 --- a/hosts/server/secrets/secrets.yaml +++ b/hosts/server/secrets/secrets.yaml @@ -1,7 +1,7 @@ umami-secret: ENC[AES256_GCM,data:tImpd4sD92Omf/YFB8YE4gxAu+g801wQNR+k5rhY6AbzIIYOzpVmQL4XGjfp9Teky3olii4s3XTcmTyuMoxMWg==,iv:QFAEzYnAnxOOtrHWiM2IkvSs0Aqk3s1T5X7j5WC+tO8=,tag:FIbgHLfRVMJ2qZ6dOJ8zLw==,type:str] sshconfig: ENC[AES256_GCM,data:R54HVxqAyj9yGO/AYL8p6cnXgYxkQKW9XveHlBMTnDXBJ7r/4HgnefdymprnXmdlbNWcWrRqmaLEuzJs/0BfixXfMvmGTUrmJ0ASVuDrz9k6rOLADAKFikQh0dib7NU4JmPgmUzMncXc2WuCd3BCG3kwBQ==,iv:Ro9FA+MzTAp+ERQMT88z8ioCox/dTj2vWcqCDOSLag4=,tag:5XiXIyz5/pjGFOB5ZjdOVg==,type:str] github-key: ENC[AES256_GCM,data:NRYhcBIwGJEV13+YECLR+2IErsn/7clbnkx0Mltr7dQajSb5WHZ3QDH0KQPylEHhplE5IVS0h4I0z+Pb1B0UteCxFmJ5wZq+2BKZkvE7G3dojqBpgHcVqJV2GLEJkRjlHfRgsbq/OBe8xcsPh20P1KUyP0WIwVbpt+9dFWGxEGYkp2uSyuBIJ98kElt0zuVgl7WcYoDO7v5WmGzZfla+yZwURvMk8zcM3gopo+4KL6YnYUs+UA3VlBBn6VK4Nvbqy6X0R0+ZA5HHAXg+OFgGmfWnENZmsyQJHXEchGGgEldzThkQ4r8yMkgN/ax+AGouLyzbITapGE4sE11FFgL6Hmp4pSXxl3UAGF+cvV5pIujbb28CXmSPRMyYpoNxI93PSYz/txAzE6Cr2dgwxR4zpMelv4i6IaGnY8NgpY8jp2Y6C0uuJxJCN0RtnjQw1rM2uRnm7vMGyU7XXz9DEVfGnYpTWnykXsEjHE5DVGy80ejYQlc6dtmf3vdTWpt+YYdCPw8/cd0PIx2D6geh1c28,iv:wl+RG24mXYMklD8CBGXVD36DMhlWT/7zh8ZMvr7vgOk=,tag:OJhqF8PoXotr7IsyFW6q1g==,type:str] -adguard-pwd: ENC[AES256_GCM,data:dOFEyLRG3yG9h74J,iv:S/TpCjqakvK5NgSzDukDyI58Y6SLl7NkuutUOY/SrY8=,tag:I9Rv3XYBG8T492ozHoCOWQ==,type:str] +adguard-pwd: ENC[AES256_GCM,data:CAmZFpKN6FFRlCk=,iv:cz45T/z2ZYHNC46FNVp2YHmdhXD4ERhM31+Jo+9PkSk=,tag:GTUvzkYSP4flXs/HUNGYhw==,type:str] recyclarr: ENC[AES256_GCM,data:eJNbGHb4SZvbF7FAHMrpRynmpVyPiTpyZqNx40Fo+lanqdm7d7oRhkLD2PfqxpTcIyV6BxJk12wGUC0uWVuAihmToL/Ih2FJWIQFUOdbaov/xNWHE9mtoRX/A3gIwD8e3DoFMK/dAk2/TyvvAfxi2eYTDJvxecEttHQGxafq1jveHFDcC9e1aFk3M8O8YlX5yF3zl90mugsUVP+iaSURnY/nglZuEDzfJ6Edge7r5OSL6WYh3OUIu1yzuuKXRZ47B/gpXO/cP89JMmxdPj3FUJkk7Htf0s9ALzpVE9fRohDGcpPIkR6COCLTL+mqvVmyopA1zPoX8/X8eiuocpaT3vqJit7Bc6InzflY/5rlg1x0SyoXWQfEsperfNBeiZGngp382I7rrZ8QSwF4AIsmngNeyDRAnfasAU5OVwK+yPIVhRueEFLNrJPG3j2hpArlzpvY2EPBVJDrYwFslis8CASoUdvu6C7VxtJXFcOZR8QemwJarJFU7v1bVhQoIkarn3V7FfAXg/8RfYrn9HAIq5AiFFbQRNHWXzIceIgNKQFb5yfagtMtMq6XKhjsV07jeYt9X/YU80XRfkPm05yiLdLQHcDNmlB3R+SFPD7qjTE7LuSH1Kdc3DvxwrKfHJLsJ+nSIL1po8gDMW8BPc0g4n4dpQ6CFK5BaDFK4eovNpgAXoRC9orkGw/16YmMozp6J78VJLzu3jcYMFbySFznDUuWcFf/7dVV+7pLAj2ffWXzScLISRBhZ9RNUMaZAKAk7WTmxBhw0yzNiih8OFUkbpp1FFLuU0bnBY0iEz+8/OSwv8H7t0HYe29HO61p1huH34B/ZkPA5VLKivFh2mOPNzbvMqtIAkq1ro82Psvc6t88gVIc+VAOZ9zDLohp0FXrNVXwnrs7fxevQa0pUClDivO1ib5G4Znor7q+13jZglmh3G7nHiniO607dRoxszzVEQdTn8ku3XAfIPStsSfQwH46nXhr2kDkspcA7BqwJph0dsKKlfzf22C0OJkDY0L1DgKFvJRmmKAhOdB6XxXYwS+BcDT+8ugejTKpulyPSsbdb0m9p9lVAVu0GMxFEbUsuE+QHiAAP5Vle7swpl4h3i8uHSfKFra3qEswwRnPAHhPSdLSaSU6O6T5gN/b0hhO6dAiNR0UOkOG59fPasL0MRpeb3SkM4Nd6g5b/hY8dXaXR7pQHvh+4GmfJFWYaWm/cZ8k9JAYAw9Sn/spWnjRmpv9bnSxADGbkdV8NDHquDDDFVIIoDnWhQJpqrL61KZITx2Ete1SYdNiy++p3mOYisJgHDsRR1RNQNxhRW4EY8c5nCzgc8x+rU432pCOfMbAuGEfQXMwMGFGeoUg6EL5xEyUEJ/aqymxI+Vjk8h7KfDnOyyL/+1BKEd/GccrjeQfeZGRLI0Tu5gVgL6twc+u4av6inNMMhPFzZuVrfeo6bip5C8R0dK6Pbdz2L/fsgn3E4NNi14NM/DgLLhJRLvKQdCQx+BT+3soNRw5htTzuNS48MD2YDwZYvNfu6mo0r4j4I7Tj8zuCjddbGVa2/5XnhcfdUBx1VOd90H1RKkk8kgSoR0bgo7mLls=,iv:HT3a2YnFy0cF9qUO671kwqxuzFfNnfqynCUVGHf+3dM=,tag:nrA++7fsnc4Cx0OPSDKaRw==,type:str] wireguard-pia: ENC[AES256_GCM,data:2IvJARGhesMuH9RdWzsyrwA7eqrhLyacQqZ1RNEkGOPUkQGX4uimKBSzkxXRy/haZ4V2k73JdLSaB9rAuI0n65GmWHmarwZekOyhRZSNb+zvFgw5BPZmywG1wR2HiTGR/qILovAaz47q/VnohUnjbbMCUvarC4PytWGxMUH96GIgZar8HjHFtK8grCSxlvpHKiDeKx8VSXnY/Pxj1EplBtIqwmtAeZdf/VjtwOL0nY54doPwHdIAvJ0B8Cu0a1zJIGEbV1NlKIHEJ1YA7rmv1ODkBnbXbIHMxAR3jeqR/UDqhDmXe41KujhiJI7nNeO7FKo2v92jK3fSbxYKatLrzXktHpE9JsMYVBXzTK7yAXPgoDdgLXzWH0OrJGBSisPrvqmxUko7MPreuwVYfFlKpll6JLifk8sML4A+94UPR8b89guXn7kBkLg1Y1oIAyguCdKpNOD31nXBMFF0nTcmCwyshDySaGTfJDgox65/77AiN1wH,iv:cdu6lBjLnEEfSFmWMC4Vn2sLKsvpCaatzXlgRNkEMeA=,tag:y1rAeNPB+DNGTpnP94iQrA==,type:str] signing-key: ENC[AES256_GCM,data:FrJzuTgH/ooZkcnYL55uQcc4u+QzNnFvNVs2wDSE4nnwku+EuCJBlb8pd/6W0KPwIXzcki/8CY0YfRcRrzjExMgMa4hwxrlxS9bk3LNPzJsrRK5RJgPg3iA8L791f1zcDxNf8RuWatIqm1TCK+Vhdk/p+221zy1Gcq1dW8X+o4XzbPBzHdLagcIdB0wpjYTtIoGP2X8GoL/NJpuzIiQBK1HdGNKvUI2+ztqCQZOsxm+Fki57NteX3/Llw8AwABjdZvviOBZ62OvJ/SsOQ9NYAvKfAkog5zCn8DLvaqAPGSxRBQEYWM8GyL2imgs54YfEsOpGa4DzMiv4Sc5m398E/asaPq357eksUqh3EYpzoKZ5bIbd5+Vs3KBWKHltUCzXLHaLrIX0CuJFQFi7DCxEbYqlb04x5t3jc/c+/7uwqBHv1Y5gwAjd8JswDWmE7Q3xSk96Za57SCxWPYTo2ErsA2XdL+yxXdhmqkhDZKtUzrcHExhnYe7YLpSlBEclJ/G2BeTOFIWoAmN+1y4rh21R,iv:VaZrv5/41ZyIax702Yae4QmFKpcEaWwPmTo2Mxao3bU=,tag:HC0eqDNit7jQKeeDAKWXKg==,type:str] @@ -18,7 +18,7 @@ sops: TEc5d01RaVFGNXc3dlljM0FTTHpENjQKOqwI+pl8UxVIVl43glnOYvW660/PsDGY yefODJGVtHrOm3yeXC2xlTi3sFW+c5wUl2yPqddbvcBt5Ud/yd4iXQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-25T19:14:13Z" - mac: ENC[AES256_GCM,data:x1OqP6JxTExZm+J75hbLsbZ3X2/WO/ncAF0U+vvI7da+ft+yjT7zf7+nGlaTL3Aus1QBrDBI0WElyemILsRlLZ6dN5tZNBPivsec1HCoJ9wb5hKtM3poZiQWYZDyFUqbFvBiXShJZI8gC7wPKxkycPe8IFLzpJhf2B/WPCBKjUc=,iv:oUZb8hZkEX3APUMllJEZ6c1wdVUJaOuZT4M7ZjW1bZY=,tag:sF/gB8qizWJRliR8PWAoMA==,type:str] + lastmodified: "2026-04-11T00:11:27Z" + mac: ENC[AES256_GCM,data:r9TA1kBOZzn5fZP9Yj6UFhtd7kfoyou0PBDeudBIi3DCBuvFkCpYmsDCQVjheYfeZT3TIpUdqTNi2WsS9ck7IXcZtr4FCrhxcLzWMFvZetnMyAET5OakzrfuaQ496xEavYLQOkPJH5ueCcTUVq7L2PhJVg8xnC61c52xgzva+wQ=,iv:4MgiU9wXOrMtdA7qvWTSLLNpcDUeiBd5GVR381iuyqM=,tag:IOwPh+6rAL6sTUMBOJChjw==,type:str] unencrypted_suffix: _unencrypted - version: 3.12.1 + version: 3.12.2 diff --git a/hosts/server/variables.nix b/hosts/server/variables.nix index 6f3c983..295e6c5 100644 --- a/hosts/server/variables.nix +++ b/hosts/server/variables.nix @@ -33,6 +33,7 @@ domain = "hadi.icu"; tunnelId = "a1dfa315-7fc3-4a65-8c02-8387932c35c3"; + networkInterface = "enp3s0"; }; # Let this here diff --git a/server-modules/adguardhome.nix b/server-modules/adguardhome.nix index 55f7145..9caa2c2 100644 --- a/server-modules/adguardhome.nix +++ b/server-modules/adguardhome.nix @@ -9,6 +9,13 @@ networking.firewall = { allowedTCPPorts = [53]; allowedUDPPorts = [53]; + # Allow containers to reach adguard UI (for glance dns-stats widget) + extraCommands = '' + iptables -I INPUT 1 -s 10.233.0.0/16 -p tcp --dport 3000 -j ACCEPT + ''; + extraStopCommands = '' + iptables -D INPUT -s 10.233.0.0/16 -p tcp --dport 3000 -j ACCEPT 2>/dev/null || true + ''; }; services.cloudflared.tunnels."${config.var.tunnelId}".ingress."adguard.${config.var.domain}" = "http://localhost:${toString config.services.adguardhome.port}"; diff --git a/server-modules/awesome-wallpapers.nix b/server-modules/awesome-wallpapers.nix index 3761518..ff8c3de 100644 --- a/server-modules/awesome-wallpapers.nix +++ b/server-modules/awesome-wallpapers.nix @@ -1,26 +1,33 @@ +{ config, inputs, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; +in { - config, - inputs, - pkgs, - ... -}: { - services = { - nginx.virtualHosts."wall.local" = { - root = "${inputs.awesome-wallpapers.packages.${pkgs.system}.default}/share/awesome-wallpapers"; - listen = [ - { - addr = "127.0.0.1"; - port = 8759; - } - ]; - locations."/" = { - tryFiles = "$uri $uri/ /index.html"; + imports = [ + (mkContainer { + name = "wallpapers"; + hostIp = "10.233.4.1"; + containerIp = "10.233.4.2"; + nixosConfig = { pkgs, ... }: { + services.nginx = { + enable = true; + virtualHosts."wallpapers" = { + root = "${inputs.awesome-wallpapers.packages.${pkgs.system}.default}/share/awesome-wallpapers"; + listen = [{ addr = "0.0.0.0"; port = 8080; }]; + locations."/" = { + tryFiles = "$uri $uri/ /index.html"; + }; + extraConfig = '' + port_in_redirect off; + absolute_redirect off; + ''; + }; + }; + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; }; - extraConfig = '' - port_in_redirect off; - absolute_redirect off; - ''; - }; - cloudflared.tunnels."${config.var.tunnelId}".ingress."wallpapers.${config.var.domain}" = "http://127.0.0.1:8759"; - }; + }) + ]; + + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."wallpapers.${config.var.domain}" = "http://10.233.4.2:8080"; } diff --git a/server-modules/blog.nix b/server-modules/blog.nix index f72b5e7..d876789 100644 --- a/server-modules/blog.nix +++ b/server-modules/blog.nix @@ -1,45 +1,57 @@ { config, inputs, - pkgs, + lib, ... -}: { - services = { - nginx.virtualHosts = { - "blog.local" = { - root = "${inputs.blog.packages.${pkgs.system}.default}/share/blog"; - listen = [ - { - addr = "127.0.0.1"; - port = 8758; - } - ]; - locations."/" = { - tryFiles = "$uri $uri/ /index.html"; +}: let + inherit (import ./mk-container.nix {inherit lib config;}) mkContainer; + domain = config.var.domain; +in { + imports = [ + (mkContainer { + name = "blog"; + hostIp = "10.233.3.1"; + containerIp = "10.233.3.2"; + nixosConfig = {pkgs, ...}: { + services.nginx = { + enable = true; + virtualHosts = { + "blog" = { + root = "${inputs.blog.packages.${pkgs.system}.default}/share/blog"; + listen = [ + { + addr = "0.0.0.0"; + port = 8080; + } + ]; + locations."/" = { + tryFiles = "$uri $uri/ /index.html"; + }; + extraConfig = '' + port_in_redirect off; + absolute_redirect off; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' data: https://umami.${domain}; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://git.${domain}; connect-src 'self' https://umami.${domain};" always; + ''; + }; + "www-redirect" = { + listen = [ + { + addr = "0.0.0.0"; + port = 8081; + } + ]; + extraConfig = "return 301 https://${domain}$request_uri;"; + }; + }; }; - extraConfig = '' - port_in_redirect off; - absolute_redirect off; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' data: https://umami.${config.var.domain}; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://git.${config.var.domain}; connect-src 'self' https://umami.${config.var.domain};" always; - ''; + networking.firewall.allowedTCPPorts = [8080 8081]; + system.stateVersion = "24.05"; }; + }) + ]; - "www.blog.local" = { - listen = [ - { - addr = "127.0.0.1"; - port = 8189; - } - ]; - extraConfig = '' - return 301 https://${config.var.domain}$request_uri; - ''; - }; - }; - - cloudflared.tunnels."${config.var.tunnelId}".ingress = { - "${config.var.domain}" = "http://127.0.0.1:8758"; - "www.${config.var.domain}" = "http://127.0.0.1:8189"; - }; + services.cloudflared.tunnels."${config.var.tunnelId}".ingress = { + "${config.var.domain}" = "http://10.233.3.2:8080"; + "www.${config.var.domain}" = "http://10.233.3.2:8081"; }; } diff --git a/server-modules/cyberchef.nix b/server-modules/cyberchef.nix index a474e75..7f2f08b 100644 --- a/server-modules/cyberchef.nix +++ b/server-modules/cyberchef.nix @@ -1,19 +1,26 @@ -# Cyberchef is a web app for analyzing and decoding data. +{ config, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; +in { - config, - pkgs, - ... -}: { - services = { - nginx.virtualHosts."cyberchef.local" = { - root = "${pkgs.cyberchef}/share/cyberchef"; - listen = [ - { - addr = "127.0.0.1"; - port = 8754; - } - ]; - }; - cloudflared.tunnels."${config.var.tunnelId}".ingress."cyberchef.${config.var.domain}" = "http://localhost:8754"; - }; + imports = [ + (mkContainer { + name = "cyberchef"; + hostIp = "10.233.5.1"; + containerIp = "10.233.5.2"; + nixosConfig = { pkgs, ... }: { + services.nginx = { + enable = true; + virtualHosts."cyberchef" = { + root = "${pkgs.cyberchef}/share/cyberchef"; + listen = [{ addr = "0.0.0.0"; port = 8080; }]; + }; + }; + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; + }; + }) + ]; + + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."cyberchef.${config.var.domain}" = "http://10.233.5.2:8080"; } diff --git a/server-modules/default-creds.nix b/server-modules/default-creds.nix index 1b84acf..39e4436 100644 --- a/server-modules/default-creds.nix +++ b/server-modules/default-creds.nix @@ -1,8 +1,33 @@ -{config, ...}: { - services.default-creds = { - enable = true; - port = 8087; - }; +{ config, inputs, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; + domain = config.var.domain; +in +{ + imports = [ + (mkContainer { + name = "def-creds"; + hostIp = "10.233.6.1"; + containerIp = "10.233.6.2"; + nixosConfig = { ... }: { + imports = [ inputs.default-creds.nixosModules.default ]; + services.default-creds = { + enable = true; + port = 8087; + }; + networking.firewall.allowedTCPPorts = [ 8087 ]; + systemd.services.default-creds.environment = { + HOST = lib.mkForce "0.0.0.0"; + PUBLIC_UMAMI_URL = "https://umami.${domain}"; + PUBLIC_UMAMI_WEBSITE_ID = "7197484c-01ad-488e-9caa-5ab7b7595f08"; + UMAMI_URL = "https://umami.${domain}"; + UMAMI_WEBSITE_ID = "7197484c-01ad-488e-9caa-5ab7b7595f08"; + }; + system.stateVersion = "24.05"; + }; + }) + ]; - services.cloudflared.tunnels."${config.var.tunnelId}".ingress."default-creds.${config.var.domain}" = "http://localhost:${toString config.services.default-creds.port}"; + services.default-creds.enable = lib.mkForce false; + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."default-creds.${config.var.domain}" = "http://10.233.6.2:8087"; } diff --git a/server-modules/eleakxir.nix b/server-modules/eleakxir.nix deleted file mode 100644 index 01d4a8d..0000000 --- a/server-modules/eleakxir.nix +++ /dev/null @@ -1,26 +0,0 @@ -# Eleakxir is a search engine for leaked data. -{ - 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/big-leaks/"]; - debug = true; - }; - - environment.systemPackages = [ - inputs.eleakxir.packages.${pkgs.stdenv.hostPlatform.system}.leak-utils - ]; - - services.cloudflared.tunnels."${config.var.tunnelId}".ingress."eleakxir-back.${config.var.domain}" = "http://localhost:${toString config.services.eleakxir.port}"; -} diff --git a/server-modules/gitea.nix b/server-modules/gitea.nix index 1c2f934..d32ffec 100644 --- a/server-modules/gitea.nix +++ b/server-modules/gitea.nix @@ -1,68 +1,79 @@ -{ - config, - pkgs, - lib, - ... -}: let +{ config, pkgs, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; + domain = config.var.domain; catppuccin-gitea = pkgs.fetchzip { url = "https://github.com/catppuccin/gitea/releases/download/v1.0.2/catppuccin-gitea.tar.gz"; sha256 = "sha256-rZHLORwLUfIFcB6K9yhrzr+UwdPNQVSadsw6rg8Q7gs="; stripRoot = false; }; -in { - services = { - postgresql = { - enable = true; - ensureDatabases = [config.services.gitea.user]; # "gitea" par défaut - ensureUsers = [ - { - name = config.services.gitea.database.user; - ensureDBOwnership = true; - } - ]; - }; - - gitea = { - enable = true; - database = { - type = "postgres"; +in +{ + imports = [ + (mkContainer { + name = "gitea"; + hostIp = "10.233.11.1"; + containerIp = "10.233.11.2"; + internet = true; + bindMounts."/var/lib/gitea" = { + hostPath = "/var/lib/gitea"; + isReadOnly = false; }; - settings = { - server = { - HTTP_ADDR = "127.0.0.1"; - HTTP_PORT = 3002; - ROOT_URL = "https://git.${config.var.domain}/"; - DOMAIN = "git.${config.var.domain}"; - LANDING_PAGE = "/anotherhadi"; + nixosConfig = { lib, ... }: { + users.users.gitea.uid = lib.mkForce 978; + users.groups.gitea.gid = lib.mkForce 968; + + services.postgresql = { + enable = true; + ensureDatabases = [ "gitea" ]; + ensureUsers = [{ + name = "gitea"; + ensureDBOwnership = true; + }]; }; - service = { - REGISTER_MANUAL_CONFIRM = true; - DISABLE_REGISTRATION = true; - DEFAULT_KEEP_EMAIL_PRIVATE = true; - SHOW_REGISTRATION_BUTTON = false; + + services.gitea = { + enable = true; + database.type = "postgres"; + settings = { + server = { + HTTP_ADDR = "0.0.0.0"; + HTTP_PORT = 3002; + ROOT_URL = "https://git.${domain}/"; + DOMAIN = "git.${domain}"; + LANDING_PAGE = "/anotherhadi"; + }; + service = { + REGISTER_MANUAL_CONFIRM = true; + DISABLE_REGISTRATION = true; + DEFAULT_KEEP_EMAIL_PRIVATE = true; + SHOW_REGISTRATION_BUTTON = false; + }; + ui = { + DEFAULT_THEME = "catppuccin-mocha-mauve"; + THEMES = "catppuccin-latte-mauve,catppuccin-frappe-mauve,catppuccin-macchiato-mauve,catppuccin-mocha-mauve"; + }; + explore = { + DISABLE_USERS_PAGE = true; + DISABLE_ORGANIZATIONS_PAGE = true; + }; + repository.DISABLE_STARS = true; + mailer.ENABLED = false; + api.ENABLE_SWAGGER = false; + other.SHOW_FOOTER_VERSION = false; + }; }; - ui = { - DEFAULT_THEME = "catppuccin-mocha-mauve"; - THEMES = "catppuccin-latte-mauve,catppuccin-frappe-mauve,catppuccin-macchiato-mauve,catppuccin-mocha-mauve"; - }; - explore = { - DISABLE_USERS_PAGE = true; - DISABLE_ORGANIZATIONS_PAGE = true; - }; - repository = { - DISABLE_STARS = true; - }; - mailer = {ENABLED = false;}; - api = {ENABLE_SWAGGER = false;}; - other = {SHOW_FOOTER_VERSION = false;}; + + systemd.services.gitea.preStart = lib.mkAfter '' + mkdir -p /var/lib/gitea/custom/public/assets + ln -sfn ${catppuccin-gitea} /var/lib/gitea/custom/public/assets/css + ''; + + networking.firewall.allowedTCPPorts = [ 3002 ]; + system.stateVersion = "24.05"; }; - }; + }) + ]; - cloudflared.tunnels."${config.var.tunnelId}".ingress."git.${config.var.domain}" = "http://localhost:3002"; - }; - - systemd.services.gitea.preStart = lib.mkAfter '' - mkdir -p ${config.services.gitea.stateDir}/custom/public/assets - ln -sfn ${catppuccin-gitea} ${config.services.gitea.stateDir}/custom/public/assets/css - ''; + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."git.${domain}" = "http://10.233.11.2:3002"; } diff --git a/server-modules/glance/default.nix b/server-modules/glance/default.nix index e48894f..a8fe7a7 100644 --- a/server-modules/glance/default.nix +++ b/server-modules/glance/default.nix @@ -1,56 +1,100 @@ -# Glance is a self-hosted homepage/dashboard service. +{ config, lib, ... }: +let + inherit (import ../mk-container.nix { inherit lib config; }) mkContainer; + domain = config.var.domain; + hostIp = "10.233.12.1"; + + # Convert 6-char hex color to "H S L" string for glance (integers, no % sign) + hexToGlanceHsl = hex: + let + h = lib.toLower hex; + d = c: + if c == "a" then 10 else if c == "b" then 11 else if c == "c" then 12 + else if c == "d" then 13 else if c == "e" then 14 else if c == "f" then 15 + else lib.toInt c; + byte = pos: d (builtins.substring pos 1 h) * 16 + d (builtins.substring (pos + 1) 1 h); + ri = byte 0; gi = byte 2; bi = byte 4; + r = ri * 1.0 / 255.0; + g = gi * 1.0 / 255.0; + b = bi * 1.0 / 255.0; + mx = if r >= g && r >= b then "r" else if g >= b then "g" else "b"; + mn = if r <= g && r <= b then "r" else if g <= b then "g" else "b"; + cmax = if mx == "r" then r else if mx == "g" then g else b; + cmin = if mn == "r" then r else if mn == "g" then g else b; + delta = cmax - cmin; + l = (cmax + cmin) / 2.0; + s = if delta < 0.0001 then 0.0 + else if l <= 0.5 then delta / (cmax + cmin) + else delta / (2.0 - cmax - cmin); + hue = + if delta < 0.0001 then 0.0 + else if mx == "r" then let raw = 60.0 * (g - b) / delta; in if raw < 0.0 then raw + 360.0 else raw + else if mx == "g" then 60.0 * ((b - r) / delta + 2.0) + else 60.0 * ((r - g) / delta + 4.0); + in "${toString (builtins.floor (hue + 0.5))} ${toString (builtins.floor (s * 100.0 + 0.5))} ${toString (builtins.floor (l * 100.0 + 0.5))}"; + + c = config.stylix.base16Scheme; +in { - config, - lib, - ... -}: { - imports = [./home.nix ./server.nix]; + # 0444 so the glance user inside the container can read the bind-mounted file + sops.secrets.adguard-pwd.mode = "0444"; - services = { - glance = { - enable = true; - settings = { - # theme.contrast-multiplier = lib.mkForce 1.4; - server.port = 5678; + imports = [ + (mkContainer { + name = "glance"; + hostIp = hostIp; + containerIp = "10.233.12.2"; + internet = true; + bindMounts."/run/secrets/adguard-pwd" = { + hostPath = config.sops.secrets.adguard-pwd.path; + isReadOnly = true; }; - }; - cloudflared.tunnels."${config.var.tunnelId}".ingress."home.${config.var.domain}" = "http://localhost:8755"; + nixosConfig = { lib, ... }: { + _module.args.domain = domain; + _module.args.adguardUrl = "http://${hostIp}:3000"; + imports = [ ./home.nix ./server.nix ]; - nginx.virtualHosts."glance.local" = { - listen = [ - { - addr = "127.0.0.1"; - port = 8755; - } - ]; - locations."/" = { - proxyPass = "http://127.0.0.1:${toString config.services.glance.settings.server.port}"; - extraConfig = '' - proxy_cache_valid 200 30m; - proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; - add_header X-Cache-Status $upstream_cache_status; - ''; + services.glance = { + enable = true; + settings = { + server = { + port = 5678; + host = "127.0.0.1"; + }; + theme = { + light = false; + background-color = hexToGlanceHsl c.base00; # background + primary-color = hexToGlanceHsl c.base0D; # accent (iris/purple) + positive-color = hexToGlanceHsl c.base0B; # positive (pine/teal) + negative-color = hexToGlanceHsl c.base08; # negative (love/rose) + }; + }; + }; + + services.nginx = { + enable = true; + appendHttpConfig = '' + proxy_cache_path /var/cache/nginx/glance levels=1:2 keys_zone=glance:1m inactive=30m max_size=100m; + ''; + virtualHosts."glance" = { + listen = [{ addr = "0.0.0.0"; port = 8080; }]; + locations."/" = { + proxyPass = "http://127.0.0.1:5678"; + extraConfig = '' + proxy_cache glance; + proxy_cache_valid 200 30m; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; + add_header X-Cache-Status $upstream_cache_status; + ''; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; }; - }; - }; + }) + ]; - 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"; - }; + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."home.${domain}" = "http://10.233.12.2:8080"; } diff --git a/server-modules/glance/home.nix b/server-modules/glance/home.nix index 469cb46..710a53e 100644 --- a/server-modules/glance/home.nix +++ b/server-modules/glance/home.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{ domain, ... }: { services.glance.settings.pages = [ { name = "Home"; @@ -97,11 +97,11 @@ } { title = "Mazanoke (image downgrading)"; - url = "https://mazanoke.${config.var.domain}"; + url = "https://mazanoke.${domain}"; } { title = "Stirling PDF"; - url = "https://pdf.${config.var.domain}"; + url = "https://pdf.${domain}"; } { title = "Vert (file converter)"; @@ -200,11 +200,11 @@ links = [ { title = "Nix 4 Cyber"; - url = "https://n4c.${config.var.domain}"; + url = "https://n4c.${domain}"; } { title = "Cyberchef"; - url = "https://cyberchef.${config.var.domain}"; + url = "https://cyberchef.${domain}"; } { title = "TryHackMe"; diff --git a/server-modules/glance/server.nix b/server-modules/glance/server.nix index 5df1e5a..79584c1 100644 --- a/server-modules/glance/server.nix +++ b/server-modules/glance/server.nix @@ -1,4 +1,8 @@ -{config, ...}: { +{ + domain, + adguardUrl, + ... +}: { services.glance.settings.pages = [ { name = "Server"; @@ -26,42 +30,62 @@ sites = [ { title = "Adguard"; - url = "https://adguard.${config.var.domain}"; + url = "https://adguard.${domain}"; icon = "si:adguard"; } + { + title = "Blog"; + url = "https://${domain}"; + icon = "si:blogger"; + } + { + title = "Gitea"; + url = "https://git.${domain}"; + icon = "si:gitea"; + } { title = "Mealie"; - url = "https://mealie.${config.var.domain}"; + url = "https://mealie.${domain}"; icon = "si:mealie"; } { - title = "Linkding"; - url = "https://linkding.${config.var.domain}"; - icon = "sh:linkding"; + title = "Umami"; + url = "https://umami.${domain}"; + icon = "si:umami"; + } + { + title = "Iknowyou"; + url = "https://iknowyou.${domain}"; + icon = "sh:iknowyou"; + } + { + title = "Iknowyou Prod"; + url = "https://iknowyou-prod.${domain}"; + icon = "sh:iknowyou"; + } + { + title = "Wallpapers"; + url = "https://wallpapers.${domain}"; + icon = "si:unsplash"; } { title = "Mazanoke"; - url = "https://mazanoke.${config.var.domain}"; + url = "https://mazanoke.${domain}"; icon = "sh:mazanoke"; } { title = "Stirling PDF"; - url = "https://pdf.${config.var.domain}"; + url = "https://pdf.${domain}"; icon = "sh:stirling-pdf"; } { title = "Default-creds"; - url = "https://default-creds.${config.var.domain}"; + url = "https://default-creds.${domain}"; icon = "si:passbolt"; } - { - title = "Blog"; - url = "https://${config.var.domain}"; - icon = "si:blogger"; - } { title = "Cyberchef"; - url = "https://cyberchef.${config.var.domain}"; + url = "https://cyberchef.${domain}"; icon = "si:codechef"; } ]; @@ -73,37 +97,37 @@ sites = [ { title = "Jellyfin"; - url = "https://media.${config.var.domain}"; + url = "https://media.${domain}"; icon = "si:jellyfin"; } { title = "Jellyseerr"; - url = "https://demandemedia.${config.var.domain}"; + url = "https://demandemedia.${domain}"; icon = "si:odysee"; } { title = "Radarr"; - url = "https://radarr.${config.var.domain}"; + url = "https://radarr.${domain}"; icon = "si:radarr"; } { title = "Sonarr"; - url = "https://sonarr.${config.var.domain}"; + url = "https://sonarr.${domain}"; icon = "si:sonarr"; } { title = "Bazarr"; - url = "https://bazarr.${config.var.domain}"; + url = "https://bazarr.${domain}"; icon = "si:subtitleedit"; } { title = "Prowlarr"; - url = "https://prowlarr.${config.var.domain}"; + url = "https://prowlarr.${domain}"; icon = "si:podcastindex"; } { title = "Transmission"; - url = "https://transmission.${config.var.domain}"; + url = "https://transmission.${domain}"; icon = "si:transmission"; } ]; @@ -114,7 +138,7 @@ { type = "dns-stats"; service = "adguard"; - url = "http://localhost:${toString config.services.adguardhome.port}"; + url = adguardUrl; username = "hadi"; password = "\${secret:adguard-pwd}"; } diff --git a/server-modules/iknowyou.nix b/server-modules/iknowyou.nix new file mode 100644 index 0000000..65ddd95 --- /dev/null +++ b/server-modules/iknowyou.nix @@ -0,0 +1,64 @@ +{ + config, + inputs, + lib, + ... +}: let + inherit (import ./mk-container.nix {inherit lib config;}) mkContainer; +in { + imports = [ + (mkContainer { + name = "iky-prod"; + hostIp = "10.233.1.1"; + containerIp = "10.233.1.2"; + internet = true; + bindMounts."/etc/iky/config.yaml" = { + hostPath = "/var/lib/iknowyou-prod/config.yaml"; + isReadOnly = false; + }; + nixosConfig = {...}: { + imports = [inputs.iknowyou.nixosModules.default]; + users.users.iknowyou.uid = 999; + users.groups.iknowyou.gid = 999; + services.iknowyou = { + enable = true; + port = 8080; + openFirewall = true; + }; + system.stateVersion = "24.05"; + }; + }) + + (mkContainer { + name = "iky-demo"; + hostIp = "10.233.2.1"; + containerIp = "10.233.2.2"; + nixosConfig = {...}: { + imports = [inputs.iknowyou.nixosModules.default]; + services.iknowyou = { + enable = true; + port = 8080; + openFirewall = true; + }; + systemd.services.iknowyou.environment.IKY_DEMO = "true"; + system.stateVersion = "24.05"; + }; + }) + ]; + + users.users.iknowyou = { + isSystemUser = true; + group = "iknowyou"; + uid = 999; + }; + users.groups.iknowyou.gid = 999; + + systemd.tmpfiles.rules = [ + "f /var/lib/iknowyou-prod/config.yaml 0600 iknowyou iknowyou -" + ]; + + services.cloudflared.tunnels."${config.var.tunnelId}".ingress = { + "iknowyou-prod.${config.var.domain}" = "http://10.233.1.2:8080"; + "iknowyou.${config.var.domain}" = "http://10.233.2.2:8080"; + }; +} diff --git a/server-modules/mazanoke.nix b/server-modules/mazanoke.nix index 5b21a2d..7e03b1c 100644 --- a/server-modules/mazanoke.nix +++ b/server-modules/mazanoke.nix @@ -1,39 +1,45 @@ -# Mazanoke is a self-hosted image downgrader +{ config, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; +in { - config, - pkgs, - ... -}: let - version = "1.1.5"; - mazanoke-pkg = pkgs.stdenv.mkDerivation { - inherit version; - pname = "mazanoke"; - src = pkgs.fetchFromGitHub { - owner = "civilblur"; - repo = "mazanoke"; - rev = "v${version}"; - hash = "sha256-B/AF4diMNxN94BzpZP/C+K8kNj9q+4SDKWa/qd4LrVU="; - }; - - installPhase = '' - mkdir -p $out/share/mazanoke - cp -r ./index.html ./favicon.ico ./manifest.json ./service-worker.js ./assets $out/share/mazanoke/ - ''; - }; -in { - services = { - nginx.virtualHosts."mazanoke.local" = { - root = "${mazanoke-pkg}/share/mazanoke"; - locations."/" = { - index = "index.html"; - }; - listen = [ + imports = [ + (mkContainer { + name = "mazanoke"; + hostIp = "10.233.7.1"; + containerIp = "10.233.7.2"; + nixosConfig = { pkgs, ... }: + let + version = "1.1.5"; + mazanoke-pkg = pkgs.stdenv.mkDerivation { + inherit version; + pname = "mazanoke"; + src = pkgs.fetchFromGitHub { + owner = "civilblur"; + repo = "mazanoke"; + rev = "v${version}"; + hash = "sha256-B/AF4diMNxN94BzpZP/C+K8kNj9q+4SDKWa/qd4LrVU="; + }; + installPhase = '' + mkdir -p $out/share/mazanoke + cp -r ./index.html ./favicon.ico ./manifest.json ./service-worker.js ./assets $out/share/mazanoke/ + ''; + }; + in { - addr = "127.0.0.1"; - port = 8755; - } - ]; - }; - cloudflared.tunnels."${config.var.tunnelId}".ingress."mazanoke.${config.var.domain}" = "http://localhost:8755"; - }; + services.nginx = { + enable = true; + virtualHosts."mazanoke" = { + root = "${mazanoke-pkg}/share/mazanoke"; + listen = [{ addr = "0.0.0.0"; port = 8080; }]; + locations."/" = { index = "index.html"; }; + }; + }; + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; + }; + }) + ]; + + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."mazanoke.${config.var.domain}" = "http://10.233.7.2:8080"; } diff --git a/server-modules/mealie.nix b/server-modules/mealie.nix index b42976d..ecf47be 100644 --- a/server-modules/mealie.nix +++ b/server-modules/mealie.nix @@ -1,9 +1,24 @@ -# Mealie is a recipe management and meal planning application. -{config, ...}: { - services.mealie = { - enable = true; - port = 8092; - }; +{ config, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; +in +{ + imports = [ + (mkContainer { + name = "mealie"; + hostIp = "10.233.8.1"; + containerIp = "10.233.8.2"; + internet = true; + nixosConfig = { ... }: { + services.mealie = { + enable = true; + port = 8080; + }; + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; + }; + }) + ]; - services.cloudflared.tunnels."${config.var.tunnelId}".ingress."mealie.${config.var.domain}" = "http://localhost:${toString config.services.mealie.port}"; + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."mealie.${config.var.domain}" = "http://10.233.8.2:8080"; } diff --git a/server-modules/mk-container.nix b/server-modules/mk-container.nix new file mode 100644 index 0000000..2a1634d --- /dev/null +++ b/server-modules/mk-container.nix @@ -0,0 +1,61 @@ +{ lib, config }: + +# Returns a NixOS module (attrset), to be used in `imports`. +# +# Options: +# internet - allow outbound internet access via NAT (default: false) +# externalInterface - WAN interface for NAT, required when internet = true +# bindMounts - host paths to mount into the container (see containers..bindMounts) +# config - NixOS module for the container +{ + mkContainer = + { + name, + hostIp, + containerIp, + internet ? false, + externalInterface ? config.var.networkInterface, + bindMounts ? {}, + nixosConfig, + }: + assert lib.assertMsg + (lib.stringLength "ve-${name}" <= 15) + "mkContainer: interface name 've-${name}' is ${toString (lib.stringLength "ve-${name}")} chars, max is 15"; + { + containers.${name} = { + autoStart = true; + privateNetwork = true; + hostAddress = hostIp; + localAddress = containerIp; + inherit bindMounts; + config = { ... }: { + imports = [ nixosConfig ]; + networking.nameservers = lib.mkIf internet [ "1.1.1.1" "1.0.0.1" ]; + }; + }; + } + // (lib.optionalAttrs internet { + boot.kernel.sysctl."net.ipv4.ip_forward" = lib.mkDefault true; + networking.nat = { + enable = true; + externalInterface = externalInterface; + internalInterfaces = [ "ve-${name}" ]; + }; + # CONTAINER-FWD (defined by another module) blocks all forwarding by default. + # Insert rules in FORWARD before it: allow return traffic, block LAN, allow internet. + networking.firewall.extraCommands = '' + iptables -I FORWARD 1 -s ${containerIp} -m conntrack --ctstate NEW -j ACCEPT + iptables -I FORWARD 1 -s ${containerIp} -d 192.168.0.0/16 -j DROP + iptables -I FORWARD 1 -s ${containerIp} -d 172.16.0.0/12 -j DROP + iptables -I FORWARD 1 -s ${containerIp} -d 10.0.0.0/8 -j DROP + iptables -I FORWARD 1 -d ${containerIp} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + ''; + networking.firewall.extraStopCommands = '' + iptables -D FORWARD -s ${containerIp} -m conntrack --ctstate NEW -j ACCEPT 2>/dev/null || true + iptables -D FORWARD -s ${containerIp} -d 192.168.0.0/16 -j DROP 2>/dev/null || true + iptables -D FORWARD -s ${containerIp} -d 172.16.0.0/12 -j DROP 2>/dev/null || true + iptables -D FORWARD -s ${containerIp} -d 10.0.0.0/8 -j DROP 2>/dev/null || true + iptables -D FORWARD -d ${containerIp} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true + ''; + }); +} diff --git a/server-modules/stirling-pdf.nix b/server-modules/stirling-pdf.nix index 80cab4d..bfcc920 100644 --- a/server-modules/stirling-pdf.nix +++ b/server-modules/stirling-pdf.nix @@ -1,9 +1,23 @@ -# Stirling-pdf is a high-performance PDF editor and viewer service. -{config, ...}: { - services.stirling-pdf = { - enable = true; - environment."SERVER_PORT" = "8083"; - }; +{ config, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; +in +{ + imports = [ + (mkContainer { + name = "stirling-pdf"; + hostIp = "10.233.9.1"; + containerIp = "10.233.9.2"; + nixosConfig = { ... }: { + services.stirling-pdf = { + enable = true; + environment."SERVER_PORT" = "8080"; + }; + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; + }; + }) + ]; - services.cloudflared.tunnels."${config.var.tunnelId}".ingress."pdf.${config.var.domain}" = "http://localhost:${toString config.services.stirling-pdf.environment.SERVER_PORT}"; + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."pdf.${config.var.domain}" = "http://10.233.9.2:8080"; } diff --git a/server-modules/umami.nix b/server-modules/umami.nix index e28b198..fbb3f4c 100644 --- a/server-modules/umami.nix +++ b/server-modules/umami.nix @@ -1,24 +1,37 @@ -{config, ...}: { - sops.secrets = { - umami-secret = { - mode = "0600"; - }; - }; - services.umami = { - enable = true; - settings = { - PORT = 8097; - APP_SECRET_FILE = config.sops.secrets.umami-secret.path; - DISABLE_TELEMETRY = true; - DISABLE_BOT_CHECK = true; - }; - }; - services.cloudflared.tunnels."${config.var.tunnelId}".ingress."umami.${config.var.domain}" = "http://localhost:${toString config.services.umami.settings.PORT}"; - systemd.services.default-creds.environment = { - PUBLIC_UMAMI_URL = "https://umami.${config.var.domain}"; - # FIXME: - PUBLIC_UMAMI_WEBSITE_ID = "7197484c-01ad-488e-9caa-5ab7b7595f08"; - UMAMI_URL = "http://localhost:8097"; - UMAMI_WEBSITE_ID = "7197484c-01ad-488e-9caa-5ab7b7595f08"; - }; +{ config, lib, ... }: +let + inherit (import ./mk-container.nix { inherit lib config; }) mkContainer; +in +{ + sops.secrets.umami-secret.mode = "0400"; + + imports = [ + (mkContainer { + name = "umami"; + hostIp = "10.233.10.1"; + containerIp = "10.233.10.2"; + bindMounts."/run/secrets/umami-secret" = { + hostPath = config.sops.secrets.umami-secret.path; + isReadOnly = true; + }; + nixosConfig = { ... }: { + services.umami = { + enable = true; + settings = { + PORT = 8080; + HOSTNAME = "0.0.0.0"; + APP_SECRET_FILE = "/run/secrets/umami-secret"; + DISABLE_TELEMETRY = true; + DISABLE_BOT_CHECK = true; + }; + }; + # PrivateUsers breaks systemd-creds inside nspawn containers (nested user namespaces) + systemd.services.umami.serviceConfig.PrivateUsers = lib.mkForce false; + networking.firewall.allowedTCPPorts = [ 8080 ]; + system.stateVersion = "24.05"; + }; + }) + ]; + + services.cloudflared.tunnels."${config.var.tunnelId}".ingress."umami.${config.var.domain}" = "http://10.233.10.2:8080"; }