Files
sisungo 1b3d2b768a initial commit
Signed-off-by: sisungo <[email protected]>
2026-09-13 11:24:21 +00:00

222 lines
7.1 KiB
Markdown

# SemiOS Build Server
A web-based package build server for SemiOS. Uses SvelteKit SSR for the UI and a Rust agent for executing builds on remote machines.
## Requirements
### Build Server
- **Node.js** >= 18
- **npm**
- **Git**
- A running instance of the [packie](https://gitea.semilabs.org/semios/packie.git) package manager on the build machines
### Build Agent (per machine)
- **Rust** >= 1.85 (edition 2024)
- **Git**
- The [ports](https://gitea.semilabs.org/semios/ports.git) repository cloned on the machine
- `packie` installed and available in `$PATH`
## Quick Start
### 1. Clone and Build the Server
```bash
git clone https://gitea.semilabs.org/semios/semios-build-server.git
cd semios-build-server
npm install
npm run build
```
### 2. Configure the Server
Copy and edit `config.toml` at the project root:
```toml
[server]
host = "0.0.0.0"
port = 3000
[ports]
repo_url = "https://gitea.semilabs.org/semios/ports.git"
repo_path = "/path/to/ports-cache"
sync_interval_secs = 300
[repo]
publish_dir = "/path/to/repo-output"
[agent]
token = "your-shared-secret-token"
listen_port = 3001
[users]
admin = "scrypt$<salt>$<hash>"
```
| Key | Description |
|-----|-------------|
| `server.host` | Bind address (`0.0.0.0` for all interfaces) |
| `server.port` | Web UI port |
| `ports.repo_url` | Git URL of the ports repository |
| `ports.repo_path` | Local path where the server clones/caches the ports repo |
| `ports.sync_interval_secs` | How often to pull from upstream (seconds) |
| `repo.publish_dir` | Where published packages are collected |
| `agent.token` | Shared secret for agent authentication |
| `agent.listen_port` | Port the server expects agents to expose (for display only) |
| `users.*` | User accounts (username = scrypt password hash) |
### 3. Add Users
Only logged-in users can start builds, add packages to the repository, or delete artifacts.
Use the **registration helper** at `/register` to generate password hashes. For each user:
1. Open `http://localhost:3000/register` in a browser
2. Enter username and password, click **Generate Config Snippet**
3. Copy the `[users]` line into `config.toml`
4. Restart the server
Or generate hashes from the command line:
```bash
node -e "
const crypto = require('crypto');
const salt = crypto.randomBytes(16).toString('hex');
const hash = crypto.scryptSync('your-password', salt, 64).toString('hex');
console.log('scrypt\$' + salt + '\$' + hash);
"
```
### 3. Start the Server
```bash
BODY_SIZE_LIMIT=52428800 node build/index.js
```
Or use the npm script:
```bash
npm run start
```
The server listens on `http://0.0.0.0:3000` by default.
#### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `BODY_SIZE_LIMIT` | - | Max request body size in bytes (set to `52428800` for artifact uploads) |
| `PORT` | - | Override the listen port |
### 4. Build and Start the Agent
On each build machine:
```bash
cd agent
cargo build --release
cp agent.toml /etc/semios-build-agent/agent.toml # or any location
./target/release/semios-build-agent
```
Edit `agent.toml` before running:
```toml
master_url = "http://server-ip:3000"
name = "worker-1"
hostname = "192.168.1.100"
port = 3001
token = "your-shared-secret-token"
ports_repo_path = "/path/to/ports-on-this-machine"
```
| Key | Description |
|-----|-------------|
| `master_url` | URL of the build server |
| `name` | Unique machine name (used for routing builds) |
| `hostname` | Reachable hostname/IP for the server to connect back |
| `port` | Port the agent listens on |
| `token` | Must match the server's `agent.token` |
| `ports_repo_path` | Path to the ports repo on this machine |
### 5. Register a Machine
Machines register automatically when they connect. You can also add them manually via the web UI at `/machines` or by calling the API:
```bash
curl -X POST http://localhost:3000/api/machines \
-H 'Content-Type: application/json' \
-d '{"name":"worker-1","hostname":"192.168.1.100","port":3001}'
```
### 6. Load Packages
Click **Sync from Git** in the web UI (`/packages`) or call:
```bash
curl -X POST http://localhost:3000/api/sync
```
## Architecture
```
┌──────────────┐ ┌──────────────┐
│ Web UI │◄───────►│ Build Server │
│ (browser) │ HTTP │ Node.js │
└──────────────┘ └──────┬───────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Agent A │ │ Agent B │ │ Agent C │
│ (aarch64)│ │ (x86_64) │ │ (riscv64)│
└──────────┘ └──────────┘ └──────────┘
```
- **Build Server** — SvelteKit SSR app with SQLite database. Manages packages, builds, artifacts, and dispatches build jobs to agents.
- **Build Agent** — Rust binary. Polls the server for pending builds, executes `./x --atombuild --target <target> build <package>`, streams logs in real-time, and uploads `.pkg` artifacts.
## File Layout
```
~/.cache/semios-build/
ports/ # cloned ports repo (server-side)
repo/ # published packages output
project-root/
config.toml # server configuration
build-server.db # SQLite database (auto-created)
uploads/ # build artifacts (build-<id>/)
logs/ # build log files
agent/
agent.toml # agent configuration
```
## Build Workflow
1. A user clicks **Build** on a package, selects architecture and atombuild option in the dialog.
2. The server creates a build record with status `queued` and computes the target (e.g. `aarch64-semios-linux`).
3. The dispatcher assigns the build to an idle machine with matching architecture.
4. The agent clones/updates the ports repo, runs the build, and streams logs to the server via `POST /api/builds/<id>/log`.
5. On completion, the agent discovers `.pkg` files and uploads them as artifacts.
6. The server marks the build as `success` or `failed`.
7. Artifacts can be added to the repository via **Add to Repo**, which calls `packie repo-admin --add-package`.
## Development
```bash
npm run dev # starts vite dev server with HMR
```
## Troubleshooting
| Symptom | Fix |
|---------|-----|
| 500 errors on pages | Kill stale processes, rebuild with `rm -rf build .svelte-kit && npm run build`, restart |
| Agent not receiving builds | Check `master_url`, `token`, and network connectivity |
| Build fails immediately | Ensure `packie` is in `$PATH` and ports repo is cloned at `ports_repo_path` |
| Artifact upload fails | Set `BODY_SIZE_LIMIT=52428800` (50 MB) on the server |
| 401 on build/repo actions | Login required — use the sidebar login link or visit `/login` |
| Cannot add users | Generate hash via `/register` helper or CLI snippet, add `[users]` section to `config.toml` |