Documentation

Everything you need to install, configure, and use YardCtl.

Requirements

  • FreeBSD 14.0 or later
  • BastilleBSD installed and bootstrapped
  • Node.js 22+ (install via pkg install node22)
  • Root or doas/sudo access for Bastille commands

Installation

Quick Install

⚠️ Install script coming soon. Join the waitlist for early access.

Manual Install (from source)

# Clone the repo
git clone  /usr/local/yardctl  # Available to beta testers
cd /usr/local/yardctl

# Install dependencies
npm install

# Copy example env
cp .env.example .env

# Start
npx tsx src/index.ts

Configuration

Configure via environment variables in .env:

# Port to listen on (default: 8080)
PORT=8080

# Privilege elevation command (doas or sudo)
ELEVATION_CMD=doas

# Mock mode — set true for development without Bastille
MOCK_MODE=false

# Comma-separated list of jails to protect from destructive ops
PROTECTED_JAILS=samba,plex,transmission

First Run

On first run with no API keys configured, YardCtl starts in bootstrap mode. All endpoints are accessible without authentication so you can create your first API key:

# Create your first API key
curl -X POST http://localhost:8080/api/keys/init \
  -H "Content-Type: application/json" \
  -d '{"name": "admin"}'

# Response:
# { "key": "yardctl_abc123...", "name": "admin" }
# ⚠️  Save this key — it's only shown once!

After the first key is created, all endpoints require authentication.

Authentication

Pass your API key via either method:

# Bearer token
curl -H "Authorization: Bearer yardctl_abc123..." \
  http://localhost:8080/api/jails

# X-API-Key header
curl -H "X-API-Key: yardctl_abc123..." \
  http://localhost:8080/api/jails

Keys are SHA-256 hashed before storage. The plaintext key is only returned at creation time.

Jail Endpoints

GET /api/jails

List all jails with status, IP, and JID.

GET /api/jails/:name

Get details for a specific jail.

POST /api/jails

Create a new jail. Body: {"name", "release", "ip", "config?"}

POST /api/jails/:name/start

Start a stopped jail.

POST /api/jails/:name/stop

Stop a running jail.

POST /api/jails/:name/restart

Restart a jail.

DELETE /api/jails/:name

Destroy a jail. Blocked for protected jails.

Create Jail — Example

curl -X POST http://localhost:8080/api/jails \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "web01",
    "release": "15.0-RELEASE",
    "ip": "10.0.0.5/24",
    "config": {
      "boot": true,
      "vnet": true,
      "allowMlock": true
    }
  }'

Note: Jail names must be lowercase alphanumeric only (no hyphens or underscores). VNET networking uses the jail name for interface naming. Release names are automatically normalized (e.g., 15.0-RELEASE-p115.0-RELEASE).

Configuration Endpoints

GET /api/config/:name

Get all configuration for a jail.

GET /api/config/:name/:key

Get a specific config property.

POST /api/config/:name/:key

Set a config property. Body: {"value": "..."}

Mount Endpoints

GET /api/mounts/:name

List mounts for a jail.

POST /api/mounts/:name

Add a mount. Body: {"hostPath", "jailPath", "mode"}

DELETE /api/mounts/:name

Remove a mount. Body: {"jailPath"}

Network Endpoints

GET /api/network/interfaces

List network interfaces on the host.

GET /api/network/scan

Scan for available and used IPs on the jail subnet.

GET /api/network/status

Network status overview.

API Key Endpoints

POST /api/keys/init

Bootstrap first API key. Only works when no keys exist.

GET /api/keys

List API keys (metadata only, no secrets).

POST /api/keys

Create a new API key.

DELETE /api/keys/:id

Revoke an API key.

Protected Jails

Set PROTECTED_JAILS in your .env to prevent destructive operations (stop, destroy) on critical jails:

PROTECTED_JAILS=samba,plex,transmission,piwigo

Attempts to stop or destroy protected jails return a 403 Forbidden with a clear error message.

Running as a Service

YardCtl includes a FreeBSD rc.d script:

# Install the service script
cp scripts/jailapi.rc /usr/local/etc/rc.d/yardctl
chmod +x /usr/local/etc/rc.d/yardctl

# Enable and start
sysrc yardctl_enable="YES"
service yardctl start

# Check status
service yardctl status

# View logs
tail -f /var/log/yardctl.log