Skip to main content
For operators. This page describes server deployment modes. If you are an end user who wants to import a GitHub repository into an existing Oxy instance, use the Workspaces page in the UI — no server configuration is required on your end.

Overview

Oxy supports two deployment modes:
  1. Multi-workspace mode (Default) — Cloud-native deployment with centralized workspace management. Multiple isolated workspaces share a single server instance.
  2. Single-workspace mode (--local) — Traditional deployment for local development. The server serves the current directory as the only workspace.

Comparison

FeatureMulti-workspace (default)Single-workspace (--local)
Workspace SourceCloned from GitHub or created via UICurrent working directory
File EditingFull IDE editing capabilitiesFull IDE editing capabilities
Workspace CountUnlimited, managed via UIOne per server instance
ConfigurationEnvironment variables + databaseconfig.yml in workspace directory
AuthenticationConfigurable (required for teams)Configurable (optional)
Use CaseCloud deployments, SaaS, teamsDevelopment, self-hosted, single user

Multi-workspace Mode (Default)

Starting the server

# Start in multi-workspace mode (default — no flag needed)
oxy serve

# With a custom port
oxy serve --port 8080

# With enterprise features (ClickHouse telemetry, OTel Collector)
oxy serve --enterprise

# Bind to all interfaces (needed in containers)
oxy serve --host 0.0.0.0 --port 3000

How it works

  1. Workspace root: On startup, Oxy creates $OXY_STATE_DIR/workspaces/ and scans it for existing workspaces.
  2. GitHub import: Users create workspaces by importing a GitHub repository. The repo is cloned into the workspace root.
  3. Workspace activation: Users switch between workspaces via the Workspaces page (/workspaces). The active workspace determines which agents, workflows, and data are available.
  4. File editing: The IDE allows full read/write access to workspace files. Changes can be committed and pushed via the built-in Git panel.

Required environment variables

# State directory (workspace storage)
OXY_STATE_DIR=/data/oxy           # defaults to ~/.local/share/oxy

# Database connection
OXY_DATABASE_URL=postgresql://user:pass@localhost:5432/oxy

# GitHub App integration (for importing repositories)
GITHUB_APP_ID=123456
GITHUB_APP_SLUG=my-oxy-app
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."
GITHUB_CLIENT_ID=Iv23liqo62Pg...
GITHUB_CLIENT_SECRET=...
GITHUB_STATE_SECRET=any-random-string   # signs OAuth state tokens

# Authentication (at least one method required for teams)
MAGIC_LINK_SECRET=...             # for magic-link email auth
GOOGLE_CLIENT_ID=...              # for Google OAuth
OKTA_CLIENT_ID=...                # for Okta OAuth

# Instance owner — this user gets Owner role on login and can promote others to Admin
OXY_OWNER=admin@example.com
If OXY_OWNER is not set and authentication is enabled, every authenticated user is treated as an admin. This is fine for single-user installs but should be set explicitly for team deployments. The owner can then grant Admin access to other users through the UI.

GitHub App setup

The GitHub integration uses a GitHub App (not personal OAuth) to import repositories. See the GitHub App Setup guide for a complete step-by-step walkthrough, including how to create the app, generate keys, and configure callback URLs. Quick summary:
  1. Create a GitHub App with Contents (Read & Write), Metadata (Read), and Administration (Read & Write) permissions
  2. Generate a private key and note your App ID, App Slug, Client ID, and Client Secret
  3. Set the environment variables listed above
  4. Install the app on your organization or user account
The callback URL (https://your-domain.com/github/callback) is derived automatically from the browser request’s Origin header — no hardcoding needed.

Workspace management

Users manage workspaces at /workspaces:
  • Import from GitHub — clone a repository and create a new workspace
  • Create blank — start with an empty workspace
  • Demo workspace — pre-loaded with sample data for exploration
  • Activate — switch to a different workspace
  • Rename / Delete — manage existing workspaces
Cloned workspaces show a “Cloning…” badge while the repository is being fetched. The workspace can be activated once cloning completes.

API endpoints

# List all workspaces
GET    /api/workspaces

# Delete a workspace
DELETE /api/workspaces/{id}

# Activate a workspace
POST   /api/workspaces/{id}/activate

# Rename a workspace
PATCH  /api/workspaces/{id}/rename

# Workspace details and status
GET    /api/{workspace_id}/details
GET    /api/{workspace_id}/status

# Branch management
GET    /api/{workspace_id}/branches
POST   /api/{workspace_id}/switch-branch
POST   /api/{workspace_id}/switch-active-branch
DELETE /api/{workspace_id}/branches/{branch_name}

# Git operations
POST   /api/{workspace_id}/pull-changes
POST   /api/{workspace_id}/push-changes
POST   /api/{workspace_id}/create-repo

Single-workspace Mode (--local)

# Navigate to your workspace directory
cd /path/to/my-workspace

# Start in single-workspace mode
oxy serve --local

# With a custom port
oxy serve --local --port 8080
In --local mode the server serves the current working directory as the sole workspace. Git sync is disabled — workspace files are assumed to already exist on disk.

When to use --local

  • Local development with files already on disk
  • Self-hosted single-user deployments
  • CI/CD pipelines running against a checked-out repo
  • Environments where workspace management via the UI is not needed

Configuration

Local mode reads config.yml from the workspace directory:
# config.yml
databases:
  - name: analytics
    dialect: duckdb
    path: ./data/analytics.db

models:
  - name: gpt-4o
    vendor: openai

Kubernetes Deployment (Helm)

# oxy-values.yaml
app:
  image: ghcr.io/oxy-hq/oxy
  imageTag: "0.5.32"
  imagePullPolicy: IfNotPresent
  # Default: multi-workspace mode. Add --local for single-workspace.
  command: ["oxy", "serve", "--enterprise"]

serviceAccount:
  create: false
  name: oxy-app-sa

persistence:
  size: 10Gi

gitSync:
  enabled: false   # workspaces are cloned on demand via the UI

env:
  OXY_STATE_DIR: "/workspace/oxy_data"
  OXY_API_URL: https://app.your-domain.com/api
  MAGIC_LINK_FROM_EMAIL: "noreply@your-domain.com"
  MAGIC_LINK_AWS_REGION: "us-west-2"
  OXY_OWNER: "admin@your-domain.com"

externalSecrets:
  envSecretNames: ["oxy-env-secret"]   # inject OXY_DATABASE_URL, GITHUB_*, etc.

ingress:
  enabled: true
  ingressClassName: nginx
  annotations:
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "route"
    nginx.ingress.kubernetes.io/session-cookie-expires: "86400"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
  hosts:
    - host: app.your-domain.com
      paths: []
helm install oxy oci://ghcr.io/oxy-hq/helm-charts/oxy-app \
  --namespace oxy-app \
  --create-namespace \
  --version 0.4.2 \
  --values oxy-values.yaml

Docker

FROM ubuntu:22.04

RUN curl --proto '=https' --tlsv1.2 -LsSf https://internal.oxy.tech | bash

ENV OXY_STATE_DIR=/data/oxy
ENV OXY_DATABASE_URL=postgresql://user:pass@db:5432/oxy

EXPOSE 3000

# Multi-workspace mode (default)
CMD ["oxy", "serve", "--host", "0.0.0.0", "--port", "3000"]

AWS ECS

{
  "family": "oxy",
  "containerDefinitions": [
    {
      "name": "oxy",
      "image": "oxy:latest",
      "command": ["oxy", "serve", "--host", "0.0.0.0", "--port", "3000"],
      "environment": [
        { "name": "OXY_STATE_DIR", "value": "/data/oxy" }
      ],
      "secrets": [
        {
          "name": "OXY_DATABASE_URL",
          "valueFrom": "arn:aws:ssm:region:account:parameter/oxy/database-url"
        },
        {
          "name": "GITHUB_APP_PRIVATE_KEY",
          "valueFrom": "arn:aws:ssm:region:account:parameter/oxy/github-key"
        }
      ],
      "portMappings": [
        { "containerPort": 3000, "protocol": "tcp" }
      ]
    }
  ]
}

Authentication

Both modes support the same authentication methods:
MethodEnvironment variables required
Magic link (email)MAGIC_LINK_SECRET, SMTP config
Google OAuthGOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
Okta OAuthOKTA_CLIENT_ID, OKTA_CLIENT_SECRET, OKTA_DOMAIN
GitHub (workspace import only)GITHUB_* vars above
When no auth method is configured, the server runs without authentication (suitable for single-user local development).

Troubleshooting

Workspaces not appearing after restart Oxy scans $OXY_STATE_DIR/workspaces/ on startup and registers any subdirectories containing config.yml. If a workspace directory exists but is missing config.yml, it won’t be registered. GitHub callback redirects to wrong domain The OAuth callback URL is derived from the Origin header of the browser request — no hardcoding is needed. Ensure your reverse proxy forwards the Origin header to the Oxy backend. Database connection errors
# Verify the connection string
echo $OXY_DATABASE_URL
psql $OXY_DATABASE_URL -c "SELECT 1"
config.yml not found in --local mode
# Ensure you're in a workspace directory
ls config.yml

# Or initialize a new workspace
oxy init
Enterprise features not starting The --enterprise flag requires ClickHouse:
OXY_CLICKHOUSE_URL=http://localhost:8123
OXY_CLICKHOUSE_USER=default       # optional
OXY_CLICKHOUSE_PASSWORD=...       # optional
OXY_CLICKHOUSE_DATABASE=otel      # optional