BYOS deployment agent for Laioutr BYOS (Bring Your Own Server) hosting. Execute bash scripts in response to deployment webhooks.
This project serves as a reference implementation and starting point for building your own webhook handler. Use it as-is for simple deployments, or as inspiration for custom implementations.
# Run directly with npx
npx @laioutr/byos-agent
# Or install globally
npm install -g @laioutr/byos-agent
laioutr-byos-agent
# Or as a local dependency
npm install @laioutr/byos-agent
npx laioutr-byos-agentnpm install @laioutr/byos-agentCreate a byos-agent.config.ts (or .js, .json) in your project root:
import type { WebhookRunnerConfigInput } from '@laioutr/byos-agent';
export default {
// Required: Your webhook signing secret from Laioutr
signingSecret: 'whsec_...',
// Required: URL of the deployed application. Can be overridden in the hosting.describe script.
baseUrl: 'https://your-server.com',
// Optional: Port to listen on (default: 4000)
port: 4000,
// Optional: Display name for your server
name: 'My Deployment Server',
// Optional: Shell to use for scripts (default: $SHELL or /bin/sh)
shell: '/bin/bash',
// Optional: Script timeout in seconds (default: 600, null for no timeout)
timeout: 600,
// Optional: Directory for temporary deployment files (default: OS temp dir)
tempDir: '/var/deployments',
// Optional: Log level (default: 'info')
logLevel: 'debug',
// Scripts to run for each webhook event
scripts: {
'hosting.deployment.created': './scripts/deploy.sh',
'hosting.deployment.cancel': 'echo "Cancelled: $LAIOUTR_DEPLOYMENT_ID"',
'hosting.deployment.delete': './scripts/cleanup.sh',
'hosting.deployment.promote': './scripts/promote.sh',
'hosting.deployment.rollback': './scripts/rollback.sh',
'hosting.connected': 'echo "Project connected"',
'hosting.disconnected': 'echo "Project disconnected"',
},
} satisfies WebhookRunnerConfigInput;Scripts can be file paths or inline shell commands.
All scripts are optional. Configure the ones you need.
All scripts receive:
| Variable | Description |
|---|---|
LAIOUTR_PROJECT |
Project identifier in format <organization-slug>/<project-slug> |
LAIOUTR_EVENT |
Event type (e.g. hosting.deployment.created) |
LAIOUTR_TIMESTAMP |
ISO timestamp of the event |
Executes when a new deployment is created. Runs in the background with status callbacks.
Additional Environment Variables:
| Variable | Description |
|---|---|
LAIOUTR_DEPLOYMENT_ID |
Unique deployment ID |
LAIOUTR_ENVIRONMENT |
Target environment (e.g. production) |
LAIOUTR_CALLBACK_URL |
URL for status updates |
LAIOUTR_PAYLOAD_FILE |
Path to full webhook payload JSON |
LAIOUTR_FILES_DIR |
Directory containing deployment files |
Working Directory: Set to LAIOUTR_FILES_DIR
Output: The last line of stdout is parsed for:
- A URL matching
(http|https)://...→ reported as deployment URL - The word
promoted(optional, case-insensitive) → marks deployment as promoted
#!/bin/bash
# Example: Output URL on success
echo "https://preview-${LAIOUTR_DEPLOYMENT_ID}.example.com"
# Or mark as success and promoted to production
echo "promoted https://example.com"
# Optionally you can just mark as success and promoted without a URL. Cockpit will use the configured baseUrl.
echo "promoted"If no URL is output but the script exits with code 0, the configured baseUrl is used.
Status Callbacks: Automatically sent to LAIOUTR_CALLBACK_URL:
| Status | When |
|---|---|
running |
Script starts |
success |
Exit code 0 |
promoted |
Exit code 0 + "promoted" in output |
error |
Non-zero exit, timeout, or cancelled |
Handles deployment cancellation. Cancellation is always supported - if a deployment is running, the process group is killed automatically. The optional script runs after termination for cleanup.
Additional Environment Variables:
| Variable | Description |
|---|---|
LAIOUTR_DEPLOYMENT_ID |
Deployment ID to cancel |
Output: Not parsed.
Executes when a deployment is deleted.
Additional Environment Variables:
| Variable | Description |
|---|---|
LAIOUTR_DEPLOYMENT_ID |
Deployment ID to delete |
Output: Not parsed.
Executes when a deployment is promoted to production.
Additional Environment Variables:
| Variable | Description |
|---|---|
LAIOUTR_DEPLOYMENT_ID |
Deployment ID to promote |
Output: Not parsed.
Executes when rolling back to a previous deployment.
Additional Environment Variables:
| Variable | Description |
|---|---|
LAIOUTR_DEPLOYMENT_ID |
Target deployment ID |
LAIOUTR_FROM_DEPLOYMENT_ID |
Previous deployment ID (may be empty) |
Output: Not parsed.
Provides hosting information. Used to override the base URL dynamically.
Output: If the last line contains a URL, it overrides baseUrl in the response.
Execute when a project connects or disconnects.
Output: Not parsed.
The webhook router can be integrated into any server that supports Hono routers:
import { Hono } from 'hono';
import { webhookRouter, loadConfig, setRuntimeConfig } from '@laioutr/byos-agent';
// Load config from byos-agent.config.ts and set it for the router
const config = await loadConfig();
setRuntimeConfig(config);
const app = new Hono();
// Mount at /webhook
app.route('/webhook', webhookRouter);
export default app;See the examples/ directory for complete deployment setups:
- Docker + Traefik - Build and run Laioutr frontends as Docker containers with Traefik reverse proxy
- PM2 - Deploy Laioutr frontends on bare metal with PM2 process manager
Both examples support preview deployments and promotion to production.
For complete webhook configuration details, event types, and implementation guidance, see the Laioutr BYOS Documentation.
MIT