Add .deb package builder script

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
tocmo0nlord
2026-04-12 16:13:21 -04:00
parent d68a557de8
commit e312420c3d

205
packaging/build-deb.sh Normal file
View File

@@ -0,0 +1,205 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────
# LLM Trainer — .deb package builder
# Run this on the Ubuntu machine after cloning the repo:
# chmod +x packaging/build-deb.sh
# ./packaging/build-deb.sh
# ─────────────────────────────────────────────────────────────
set -euo pipefail
PKG_NAME="llm-trainer"
PKG_VERSION="1.0.0"
PKG_ARCH="amd64"
PKG_DIR="${PKG_NAME}_${PKG_VERSION}_${PKG_ARCH}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
OUT_DIR="${REPO_ROOT}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " LLM Trainer .deb Builder"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# ── Check dependencies ────────────────────────────────────────
for cmd in node npm python3 pip3 dpkg-deb nginx; do
if ! command -v "$cmd" &>/dev/null; then
echo "[ERROR] Required command not found: $cmd"
echo " Install with: sudo apt install nodejs npm python3-pip nginx"
exit 1
fi
done
# ── Build frontend ────────────────────────────────────────────
echo ""
echo "[1/4] Building React frontend..."
cd "${REPO_ROOT}/frontend"
npm install --silent
npm run build
echo " Frontend built → frontend/dist"
# ── Create package directory tree ─────────────────────────────
echo ""
echo "[2/4] Creating package structure..."
BUILD="${REPO_ROOT}/${PKG_DIR}"
rm -rf "${BUILD}"
install -d "${BUILD}/DEBIAN"
install -d "${BUILD}/opt/llm-trainer/backend"
install -d "${BUILD}/opt/llm-trainer/frontend"
install -d "${BUILD}/opt/llm-trainer/venv"
install -d "${BUILD}/lib/systemd/system"
install -d "${BUILD}/etc/nginx/sites-available"
install -d "${BUILD}/etc/nginx/sites-enabled"
install -d "${BUILD}/etc/llm-trainer"
install -d "${BUILD}/var/log/llm-trainer"
# Copy backend
cp "${REPO_ROOT}/backend/"*.py "${BUILD}/opt/llm-trainer/backend/"
cp "${REPO_ROOT}/backend/requirements.txt" "${BUILD}/opt/llm-trainer/backend/"
# Copy built frontend
cp -r "${REPO_ROOT}/frontend/dist/." "${BUILD}/opt/llm-trainer/frontend/"
# ── Write control files ───────────────────────────────────────
cat > "${BUILD}/DEBIAN/control" <<EOF
Package: ${PKG_NAME}
Version: ${PKG_VERSION}
Architecture: ${PKG_ARCH}
Maintainer: tocmo0nlord
Depends: python3 (>= 3.10), python3-pip, python3-venv, nginx
Description: LLM Trainer Dashboard
Web dashboard for managing LLM training pipelines via SSH.
Includes document ingestion, QA pair generation, curation,
training monitor, and an interactive terminal.
EOF
# ── Systemd service ───────────────────────────────────────────
cat > "${BUILD}/lib/systemd/system/llm-trainer.service" <<EOF
[Unit]
Description=LLM Trainer Backend
After=network.target
[Service]
Type=simple
User=llm-trainer
Group=llm-trainer
WorkingDirectory=/opt/llm-trainer/backend
ExecStart=/opt/llm-trainer/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8080
Restart=always
RestartSec=5
StandardOutput=append:/var/log/llm-trainer/backend.log
StandardError=append:/var/log/llm-trainer/backend.log
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
EOF
# ── Nginx config ──────────────────────────────────────────────
cat > "${BUILD}/etc/nginx/sites-available/llm-trainer" <<'EOF'
server {
listen 3000;
server_name _;
root /opt/llm-trainer/frontend;
index index.html;
# Serve React SPA
location / {
try_files $uri $uri/ /index.html;
}
# Proxy REST API to FastAPI backend
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# WebSocket support (terminal, log streaming)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
EOF
# ── postinst ──────────────────────────────────────────────────
cat > "${BUILD}/DEBIAN/postinst" <<'POSTINST'
#!/bin/bash
set -e
# Create system user
if ! id -u llm-trainer &>/dev/null; then
useradd --system --no-create-home --shell /usr/sbin/nologin llm-trainer
fi
# Set permissions
chown -R llm-trainer:llm-trainer /opt/llm-trainer
chown -R llm-trainer:llm-trainer /var/log/llm-trainer
# Build Python venv and install deps
echo "Installing Python dependencies..."
python3 -m venv /opt/llm-trainer/venv
/opt/llm-trainer/venv/bin/pip install --quiet --upgrade pip
/opt/llm-trainer/venv/bin/pip install --quiet -r /opt/llm-trainer/backend/requirements.txt
chown -R llm-trainer:llm-trainer /opt/llm-trainer/venv
# Enable nginx site
ln -sf /etc/nginx/sites-available/llm-trainer /etc/nginx/sites-enabled/llm-trainer
nginx -t && systemctl reload nginx || true
# Enable and start backend service
systemctl daemon-reload
systemctl enable llm-trainer
systemctl start llm-trainer
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " LLM Trainer installed successfully!"
echo " Open: http://$(hostname -I | awk '{print $1}'):3000"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
POSTINST
chmod 0755 "${BUILD}/DEBIAN/postinst"
# ── prerm ─────────────────────────────────────────────────────
cat > "${BUILD}/DEBIAN/prerm" <<'PRERM'
#!/bin/bash
set -e
systemctl stop llm-trainer 2>/dev/null || true
systemctl disable llm-trainer 2>/dev/null || true
rm -f /etc/nginx/sites-enabled/llm-trainer
systemctl reload nginx 2>/dev/null || true
PRERM
chmod 0755 "${BUILD}/DEBIAN/prerm"
# ── postrm ────────────────────────────────────────────────────
cat > "${BUILD}/DEBIAN/postrm" <<'POSTRM'
#!/bin/bash
set -e
if [ "$1" = "purge" ]; then
rm -rf /opt/llm-trainer
rm -rf /var/log/llm-trainer
rm -f /etc/nginx/sites-available/llm-trainer
userdel llm-trainer 2>/dev/null || true
fi
POSTRM
chmod 0755 "${BUILD}/DEBIAN/postrm"
# ── Build .deb ────────────────────────────────────────────────
echo ""
echo "[3/4] Building .deb package..."
cd "${REPO_ROOT}"
dpkg-deb --build --root-owner-group "${PKG_DIR}"
echo " Package built → ${PKG_DIR}.deb"
# ── Cleanup ───────────────────────────────────────────────────
rm -rf "${BUILD}"
echo ""
echo "[4/4] Done!"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Install with:"
echo " sudo dpkg -i ${PKG_DIR}.deb"
echo " sudo apt-get install -f # fix any missing deps"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"