Add a homepage module that generates a static landing page served on port 9999 via nginx. Each service module registers itself via the shared mod.homepage.services option, so enabling a module automatically adds it to the page.
110 lines
2.9 KiB
Nix
110 lines
2.9 KiB
Nix
{
|
|
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 ];
|
|
};
|
|
}
|