From 8d5c564e75ad2928e77ea66decc979366ca5ccd5 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Mon, 31 Aug 2026 10:49:45 +0200 Subject: feat(packaging): 4-package .deb/.rpm build system under /opt Shared venv architecture: meshbay-common owns the Python venv with all pip deps pre-installed; hub and node add only their code into it. Client is a standalone Electron app. No pip runs at install time. - Add build scripts (packaging/build/) for common, hub, node, client - Add orchestrator build-packages.sh with deb/rpm auto-detection - Add .deb control/postinst for all 4 packages - Add .rpm specs for all 4 packages (replaces python3-meshbay-common) - Add Gnome .desktop launcher and icon resizing - Add firewalld services (meshbay-cast, meshbay-node) and UFW profiles - Update systemd units to use /opt/meshbay-common/venv/bin/ paths - TMDB token baked into node package at build time via QE/node.env - Fix package-lock.json sync for protobufjs override Co-Authored-By: Claude Opus 4.6 --- packaging/README.md | 104 +++++++++-------- packaging/build/build-client.sh | 116 +++++++++++++++++++ packaging/build/build-common.sh | 75 +++++++++++++ packaging/build/build-hub.sh | 73 ++++++++++++ packaging/build/build-node.sh | 89 +++++++++++++++ packaging/build/build-packages.sh | 156 ++++++++++++++++++++++++++ packaging/deb/meshbay-client/DEBIAN/control | 17 +++ packaging/deb/meshbay-client/DEBIAN/postinst | 22 ++++ packaging/deb/meshbay-common/DEBIAN/control | 14 +++ packaging/deb/meshbay-common/DEBIAN/postinst | 15 +++ packaging/deb/meshbay-hub/DEBIAN/control | 17 ++- packaging/deb/meshbay-hub/DEBIAN/postinst | 9 +- packaging/deb/meshbay-node/DEBIAN/control | 18 +-- packaging/deb/meshbay-node/DEBIAN/postinst | 13 +++ packaging/desktop/meshbay.desktop | 10 ++ packaging/firewall/firewalld/meshbay-cast.xml | 7 ++ packaging/firewall/firewalld/meshbay-node.xml | 6 + packaging/firewall/ufw/meshbay | 9 ++ packaging/rpm/meshbay-client.spec | 53 +++++++++ packaging/rpm/meshbay-common.spec | 25 +++++ packaging/rpm/meshbay-hub.spec | 107 ++++-------------- packaging/rpm/meshbay-node.spec | 99 +++++----------- packaging/rpm/python3-meshbay-common.spec | 59 ---------- packaging/systemd/meshbay-hub.service | 4 +- packaging/systemd/meshbay-node-user.service | 2 +- packaging/systemd/meshbay-node.service | 2 +- 26 files changed, 830 insertions(+), 291 deletions(-) create mode 100755 packaging/build/build-client.sh create mode 100755 packaging/build/build-common.sh create mode 100755 packaging/build/build-hub.sh create mode 100755 packaging/build/build-node.sh create mode 100755 packaging/build/build-packages.sh create mode 100644 packaging/deb/meshbay-client/DEBIAN/control create mode 100644 packaging/deb/meshbay-client/DEBIAN/postinst create mode 100644 packaging/deb/meshbay-common/DEBIAN/control create mode 100644 packaging/deb/meshbay-common/DEBIAN/postinst create mode 100644 packaging/deb/meshbay-node/DEBIAN/postinst create mode 100644 packaging/desktop/meshbay.desktop create mode 100644 packaging/firewall/firewalld/meshbay-cast.xml create mode 100644 packaging/firewall/firewalld/meshbay-node.xml create mode 100644 packaging/firewall/ufw/meshbay create mode 100644 packaging/rpm/meshbay-client.spec create mode 100644 packaging/rpm/meshbay-common.spec delete mode 100644 packaging/rpm/python3-meshbay-common.spec (limited to 'packaging') diff --git a/packaging/README.md b/packaging/README.md index 13b8fbf..a7f2d84 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -1,72 +1,67 @@ # MeshBay — Packaging -Three distributable packages: +Four packages, installed under `/opt//`: | Package | RPM spec | DEB control | Description | |---|---|---|---| -| `python3-meshbay-common` | `rpm/python3-meshbay-common.spec` | `deb/python3-meshbay-common/` | Shared crypto + protocol lib | +| `meshbay-common` | `rpm/meshbay-common.spec` | `deb/meshbay-common/` | Shared Python venv + all pip deps | | `meshbay-hub` | `rpm/meshbay-hub.spec` | `deb/meshbay-hub/` | Hub server (FastAPI + PostgreSQL) | | `meshbay-node` | `rpm/meshbay-node.spec` | `deb/meshbay-node/` | Node daemon + local UI | +| `meshbay-client` | `rpm/meshbay-client.spec` | `deb/meshbay-client/` | Electron desktop app | -## Building RPMs (Fedora/RHEL) +## Building packages ```bash -# Install build tools -sudo dnf install -y rpm-build python3-pip +# On Ubuntu 26.04: +bash packaging/build/build-packages.sh deb -# Build all three packages -for pkg in python3-meshbay-common meshbay-hub meshbay-node; do - rpmbuild -ba packaging/rpm/${pkg}.spec -done +# On Fedora 44 (local): +bash packaging/build/build-packages.sh rpm + +# On Raspberry Pi (arm64, deferred): +bash packaging/build/build-packages.sh deb --arm64 ``` -## Building DEBs (Debian/Ubuntu) +Output: `meshbay-{common,hub,node,client}_0.8.0_{arch}.{deb,rpm}` in `/tmp/meshbay-build/out/`. + +## Install order + +Always install `meshbay-common` first (owns the shared Python venv). ```bash -# Install build tools -sudo apt install -y dpkg-dev debhelper python3-pip - -# Build common library first (dependency) -dpkg-deb --build packaging/deb/python3-meshbay-common -dpkg-deb --build packaging/deb/meshbay-hub -dpkg-deb --build packaging/deb/meshbay-node - -# Install -sudo dpkg -i python3-meshbay-common_0.2.0_all.deb -sudo dpkg -i meshbay-hub_0.2.0_all.deb -sudo dpkg -i meshbay-node_0.2.0_all.deb +# Ubuntu/Debian +sudo dpkg -i meshbay-common_*.deb +sudo dpkg -i meshbay-hub_*.deb meshbay-node_*.deb +sudo dpkg -i meshbay-client_*.deb + +# Fedora +sudo rpm -ivh meshbay-common-*.rpm +sudo rpm -ivh meshbay-hub-*.rpm meshbay-node-*.rpm +sudo rpm -ivh meshbay-client-*.rpm ``` -## Install order +## Architecture -Always install `python3-meshbay-common` first (dependency of both hub and node). +meshbay-common owns the shared Python virtual environment at +`/opt/meshbay-common/venv/`. Hub and node install their code into that venv. +The client is a standalone Electron app at `/opt/meshbay-client/`. + +No pip runs at install time — everything is pre-built. ## Post-install (hub) ```bash -# Generate hub keypair -sudo -u meshbay meshbay-hub --generate-keys - -# Edit config +meshbay-hub --generate-keys +sudo cp /opt/meshbay-hub/share/hub.toml.example /etc/meshbay/hub.toml sudo nano /etc/meshbay/hub.toml - -# Configure Caddy for HTTPS -sudo nano /etc/caddy/Caddyfile - -# Start sudo systemctl enable --now meshbay-hub ``` ## Post-install (node) ```bash -# Initialize node (writes example config) -meshbay-node init - -# Edit config +meshbay-node init # copies default.env (with TMDB token) nano ~/.config/meshbay/node.toml - -# Start as user service systemctl --user enable --now meshbay-node ``` @@ -74,29 +69,42 @@ systemctl --user enable --now meshbay-node The Electron client runs an HTTP relay on **TCP 19550-19553** to stream decrypted video to Chromecast / Smart TV devices on the local network. -Chromecast discovery uses **mDNS (UDP 5353)**. These ports must be open on the -machine running the client. +Chromecast discovery uses **mDNS (UDP 5353)**. ### Fedora / RHEL (firewalld) +Pre-installed service files at `/usr/lib/firewalld/services/`: + ```bash -sudo firewall-cmd --permanent --add-service=mdns -sudo firewall-cmd --permanent --add-port=19550-19553/tcp +sudo firewall-cmd --permanent --add-service=meshbay-cast sudo firewall-cmd --reload ``` ### Ubuntu / Debian (ufw) +Pre-installed application profile at `/etc/ufw/applications.d/meshbay`: + ```bash -sudo ufw allow 5353/udp comment "mDNS - Chromecast discovery" -sudo ufw allow 19550:19553/tcp comment "meshbay cast relay" +sudo ufw allow "MeshBay Cast" ``` -## Systemd service files +## Systemd units | File | Location | |---|---| | `systemd/meshbay-hub.service` | `/usr/lib/systemd/system/meshbay-hub.service` | -| `systemd/meshbay-node.service` | `/usr/lib/systemd/user/meshbay-node.service` | +| `systemd/meshbay-node@.service` | `/usr/lib/systemd/system/meshbay-node@.service` | +| `systemd/meshbay-node.service` (user) | `/usr/lib/systemd/user/meshbay-node.service` | + +The node user service is enabled by the person themselves: + +```bash +systemctl --user enable --now meshbay-node +loginctl enable-linger $USER # keep serving when logged out +``` + +## Desktop launcher -The node service is a **user service** (runs as the user's own account, with access to their home directory). The hub is a **system service** (runs as the `meshbay` system account). +The client installs a Gnome `.desktop` file at +`/usr/share/applications/meshbay.desktop` — the application appears as +**"MeshBay"** in the applications menu. diff --git a/packaging/build/build-client.sh b/packaging/build/build-client.sh new file mode 100755 index 0000000..fbdf51e --- /dev/null +++ b/packaging/build/build-client.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# Build the meshbay-client package: Electron app + .desktop launcher. +# +# Usage: ./build-client.sh [staging-dir] [--arm64] +# +# Requires Node >= 22. If not in PATH, set NODEJS_DIR=/opt/nodejs or similar. +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +STAGING="${1:-/tmp/meshbay-build}" +ROOT="$STAGING/meshbay-client-root" +CLIENT="$REPO/packages/meshbay-client" + +ARCH_FLAG="" +ELECTRON_ARCH="x64" +DEB_ARCH="amd64" +for arg in "$@"; do + if [ "$arg" = "--arm64" ]; then + ARCH_FLAG="--arm64" + ELECTRON_ARCH="arm64" + DEB_ARCH="arm64" + fi +done + +# Node.js version check +if [ -n "${NODEJS_DIR:-}" ]; then + export PATH="$NODEJS_DIR/bin:$PATH" +fi +NODE_VER=$(node --version 2>/dev/null || echo "none") +echo "==> meshbay-client (Node $NODE_VER, arch=$ELECTRON_ARCH)" + +if ! node --version >/dev/null 2>&1; then + echo "!! Node.js not found. Set NODEJS_DIR or install Node >= 22." >&2 + exit 1 +fi + +NODE_MAJOR=$(node -e "process.stdout.write(String(process.versions.node.split('.')[0]))") +if [ "$NODE_MAJOR" -lt 22 ]; then + echo "!! Node $NODE_VER is too old — need >= 22 for Electron" >&2 + exit 1 +fi + +rm -rf "$ROOT" +mkdir -p "$ROOT" + +# --- Build the Electron app ----------------------------------------------- +cd "$CLIENT" + +echo " npm ci" +npm ci --ignore-scripts 2>&1 | tail -3 + +echo " approving + installing electron" +npm approve-scripts electron 2>/dev/null || true +node node_modules/electron/install.js 2>&1 | tail -1 + +echo " syncing UI from hub package" +npm run sync-ui 2>&1 | tail -1 + +echo " electron-builder --dir $ARCH_FLAG" +npx electron-builder --dir --linux $ARCH_FLAG 2>&1 | tail -5 + +# Determine the unpacked output directory +if [ "$ELECTRON_ARCH" = "arm64" ]; then + UNPACKED="$CLIENT/dist/linux-arm64-unpacked" +else + UNPACKED="$CLIENT/dist/linux-unpacked" +fi + +[ -d "$UNPACKED" ] || { echo "!! electron-builder output not found at $UNPACKED" >&2; exit 1; } + +# --- Assemble the package tree -------------------------------------------- +echo " assembling /opt/meshbay-client/" +mkdir -p "$ROOT/opt/meshbay-client" +cp -a "$UNPACKED"/* "$ROOT/opt/meshbay-client/" + +# Rename the electron binary +if [ -f "$ROOT/opt/meshbay-client/meshbay-client" ]; then + mv "$ROOT/opt/meshbay-client/meshbay-client" "$ROOT/opt/meshbay-client/meshbay" +elif [ -f "$ROOT/opt/meshbay-client/electron" ]; then + mv "$ROOT/opt/meshbay-client/electron" "$ROOT/opt/meshbay-client/meshbay" +fi + +# Symlink in PATH +mkdir -p "$ROOT/usr/bin" +ln -sf /opt/meshbay-client/meshbay "$ROOT/usr/bin/meshbay" + +# --- Desktop launcher ----------------------------------------------------- +mkdir -p "$ROOT/usr/share/applications" +cp "$REPO/packaging/desktop/meshbay.desktop" "$ROOT/usr/share/applications/" + +# --- Icons ---------------------------------------------------------------- +ICON_SRC="$CLIENT/build/icon.png" +if [ -f "$ICON_SRC" ]; then + for size in 128 256 512; do + ICON_DIR="$ROOT/usr/share/icons/hicolor/${size}x${size}/apps" + mkdir -p "$ICON_DIR" + if command -v convert >/dev/null 2>&1; then + convert "$ICON_SRC" -resize "${size}x${size}" "$ICON_DIR/meshbay.png" + elif command -v magick >/dev/null 2>&1; then + magick "$ICON_SRC" -resize "${size}x${size}" "$ICON_DIR/meshbay.png" + else + # Fallback: copy the original at all sizes (better than no icon) + cp "$ICON_SRC" "$ICON_DIR/meshbay.png" + fi + done + echo " icons installed" +else + echo " !! icon.png not found at $ICON_SRC — no icons" >&2 +fi + +# --- Firewall profile (Chromecast) ---------------------------------------- +mkdir -p "$ROOT/usr/lib/firewalld/services" +cp "$REPO/packaging/firewall/firewalld/meshbay-cast.xml" \ + "$ROOT/usr/lib/firewalld/services/" + +echo "==> meshbay-client staging ready at $ROOT ($DEB_ARCH)" diff --git a/packaging/build/build-common.sh b/packaging/build/build-common.sh new file mode 100755 index 0000000..3045689 --- /dev/null +++ b/packaging/build/build-common.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# Build the meshbay-common package: shared venv with ALL Python dependencies. +# +# Usage: ./build-common.sh [staging-dir] +# staging-dir defaults to /tmp/meshbay-build +# +# Output: $STAGING/meshbay-common-root/ (ready for dpkg-deb or rpmbuild) +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +STAGING="${1:-/tmp/meshbay-build}" +ROOT="$STAGING/meshbay-common-root" +VENV_FINAL="/opt/meshbay-common/venv" +VENV_BUILD="$ROOT$VENV_FINAL" +WHEEL_DIR="$STAGING/wheels" + +VERSION=$(python3 -c " +import tomllib, pathlib +p = pathlib.Path('$REPO/packages/meshbay-common/pyproject.toml') +print(tomllib.loads(p.read_text())['project']['version']) +") +echo "==> meshbay-common $VERSION" + +rm -rf "$ROOT" +mkdir -p "$ROOT/opt/meshbay-common" "$WHEEL_DIR" + +# --- Create venv ----------------------------------------------------------- +echo " creating venv at $VENV_BUILD" +python3 -m venv "$VENV_BUILD" +"$VENV_BUILD/bin/pip" install --upgrade pip wheel 2>&1 | tail -1 + +# --- Build wheels for all three packages ----------------------------------- +echo " building wheels" +for pkg in meshbay-common meshbay-hub meshbay-node; do + "$VENV_BUILD/bin/pip" wheel \ + --no-deps \ + --wheel-dir "$WHEEL_DIR" \ + "$REPO/packages/$pkg" 2>&1 | tail -1 +done + +# --- Install everything into the venv ------------------------------------- +echo " installing all packages + dependencies" +"$VENV_BUILD/bin/pip" install \ + --find-links "$WHEEL_DIR" \ + meshbay-common meshbay-hub meshbay-node 2>&1 | tail -3 + +# --- Strip build tools from the venv (not needed at runtime) --------------- +echo " stripping build tools" +"$VENV_BUILD/bin/pip" uninstall -y pip setuptools wheel 2>&1 | tail -1 +rm -rf "$VENV_BUILD/lib"/python*/site-packages/pip* +rm -rf "$VENV_BUILD/lib"/python*/site-packages/setuptools* +rm -rf "$VENV_BUILD/lib"/python*/site-packages/wheel* +rm -f "$VENV_BUILD/bin/pip"* + +# --- Fix shebangs and pyvenv.cfg ------------------------------------------ +# The venv was built under $ROOT but will be installed at /opt/meshbay-common/venv/ +echo " fixing paths ($ROOT -> '')" +for f in "$VENV_BUILD/bin"/*; do + [ -f "$f" ] || continue + [ -L "$f" ] && continue + head -1 "$f" | grep -q "^#!" || continue + sed -i "1s|$ROOT||" "$f" +done +sed -i "s|$ROOT||g" "$VENV_BUILD/pyvenv.cfg" + +# --- Remove __pycache__ (will be regenerated on first import) -------------- +find "$VENV_BUILD" -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true + +# --- Keep a copy of the wheels for reference ------------------------------- +mkdir -p "$ROOT/opt/meshbay-common/wheels" +cp "$WHEEL_DIR"/meshbay_common-*.whl "$ROOT/opt/meshbay-common/wheels/" + +echo "==> meshbay-common staging ready at $ROOT" +echo " venv: $VENV_BUILD" +echo " version: $VERSION" diff --git a/packaging/build/build-hub.sh b/packaging/build/build-hub.sh new file mode 100755 index 0000000..45d2ab9 --- /dev/null +++ b/packaging/build/build-hub.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# Build the meshbay-hub package: hub-specific files on top of meshbay-common. +# +# Expects build-common.sh to have run first (shared venv exists in staging). +# +# Usage: ./build-hub.sh [staging-dir] +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +STAGING="${1:-/tmp/meshbay-build}" +COMMON_ROOT="$STAGING/meshbay-common-root" +ROOT="$STAGING/meshbay-hub-root" + +VENV="$COMMON_ROOT/opt/meshbay-common/venv" +PYVER=$(basename "$VENV"/lib/python3.*) +SITE="$VENV/lib/$PYVER/site-packages" + +VERSION=$(python3 -c " +import tomllib, pathlib +p = pathlib.Path('$REPO/packages/meshbay-hub/pyproject.toml') +print(tomllib.loads(p.read_text())['project']['version']) +") +echo "==> meshbay-hub $VERSION" + +[ -d "$VENV" ] || { echo "!! shared venv not found — run build-common.sh first" >&2; exit 1; } + +rm -rf "$ROOT" +mkdir -p "$ROOT" + +# --- Hub code in the shared venv (owned by meshbay-hub package) ----------- +# MOVE (not copy) from the common staging tree so dpkg/rpm knows these files +# belong to meshbay-hub, not meshbay-common. build-common.sh installed them +# so that shebangs and dependency resolution are correct. +HUB_ROOT="$ROOT/opt/meshbay-common/venv/lib/$PYVER/site-packages" +mkdir -p "$HUB_ROOT" +mv "$SITE/meshbay_hub" "$HUB_ROOT/" +mv "$SITE"/meshbay_hub-*.dist-info "$HUB_ROOT/" + +# Entry point +mkdir -p "$ROOT/opt/meshbay-common/venv/bin" +mv "$VENV/bin/meshbay-hub" "$ROOT/opt/meshbay-common/venv/bin/" + +# Symlink in PATH +mkdir -p "$ROOT/usr/bin" +ln -sf /opt/meshbay-common/venv/bin/meshbay-hub "$ROOT/usr/bin/meshbay-hub" + +# --- Hub-specific assets -------------------------------------------------- +mkdir -p "$ROOT/opt/meshbay-hub" + +# Alembic config (migrations are inside the installed package at meshbay_hub/db/migrations/) +if [ -f "$REPO/packages/meshbay-hub/alembic.ini" ]; then + mkdir -p "$ROOT/opt/meshbay-hub/migrations" + cp "$REPO/packages/meshbay-hub/alembic.ini" "$ROOT/opt/meshbay-hub/migrations/" +fi + +# Config example +mkdir -p "$ROOT/opt/meshbay-hub/share" +if [ -f "$REPO/packaging/conf/hub.toml.example" ]; then + cp "$REPO/packaging/conf/hub.toml.example" "$ROOT/opt/meshbay-hub/share/" +fi + +# Also install to /etc/meshbay/ for discoverability +mkdir -p "$ROOT/etc/meshbay" +if [ -f "$ROOT/opt/meshbay-hub/share/hub.toml.example" ]; then + cp "$ROOT/opt/meshbay-hub/share/hub.toml.example" "$ROOT/etc/meshbay/" +fi + +# --- Systemd unit --------------------------------------------------------- +mkdir -p "$ROOT/usr/lib/systemd/system" +cp "$REPO/packaging/systemd/meshbay-hub.service" \ + "$ROOT/usr/lib/systemd/system/meshbay-hub.service" + +echo "==> meshbay-hub staging ready at $ROOT" diff --git a/packaging/build/build-node.sh b/packaging/build/build-node.sh new file mode 100755 index 0000000..d8a5af4 --- /dev/null +++ b/packaging/build/build-node.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# Build the meshbay-node package: node-specific files on top of meshbay-common. +# +# Expects build-common.sh to have run first (shared venv exists in staging). +# +# Usage: ./build-node.sh [staging-dir] +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +STAGING="${1:-/tmp/meshbay-build}" +COMMON_ROOT="$STAGING/meshbay-common-root" +ROOT="$STAGING/meshbay-node-root" + +VENV="$COMMON_ROOT/opt/meshbay-common/venv" +PYVER=$(basename "$VENV"/lib/python3.*) +SITE="$VENV/lib/$PYVER/site-packages" + +VERSION=$(python3 -c " +import tomllib, pathlib +p = pathlib.Path('$REPO/packages/meshbay-node/pyproject.toml') +print(tomllib.loads(p.read_text())['project']['version']) +") +echo "==> meshbay-node $VERSION" + +[ -d "$VENV" ] || { echo "!! shared venv not found — run build-common.sh first" >&2; exit 1; } + +rm -rf "$ROOT" +mkdir -p "$ROOT" + +# --- Node code in the shared venv (owned by meshbay-node package) --------- +# MOVE (not copy) from the common staging tree — same rationale as build-hub.sh. +NODE_ROOT="$ROOT/opt/meshbay-common/venv/lib/$PYVER/site-packages" +mkdir -p "$NODE_ROOT" +mv "$SITE/meshbay_node" "$NODE_ROOT/" +mv "$SITE"/meshbay_node-*.dist-info "$NODE_ROOT/" + +# Entry point +mkdir -p "$ROOT/opt/meshbay-common/venv/bin" +mv "$VENV/bin/meshbay-node" "$ROOT/opt/meshbay-common/venv/bin/" + +# Symlink in PATH +mkdir -p "$ROOT/usr/bin" +ln -sf /opt/meshbay-common/venv/bin/meshbay-node "$ROOT/usr/bin/meshbay-node" + +# --- Node-specific assets ------------------------------------------------- +mkdir -p "$ROOT/opt/meshbay-node/share" + +# Default env with TMDB token (read at build time). +# Override with MESHBAY_TMDB_TOKEN_FILE; falls back to QE/node.env (gitignored). +TMDB_TOKEN_FILE="${MESHBAY_TMDB_TOKEN_FILE:-$REPO/QE/node.env}" +TMDB_TOKEN="" +if [ -f "$TMDB_TOKEN_FILE" ]; then + TMDB_TOKEN=$(grep -oP 'MESHBAY_TMDB_DEFAULT_TOKEN=\K.*' "$TMDB_TOKEN_FILE" || true) +fi +if [ -n "$TMDB_TOKEN" ]; then + cat > "$ROOT/opt/meshbay-node/share/default.env" <&2 + touch "$ROOT/opt/meshbay-node/share/default.env" +fi + +# --- Systemd units -------------------------------------------------------- +mkdir -p "$ROOT/usr/lib/systemd/system" +mkdir -p "$ROOT/usr/lib/systemd/user" +cp "$REPO/packaging/systemd/meshbay-node.service" \ + "$ROOT/usr/lib/systemd/system/meshbay-node@.service" +cp "$REPO/packaging/systemd/meshbay-node-user.service" \ + "$ROOT/usr/lib/systemd/user/meshbay-node.service" + +# --- Firewall profiles ---------------------------------------------------- +# firewalld (Fedora) +mkdir -p "$ROOT/usr/lib/firewalld/services" +cp "$REPO/packaging/firewall/firewalld/meshbay-node.xml" \ + "$ROOT/usr/lib/firewalld/services/" + +# UFW (Ubuntu/Debian) +mkdir -p "$ROOT/etc/ufw/applications.d" +cp "$REPO/packaging/firewall/ufw/meshbay" \ + "$ROOT/etc/ufw/applications.d/" + +echo "==> meshbay-node staging ready at $ROOT" diff --git a/packaging/build/build-packages.sh b/packaging/build/build-packages.sh new file mode 100755 index 0000000..ccacb81 --- /dev/null +++ b/packaging/build/build-packages.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash +# Build all MeshBay packages for the current platform. +# +# Usage: +# ./build-packages.sh # auto-detect format (deb on Ubuntu, rpm on Fedora) +# ./build-packages.sh deb # force .deb +# ./build-packages.sh rpm # force .rpm +# ./build-packages.sh deb --arm64 # arm64 .deb (Pi) +# +# Expects to run on the target machine: +# - Ubuntu 26.04 (cbesson@meshbay.org) for .deb amd64 +# - Fedora 44 (local) for .rpm x86_64 +# - Raspberry Pi for .deb arm64 (deferred) +# +# Output: packages in $STAGING/out/ +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO="$(cd "$SCRIPT_DIR/../.." && pwd)" +STAGING="${MESHBAY_BUILD_DIR:-/tmp/meshbay-build}" +OUT="$STAGING/out" + +# --- Detect format -------------------------------------------------------- +FORMAT="${1:-auto}" +shift 2>/dev/null || true +ARM64_FLAG="" +for arg in "$@"; do + [ "$arg" = "--arm64" ] && ARM64_FLAG="--arm64" +done + +if [ "$FORMAT" = "auto" ]; then + if [ -f /etc/debian_version ]; then + FORMAT="deb" + elif [ -f /etc/fedora-release ] || [ -f /etc/redhat-release ]; then + FORMAT="rpm" + else + echo "!! Cannot detect OS — pass 'deb' or 'rpm' as argument" >&2 + exit 1 + fi +fi + +ARCH=$(dpkg --print-architecture 2>/dev/null || rpm --eval '%{_arch}' 2>/dev/null || uname -m) +if [ -n "$ARM64_FLAG" ]; then + ARCH="arm64" +fi + +VERSION=$(python3 -c " +import tomllib, pathlib +p = pathlib.Path('$REPO/packages/meshbay-common/pyproject.toml') +print(tomllib.loads(p.read_text())['project']['version']) +") + +echo "========================================" +echo " MeshBay $VERSION — $FORMAT $ARCH" +echo "========================================" +echo " Repo: $REPO" +echo " Staging: $STAGING" +echo " Output: $OUT" +echo "" + +rm -rf "$OUT" +mkdir -p "$OUT" + +# --- Step 1: Build staging trees ------------------------------------------ + +echo "--- [1/4] meshbay-common (shared venv + all deps) ---" +bash "$SCRIPT_DIR/build-common.sh" "$STAGING" + +echo "" +echo "--- [2/4] meshbay-hub ---" +bash "$SCRIPT_DIR/build-hub.sh" "$STAGING" + +echo "" +echo "--- [3/4] meshbay-node ---" +bash "$SCRIPT_DIR/build-node.sh" "$STAGING" + +echo "" +echo "--- [4/4] meshbay-client ---" +bash "$SCRIPT_DIR/build-client.sh" "$STAGING" $ARM64_FLAG + +# --- Step 2: Package ------------------------------------------------------ + +echo "" +echo "--- Packaging ($FORMAT) ---" + +if [ "$FORMAT" = "deb" ]; then + build_deb() { + local pkg="$1" + local root="$STAGING/${pkg}-root" + local deb_src="$REPO/packaging/deb/$pkg/DEBIAN" + local deb_dir="$root/DEBIAN" + + mkdir -p "$deb_dir" + for f in "$deb_src"/*; do + [ -f "$f" ] || continue + sed -e "s/__VERSION__/$VERSION/g" \ + -e "s/__ARCH__/$ARCH/g" \ + "$f" > "$deb_dir/$(basename "$f")" + chmod 755 "$deb_dir/$(basename "$f")" 2>/dev/null || true + done + # control files should be 644, scripts 755 + [ -f "$deb_dir/control" ] && chmod 644 "$deb_dir/control" + [ -f "$deb_dir/conffiles" ] && chmod 644 "$deb_dir/conffiles" + + dpkg-deb --build --root-owner-group "$root" "$OUT/${pkg}_${VERSION}_${ARCH}.deb" + echo " -> $OUT/${pkg}_${VERSION}_${ARCH}.deb" + } + + build_deb meshbay-common + build_deb meshbay-hub + build_deb meshbay-node + build_deb meshbay-client + +elif [ "$FORMAT" = "rpm" ]; then + RPMBUILD_DIR="$STAGING/rpmbuild" + rm -rf "$RPMBUILD_DIR" + mkdir -p "$RPMBUILD_DIR"/{SPECS,SOURCES,BUILD,RPMS,SRPMS} + + build_rpm() { + local pkg="$1" + local spec="$REPO/packaging/rpm/${pkg}.spec" + local root="$STAGING/${pkg}-root" + + # Substitute version and pass the staging root as a macro + sed "s/__VERSION__/$VERSION/g" "$spec" > "$RPMBUILD_DIR/SPECS/${pkg}.spec" + + rpmbuild \ + --define "_topdir $RPMBUILD_DIR" \ + --define "_staging_root $root" \ + -bb "$RPMBUILD_DIR/SPECS/${pkg}.spec" 2>&1 | tail -5 + + local rpm_file + rpm_file=$(find "$RPMBUILD_DIR/RPMS" -name "${pkg}-${VERSION}*.rpm" -print -quit) + if [ -n "$rpm_file" ]; then + cp "$rpm_file" "$OUT/" + echo " -> $OUT/$(basename "$rpm_file")" + fi + } + + build_rpm meshbay-common + build_rpm meshbay-hub + build_rpm meshbay-node + build_rpm meshbay-client +fi + +# --- Summary -------------------------------------------------------------- +echo "" +echo "========================================" +echo " Build complete" +echo "========================================" +ls -lh "$OUT"/ +echo "" +echo "Install order:" +echo " 1. meshbay-common" +echo " 2. meshbay-hub and/or meshbay-node" +echo " 3. meshbay-client" diff --git a/packaging/deb/meshbay-client/DEBIAN/control b/packaging/deb/meshbay-client/DEBIAN/control new file mode 100644 index 0000000..e6a49b9 --- /dev/null +++ b/packaging/deb/meshbay-client/DEBIAN/control @@ -0,0 +1,17 @@ +Package: meshbay-client +Version: __VERSION__ +Section: net +Priority: optional +Architecture: __ARCH__ +Maintainer: MeshBay Team +Homepage: https://meshbay.org +Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, + libatspi2.0-0, libdrm2, libgbm1, libasound2 +Recommends: meshbay-node +Description: MeshBay — peer-to-peer file sharing, streaming and group chat + Desktop client for MeshBay. Connects to MeshBay nodes over WebRTC for + file sharing, video streaming, and group chat. Includes Chromecast and + Smart TV casting support. + . + Installs the Electron application to /opt/meshbay-client/ and a Gnome + launcher named "MeshBay". diff --git a/packaging/deb/meshbay-client/DEBIAN/postinst b/packaging/deb/meshbay-client/DEBIAN/postinst new file mode 100644 index 0000000..f262665 --- /dev/null +++ b/packaging/deb/meshbay-client/DEBIAN/postinst @@ -0,0 +1,22 @@ +#!/bin/sh +set -e + +case "$1" in + configure) + # chrome-sandbox requires SUID root for Chromium's namespace sandbox + if [ -f /opt/meshbay-client/chrome-sandbox ]; then + chown root:root /opt/meshbay-client/chrome-sandbox + chmod 4755 /opt/meshbay-client/chrome-sandbox + fi + + # Update desktop database and icon cache + if command -v update-desktop-database >/dev/null 2>&1; then + update-desktop-database /usr/share/applications || true + fi + if command -v gtk-update-icon-cache >/dev/null 2>&1; then + gtk-update-icon-cache -f -t /usr/share/icons/hicolor || true + fi + ;; +esac + +#DEBHELPER# diff --git a/packaging/deb/meshbay-common/DEBIAN/control b/packaging/deb/meshbay-common/DEBIAN/control new file mode 100644 index 0000000..4089f4b --- /dev/null +++ b/packaging/deb/meshbay-common/DEBIAN/control @@ -0,0 +1,14 @@ +Package: meshbay-common +Version: __VERSION__ +Section: python +Priority: optional +Architecture: __ARCH__ +Maintainer: MeshBay Team +Homepage: https://meshbay.org +Depends: python3 (>= 3.12) +Description: MeshBay shared Python runtime and libraries + Provides the shared Python virtual environment, cryptographic primitives + (Ed25519, X25519, GEK wrap/unwrap, ChaCha20-Poly1305), protocol types (MNP, + MHP), and all pip dependencies used by meshbay-hub and meshbay-node. + . + Installs to /opt/meshbay-common/venv/. diff --git a/packaging/deb/meshbay-common/DEBIAN/postinst b/packaging/deb/meshbay-common/DEBIAN/postinst new file mode 100644 index 0000000..d675c0c --- /dev/null +++ b/packaging/deb/meshbay-common/DEBIAN/postinst @@ -0,0 +1,15 @@ +#!/bin/sh +set -e + +case "$1" in + configure) + # Recompile bytecode for the installed Python version. + # The venv was built on the build machine; .pyc files may reference + # a different path or Python micro-version. + if command -v py3compile >/dev/null 2>&1; then + py3compile /opt/meshbay-common/venv/lib/ 2>/dev/null || true + fi + ;; +esac + +#DEBHELPER# diff --git a/packaging/deb/meshbay-hub/DEBIAN/control b/packaging/deb/meshbay-hub/DEBIAN/control index 2f3541c..07799a1 100644 --- a/packaging/deb/meshbay-hub/DEBIAN/control +++ b/packaging/deb/meshbay-hub/DEBIAN/control @@ -1,19 +1,16 @@ Package: meshbay-hub -Version: 0.2.0 +Version: __VERSION__ Section: net Priority: optional Architecture: all Maintainer: MeshBay Team Homepage: https://meshbay.org -Depends: python3 (>= 3.12), - python3-meshbay-common (= 0.2.0), - postgresql, - python3-fastapi, - python3-uvicorn, - adduser -Recommends: caddy +Depends: meshbay-common (= __VERSION__), adduser +Recommends: caddy, postgresql Description: MeshBay Hub — identity authority and group registry server MeshBay Hub provides user registration, JWT issuance, group management, - GEK bundle distribution, revocation, and moderation for MeshBay networks. + WebRTC signaling, notifications, and moderation for MeshBay networks. . - Runs as a systemd service behind Caddy for HTTPS (auto Let's Encrypt). + Installs hub code into the shared venv at /opt/meshbay-common/venv/ and + Alembic migrations at /opt/meshbay-hub/migrations/. + Runs as a systemd service behind Caddy for HTTPS. diff --git a/packaging/deb/meshbay-hub/DEBIAN/postinst b/packaging/deb/meshbay-hub/DEBIAN/postinst index 48921f2..3cf66a9 100644 --- a/packaging/deb/meshbay-hub/DEBIAN/postinst +++ b/packaging/deb/meshbay-hub/DEBIAN/postinst @@ -13,15 +13,16 @@ case "$1" in --gecos "MeshBay service account" meshbay fi - # Create data directory + # Create data and log directories install -d -o meshbay -g meshbay -m 750 /var/lib/meshbay/hub install -d -o meshbay -g meshbay -m 750 /var/log/meshbay - # Enable and start service + # Create config directory (files are placed by the admin, not by us) + install -d -m 755 /etc/meshbay + + # Reload systemd if available if [ -d /run/systemd/system ]; then systemctl daemon-reload || true - systemctl enable meshbay-hub.service || true - systemctl start meshbay-hub.service || true fi ;; esac diff --git a/packaging/deb/meshbay-node/DEBIAN/control b/packaging/deb/meshbay-node/DEBIAN/control index 8d74ee4..0c9d73d 100644 --- a/packaging/deb/meshbay-node/DEBIAN/control +++ b/packaging/deb/meshbay-node/DEBIAN/control @@ -1,17 +1,17 @@ Package: meshbay-node -Version: 0.2.0 +Version: __VERSION__ Section: net Priority: optional Architecture: all Maintainer: MeshBay Team Homepage: https://meshbay.org -Depends: python3 (>= 3.12), - python3-meshbay-common (= 0.2.0), - adduser +Depends: meshbay-common (= __VERSION__) Recommends: ffmpeg -Description: MeshBay Node — local file host and streaming server - MeshBay Node indexes local directories and serves encrypted files - to authenticated group members over QUIC (MNP v2) or TCP+TLS (MNP v1). +Description: MeshBay Node — local file host, streaming server, and group daemon + MeshBay Node indexes local directories and serves encrypted files to + authenticated group members over WebRTC. Includes video streaming (fMP4 + remux via ffmpeg), group chat, and a local admin UI on localhost:18000. . - Includes a local management web UI at http://localhost:18000. - Designed to run on a home server or NAS. + Installs node code into the shared venv at /opt/meshbay-common/venv/. + Ships a default TMDB API token for the Videos app. + Runs as a systemd user service. diff --git a/packaging/deb/meshbay-node/DEBIAN/postinst b/packaging/deb/meshbay-node/DEBIAN/postinst new file mode 100644 index 0000000..ba16633 --- /dev/null +++ b/packaging/deb/meshbay-node/DEBIAN/postinst @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +case "$1" in + configure) + # Reload systemd if available + if [ -d /run/systemd/system ]; then + systemctl daemon-reload || true + fi + ;; +esac + +#DEBHELPER# diff --git a/packaging/desktop/meshbay.desktop b/packaging/desktop/meshbay.desktop new file mode 100644 index 0000000..9c1f6a5 --- /dev/null +++ b/packaging/desktop/meshbay.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Type=Application +Name=MeshBay +Comment=Peer-to-peer file sharing, streaming and group chat +Exec=/opt/meshbay-client/meshbay %U +Icon=meshbay +Terminal=false +Categories=Network;FileTransfer;Chat; +MimeType=x-scheme-handler/meshbay; +StartupWMClass=MeshBay diff --git a/packaging/firewall/firewalld/meshbay-cast.xml b/packaging/firewall/firewalld/meshbay-cast.xml new file mode 100644 index 0000000..065820b --- /dev/null +++ b/packaging/firewall/firewalld/meshbay-cast.xml @@ -0,0 +1,7 @@ + + + MeshBay Cast + HTTP relay for casting decrypted video to Chromecast and Smart TV devices on the local network. Includes mDNS for device discovery. + + + diff --git a/packaging/firewall/firewalld/meshbay-node.xml b/packaging/firewall/firewalld/meshbay-node.xml new file mode 100644 index 0000000..3443b54 --- /dev/null +++ b/packaging/firewall/firewalld/meshbay-node.xml @@ -0,0 +1,6 @@ + + + MeshBay Node + MeshBay Node local administration interface (localhost only by default). + + diff --git a/packaging/firewall/ufw/meshbay b/packaging/firewall/ufw/meshbay new file mode 100644 index 0000000..5a610a5 --- /dev/null +++ b/packaging/firewall/ufw/meshbay @@ -0,0 +1,9 @@ +[MeshBay Cast] +title=MeshBay Chromecast relay +description=HTTP relay for casting decrypted video to LAN devices +ports=19550:19553/tcp|5353/udp + +[MeshBay Node] +title=MeshBay Node admin UI +description=Local administration interface (localhost only by default) +ports=18000/tcp diff --git a/packaging/rpm/meshbay-client.spec b/packaging/rpm/meshbay-client.spec new file mode 100644 index 0000000..8788e67 --- /dev/null +++ b/packaging/rpm/meshbay-client.spec @@ -0,0 +1,53 @@ +Name: meshbay-client +Version: __VERSION__ +Release: 1%{?dist} +Summary: MeshBay — peer-to-peer file sharing, streaming and group chat +License: AGPLv3+ +URL: https://meshbay.org + +AutoReqProv: no + +Requires: gtk3 +Requires: libnotify +Requires: nss +Requires: libXScrnSaver +Requires: libXtst +Requires: at-spi2-core +Requires: libdrm +Requires: mesa-libgbm +Requires: alsa-lib +Recommends: meshbay-node + +%description +Desktop client for MeshBay. Connects to MeshBay nodes over WebRTC for +file sharing, video streaming, and group chat. Includes Chromecast and +Smart TV casting support. + +Installs the Electron application to /opt/meshbay-client/ and a Gnome +launcher named "MeshBay". + +%install +cp -a %{_staging_root}/* %{buildroot}/ + +%post +if [ -f /opt/meshbay-client/chrome-sandbox ]; then + chown root:root /opt/meshbay-client/chrome-sandbox + chmod 4755 /opt/meshbay-client/chrome-sandbox +fi +update-desktop-database /usr/share/applications 2>/dev/null || true +gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true + +%postun +update-desktop-database /usr/share/applications 2>/dev/null || true +gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true + +%files +/opt/meshbay-client +/usr/bin/meshbay +/usr/share/applications/meshbay.desktop +/usr/share/icons/hicolor/*/apps/meshbay.png +/usr/lib/firewalld/services/meshbay-cast.xml + +%changelog +* Sun Aug 31 2026 MeshBay Team - %{version}-1 +- Initial packaging of the desktop client diff --git a/packaging/rpm/meshbay-common.spec b/packaging/rpm/meshbay-common.spec new file mode 100644 index 0000000..e1088d4 --- /dev/null +++ b/packaging/rpm/meshbay-common.spec @@ -0,0 +1,25 @@ +Name: meshbay-common +Version: __VERSION__ +Release: 1%{?dist} +Summary: MeshBay shared Python runtime and libraries +License: AGPLv3+ +URL: https://meshbay.org + +AutoReqProv: no + +%description +Shared Python virtual environment, cryptographic primitives +(Ed25519, X25519, GEK wrap/unwrap, ChaCha20-Poly1305), protocol types +(MNP, MHP), and all pip dependencies used by meshbay-hub and meshbay-node. + +Installs to /opt/meshbay-common/venv/. + +%install +cp -a %{_staging_root}/* %{buildroot}/ + +%files +/opt/meshbay-common + +%changelog +* Sun Aug 31 2026 MeshBay Team - %{version}-1 +- Packaging overhaul: shared venv under /opt/meshbay-common/venv/ diff --git a/packaging/rpm/meshbay-hub.spec b/packaging/rpm/meshbay-hub.spec index dd4803f..73df0b9 100644 --- a/packaging/rpm/meshbay-hub.spec +++ b/packaging/rpm/meshbay-hub.spec @@ -1,61 +1,38 @@ Name: meshbay-hub -Version: 0.6.0 +Version: __VERSION__ Release: 1%{?dist} Summary: MeshBay Hub — identity authority and group registry server License: AGPLv3+ URL: https://meshbay.org -Source0: %{name}-%{version}.tar.gz +AutoReqProv: no BuildArch: noarch -BuildRequires: python3-devel >= 3.12 -BuildRequires: python3-pip -BuildRequires: python3-hatchling -Requires: python3 >= 3.12 -Requires: python3-meshbay-common = %{version} -Requires: python3-fastapi -Requires: python3-uvicorn -Requires: python3-sqlalchemy >= 2.0 -Requires: python3-alembic -Requires: python3-asyncpg -Requires: python3-pyjwt -Requires: python3-blake3 -Requires: python3-slowapi -Requires: postgresql-server +Requires: meshbay-common = %{version} +Recommends: caddy +Recommends: postgresql-server %description -MeshBay Hub provides identity management, group registry, -GEK bundle distribution, and coordination for MeshBay nodes. -Runs as a systemd service behind Caddy (HTTPS). +MeshBay Hub provides user registration, JWT issuance, group management, +WebRTC signaling, notifications, and moderation for MeshBay networks. -%prep -%autosetup - -%build -%{python3} -m pip wheel --no-deps --wheel-dir dist . +Installs hub code into the shared venv at /opt/meshbay-common/venv/. +Runs as a systemd service behind Caddy for HTTPS. %install -%{python3} -m pip install --root %{buildroot} --no-index --find-links dist meshbay-hub - -# systemd service -install -Dm644 packaging/systemd/meshbay-hub.service \ - %{buildroot}%{_unitdir}/meshbay-hub.service - -# Config file template -install -Dm644 packaging/conf/hub.toml.example \ - %{buildroot}%{_sysconfdir}/meshbay/hub.toml.example - -# Data directory -install -d %{buildroot}%{_sharedstatedir}/meshbay/hub +cp -a %{_staging_root}/* %{buildroot}/ %pre getent group meshbay >/dev/null || groupadd -r meshbay getent passwd meshbay >/dev/null || \ - useradd -r -g meshbay -d %{_sharedstatedir}/meshbay -s /sbin/nologin \ + useradd -r -g meshbay -d /var/lib/meshbay -s /sbin/nologin \ -c "MeshBay service account" meshbay %post %systemd_post meshbay-hub.service +install -d -o meshbay -g meshbay -m 750 /var/lib/meshbay/hub +install -d -o meshbay -g meshbay -m 750 /var/log/meshbay +install -d -m 755 /etc/meshbay %preun %systemd_preun meshbay-hub.service @@ -64,55 +41,13 @@ getent passwd meshbay >/dev/null || \ %systemd_postun_with_restart meshbay-hub.service %files -%license LICENSE -%doc README.md -%{python3_sitelib}/meshbay_hub/ -%{python3_sitelib}/meshbay_hub-*.dist-info/ -%{_bindir}/meshbay-hub +/opt/meshbay-hub +/opt/meshbay-common/venv/lib/python*/site-packages/meshbay_hub/ +/opt/meshbay-common/venv/lib/python*/site-packages/meshbay_hub-*.dist-info/ +/opt/meshbay-common/venv/bin/meshbay-hub +/usr/bin/meshbay-hub %{_unitdir}/meshbay-hub.service -%config(noreplace) %{_sysconfdir}/meshbay/hub.toml.example -%dir %attr(750, meshbay, meshbay) %{_sharedstatedir}/meshbay/hub %changelog -* Sun Aug 23 2026 MeshBay Team - 0.6.0-1 -- Group UI split into a pluggable "applications" architecture (Chat, Files - today; Videos/Music/Photos can register without touching GroupPage) -- Operators can enable/disable applications per group from Settings -- Group Settings sections reordered: Invite, Pairing, Applications, Shared - directories, Uploads, danger zone, Your devices, Members -- Fixed: a fresh access token was never picked up when a "not a member" - handshake retry fired, wrongly locking a member (including a group's own - creator) out of a group they had just joined -- Fixed: opening Chat on a group with existing messages threw and wedged the - page's rendering, leaving every button unresponsive until reload - -* Sun Aug 16 2026 MeshBay Team - 0.5.0-1 -- Leave a group; public groups capped at 10 per owner, staff exempt -- Groups are listed only once a node has announced them; prune-groups collects the rest -- Node presence dot in the sidebar, from the signaling registry — no polling -- Chat opens on the newest 100 messages and pages backwards (it used to page forwards) -- Profile split out of Settings; public groups are open, invite-only is private -- Streamed downloads verify the service worker is really serving before writing -- Static assets are revalidated, so a half-updated SPA cannot load - -* Sun Aug 16 2026 MeshBay Team - 0.4.0-1 -- Web client translated into fr, es, pt-BR, zh-CN, ja, de, it, nl and pl -- Catalogues load on demand, one file per language, English as fallback -- Plural forms selected through Intl.PluralRules (Polish needs four) -- Locale matching keeps the region, so pt-BR and zh-CN resolve -- Static assets are revalidated, so a half-updated SPA cannot load - -* Sat Aug 15 2026 MeshBay Team - 0.3.0-1 -- Transfers survive leaving a group; downloads stream to disk in every browser -- Download a folder as a zip, built in the browser (zip64, store-only) -- Group owner can remove a member; editable group description -- Nodes are recorded at the address their signed announcement arrived from -- Deleted accounts stop being counted; the connection log keeps their name - -* Fri Aug 14 2026 MeshBay Team - 0.2.0-1 -- Hub no longer stores or publishes user identity keys (H3); schema migration -- Access tokens carry no pk_user claim -- SPA: Argon2id for the keypair bundle, per-node identity, invitation codes - -* Sat Aug 09 2026 MeshBay Team - 0.1.0-1 -- Initial package +* Sun Aug 31 2026 MeshBay Team - %{version}-1 +- Packaging overhaul: installs into shared venv under /opt diff --git a/packaging/rpm/meshbay-node.spec b/packaging/rpm/meshbay-node.spec index e4f386e..20d69bc 100644 --- a/packaging/rpm/meshbay-node.spec +++ b/packaging/rpm/meshbay-node.spec @@ -1,92 +1,49 @@ Name: meshbay-node -Version: 0.6.0 +Version: __VERSION__ Release: 1%{?dist} Summary: MeshBay Node — local file host, streaming server, and group daemon License: AGPLv3+ URL: https://meshbay.org -Source0: %{name}-%{version}.tar.gz +AutoReqProv: no BuildArch: noarch -BuildRequires: python3-devel >= 3.12 -BuildRequires: python3-pip -BuildRequires: python3-hatchling -Requires: python3 >= 3.12 -Requires: python3-meshbay-common = %{version} -Requires: python3-fastapi -Requires: python3-uvicorn -Requires: python3-httpx -Requires: python3-watchdog -Requires: python3-aioquic >= 1.0 -Requires: python3-aioice -Requires: python3-pyjwt -Requires: python3-blake3 -Requires: python3-msgpack -Requires: python3-zstandard -# Optional: ffmpeg for HLS streaming +Requires: meshbay-common = %{version} Recommends: ffmpeg %description -MeshBay Node indexes local directories and serves encrypted files -to authenticated group members over QUIC (MNP v2) or TCP+TLS (MNP v1). -Includes a local web UI at http://localhost:18000. +MeshBay Node indexes local directories and serves encrypted files to +authenticated group members over WebRTC. Includes video streaming (fMP4 +remux via ffmpeg), group chat, and a local admin UI on localhost:18000. -%prep -%autosetup - -%build -%{python3} -m pip wheel --no-deps --wheel-dir dist . +Installs node code into the shared venv at /opt/meshbay-common/venv/. +Ships a default TMDB API token for the Videos app. +Runs as a systemd user service. %install -%{python3} -m pip install --root %{buildroot} --no-index --find-links dist meshbay-node +cp -a %{_staging_root}/* %{buildroot}/ + +%post +if [ -d /run/systemd/system ]; then + systemctl daemon-reload || true +fi -# Two units, because there are two personas and one file cannot be both. -# -# The SYSTEM template carries User=%%i and is instantiated per person by root -# (`systemctl enable --now meshbay-node@alice`) — the server case. A *user* unit -# cannot carry User= at all: it already runs as its owner, and systemd refuses -# the file. This spec used to install the template into the user unit directory, -# where it could never have started. -install -Dm644 packaging/systemd/meshbay-node.service \ - %{buildroot}%{_unitdir}/meshbay-node@.service -install -Dm644 packaging/systemd/meshbay-node-user.service \ - %{buildroot}%{_userunitdir}/meshbay-node.service +%preun +if [ -d /run/systemd/system ]; then + systemctl daemon-reload || true +fi %files -%license LICENSE -%doc README.md -%{python3_sitelib}/meshbay_node/ -%{python3_sitelib}/meshbay_node-*.dist-info/ -%{_bindir}/meshbay-node +/opt/meshbay-node +/opt/meshbay-common/venv/lib/python*/site-packages/meshbay_node/ +/opt/meshbay-common/venv/lib/python*/site-packages/meshbay_node-*.dist-info/ +/opt/meshbay-common/venv/bin/meshbay-node +/usr/bin/meshbay-node %{_unitdir}/meshbay-node@.service %{_userunitdir}/meshbay-node.service +/usr/lib/firewalld/services/meshbay-node.xml +/etc/ufw/applications.d/meshbay %changelog -* Sun Aug 23 2026 MeshBay Team - 0.6.0-1 -- Per-group application enablement: roster setting, signed apps_enabled op, - enforced by the same admin-authority check as member_upload - -* Sun Aug 16 2026 MeshBay Team - 0.5.0-1 -- Abandoned video streams release their transcode slot at once -- Background tasks are held, so none is collected mid-flight losing a slot -- ffmpeg is reaped without deadlocking on its own unread output -- Chunk replies wait for room on the channel instead of queueing 8 MB -- Chat history pages backwards; upload names accept any script, and errors name the file - -* Sun Aug 16 2026 MeshBay Team - 0.4.0-1 -- No functional change; released in step with the other packages - -* Sat Aug 15 2026 MeshBay Team - 0.3.0-1 -- Video streaming is paced by the client; stream_stop frees the transcode slot -- Operator can remove an empty directory and revoke a member over MNP -- meshbay-node group add: host another of your hub groups -- admin_pk_ed25519 removed; the roster is the only source of node authority - -* Fri Aug 14 2026 MeshBay Team - 0.2.0-1 -- Node wraps the group key itself; members are admitted from a local roster -- Identity keys are per node, created at first contact and pinned there -- Operator surface over SSH: operator pair, member list|invite|revoke|unpin -- Unauthenticated HTTP file API and TCP transport removed (C1, C6) - -* Sat Aug 09 2026 MeshBay Team - 0.1.0-1 -- Initial package +* Sun Aug 31 2026 MeshBay Team - %{version}-1 +- Packaging overhaul: installs into shared venv under /opt diff --git a/packaging/rpm/python3-meshbay-common.spec b/packaging/rpm/python3-meshbay-common.spec deleted file mode 100644 index 6af8ed9..0000000 --- a/packaging/rpm/python3-meshbay-common.spec +++ /dev/null @@ -1,59 +0,0 @@ -Name: python3-meshbay-common -Version: 0.6.0 -Release: 1%{?dist} -Summary: MeshBay shared cryptographic primitives and protocol types -License: AGPLv3+ -URL: https://meshbay.org -Source0: meshbay-common-%{version}.tar.gz - -BuildArch: noarch -BuildRequires: python3-devel >= 3.12 -BuildRequires: python3-pip -BuildRequires: python3-hatchling - -Requires: python3 >= 3.12 -Requires: python3-cryptography >= 43.0 -Requires: python3-pyjwt >= 2.9 -Requires: python3-blake3 >= 1.0 -Requires: python3-msgpack >= 1.1 -Requires: python3-zstandard >= 0.23 - -%description -Shared library for MeshBay hub and node packages. -Provides: Ed25519/X25519 operations, GEK wrap/unwrap, chunk -encryption/signing, keystore AES-256-GCM, and MNP protocol types. - -%prep -%autosetup -n meshbay-common-%{version} - -%build -%{python3} -m pip wheel --no-deps --wheel-dir dist . - -%install -%{python3} -m pip install --root %{buildroot} --no-index --find-links dist meshbay-common - -%files -%license LICENSE -%{python3_sitelib}/meshbay_common/ -%{python3_sitelib}/meshbay_common-*.dist-info/ - -%changelog -* Sun Aug 23 2026 MeshBay Team - 0.6.0-1 -- MNP 0.4: apps_enabled/apps_enabled_ack, enabled_apps on the handshake ack - -* Sun Aug 16 2026 MeshBay Team - 0.5.0-1 -- MNP 0.2: PING/PONG, and backward chat paging (before / has_more) - -* Sun Aug 16 2026 MeshBay Team - 0.4.0-1 -- No functional change; released in step with the other packages - -* Sat Aug 15 2026 MeshBay Team - 0.3.0-1 -- MNP: dir_delete, member_revoke, stream_more/stream_stop; file_chunk names its file - -* Fri Aug 14 2026 MeshBay Team - 0.2.0-1 -- Join and pairing transcripts (meshbay:join:v1) -- Handshake refusals carry a machine-readable code -- gek_bundle_store removed from the protocol; no member supplies key material - -* Sat Aug 09 2026 MeshBay Team - 0.1.0-1 -- Initial package diff --git a/packaging/systemd/meshbay-hub.service b/packaging/systemd/meshbay-hub.service index 2bea8ea..40cdb98 100644 --- a/packaging/systemd/meshbay-hub.service +++ b/packaging/systemd/meshbay-hub.service @@ -16,8 +16,8 @@ EnvironmentFile=-/etc/meshbay/hub.env Environment=MESHBAY_DATABASE_URL=postgresql+asyncpg://meshbay:CHANGEME@localhost/meshbay_hub Environment=MESHBAY_HUB_KEY=/etc/meshbay/hub_private.pem -ExecStartPre=/usr/bin/meshbay-hub-migrate -ExecStart=/usr/bin/meshbay-hub --config /etc/meshbay/hub.toml +ExecStartPre=/opt/meshbay-common/venv/bin/alembic -c /opt/meshbay-hub/migrations/alembic.ini upgrade head +ExecStart=/opt/meshbay-common/venv/bin/meshbay-hub --config /etc/meshbay/hub.toml Restart=always RestartSec=5 TimeoutStopSec=30 diff --git a/packaging/systemd/meshbay-node-user.service b/packaging/systemd/meshbay-node-user.service index 62ca4de..feb415b 100644 --- a/packaging/systemd/meshbay-node-user.service +++ b/packaging/systemd/meshbay-node-user.service @@ -36,7 +36,7 @@ Type=simple # configures a contact in Settings. EnvironmentFile=-%h/.config/meshbay/node.env -ExecStart=/usr/bin/meshbay-node --config %h/.config/meshbay/node.toml +ExecStart=/opt/meshbay-common/venv/bin/meshbay-node --config %h/.config/meshbay/node.toml # The client asks for a reload after changing a group's directories, and that # must not drop a member who is watching a film. ExecReload=/bin/kill -HUP $MAINPID diff --git a/packaging/systemd/meshbay-node.service b/packaging/systemd/meshbay-node.service index 5c4de6b..ad4dc40 100644 --- a/packaging/systemd/meshbay-node.service +++ b/packaging/systemd/meshbay-node.service @@ -24,7 +24,7 @@ WorkingDirectory=%h # configures a contact in Settings. EnvironmentFile=-%h/.config/meshbay/node.env -ExecStart=/usr/bin/meshbay-node --config %h/.config/meshbay/node.toml +ExecStart=/opt/meshbay-common/venv/bin/meshbay-node --config %h/.config/meshbay/node.toml Restart=on-failure RestartSec=10 TimeoutStopSec=30 -- cgit v1.2.3