refactor: refactor the site into a module
This commit is contained in:
parent
fda7580404
commit
3d5c125006
3 changed files with 231 additions and 1 deletions
|
|
@ -6,7 +6,8 @@
|
||||||
./foundry.nix
|
./foundry.nix
|
||||||
./dokuwiki.nix
|
./dokuwiki.nix
|
||||||
./forgejo.nix
|
./forgejo.nix
|
||||||
./wynne.nix
|
../../modules/site.nix
|
||||||
|
./sites.nix
|
||||||
./fail2ban.nix
|
./fail2ban.nix
|
||||||
./uptime-kuma.nix
|
./uptime-kuma.nix
|
||||||
];
|
];
|
||||||
|
|
|
||||||
23
hosts/lab/sites.nix
Normal file
23
hosts/lab/sites.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{ ... }:
|
||||||
|
let
|
||||||
|
wynneDataDir = "/srv/website";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.site.wynne = {
|
||||||
|
domain = "wynne.rs";
|
||||||
|
redirectDomains = [ "ily.rs" ];
|
||||||
|
repo = "https://git.ily.rs/lew/website";
|
||||||
|
branch = "master";
|
||||||
|
port = 4322;
|
||||||
|
packageManager = "pnpm";
|
||||||
|
dataDir = wynneDataDir;
|
||||||
|
environment = {
|
||||||
|
ASTRO_DB_REMOTE_URL = "file:${wynneDataDir}/data/guestbook.db";
|
||||||
|
};
|
||||||
|
buildEnvironment = {
|
||||||
|
ASTRO_DB_REMOTE_URL = "file:${wynneDataDir}/data/guestbook.db";
|
||||||
|
};
|
||||||
|
readWritePaths = [ "${wynneDataDir}/data" ];
|
||||||
|
afterServices = [ "forgejo.service" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
206
modules/site.nix
Normal file
206
modules/site.nix
Normal file
|
|
@ -0,0 +1,206 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib) mkOption types mkIf mkMerge mapAttrsToList optional;
|
||||||
|
|
||||||
|
siteModule = types.submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
domain = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Primary domain name.";
|
||||||
|
};
|
||||||
|
|
||||||
|
redirectDomains = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "Domains that redirect to the primary domain.";
|
||||||
|
};
|
||||||
|
|
||||||
|
repo = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Git repository URL.";
|
||||||
|
};
|
||||||
|
|
||||||
|
branch = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "main";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
description = "Port the Node.js server listens on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
webhookPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = config.port + 1;
|
||||||
|
description = "Port for the rebuild webhook listener.";
|
||||||
|
};
|
||||||
|
|
||||||
|
packageManager = mkOption {
|
||||||
|
type = types.enum [ "npm" "pnpm" ];
|
||||||
|
default = "pnpm";
|
||||||
|
};
|
||||||
|
|
||||||
|
entryPoint = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "dist/server/entry.mjs";
|
||||||
|
description = "Node.js entry point relative to repo root.";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment = mkOption {
|
||||||
|
type = types.attrsOf types.str;
|
||||||
|
default = {};
|
||||||
|
description = "Extra environment variables for the running server.";
|
||||||
|
};
|
||||||
|
|
||||||
|
buildEnvironment = mkOption {
|
||||||
|
type = types.attrsOf types.str;
|
||||||
|
default = {};
|
||||||
|
description = "Extra environment variables for building.";
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/srv/${name}";
|
||||||
|
};
|
||||||
|
|
||||||
|
readWritePaths = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "Extra paths the server can write to at runtime.";
|
||||||
|
};
|
||||||
|
|
||||||
|
afterServices = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "Systemd units to wait for before building.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
cfg = config.services.site;
|
||||||
|
|
||||||
|
makeSiteConfig = name: site:
|
||||||
|
let
|
||||||
|
dataDir = site.dataDir;
|
||||||
|
pmBin =
|
||||||
|
if site.packageManager == "pnpm"
|
||||||
|
then "${pkgs.pnpm}/bin/pnpm"
|
||||||
|
else "${pkgs.nodejs}/bin/npm";
|
||||||
|
installCmd =
|
||||||
|
if site.packageManager == "pnpm"
|
||||||
|
then "${pmBin} install --frozen-lockfile"
|
||||||
|
else "${pmBin} ci";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.caddy.virtualHosts = {
|
||||||
|
${site.domain} = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy localhost:${toString site.port}
|
||||||
|
encode zstd gzip
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
} // builtins.listToAttrs (map (d: {
|
||||||
|
name = d;
|
||||||
|
value.extraConfig = ''
|
||||||
|
redir https://${site.domain}{uri} permanent
|
||||||
|
'';
|
||||||
|
}) site.redirectDomains);
|
||||||
|
|
||||||
|
systemd.services.${name} = {
|
||||||
|
description = site.domain;
|
||||||
|
environment = {
|
||||||
|
HOST = "127.0.0.1";
|
||||||
|
PORT = toString site.port;
|
||||||
|
} // site.environment;
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
WorkingDirectory = "${dataDir}/repo";
|
||||||
|
ExecStart = "${pkgs.nodejs}/bin/node ${site.entryPoint}";
|
||||||
|
Restart = "on-failure";
|
||||||
|
User = name;
|
||||||
|
Group = name;
|
||||||
|
ReadWritePaths = site.readWritePaths;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."${name}-rebuild" = {
|
||||||
|
description = "Clone/pull and build ${site.domain}";
|
||||||
|
after = [ "network-online.target" ] ++ site.afterServices;
|
||||||
|
path = [ pkgs.nodejs pkgs.bash ]
|
||||||
|
++ optional (site.packageManager == "pnpm") pkgs.pnpm;
|
||||||
|
environment = site.buildEnvironment;
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = false;
|
||||||
|
ExecStartPre = "+${pkgs.writeShellScript "prepare-${name}" ''
|
||||||
|
mkdir -p ${dataDir}
|
||||||
|
chown -R ${name}:${name} ${dataDir}
|
||||||
|
''}";
|
||||||
|
ExecStart = pkgs.writeShellScript "rebuild-${name}" ''
|
||||||
|
set -euo pipefail
|
||||||
|
if [ ! -d ${dataDir}/repo/.git ]; then
|
||||||
|
${pkgs.git}/bin/git clone ${site.repo} ${dataDir}/repo
|
||||||
|
fi
|
||||||
|
cd ${dataDir}/repo
|
||||||
|
${pkgs.git}/bin/git fetch origin
|
||||||
|
${pkgs.git}/bin/git reset --hard origin/${site.branch}
|
||||||
|
${installCmd}
|
||||||
|
${pmBin} run build
|
||||||
|
'';
|
||||||
|
ExecStartPost = "+/run/current-system/sw/bin/systemctl restart ${name}";
|
||||||
|
User = name;
|
||||||
|
Group = name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.paths."${name}-rebuild-trigger" = {
|
||||||
|
description = "Watch for ${name} rebuild trigger";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
pathConfig = {
|
||||||
|
PathModified = "${dataDir}/trigger";
|
||||||
|
Unit = "${name}-rebuild.service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."${name}-webhook" = {
|
||||||
|
description = "Webhook listener for ${site.domain}";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = let
|
||||||
|
hooks = pkgs.writeText "${name}-hooks.json" (builtins.toJSON [{
|
||||||
|
id = "${name}-rebuild";
|
||||||
|
execute-command = "/run/current-system/sw/bin/touch";
|
||||||
|
pass-arguments-to-command = [
|
||||||
|
{ source = "string"; name = "${dataDir}/trigger"; }
|
||||||
|
];
|
||||||
|
}]);
|
||||||
|
in "${pkgs.webhook}/bin/webhook -hooks ${hooks} -port ${toString site.webhookPort} -verbose";
|
||||||
|
Restart = "always";
|
||||||
|
User = name;
|
||||||
|
Group = name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.${name} = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = name;
|
||||||
|
home = dataDir;
|
||||||
|
};
|
||||||
|
users.groups.${name} = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.site = mkOption {
|
||||||
|
type = types.attrsOf siteModule;
|
||||||
|
default = {};
|
||||||
|
description = "Node.js web site services with git clone, build, and webhook support.";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (cfg != {}) (mkMerge (mapAttrsToList makeSiteConfig cfg));
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue