feat: align with upstream 1.5.9.9

This commit is contained in:
2026-09-12 18:21:11 +08:00
commit 34f0679117
805 changed files with 376275 additions and 0 deletions
+360
View File
@@ -0,0 +1,360 @@
{
description = "VoiceHub - 校园广播站点歌管理系统";
nixConfig = {
extra-substituters = [ "https://voicehub.cachix.org" ];
extra-trusted-public-keys = [ "voicehub.cachix.org-1:CKw4/RvZy5c0WVpyo5ZyLbJgdpHZ/+epofIwGOeIOhU=" ];
};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{ self
, nixpkgs
, flake-utils
}:
flake-utils.lib.eachDefaultSystem
(
system:
let
pkgs = import nixpkgs { inherit system; };
pnpm = pkgs.pnpm_10.override {
version = "10.29.3";
hash = "sha256-p09NvT9afKh00AQTUnHwtpe2g78f0vwhM5YRYc0lspw=";
};
version = (builtins.fromJSON (builtins.readFile ./package.json)).version;
voicehub = pkgs.stdenv.mkDerivation (finalAttrs: {
pname = "voicehub";
inherit version;
src = self;
pnpmDeps = pkgs.fetchPnpmDeps {
inherit (finalAttrs) pname version src;
inherit pnpm;
fetcherVersion = 4;
hash = "sha256-i+blFH1M2IShWdqE+0fdSeuCtkSnZTut16wUdbPbVQk=";
};
nativeBuildInputs = [
pkgs.nodejs_24
pkgs.pnpmConfigHook
pnpm
pkgs.makeWrapper
];
configurePhase = ''
runHook preConfigure
export HOME="$TMPDIR"
export CI=true
export NODE_OPTIONS="--max-old-space-size=6144"
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
export NUXT_TELEMETRY_DISABLED=1
pnpm run build
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p "$out/lib/voicehub" "$out/bin"
cp -r .output "$out/lib/voicehub/"
cp -r node_modules "$out/lib/voicehub/"
cp package.json "$out/lib/voicehub/"
cp drizzle.config.ts "$out/lib/voicehub/"
mkdir -p "$out/lib/voicehub/app/drizzle"
cp -r app/drizzle/. "$out/lib/voicehub/app/drizzle/"
cp -r scripts "$out/lib/voicehub/"
makeWrapper ${pkgs.nodejs_24}/bin/node "$out/bin/voicehub" \
--add-flags ".output/server/index.mjs" \
--chdir "$out/lib/voicehub" \
--set PREBUILT true \
--set NODE_ENV production \
--prefix PATH : ${pnpm}/bin
runHook postInstall
'';
meta = with pkgs.lib; {
description = "校园广播站点歌管理系统";
homepage = "https://github.com/laoshuikaixue/VoiceHub";
license = licenses.gpl3Only;
mainProgram = "voicehub";
platforms = pkgs.nodejs_24.meta.platforms;
};
});
in
{
packages = {
inherit voicehub;
default = voicehub;
};
devShells = {
default = pkgs.mkShell {
buildInputs = [
pkgs.nodejs_24
pnpm
pkgs.postgresql_15
pkgs.git
];
shellHook = ''
echo ""
echo " VoiceHub 开发环境"
echo " -----------------"
echo " Node.js : $(node --version)"
echo " pnpm : $(pnpm --version)"
echo ""
echo " 快速开始:"
echo " cp .env.example .env # 配置 DATABASE_URL + JWT_SECRET"
echo " pnpm install # 安装依赖"
echo " pnpm run dev # 启动开发服务器 (port 3000)"
echo " pnpm run build # 构建"
echo ""
'';
};
};
apps = {
default = {
type = "app";
program = "${voicehub}/bin/voicehub";
};
# Impure build helper — use this to compute the pnpmDeps hash
build = {
type = "app";
program =
let
buildScript = pkgs.writeShellApplication {
name = "voicehub-build";
runtimeInputs = [
pkgs.nodejs_24
pnpm
pkgs.git
pkgs.cacert
];
text = ''
set -euo pipefail
echo "正在构建 VoiceHub v${version} ..."
export HOME="''${HOME:-/tmp}"
export NODE_OPTIONS="--max-old-space-size=6144"
export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
pnpm install --frozen-lockfile
pnpm run build
echo "构建完成: $(pwd)/.output"
'';
};
in
"${buildScript}/bin/voicehub-build";
};
};
}
)
// {
# ──────────────────────────────────────────────────────────────
# NixOS Module
# ──────────────────────────────────────────────────────────────
nixosModules.default =
{ config
, lib
, pkgs
, ...
}:
let
nodejs = pkgs.nodejs_24;
pnpm = pkgs.pnpm_10.override {
version = "10.29.3";
hash = "sha256-p09NvT9afKh00AQTUnHwtpe2g78f0vwhM5YRYc0lspw=";
};
cfg = config.services.voicehub;
in
{
options.services.voicehub = {
enable = lib.mkEnableOption "启用 VoiceHub 服务";
package = lib.mkOption {
type = lib.types.package;
default = self.packages.${pkgs.stdenv.hostPlatform.system}.default;
defaultText = lib.literalExpression "self.packages.''${pkgs.stdenv.hostPlatform.system}.default";
description = "使用的 VoiceHub 包";
};
port = lib.mkOption {
type = lib.types.port;
default = 3000;
description = "HTTP 监听端口";
};
host = lib.mkOption {
type = lib.types.str;
default = "0.0.0.0";
description = "监听地址";
};
database = {
createLocally = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
是否自动配置本地 PostgreSQL 数据库。
启用后将自动启用 services.postgresql、创建数据库和用户,
并从 database 选项自动构造 DATABASE_URL。
'';
};
name = lib.mkOption {
type = lib.types.str;
default = "voicehub";
};
user = lib.mkOption {
type = lib.types.str;
default = "voicehub";
};
host = lib.mkOption {
type = lib.types.str;
default = "/run/postgresql";
description = "PostgreSQL 主机地址。默认为 Unix 套接字路径,用于本地对等认证。";
};
};
environmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = "包含敏感变量的环境文件路径(如 JWT_SECRET)";
};
extraEnvironment = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
description = "额外环境变量";
};
runDeployScript = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
是否在启动前运行部署脚本(db:migrate + create-admin)。
当使用独立的迁移流程时可设为 false。
'';
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "在防火墙中开放 VoiceHub 端口";
};
};
config = lib.mkIf cfg.enable {
services.postgresql = lib.mkIf cfg.database.createLocally {
enable = true;
ensureDatabases = [ cfg.database.name ];
ensureUsers = [{ name = cfg.database.user; ensureDBOwnership = true; }];
};
networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [ cfg.port ];
systemd.services.voicehub = {
description = "VoiceHub - 校园广播站点歌服务";
documentation = [ "https://github.com/laoshuikaixue/VoiceHub" ];
unitConfig = {
StartLimitIntervalSec = 600;
StartLimitBurst = 3;
};
after = [ "network.target" ]
++ lib.optionals cfg.database.createLocally [ "postgresql.target" ];
requires = lib.optionals cfg.database.createLocally [ "postgresql.target" ];
wantedBy = [ "multi-user.target" ];
environment =
{
NODE_ENV = "production";
PORT = toString cfg.port;
HOST = cfg.host;
PREBUILT = "true";
SKIP_INSTALL = "true";
SKIP_BUILD = "true";
}
// cfg.extraEnvironment;
serviceConfig = {
Type = "simple";
ExecStart =
let
startScript = pkgs.writeShellScript "voicehub-start" ''
set -e
cd "${cfg.package}/lib/voicehub"
export PATH="${pkgs.lib.makeBinPath [ nodejs pnpm pkgs.util-linux pkgs.bash ]}:$PATH"
export SHELL="$(command -v bash)"
${lib.optionalString cfg.database.createLocally ''
export DATABASE_URL="postgresql:///${cfg.database.name}"
export PGHOST="${cfg.database.host}"
''}
${lib.optionalString cfg.runDeployScript ''
script -q -c "node scripts/deploy.js" /dev/null || {
echo "❌ 部署脚本执行失败"
exit 1
}
''}
exec ${cfg.package}/bin/voicehub
'';
in
"${startScript}";
Restart = "always";
RestartSec = "5s";
WorkingDirectory = "${cfg.package}/lib/voicehub";
DynamicUser = true;
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
MemoryHigh = "4G";
MemoryMax = "6G";
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
SystemCallFilter = [
"@system-service"
"~@privileged"
];
};
};
};
};
};
}