Add Nix package, NixOS module, and tests for bambuddy
- packages.bambuddy: FastAPI backend + prebuilt React frontend assembled into the app-root layout upstream expects, behind a single `bambuddy` launcher (uvicorn --loop asyncio, ffmpeg on PATH, XDG state defaults). Pins upstream maziggy/bambuddy v1.2.5.7. - nixosModules.default: services.bambuddy with host/port/dataDir, openFirewall, environment + environmentFile, extraPackages, DynamicUser + StateDirectory, systemd hardening, and CAP_NET_BIND_SERVICE for the virtual-printer FTPS/RTSP ports. - checks.bambuddy-import: backend import + admin CLI smoke test. - checks.bambuddy-service: two-node NixOS VM test covering the health endpoint, UI/static assets/manifest, SQLite + logs in the StateDirectory, journal startup check, cross-node reachability with openFirewall, custom host/port/env node, and loopback-only binding. - overlay, run app, devShell, README, .gitignore.
This commit is contained in:
commit
5fb8e8d724
9 changed files with 761 additions and 0 deletions
204
pkgs/bambuddy/default.nix
Normal file
204
pkgs/bambuddy/default.nix
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
buildNpmPackage,
|
||||
python3,
|
||||
makeWrapper,
|
||||
ffmpeg,
|
||||
}:
|
||||
let
|
||||
pname = "bambuddy";
|
||||
version = "1.2.5.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "maziggy";
|
||||
repo = "bambuddy";
|
||||
rev = "188df76f8a7342542c0876dac68990ea2a8c8313"; # v1.2.5.7
|
||||
hash = "sha256-KmlAdFoSIMa6Wahd4XPBvaBtpVR/5LPNMyaimuDZVb0=";
|
||||
};
|
||||
|
||||
# Runtime Python dependencies, mirroring upstream requirements.txt.
|
||||
# All of these ship in nixpkgs. Optional heavy extras (opencv4,
|
||||
# fast-simplification) are included for feature parity with the upstream
|
||||
# Docker image, which installs requirements.txt in full; the affected
|
||||
# features (plate detection, STL thumbnails) degrade gracefully if absent.
|
||||
pythonDeps =
|
||||
ps: with ps; [
|
||||
# Web framework
|
||||
fastapi
|
||||
uvicorn
|
||||
uvloop
|
||||
httptools
|
||||
websockets
|
||||
python-dotenv
|
||||
|
||||
# Database
|
||||
sqlalchemy
|
||||
aiosqlite
|
||||
asyncpg
|
||||
greenlet
|
||||
|
||||
# Pydantic / settings
|
||||
pydantic
|
||||
pydantic-settings
|
||||
|
||||
# Bambu Lab printer communication (MQTT / FTP)
|
||||
paho-mqtt
|
||||
aioftp
|
||||
pyftpdlib
|
||||
cryptography
|
||||
pyopenssl
|
||||
asyncssh
|
||||
|
||||
# 3MF processing
|
||||
defusedxml
|
||||
|
||||
# Excel export
|
||||
openpyxl
|
||||
|
||||
# Utilities
|
||||
python-multipart
|
||||
aiofiles
|
||||
|
||||
# QR codes / PDF generation / PDF thumbnails
|
||||
qrcode
|
||||
reportlab
|
||||
pypdfium2
|
||||
|
||||
# STL thumbnails
|
||||
trimesh
|
||||
matplotlib
|
||||
fast-simplification
|
||||
networkx
|
||||
lxml
|
||||
|
||||
# System monitoring
|
||||
psutil
|
||||
|
||||
# Authentication
|
||||
pyjwt
|
||||
passlib
|
||||
bcrypt
|
||||
ldap3
|
||||
pyotp
|
||||
|
||||
# HTTP clients
|
||||
idna
|
||||
httpx
|
||||
certifi
|
||||
curl-cffi
|
||||
urllib3
|
||||
aiohttp
|
||||
|
||||
# Plate detection
|
||||
opencv4
|
||||
numpy
|
||||
pillow
|
||||
];
|
||||
|
||||
pythonEnv = python3.withPackages pythonDeps;
|
||||
|
||||
|
||||
# Prebuilt React frontend. `vite build` emits to `../static` (the app root,
|
||||
# next to `backend/`), matching the upstream Dockerfile.
|
||||
frontend = buildNpmPackage {
|
||||
pname = "${pname}-web";
|
||||
inherit version src;
|
||||
|
||||
sourceRoot = "${src.name}/frontend";
|
||||
npmDepsHash = "sha256-S+WU4jgs2DPWHHfspeo5k8vPECK+5SidGa8kzI4K4lw=";
|
||||
|
||||
# The source tree arrives from the store read-only, but `vite build`
|
||||
# empties and writes ../static (the repo ships a committed static/ dir).
|
||||
preBuild = ''
|
||||
chmod -R u+w "$NIX_BUILD_TOP/${src.name}"
|
||||
rm -rf ../static
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/share
|
||||
cp -r ../static $out/share/static
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Web frontend for Bambuddy";
|
||||
license = lib.licenses.agpl3Only;
|
||||
platforms = lib.platforms.unix;
|
||||
};
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
inherit pname version src;
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
|
||||
buildInputs = [ pythonEnv ];
|
||||
|
||||
passthru = {
|
||||
inherit pythonEnv frontend;
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
# App root: `backend/` (Python sources) + `static/` (prebuilt frontend).
|
||||
# backend.app.core.config resolves both relative to this root, exactly
|
||||
# like the upstream Docker image (/app/backend + /app/static).
|
||||
mkdir -p $out/share/bambuddy
|
||||
cp -r ${src}/backend $out/share/bambuddy/backend
|
||||
cp -r ${frontend}/share/static $out/share/bambuddy/static
|
||||
chmod -R u+w $out/share/bambuddy
|
||||
|
||||
# The upstream test suite is not shipped in the runtime package.
|
||||
rm -rf $out/share/bambuddy/backend/tests
|
||||
find $out/share/bambuddy -type d -name __pycache__ -prune -exec rm -rf {} +
|
||||
|
||||
install -Dm644 ${src}/LICENSE -t $out/share/licenses/bambuddy
|
||||
|
||||
mkdir -p $out/bin
|
||||
install -Dm755 ${./wrapper.sh} $out/bin/bambuddy
|
||||
# Substitute at build time so @out@ resolves to THIS package's path.
|
||||
# (A separate replaceVars derivation would substitute its own outPath
|
||||
# instead — which silently broke the PYTHONPATH in the launcher.)
|
||||
substituteInPlace $out/bin/bambuddy \
|
||||
--replace-warn '@out@' "$out" \
|
||||
--replace-warn '@pythonEnv@' "${pythonEnv}"
|
||||
# ffmpeg is used for timelapse conversion and camera stream re-encoding.
|
||||
wrapProgram $out/bin/bambuddy \
|
||||
--prefix PATH : ${lib.makeBinPath [ ffmpeg ]}
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
# Fix up the interpreter reference in the substituted wrapper.
|
||||
preFixup = ''
|
||||
patchShebangs $out/bin/bambuddy
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Self-hosted command center for Bambu Lab 3D printers";
|
||||
longDescription = ''
|
||||
Bambuddy is a self-hosted command center for Bambu Lab 3D printers —
|
||||
from a single A1 to an entire print farm. Monitor printers in real
|
||||
time, archive every print automatically, slice and queue jobs locally,
|
||||
and manage the whole workflow without Bambu's cloud.
|
||||
|
||||
This package bundles the FastAPI backend and the prebuilt React
|
||||
frontend behind a single `bambuddy` launcher. Configuration is done via
|
||||
environment variables (DATA_DIR, LOG_DIR, HOST, PORT, ...) — see the
|
||||
NixOS module (`services.bambuddy`) or upstream `.env.example` for the
|
||||
full list.
|
||||
'';
|
||||
homepage = "https://bambuddy.cool/";
|
||||
changelog = "https://github.com/maziggy/bambuddy/releases/tag/v${version}";
|
||||
license = lib.licenses.agpl3Only;
|
||||
sourceProvenance = with lib.sourceTypes; [ fromSource ];
|
||||
platforms = lib.platforms.unix;
|
||||
mainProgram = "bambuddy";
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue