xbp 10.8.4

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation

xbp universal build and deployment toolkit

xbp helps you build deploy and manage rust nextjs nodejs python expressjs and more integrates tightly with nginx and modern cloud devops workflows modular scriptable and built with extensibility in mind

current version: 10.8.4

Coverage XBP vs PM2

  • Process manager
  • Zero downtime reloads
  • Terminal based monitoring
  • web based monitor interface
  • synthetic application overview
  • track bugs and exceptions
  • custom metrics
  • consult application logs
  • monitor node.js v8 behavior
  • Receive emails / slack notifications
  • server health check monitoring
  • in-situ cpu and memory profiling
  • transaction tracing
  • advanced rule-based alerting
  • custom dashboards
  • long term data retention
  • dedicated or on-premise install
  • go / python integration

features

  • deploy and manage rust js nextjs python expressjs and custom multi language projects
  • nginx integration and config templating
  • modular cli with portable library core
  • easy yaml config ssh support secrets management
  • lightweight minimal dependencies cross platform
  • multi service deployment support with pm2 integration
  • version management via api integration
  • service based configuration with validation

quickstart

# install rust cargo required
cargo install xbp-cli
# or build from source
cargo build --release

# list all running network ports
xbp ports
# filter by port number
xbp ports -p 3000
# list all services in current project
xbp services
# build a service
xbp service build zeus
# redeploy a service
xbp redeploy zeus

installation

  • release binaries see releases
  • from source requires rust 1.72+
git clone https://github.com/xylex-group/xbp.git
cd xbp
cargo build --release
./target/release/xbp --help

configuration

xbp uses configuration files located in .xbp/xbp.json, .xbp/xbp.yaml, or in the project root. both json and yaml formats are supported.

configuration file locations

xbp searches for configuration files in the following order:

  1. .xbp/xbp.yaml or .xbp/xbp.json (recommended)
  2. xbp.yaml or xbp.json (project root)

xbp.json schema

minimal configuration

{
  "project_name": "my-app",
  "port": 3000,
  "build_dir": "/path/to/project"
}

complete json schema with all fields

{
  "project_name": "string (required) - project name",
  "port": "number (required) - main application port 1-65535",
  "build_dir": "string (required) - absolute path to project directory",
  "app_type": "string (optional) - application type: rust, nextjs, nodejs, python, expressjs",
  "build_command": "string (optional) - command to build the application",
  "start_command": "string (optional) - command to start the application",
  "install_command": "string (optional) - command to install dependencies",
  "environment": {
    "KEY": "value - optional environment variables as key-value pairs"
  },
  "services": [
    {
      "name": "string (required) - unique service name",
      "target": "string (required) - one of: python, expressjs, nextjs, rust",
      "branch": "string (required) - git branch to deploy from",
      "port": "number (required) - service port number",
      "root_directory": "string (optional) - relative or absolute path to service root",
      "environment": {
        "KEY": "value - optional environment variables for this service"
      },
      "url": "string (optional) - service url for healthchecks",
      "healthcheck_path": "string (optional) - path for healthcheck requests",
      "restart_policy": "string (optional) - pm2 restart policy, defaults to on_failure",
      "restart_policy_max_failure_count": "number (optional) - max failures before stopping, defaults to 10",
      "start_wrapper": "string (optional) - wrapper for start command, typically pm2",
      "force_run_from_root": "boolean (optional) - if true runs commands from project root, defaults to false",
      "commands": {
        "pre": "string (optional) - command to run before install",
        "install": "string (optional) - command to install dependencies",
        "build": "string (optional) - command to build the service",
        "start": "string (optional) - command to start the service",
        "dev": "string (optional) - command to run in development mode"
      }
    }
  ],
  "monitor_url": "string (optional) - url to monitor for health checks",
  "monitor_method": "string (optional) - http method for monitoring: GET, POST, etc",
  "monitor_expected_code": "number (optional) - expected http status code, defaults to 200",
  "monitor_interval": "number (optional) - interval between health checks in seconds, defaults to 60",
  "log_files": ["array of strings (optional) - log files to tail"],
  "kafka_brokers": "string (optional) - kafka broker addresses, format: host:port or host1:port1,host2:port2",
  "kafka_topic": "string (optional) - kafka topic for logs",
  "kafka_public_url": "string (optional) - public kafka url",
  "target": "string (deprecated) - use app_type instead",
  "branch": "string (optional) - git branch name for legacy single service",
  "crate_name": "string (optional) - rust crate name for legacy single service",
  "npm_script": "string (optional) - npm script to run for legacy single service",
  "url": "string (optional) - public url for legacy single service"
}

multi service example with all features

{
  "project_name": "my-microservices",
  "port": 3000,
  "build_dir": "/home/user/projects/microservices",
  "services": [
    {
      "name": "api",
      "target": "rust",
      "branch": "main",
      "port": 3000,
      "root_directory": "apps/api",
      "url": "https://api.example.com",
      "healthcheck_path": "/health",
      "restart_policy": "on_failure",
      "restart_policy_max_failure_count": 10,
      "start_wrapper": "pm2",
      "force_run_from_root": false,
      "environment": {
        "RUST_LOG": "info",
        "DATABASE_URL": "postgresql://localhost/db"
      },
      "commands": {
        "pre": "rustup update stable",
        "install": "cargo fetch",
        "build": "cargo build --release",
        "start": "./target/release/api",
        "dev": "cargo watch -x run"
      }
    },
    {
      "name": "frontend",
      "target": "nextjs",
      "branch": "main",
      "port": 3001,
      "root_directory": "apps/frontend",
      "url": "https://app.example.com",
      "healthcheck_path": "/api/health",
      "restart_policy": "always",
      "start_wrapper": "pm2",
      "force_run_from_root": false,
      "environment": {
        "NODE_ENV": "production",
        "NEXT_PUBLIC_API_URL": "https://api.example.com"
      },
      "commands": {
        "pre": "npm install -g pnpm",
        "install": "pnpm install",
        "build": "pnpm run build",
        "start": "pnpm run start",
        "dev": "pnpm run dev"
      }
    },
    {
      "name": "worker",
      "target": "python",
      "branch": "main",
      "port": 3002,
      "root_directory": "apps/worker",
      "restart_policy": "on_failure",
      "start_wrapper": "pm2",
      "environment": {
        "PYTHONPATH": "/home/user/projects/microservices/apps/worker"
      },
      "commands": {
        "install": "pip install -r requirements.txt",
        "start": "python main.py"
      }
    }
  ],
  "monitor_url": "https://api.example.com/health",
  "monitor_method": "GET",
  "monitor_expected_code": 200,
  "monitor_interval": 60,
  "log_files": [
    "/var/log/app/api.log",
    "/var/log/app/frontend.log",
    "/home/user/.pm2/logs/api-out.log"
  ],
  "kafka_brokers": "localhost:9092",
  "kafka_topic": "application-logs",
  "kafka_public_url": "https://kafka.example.com:9092",
  "environment": {
    "NODE_ENV": "production",
    "LOG_LEVEL": "info"
  }
}

xbp.yaml schema

xbp also supports yaml format which is more readable and supports comments.

minimal yaml configuration

project_name: my-app
port: 3000
build_dir: /path/to/project

complete yaml schema with all fields

# Core configuration (all required)
project_name: string # project name
port: 3000 # main application port 1-65535
build_dir: /path/to/project # absolute path to project directory

# Application configuration (optional)
app_type: rust # application type: rust, nextjs, nodejs, python, expressjs
build_command: cargo build --release # command to build the application
start_command: ./target/release/my-app # command to start the application
install_command: cargo fetch # command to install dependencies

# Environment variables (optional)
environment:
  NODE_ENV: production
  RUST_LOG: info
  DATABASE_URL: postgresql://localhost/mydb

# Multi-service configuration (optional)
services:
  - name: api # unique service name (required)
    target: rust # one of: python, expressjs, nextjs, rust (required)
    branch: main # git branch to deploy from (required)
    port: 3000 # service port number (required)
    root_directory: apps/api # relative or absolute path to service root (optional)
    url: https://api.example.com # service url for healthchecks (optional)
    healthcheck_path: /health # path for healthcheck requests (optional)
    restart_policy: on_failure # pm2 restart policy (optional, defaults to on_failure)
    restart_policy_max_failure_count: 10 # max failures before stopping (optional, defaults to 10)
    start_wrapper: pm2 # wrapper for start command (optional, typically pm2)
    force_run_from_root: false # if true runs commands from project root (optional, defaults to false)
    environment:
      RUST_LOG: info
      DATABASE_URL: postgresql://localhost/db
    commands:
      pre: rustup update stable # command to run before install (optional)
      install: cargo fetch # command to install dependencies (optional)
      build: cargo build --release # command to build the service (optional)
      start: ./target/release/api # command to start the service (optional)
      dev: cargo watch -x run # command to run in development mode (optional)

# Monitoring configuration (optional)
monitor_url: https://api.example.com/health # url to monitor for health checks
monitor_method: GET # http method for monitoring: GET, POST, etc
monitor_expected_code: 200 # expected http status code (defaults to 200)
monitor_interval: 60 # interval between health checks in seconds (defaults to 60)

# Logging configuration (optional)
log_files:
  - /var/log/app/api.log
  - /var/log/app/frontend.log
  - /home/user/.pm2/logs/api-out.log

# Kafka configuration (optional)
kafka_brokers: localhost:9092 # kafka broker addresses, format: host:port or host1:port1,host2:port2
kafka_topic: application-logs # kafka topic for logs
kafka_public_url: https://kafka.example.com:9092 # public kafka url

# Legacy fields for backward compatibility (optional)
target: rust # deprecated - use app_type instead
branch: main # git branch name for legacy single service
crate_name: my_api # rust crate name for legacy single service
npm_script: start # npm script to run for legacy single service
url: https://example.com # public url for legacy single service

multi service yaml example with all features

project_name: my-microservices
port: 3000
build_dir: /home/user/projects/microservices

services:
  - name: api
    target: rust
    branch: main
    port: 3000
    root_directory: apps/api
    url: https://api.example.com
    healthcheck_path: /health
    restart_policy: on_failure
    restart_policy_max_failure_count: 10
    start_wrapper: pm2
    force_run_from_root: false
    environment:
      RUST_LOG: info
      DATABASE_URL: postgresql://localhost/db
    commands:
      pre: rustup update stable
      install: cargo fetch
      build: cargo build --release
      start: ./target/release/api
      dev: cargo watch -x run

  - name: frontend
    target: nextjs
    branch: main
    port: 3001
    root_directory: apps/frontend
    url: https://app.example.com
    healthcheck_path: /api/health
    restart_policy: always
    start_wrapper: pm2
    force_run_from_root: false
    environment:
      NODE_ENV: production
      NEXT_PUBLIC_API_URL: https://api.example.com
    commands:
      pre: npm install -g pnpm
      install: pnpm install
      build: pnpm run build
      start: pnpm run start
      dev: pnpm run dev

  - name: worker
    target: python
    branch: main
    port: 3002
    root_directory: apps/worker
    restart_policy: on_failure
    start_wrapper: pm2
    environment:
      PYTHONPATH: /home/user/projects/microservices/apps/worker
    commands:
      install: pip install -r requirements.txt
      start: python main.py

monitor_url: https://api.example.com/health
monitor_method: GET
monitor_expected_code: 200
monitor_interval: 60

log_files:
  - /var/log/app/api.log
  - /var/log/app/frontend.log
  - /home/user/.pm2/logs/api-out.log

kafka_brokers: localhost:9092
kafka_topic: application-logs
kafka_public_url: https://kafka.example.com:9092

environment:
  NODE_ENV: production
  LOG_LEVEL: info

service configuration field reference

required fields

  • name - unique service name
  • target - one of: python, expressjs, nextjs, rust
  • branch - git branch to deploy from
  • port - service port number (1-65535)

optional fields

  • root_directory - relative or absolute path to service root (defaults to project root)
  • url - service url for healthchecks
  • healthcheck_path - path for healthcheck requests
  • restart_policy - pm2 restart policy (defaults to on_failure)
  • restart_policy_max_failure_count - max failures before stopping (defaults to 10)
  • start_wrapper - wrapper for start command, typically pm2
  • force_run_from_root - if true, runs commands from project root instead of root_directory (defaults to false)
  • environment - object containing environment variables for the service
  • commands - object containing pre, install, build, start, dev commands

configuration validation

xbp validates service configurations and will error if:

  • duplicate service names found
  • duplicate ports found
  • duplicate urls found
  • invalid target type (not one of: python, expressjs, nextjs, rust)
  • missing required fields (project_name, port, build_dir for top level; name, target, branch, port for services)

commands

service management

  • xbp services list all services from current xbp.json config
  • xbp service <command> <service-name> run command for a service
    • commands: build install start dev
    • example: xbp service build zeus
  • xbp service --help <service-name> show help for a specific service
  • xbp redeploy <service-name> redeploy a specific service via pm2

deployment

  • xbp redeploy [<service-name>] redeploy using redeploy.sh legacy or specific service
  • xbp redeploy_v2 [-p <password>] [-u <username>] [-h <host>] [-d <project-dir>] remotely redeploy using redeploy.sh

general

  • xbp ports [-p <port>] [--kill] [-n] list active ports and processes optionally search nginx configs
  • xbp setup run initial setup commands
  • xbp config display xbp.json contents
  • xbp install <package> install a package
  • xbp logs [<project>] view pm2 logs
  • xbp list list pm2 processes
  • xbp -l list pm2 processes shortcut
  • xbp curl [<url>] fetch url and display response

redeploy workflow

when you run xbp redeploy <service-name> the following happens

  1. git reset --hard to clean local changes
  2. git pull origin to get latest code
  3. fetch version from api.xbp.app/version?project_name=
  4. create dist folder at /home/{USER}/.xbp/dist/{version}/
  5. run pre command if configured
  6. run install command if configured
  7. run build command if configured
  8. stop existing pm2 process for the service
  9. copy build artifacts to dist folder
  10. start pm2 process with wrapped start command
  11. write logs to .xbp/logs/{service-name}/
  12. update version via api increment endpoint
  13. cleanup stopped and errored pm2 processes

service commands

service commands respect the root_directory and force_run_from_root settings

  • if force_run_from_root is true commands run from project root
  • if root_directory is set and force_run_from_root is false commands run from root_directory
  • if neither is set commands run from project root

start commands are automatically wrapped with pm2 when start_wrapper is set to pm2 the start command will be executed as pm2 start "{start_command}" --name {name} -- --port {port}

pm2 integration

xbp integrates with pm2 for process management

  • processes are named using the service name
  • logs are written to .xbp/logs/{service-name}/stdout.log and stderr.log
  • pm2 save is called after deployments to persist process list
  • stopped and errored processes are automatically cleaned up

version management

xbp integrates with the xbp version api for version tracking

  • versions are fetched from api.xbp.app/version?project_name=
  • versions are incremented via api.xbp.app/version/increment after successful deployment
  • version folders are created at /home/{USER}/.xbp/dist/{version}/

logging

xbp writes logs to multiple locations

  • general logs: /var/log/xbp/ or ~/.xbp/logs/
  • service logs: .xbp/logs/{service-name}/stdout.log and stderr.log
  • pm2 logs: redirected to service log directories

logs are rotated when they exceed 10mb

architecture

  • /src/main.rs cli entrypoint command parsing and dispatch
  • /src/lib.rs core library module exports
  • /src/commands/ cli subcommand implementations
    • service.rs service management commands
    • redeploy_service.rs service redeployment logic
    • pm2.rs pm2 process management
    • config_cmd.rs configuration display
    • and more
  • /src/strategies/ deployment strategies and config management
    • deployment_config.rs config loading validation and service management
    • project_detector.rs project type detection
    • deployment_executor.rs deployment execution
  • /src/utils/ utility functions
    • version.rs version api integration
  • /src/logging.rs structured async logging
  • /src/config.rs ssh and yaml config management

backward compatibility

xbp maintains backward compatibility with legacy single service configurations if no services array is found in xbp.json the top level config is treated as a single service this allows existing projects to continue working without modification

examples

list all services

xbp services

build a service

xbp service build zeus

install dependencies for a service

xbp service install zeus

start a service with pm2

xbp service start zeus

run dev mode for a service

xbp service dev zeus

redeploy a service

xbp redeploy zeus

show help for a service

xbp service --help zeus

contributing

prs welcome please document new modules and keep interfaces generic and reusable see src/lib.rs for api docs all code must follow rust conventions documentation should be lowercase with minimal punctuation

license

mit