Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pixlcore/xyops/llms.txt

Use this file to discover all available pages before exploring further.

Overview

This guide covers self-hosting xyOps on your own infrastructure. You’ll learn how to deploy xyOps with Docker, add worker servers, configure TLS certificates, and set up external storage backends.
For production deployments, we strongly recommend our Enterprise Plan. You’ll get white-glove onboarding, configuration validation, priority support, and live chat with xyOps engineers.

Prerequisites

Before you begin:

Critical requirement

The server or container running xyOps must be addressable on your network by its hostname. Worker servers connect to the conductor by hostname, so it must resolve to a reachable IP address.With Docker, set the container hostname to something that resolves on your network.

Docker deployment

Quick-start command

Deploy xyOps with a single Docker command:
Docker
docker run \
  --detach \
  --init \
  --name "xyops01" \
  --hostname "xyops01" \
  --restart unless-stopped \
  -v xy-data:/opt/xyops/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e XYOPS_xysat_local="true" \
  -e TZ="America/Los_Angeles" \
  -p 5522:5522 \
  -p 5523:5523 \
  ghcr.io/pixlcore/xyops:latest
Change the hostname from xyops01 to something that resolves on your network. Without this, many features will not work properly.

Docker Compose deployment

For production environments, use Docker Compose:
docker-compose.yml
services:
  xyops01:
    image: ghcr.io/pixlcore/xyops:latest
    container_name: xyops01
    hostname: xyops01  # Change this to your actual hostname

    init: true
    restart: unless-stopped

    environment:
      XYOPS_xysat_local: "true"
      TZ: America/Los_Angeles

    volumes:
      - xy-data:/opt/xyops/data
      - /local/path/to/xyops-conf:/opt/xyops/conf
      - /var/run/docker.sock:/var/run/docker.sock

    ports:
      - "5522:5522"
      - "5523:5523"

volumes:
  xy-data:
Change /local/path/to/xyops-conf to a suitable location on the host machine. xyOps will automatically populate this directory with default configuration files on first launch.

What’s included

After starting the container:
  • Web interface: Access at http://localhost:5522 (HTTP) or https://localhost:5523 (HTTPS)
  • Default credentials: Username admin, password admin
  • Data persistence: Docker volume xy-data stores the database (SQLite + filesystem by default)
  • Self-signed certificate: HTTPS uses a self-signed cert (see TLS configuration below)
Change the default admin password immediately after first login. Also rotate the secret key if you plan to use the container long-term.

Configuration directory

The main configuration file is located at /opt/xyops/conf/config.json. UI-modified settings are saved to /opt/xyops/conf/overrides.json. To persist configuration across container restarts, bind mount the entire conf directory:
-v /local/path/to/xyops-conf:/opt/xyops/conf
xyOps will copy default configuration files on first launch. Full configuration reference

Worker server setup

xyOps uses lightweight satellite workers (xySat) to execute jobs on your servers.

Adding workers via UI

The easiest way to add servers:
1

Open the Servers page

Click Servers in the sidebar, then Add Server.
2

Configure server options

  • Label: Optional friendly name
  • Icon: Optional emoji or icon
  • Groups: Assign to server groups or use automatic grouping
  • Enabled: Start enabled (default)
3

Copy the install command

Choose your target platform:
docker run --detach --init --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e XYOPS_setup="http://xyops01:5522/api/app/satellite/config?t=TOKEN" \
  --name "xyops-worker" \
  ghcr.io/pixlcore/xysat:latest
The token expires in 24 hours. For automated provisioning, see Automated bootstrap below.
4

Run the command on your server

Execute the command on the target host. The installer:
  • Authenticates with the conductor
  • Installs xySat as a system service (systemd/launchd/Windows Service)
  • Writes configuration
  • Starts the agent
The server appears immediately in the UI and begins streaming metrics.

Automated bootstrap

For autoscaling or ephemeral hosts:
1

Create an API key

  1. Go to SettingsAPI Keys
  2. Create a new key with only the add_servers privilege
  3. Copy the API key
2

Modify the install command

Replace the temporary token with your API key:
Linux/macOS
curl -s "https://xyops01.mycompany.com/api/app/satellite/install?t=YOUR_API_KEY" | sudo sh
For Docker workers:
docker-compose.yml
services:
  worker1:
    image: ghcr.io/pixlcore/xysat:latest
    init: true
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      XYOPS_setup: http://xyops01:5522/api/app/satellite/config?t=YOUR_API_KEY

  worker2:
    image: ghcr.io/pixlcore/xysat:latest
    init: true
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      XYOPS_setup: http://xyops01:5522/api/app/satellite/config?t=YOUR_API_KEY
All workers can use the same API key. Each request generates a unique server ID and permanent auth token.
3

Add to provisioning scripts

Include the command in your cloud-init, AMI, Packer template, or custom init scripts.
Wait for networking to be fully up before running the bootstrap command.

TLS configuration

xyOps supports TLS certificates via the built-in web server.

Let’s Encrypt / ACME

The xyOps web server (pixl-server-web) supports automatic Let’s Encrypt certificate provisioning. Let’s Encrypt setup guide

Custom certificates

To use your own certificates:
  1. Edit /opt/xyops/conf/config.json:
config.json
{
  "WebServer": {
    "https": true,
    "https_port": 5523,
    "https_cert_file": "/path/to/cert.pem",
    "https_key_file": "/path/to/key.pem"
  }
}
  1. Restart xyOps:
docker restart xyops01

Reverse proxy

Alternatively, use a reverse proxy (Nginx, Caddy, Traefik) to handle TLS termination. See Multi-conductor with Nginx below for a full example.

Storage backends

The default storage engine is a hybrid of SQLite (for data) and the filesystem (for files). For production or multi-conductor setups, use external storage.

MinIO (S3-compatible)

As of February 2026, MinIO’s open-source repository has been archived. The Chainguard Docker images still work, but we’re evaluating RustFS as a replacement.
1

Create a MinIO container

docker volume create minio-data
docker run --detach --name minio \
  -p 9000:9000 -p 9001:9001 \
  -v minio-data:/data \
  cgr.dev/chainguard/minio:latest server /data --console-address ":9001"
If running xyOps and MinIO in separate containers on the same host, create a Docker network and add both containers to it.
2

Configure MinIO

  1. Open http://MINIO_HOSTNAME:9001 in your browser
  2. Log in with default credentials: minioadmin / minioadmin
  3. Create a new bucket (e.g., xydata)
  4. Create access credentials
3

Configure xyOps

Export your data from the System tab (if migrating), then shut down xyOps.Edit /opt/xyops/conf/config.json:
config.json
{
  "Storage": {
    "engine": "S3"
  },
  "AWS": {
    "endpoint": "http://MINIO_HOSTNAME:9000",
    "endpointPrefix": false,
    "forcePathStyle": true,
    "hostPrefixEnabled": false,
    "region": "us-west-1",
    "credentials": {
      "accessKeyId": "YOUR_MINIO_USERNAME",
      "secretAccessKey": "YOUR_MINIO_PASSWORD"
    }
  },
  "S3": {
    "connectTimeout": 5000,
    "socketTimeout": 5000,
    "maxAttempts": 50,
    "keyPrefix": "",
    "fileExtensions": true,
    "params": {
      "Bucket": "YOUR_MINIO_BUCKET_ID"
    },
    "cache": {
      "enabled": true,
      "maxItems": 100000,
      "maxBytes": 104857600
    }
  }
}
4

Start xyOps

Restart xyOps. It will create default records on first launch. Re-import your data from the System tab to restore everything.

RustFS

RustFS is an open-source S3-compatible storage system (currently in alpha).
1

Create a RustFS container

docker volume create rustfs-data
docker run -d --name rustfs \
  -p 9000:9000 -p 9001:9001 \
  -v rustfs-data:/data \
  rustfs/rustfs:latest
2

Configure RustFS

  1. Open http://RUSTFS_HOSTNAME:9001
  2. Log in with rustfsadmin / rustfsadmin
  3. Create a bucket (e.g., xydata)
  4. Create an access key and save both the key and secret
3

Configure xyOps

Edit /opt/xyops/conf/config.json with the same structure as MinIO, replacing hostnames and credentials:
config.json
{
  "AWS": {
    "endpoint": "http://RUSTFS_HOSTNAME:9000",
    "credentials": {
      "accessKeyId": "YOUR_RUSTFS_ACCESS_KEY",
      "secretAccessKey": "YOUR_RUSTFS_SECRET_KEY"
    }
  },
  "S3": {
    "params": {
      "Bucket": "YOUR_RUSTFS_BUCKET_ID"
    }
  }
}

AWS S3

For AWS S3, configure the AWS and S3 objects in config.json:
config.json
{
  "Storage": {
    "engine": "S3"
  },
  "AWS": {
    "region": "us-east-1",
    "credentials": {
      "accessKeyId": "YOUR_AWS_ACCESS_KEY",
      "secretAccessKey": "YOUR_AWS_SECRET_KEY"
    }
  },
  "S3": {
    "params": {
      "Bucket": "your-bucket-name"
    }
  }
}
Storage engine documentation

Multi-conductor with Nginx

For high availability, deploy multiple conductor servers with Nginx as a load balancer.

Prerequisites

  • External storage: Multi-conductor requires S3, MinIO, or another shared storage backend
  • Custom domain: e.g., xyops.yourcompany.com for user-facing access
  • TLS certificates: Ready to mount into Nginx

Architecture

  • User-facing domain: xyops.yourcompany.com (routes to Nginx)
  • Conductor domains: xyops01.yourcompany.com, xyops02.yourcompany.com (internal)
  • Worker connections: Workers connect directly to conductors (not through Nginx) for better performance

Nginx deployment

1

Deploy Nginx with health check

Docker
docker run \
  --detach \
  --init \
  --name xyops-nginx \
  -e XYOPS_masters="xyops01.yourcompany.com,xyops02.yourcompany.com" \
  -e XYOPS_port="5522" \
  -v "$(pwd)/tls.crt:/etc/tls.crt:ro" \
  -v "$(pwd)/tls.key:/etc/tls.key:ro" \
  -p 443:443 \
  ghcr.io/pixlcore/xyops-nginx:latest
Docker Compose:
docker-compose.yml
services:
  nginx:
    image: ghcr.io/pixlcore/xyops-nginx:latest
    init: true
    environment:
      XYOPS_masters: xyops01.yourcompany.com,xyops02.yourcompany.com
      XYOPS_port: 5522
    volumes:
      - "./tls.crt:/etc/tls.crt:ro"
      - "./tls.key:/etc/tls.key:ro"
    ports:
      - "443:443"
The image includes the xyOps Health Check daemon, which monitors conductor status and dynamically reconfigures Nginx to route to the current primary.
2

Deploy conductor servers

Docker
docker run \
  --detach \
  --init \
  --name xyops1 \
  --hostname xyops01.yourcompany.com \
  --restart unless-stopped \
  -e XYOPS_masters="xyops01.yourcompany.com,xyops02.yourcompany.com" \
  -e TZ="America/Los_Angeles" \
  -v "/local/path/to/xyops-conf:/opt/xyops/conf" \
  -v "/var/run/docker.sock:/var/run/docker.sock" \
  -p 5522:5522 \
  -p 5523:5523 \
  ghcr.io/pixlcore/xyops:latest
Docker Compose:
docker-compose.yml
services:
  xyops1:
    image: ghcr.io/pixlcore/xyops:latest
    hostname: xyops01.yourcompany.com  # Change per conductor
    init: true
    environment:
      XYOPS_masters: xyops01.yourcompany.com,xyops02.yourcompany.com
      TZ: America/Los_Angeles
    volumes:
      - "/local/path/to/xyops-conf:/opt/xyops/conf"
      - "/var/run/docker.sock:/var/run/docker.sock"
    ports:
      - "5522:5522"
      - "5523:5523"
Duplicate for additional conductors, changing the hostname each time.
3

Configure shared storage

All conductors must share the same configuration and storage backend. See Storage backends above.

Secret key rotation

xyOps uses a single secret key to encrypt secrets, sign tokens, and authenticate workers.

Rotation process

  1. Go to SystemKey Rotation
  2. Click Start Rotation
  3. The system:
    • Pauses the scheduler
    • Flushes queued jobs and aborts active jobs
    • Generates a new key
    • Re-encrypts all stored secrets
    • Re-authenticates all worker servers
    • Distributes the new key to backup conductors
    • Writes the key to /opt/xyops/conf/overrides.json
  4. Resume the scheduler (click the Paused icon in the header)
Before rotation, ensure all conductors and workers are online. Offline nodes will not receive the new key automatically and will require manual recovery.

Offline recovery

If a worker or conductor was offline during rotation:
Compute a new auth token:
printf "%s" "SERVER_IDSECRET_KEY" | openssl dgst -sha256 -r | awk '{print $1}'
  • SERVER_ID: Alphanumeric ID from /opt/xyops/satellite/config.json
  • SECRET_KEY: Current key from the primary conductor at /opt/xyops/conf/overrides.json
Edit /opt/xyops/satellite/config.json on the worker and set auth_token to the computed SHA-256 hex. The satellite will auto-reload within ~30 seconds.
SSH to the offline conductor and edit /opt/xyops/conf/overrides.json. Set secret_key to the new key from the primary conductor. Restart the conductor service.
Full secret key rotation documentation

Environment variables

xyOps supports environment variable overrides for configuration. Use the format XYOPS_key where key is a JSON property path.

Common overrides

VariableExample ValueDescription
XYOPS_foregroundtrueRun in foreground (no daemon fork)
XYOPS_echotrueEcho event log to STDOUT
XYOPS_colortrueColor-coded log output
XYOPS_base_app_urlhttp://xyops.yourcompany.comOverride base app URL
XYOPS_WebServer__port80Override HTTP port
XYOPS_WebServer__https_port443Override HTTPS port
XYOPS_Storage__Filesystem__base_dir/data/xyopsOverride storage directory
For nested properties, use double underscores (__) as separators. Full environment variable reference

Daily backups

Generate daily backups using the API:
1

Create an API key

Create an API key with the bulk_export privilege.
2

Schedule a backup job

curl -X POST "https://xyops.yourcompany.com/api/app/admin_export_data" \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"lists":"all","indexes":["tickets"]}' \
  -O -J
This saves a .txt.gz file with the pattern:
xyops-data-export-YYYY-MM-DD-UNIQUEID.txt.gz
3

Full backup (optional)

For a complete backup including job history:
curl -X POST "https://xyops.yourcompany.com/api/app/admin_export_data" \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"lists":"all","indexes":"all","extras":"all"}' \
  -O -J
Full backups can be very large and take significant time depending on database size.
Backup API documentation

Next steps

Configuration reference

Deep dive into all configuration options, logging, maintenance schedules, and advanced settings.

Scaling guide

Best practices for running xyOps at scale: hardware sizing, caching, multi-conductor setup, and security checklists.

CLI tools

Command-line utilities for service control, database management, and admin operations.

Air-gapped mode

Configure xyOps for air-gapped environments with IP whitelisting and offline software upgrades.