From 415e9862b6e6a8e92b346d2ff3bfa14c2e9f4a78 Mon Sep 17 00:00:00 2001 From: ulic-youthlic Date: Thu, 19 Feb 2026 13:34:09 +0800 Subject: [PATCH] feat: Add module for self-hosted cinny --- nixos/configurations/Tytonidae/default.nix | 14 ++++ nixos/modules/programs/caddy/cinny.nix | 27 +++++++ nixos/modules/programs/miniserve/cinny.nix | 16 ++++ nixos/modules/programs/miniserve/default.nix | 84 ++++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 nixos/modules/programs/caddy/cinny.nix create mode 100644 nixos/modules/programs/miniserve/cinny.nix create mode 100644 nixos/modules/programs/miniserve/default.nix diff --git a/nixos/configurations/Tytonidae/default.nix b/nixos/configurations/Tytonidae/default.nix index 208e7b9..1f72c13 100644 --- a/nixos/configurations/Tytonidae/default.nix +++ b/nixos/configurations/Tytonidae/default.nix @@ -3,6 +3,7 @@ lib, inputs, outputs, + config, ... }: { imports = @@ -39,6 +40,19 @@ }; }; programs = { + miniserve = { + enable = true; + apps = let + cinny-template = config.youthlic.programs.miniserve.templates.cinny; + in { + cinny-1 = cinny-template { + port = 9093; + }; + cinny-2 = cinny-template { + port = 9094; + }; + }; + }; bash.enable = true; guix.enable = true; dae.enable = true; diff --git a/nixos/modules/programs/caddy/cinny.nix b/nixos/modules/programs/caddy/cinny.nix new file mode 100644 index 0000000..a1b9aae --- /dev/null +++ b/nixos/modules/programs/caddy/cinny.nix @@ -0,0 +1,27 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.youthlic.programs.caddy.cinny; + caddy-cfg = config.youthlic.programs.caddy; +in { + options = { + youthlic.programs.caddy.cinny = { + enable = lib.mkEnableOption "caddy.cinny"; + }; + }; + config = lib.mkIf (cfg.enable && caddy-cfg.enable) { + services.caddy.virtualHosts = { + "cinny.${caddy-cfg.baseDomain}" = { + extraConfig = '' + root * ${pkgs.cinny} + encode gzip zstd + try_files {path} /index.html + file_server + ''; + }; + }; + }; +} diff --git a/nixos/modules/programs/miniserve/cinny.nix b/nixos/modules/programs/miniserve/cinny.nix new file mode 100644 index 0000000..8505e09 --- /dev/null +++ b/nixos/modules/programs/miniserve/cinny.nix @@ -0,0 +1,16 @@ +{ + pkgs, + lib, + ... +}: { + config.youthlic.programs.miniserve.templates.cinny = {port, ...} @ args: + { + inherit port; + directory = args.cinny or (toString pkgs.cinny); + defaultIndex = "index.html"; + isSpa = true; + } + // (lib.optionalAttrs (args ? interface) { + inherit (args) interface; + }); +} diff --git a/nixos/modules/programs/miniserve/default.nix b/nixos/modules/programs/miniserve/default.nix new file mode 100644 index 0000000..2166627 --- /dev/null +++ b/nixos/modules/programs/miniserve/default.nix @@ -0,0 +1,84 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.youthlic.programs.miniserve; +in { + imports = lib.youthlic.loadImports ./.; + options = { + youthlic.programs.miniserve = { + enable = lib.mkEnableOption "miniserve"; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.miniserve; + }; + templates = lib.mkOption { + type = lib.types.attrsOf lib.types.anything; + default = {}; + }; + apps = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({...}: { + options = { + port = lib.mkOption { + type = lib.types.port; + }; + interface = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + }; + isSpa = lib.mkEnableOption "is spa"; + directory = lib.mkOption { + type = lib.types.either lib.types.package lib.types.path; + }; + defaultIndex = lib.mkOption { + type = lib.types.str; + default = "index.html"; + }; + }; + })); + default = {}; + }; + }; + }; + config = lib.mkIf (cfg.enable && (cfg.apps != {})) { + systemd.services = + lib.concatMapAttrs (name: value: { + "miniserve-${name}" = { + description = '' + miniserve for ${name} + ''; + after = ["network-online.target"]; + wants = ["network-online.target"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + ExecStart = '' + ${lib.getExe cfg.package} ${lib.optionalString value.isSpa "--spa"} --index ${value.directory}/${value.defaultIndex} --port ${toString value.port} --interfaces ${value.interface} ${value.directory} + ''; + IPAccounting = "yes"; + IPAddressAllow = value.interface; + IPAddressDeny = "any"; + DynamicUser = "yes"; + PrivateTmp = "yes"; + PrivateUsers = "yes"; + PrivateDevices = "yes"; + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = "yes"; + ProtectClock = "yes"; + ProtectControlGroups = "yes"; + ProtectKernelLogs = "yes"; + ProtectKernelModules = "yes"; + ProtectKernelTunables = "yes"; + ProtectProc = "invisible"; + CapabilityBoundingSet = [ + "CAP_NET_BIND_SERVICE" + "CAP_DAC_READ_SEARCH" + ]; + }; + }; + }) + cfg.apps; + }; +}