feat: align with upstream 1.5.9.9
This commit is contained in:
@@ -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"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user