manatee: Add services homepage with auto-discovery

Add a homepage module that generates a static landing page served on
port 80 via nginx. Each service module registers itself via the shared
mod.homepage.services option, so enabling a module automatically adds
it to the page.
This commit is contained in:
Alexander Heldt
2026-02-28 21:46:44 +01:00
parent f2130be7e4
commit cd83e17d46
10 changed files with 165 additions and 0 deletions

View File

@@ -10,6 +10,12 @@ in
};
config = lib.mkIf enabled {
mod.homepage.services = [{
name = "Audiobookshelf";
port = 8000;
description = "Audiobooks & podcasts";
}];
users.users.audiobookshelf = {
isSystemUser = true;
description = "audiobookshelf";

View File

@@ -10,6 +10,12 @@ in
};
config = lib.mkIf enabled {
mod.homepage.services = [{
name = "Calibre-Web";
port = 8083;
description = "E-book library";
}];
services = {
calibre-web = {
enable = true;

View File

@@ -22,6 +22,7 @@ in
immich.enable = true;
navidrome.enable = true;
komga.enable = true;
homepage.enable = true;
};
};
}

View File

@@ -0,0 +1,109 @@
{
pkgs,
lib,
config,
...
}:
let
enabled = config.mod.homepage.enable;
nginxEnabled = config.mod.nginx.enable;
services = config.mod.homepage.services;
serviceToCard = svc: ''
<a class="card" href="http://manatee:${toString svc.port}">
<div class="name">${svc.name}</div>
<div class="desc">${svc.description}</div>
<div class="port">:${toString svc.port}</div>
</a>
'';
page = pkgs.writeTextDir "index.html" ''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>manatee</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #1a1b26;
color: #c0caf5;
min-height: 100vh;
padding: 3rem 1.5rem;
}
h1 {
text-align: center;
font-size: 1.5rem;
font-weight: 400;
color: #7aa2f7;
margin-bottom: 2rem;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
max-width: 900px;
margin: 0 auto;
}
.card {
display: block;
background: #24283b;
border: 1px solid #414868;
border-radius: 8px;
padding: 1.25rem;
text-decoration: none;
color: inherit;
transition: border-color 0.15s;
}
.card:hover { border-color: #7aa2f7; }
.name { font-size: 1.1rem; font-weight: 600; color: #c0caf5; }
.desc { font-size: 0.85rem; color: #565f89; margin-top: 0.35rem; }
.port { font-size: 0.8rem; color: #414868; margin-top: 0.5rem; font-family: monospace; }
</style>
</head>
<body>
<h1>manatee</h1>
<div class="grid">
${lib.concatMapStrings serviceToCard services}
</div>
</body>
</html>
'';
in
{
options = {
mod.homepage = {
enable = lib.mkEnableOption "Enable homepage module";
services = lib.mkOption {
type = lib.types.listOf (lib.types.submodule {
options = {
name = lib.mkOption { type = lib.types.str; };
port = lib.mkOption { type = lib.types.port; };
description = lib.mkOption { type = lib.types.str; };
};
});
default = [ ];
description = "Services to display on the homepage";
};
};
};
config = lib.mkIf (enabled && nginxEnabled) {
services.nginx.virtualHosts."homepage" = {
listen = [
{
addr = "0.0.0.0";
port = 9999;
}
];
root = page;
locations."/" = {
index = "index.html";
};
};
networking.firewall.allowedTCPPorts = [ 9999 ];
};
}

View File

@@ -10,6 +10,12 @@ in
};
config = lib.mkIf enabled {
mod.homepage.services = [{
name = "Immich";
port = 2283;
description = "Photo library";
}];
users.users.immich = {
isSystemUser = true;
group = "storage";

View File

@@ -47,6 +47,12 @@ in
};
};
mod.homepage.services = [{
name = "Jellyfin";
port = 8096;
description = "Media streaming";
}];
networking = {
firewall.allowedTCPPorts = [ 8096 ];
};

View File

@@ -19,6 +19,19 @@ in
imports = [ inputs.komga-comictracker.nixosModules.default ];
config = lib.mkIf enabled {
mod.homepage.services = [
{
name = "Komga";
port = 8002;
description = "Comic library";
}
{
name = "Komga Reader";
port = 8888;
description = "Comic reader";
}
];
users.users.komga = {
isSystemUser = true;
group = "storage";

View File

@@ -15,6 +15,12 @@ in
};
config = {
mod.homepage.services = lib.mkIf navidromeEnabled [{
name = "Navidrome";
port = 4533;
description = "Music streaming";
}];
services = lib.mkIf navidromeEnabled {
navidrome = {
enable = true;

View File

@@ -10,6 +10,12 @@ in
};
config = lib.mkIf enabled {
mod.homepage.services = [{
name = "Syncthing";
port = 8384;
description = "File sync";
}];
services.syncthing = {
enable = true;

View File

@@ -15,6 +15,12 @@ in
};
config = lib.mkIf enabled {
mod.homepage.services = [{
name = "Transmission";
port = 9091;
description = "Torrent client";
}];
services = {
transmission = {
enable = true;