This guide explains how to deploy Oxy using Docker containers, providing an alternative to the traditional server-based deployment approach.

Using Docker simplifies the deployment process and environment setup, making it easier to run Oxy in a consistent environment across different platforms.

Prerequisites

Before you start, ensure you have:

  • Docker installed on your host system
  • An Oxy workspace with your configuration files, agents, and workflows
  • Required API keys and environment variables for your deployment

We recommend your Docker host machine have a minimum of 4GB RAM for optimal performance of Oxy and related services.

Quick Start

The fastest way to get started with Oxy on Docker is to use the pre-built image from GitHub Packages:

# Pull the latest Oxy Docker image
docker pull ghcr.io/oxy-hq/oxy:0.2.3

# Run Oxy with a mounted workspace
docker run -d \
  --name oxy-instance \
  -p 3000:3000 \
  -v /path/to/your/workspace:/app \
  -e OPENAI_API_KEY=your-api-key \
  -e OXY_STATE_DIR=/app \
  ghcr.io/oxy-hq/oxy:0.2.3

Why Use Docker Compose?

Docker Compose lets you define and manage multi-container applications with a single YAML file. For Oxy, Compose makes it easy to:

  • Start Oxy and related services (like databases or proxies) with one command
  • Configure environment variables, volumes, and ports in one place
  • Ensure all containers are networked and started in the right order
  • Reproduce your deployment setup easily across machines or teams

In short: Docker Compose simplifies running Oxy in production or development, especially when you need more than one container.

Reference Architecture Diagram

Detailed Deployment Steps

1

Prepare Your Workspace

Before deploying, ensure you have an Oxy workspace ready with your configuration files. Your workspace directory should typically include:

  • config.yml - Main configuration file
  • Your agent definitions (.agent.yml files)
  • Your workflow definitions (.workflow.yml files)
  • Any other resources your agents and workflows need
# Example workspace structure
workspace/
├── config.yml
├── my-agent.agent.yml
├── my-workflow.workflow.yml
└── resources/
    └── data.json
2

Create a Docker Compose File

For easier management, create a docker-compose.yml file:

version: '3'
services:
  oxy:
    image: ghcr.io/oxy-hq/oxy:0.2.3
    container_name: oxy-instance
    ports:
      - "3000:3000"
    working_dir: /workspace
    volumes:
      - ./workspace:/workspace
      - ./oxy-data:/data
    environment:
      - OPENAI_API_KEY=your-openai-api-key
      - OXY_STATE_DIR=/data
    restart: unless-stopped
    command: ["oxy", "serve", "--host", "0.0.0.0", "--port", "3000"]

Replace your-openai-api-key with your actual OpenAI API key. For production deployments, consider using Docker secrets or environment files to avoid storing sensitive data in your compose file.

3

Start the Container

Launch your Oxy container:

docker-compose up -d

By default, the container’s working directory is /app. If you want to use /workspace as your working directory (as in the example above), make sure to set working_dir: /workspace in your Docker Compose file and mount your workspace to /workspace.

4

Configure Reverse Proxy (Optional)

For production deployments, you’ll want to add a reverse proxy to handle SSL termination and provide additional security.

Add Caddy to your docker-compose.yml:

version: '3'
services:
  oxy:
    # ...existing Oxy configuration...
  
  caddy:
    image: caddy:2.10.0
    container_name: caddy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    restart: unless-stopped
    depends_on:
      - oxy

volumes:
  caddy_data:
  caddy_config:

Create a Caddyfile in the same directory:

(reverse_proxy_app) {
    reverse_proxy 127.0.0.1:3000 {
        flush_interval -1
        transport http {
            versions 1.1 2 h2c
        }
    }
}

(reverse_proxy_oauth2) {
    reverse_proxy 127.0.0.1:4180 {
        header_up x-real-ip {remote_host}
        header_up x-forwarded-uri {uri}
    }
}

your-domain.com {
    @static_assets {
        path *.js *.css *.svg *.json *.gif *.wasm
    }

    handle /auth        import reverse_proxy_oauth2
    }

    # Defer Authorization header for static assets
    handle @static_assets {
        import reverse_proxy_app
    }

    handle {
        @except not path 
        forward_auth @except 127.0.0.1:4180 {
            uri /auth
            header_up x-real-ip {remote_host}
            copy_headers x-auth-request-user x-auth-request-email x-auth-request-access-token authorization

            @error status 401
            handle_response @error {
                redir * 
            }
        }

        import reverse_proxy_app
    }
}

Note: Replace your-domain.com with your actual domain name or use localhost for local testing. Adjust the port if your Oxy instance listens on a different port.

5

Set Up Authentication

For securing your Oxy instance, you can add authentication at the reverse proxy level:

Update your Caddyfile to include basic authentication:

your-domain.com {
  basicauth {
    <username> <hashed_password>
  }
  reverse_proxy oxy:3000
}

Generate a password hash:

docker run --rm caddy:2 caddy hash-password
# Enter your password when prompted

Example Caddyfile for Oxy Serve

(reverse_proxy_app) {
    reverse_proxy 127.0.0.1:3000 {
        flush_interval -1
        transport http {
            versions 1.1 2 h2c
        }
    }
}

(reverse_proxy_oauth2) {
    reverse_proxy 127.0.0.1:4180 {
        header_up x-real-ip {remote_host}
        header_up x-forwarded-uri {uri}
    }
}

your-domain.com {
    @static_assets {
        path *.js *.css *.svg *.json *.gif *.wasm
    }

    handle /auth        import reverse_proxy_oauth2
    }

    # Defer Authorization header for static assets
    handle @static_assets {
        import reverse_proxy_app
    }

    handle {
        @except not path 
        forward_auth @except 127.0.0.1:4180 {
            uri /auth
            header_up x-real-ip {remote_host}
            copy_headers x-auth-request-user x-auth-request-email x-auth-request-access-token authorization

            @error status 401
            handle_response @error {
                redir * 
            }
        }

        import reverse_proxy_app
    }
}

Note: Replace your-domain.com with your actual domain name or use localhost for local testing. Adjust the port if your Oxy instance listens on a different port.

Volume Mounting Explained

When running Oxy in Docker, you’ll typically need to mount two types of directories:

  1. Workspace Mount: Maps your local Oxy workspace to the container

    -v /path/to/your/workspace:/workspace

    This allows Oxy to access your configuration, agents, and workflows.

  2. Data Mount: Provides persistent storage for Oxy’s state

    -v /path/to/persistent/data:/data

    This ensures your data is preserved even if the container is restarted.

Data Persistence

Oxy uses SQLite for data storage by default, which means proper volume mounting is essential for maintaining your data across container restarts or updates.

Storage Location

  • By default, Oxy stores its data in ~/.local/share/oxy/ on the host system
  • When using Docker, you should explicitly set the OXY_STATE_DIR environment variable (typically to /data) and mount a volume to that location

What Data Is Stored

Oxy stores several types of data that need to be persisted:

  • SQLite database files containing state information
  • Semantic information from synchronized databases
  • Cached query results and intermediate data
  • Workflow execution history and checkpoints

Example Docker Setup with Proper Data Persistence

version: '3'
services:
  oxy:
    image: ghcr.io/oxy-hq/oxy:0.2.3
    container_name: oxy-instance
    ports:
      - "3000:3000"
    working_dir: /workspace
    volumes:
      - ./workspace:/workspace
      - ./oxy-data:/data  # Essential for data persistence
    environment:
      - OPENAI_API_KEY=your-openai-api-key
      - OXY_STATE_DIR=/data  # Points to the mounted volume
    restart: unless-stopped
    command: ["oxy", "serve", "--host", "0.0.0.0", "--port", "3000"]

For production deployments, ensure your data volume is backed by reliable storage. In cloud environments, consider using:

  • Amazon EBS volumes (AWS)
  • Persistent Disks (Google Cloud)
  • Azure Disk Storage
  • Network-attached storage (NAS) for multi-node setups

When using Docker Compose, your data will persist as long as you don’t remove the volumes. Use docker-compose down -v with caution as it will delete the volumes.

Environment Variables

Common environment variables to configure in your Oxy container:

VariableDescriptionExample
OPENAI_API_KEYYour OpenAI API keysk-...
OXY_STATE_DIRDirectory for Oxy state persistence/data
DATABASE_URLConnection URL if using a databasepostgres://...
PORTOverride the default port8080

Advanced Configuration

Custom Docker Images

If you need to extend the official Oxy image with additional dependencies or configuration, you can create your own Dockerfile:

FROM ghcr.io/oxy-hq/oxy:0.2.3

# Add custom dependencies
RUN apt-get update && apt-get install -y your-package

# Add custom files
COPY ./custom-config.yml /default-config.yml

# Override the default command if needed
CMD ["oxy", "serve", "--config", "/default-config.yml"]

Health Checks

Add health checks to ensure your container is running properly:

services:
  oxy:
    # ...existing configuration...
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Troubleshooting

For further help or to ask questions, join our community on Discord.

Next Steps

Once your Docker deployment is up and running, you can:

  • Set up CI/CD pipelines to automatically update your Oxy instance
  • Implement monitoring and logging solutions
  • Configure backups for your persistent data
  • Scale horizontally for higher availability

For more information on using Oxy, refer to the main documentation.