Server Deployment
Before provisioning a self-managed environment, review the deployment checklist. If you have a VikingDB / OpenViking private deployment package, use Enterprise Deployment and operations.
OpenViking runs as an HTTP service. Choose who operates it before installing a server:
| Service | What you need |
|---|---|
| Volcano Engine managed OpenViking | Obtain an API key in the console, then connect with the independent CLI. No local server or model configuration is needed. |
| An existing team or remote deployment | Obtain the service URL and a user/admin key from its administrator. |
| Self-hosted OpenViking | Install and configure the server using the instructions below. |
Managed and existing-service users can start with the CLI quickstart. For managed-service availability, plans, and limits, see the official service documentation.
The rest of this guide covers self-hosting.
For sizing, measure memory and disk use with a representative corpus and expected concurrency. Budget storage for source files, indexes, and snapshots; use observability to check headroom before expanding the workload.
Quick Start
Install the server first using the self-hosted quickstart. For Volcengine Ark on Python 3.14, the upstream Python SDK may emit Pydantic V1 compatibility warnings; Python 3.13 avoids that warning in this setup.
# Create or refresh ~/.openviking/ov.conf with the setup wizard
openviking-server init
# If you select OpenAI Codex in the wizard, init can import/login Codex for you
# Validate local config, model access, and auth before starting
openviking-server doctor
# Start server (reads ~/.openviking/ov.conf by default)
openviking-server
# Or specify a custom config path
openviking-server --config /path/to/ov.conf
# In another terminal, configure ov for this server using the quickstart, then verify
ov healthCommand Line Options
| Option | Description | Default |
|---|---|---|
--config | Path to ov.conf file | ~/.openviking/ov.conf |
--host | Host to bind to | 127.0.0.1 |
--port | Port to bind to | 1933 |
Examples
# With default config
openviking-server
# With custom port
openviking-server --port 8000
# With custom config, host, and port
openviking-server --config /path/to/ov.conf --host 127.0.0.1 --port 8000Configuration
The server reads ov.conf and supports the corresponding environment-variable and startup-option overrides. See Configuration Guide for full details on config file format.
Merge this listener, authentication, and storage excerpt with your existing embedding/VLM configuration:
{
"server": {
"host": "0.0.0.0",
"port": 1933,
"root_api_key": "your-secret-root-key",
"cors_origins": ["*"]
},
"storage": {
"workspace": "./data",
"agfs": { "backend": "local" },
"vectordb": { "backend": "local" }
}
}Deployment Modes
Standalone (Embedded Storage)
Server manages local RAGFS and VectorDB. Configure the storage path in ov.conf:
{
"storage": {
"workspace": "./data",
"agfs": { "backend": "local" },
"vectordb": { "backend": "local" }
}
}openviking-serverDeploying with Systemd (Recommended)
For Linux systems, you can use Systemd to manage OpenViking as a service, enabling automatic restart and startup on boot. Install, configure, and verify OpenViking before creating the service.
Create Systemd Service File
Create /etc/systemd/system/openviking.service file:
[Unit]
Description=OpenViking HTTP Server
After=network.target
[Service]
Type=simple
# Replace with the user and group that run OpenViking
User=your-username
Group=your-group
# Replace with your working directory
WorkingDirectory=/var/lib/openviking
# Use the absolute executable path from your installation
ExecStart=/path/to/your/python/bin/openviking-server
Restart=always
RestartSec=5
# Path to config file
Environment="OPENVIKING_CONFIG_FILE=/etc/openviking/ov.conf"
[Install]
WantedBy=multi-user.targetBefore starting, replace every placeholder. Run command -v openviking-server as the service user to find the executable, create the working directory, and grant that user access to the config, workspace, and any local encryption key. The config shown here is /etc/openviking/ov.conf; a config generated under your own home directory is not automatically used by this unit. Omitting User from a system service runs it as root.
Manage the Service
After creating the service file, use the following commands to manage the OpenViking service:
# Reload systemd configuration
sudo systemctl daemon-reload
# Start the service
sudo systemctl start openviking.service
# Enable service on boot
sudo systemctl enable openviking.service
# Check service status
sudo systemctl status openviking.service
# View service logs
sudo journalctl -u openviking.service -fConnecting Clients
Python SDK
python -m pip install --upgrade openviking-sdkimport openviking_sdk as ov
client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()
results = client.find(query="how to use openviking")
client.close()CLI
The CLI reads connection settings from ovcli.conf. Create ~/.openviking/ovcli.conf:
{
"url": "http://localhost:1933",
"api_key": "your-key"
}Or set the config path via environment variable:
export OPENVIKING_CLI_CONFIG_FILE=/path/to/ovcli.confThen use the CLI:
ov ls viking://resources/curl
curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
-H "X-API-Key: your-key"Cloud Deployment
Docker
OpenViking provides pre-built Docker images published to GitHub Container Registry. The runtime working directory is /app/.openviking, so the default storage.workspace (./data) resolves to /app/.openviking/data. The default workspace, ov.conf, and ovcli.conf therefore share one persistent mount. If you configure an absolute workspace outside this directory, mount that path separately:
docker run -d \
--name openviking \
-p 1933:1933 \
-v ~/.openviking:/app/.openviking \
--restart unless-stopped \
ghcr.io/volcengine/openviking:latestWe recommend the
ghcr.ioimage. Ifghcr.iois hard to reach, useopenviking-cn-beijing.cr.volces.com/volcengine/openviking:latestinstead. The same applies to the commands below.
By default, the Docker image starts:
- OpenViking HTTP service on port
1933(bound to0.0.0.0), also serving the Web Studio UI at/studio vikingbotgateway
Since the server binds to 0.0.0.0 inside the container (required for Docker port-mapping to work), you must set root_api_key in your ov.conf:
{
"server": {
"root_api_key": "your-secret-root-key"
}
}When auth_mode is unset and no root_api_key is configured, the server auto-detects dev mode and refuses to start on a non-loopback address. The example above uses API key authentication; see Authentication for other modes. Override the bind address with OPENVIKING_SERVER_HOST if needed.
The image enables Bot by default. In API key mode, Bot also needs a valid User/Admin key in bot.ov_server.api_key; a root key is not a data credential. For a server-only deployment, use --without-bot below. To run Bot, complete the identity settings in VikingBot Configuration.
Upgrading from an older image: images that started in /app resolved ./data to /app/data, outside the default mount. Before removing the old container, stop it and back up its configured workspace (for example, docker cp openviking:/app/data ./openviking-data-backup). Restore that backup into the mounted host workspace, normally ~/.openviking/data, before starting the replacement. Do not overwrite an existing workspace without checking which data to retain. Absolute workspace paths are unchanged; other relative paths now resolve from /app/.openviking.
Upgrade the container:
docker stop openviking
docker pull ghcr.io/volcengine/openviking:latest
docker rm openviking
# Then re-run docker run ...If you want to disable vikingbot for a specific container run, you can use either of the following:
docker run -d \
--name openviking \
-p 1933:1933 \
-v ~/.openviking:/app/.openviking \
--restart unless-stopped \
ghcr.io/volcengine/openviking:latest \
--without-botdocker run -d \
--name openviking \
-e OPENVIKING_WITH_BOT=0 \
-p 1933:1933 \
-v ~/.openviking:/app/.openviking \
--restart unless-stopped \
ghcr.io/volcengine/openviking:latestWhen docker -v is not available
Some managed platforms (Railway, Fly.io, Heroku-style PaaS) don't let you bind-mount a host path. If ov.conf doesn't exist when the container starts, the entrypoint will not crash — it prints a fix-it message and waits for the file to appear. You have two ways to provide it:
Option A: pass the full config through OPENVIKING_CONF_CONTENT. The entrypoint writes the env value to OPENVIKING_CONFIG_FILE (defaults to /app/.openviking/ov.conf) before starting the server:
docker run -d \
--name openviking \
-p 1933:1933 \
-e OPENVIKING_CONF_CONTENT="$(cat ~/.openviking/ov.conf)" \
--restart unless-stopped \
ghcr.io/volcengine/openviking:latestOption B: configure interactively after the container is up. While the container is sleeping (waiting for ov.conf), docker exec in and run the setup wizard — it honors OPENVIKING_CONFIG_FILE and writes to the path the server is watching:
docker exec -it openviking openviking-server initAs soon as ov.conf appears, the entrypoint resumes and starts the server automatically.
You can also use Docker Compose, which provides a docker-compose.yml in the project root:
docker compose up -dAfter startup, you can access:
- API service:
http://localhost:1933 - Web Studio:
http://localhost:1933/studio(same origin as the API) - Caddy entry point:
http://localhost:1934. It proxies every path to 1933 and is kept for existing deployments. With OpenViking Gateway enabled, the gateway is served under/gatewayon the same port, for examplehttp://localhost:1933/gateway/v1; see OpenViking Gateway deployment and operations.
Deploy on Railway
Click the badge below to deploy OpenViking on Railway:
Provisioned Resources & Defaults
- Container Image: Uses official image
ghcr.io/volcengine/openviking:latest, listening on port 1933 with an automatically assigned HTTPS domain. - Persistent Storage: Mounts a persistent volume at
/app/.openviking. The configuredstorage.workspace(/app/.openviking/data) is stored on this volume, ensuring accounts, resources, and vector data persist across redeployments. - Default Configuration: Preconfigured with OpenAI defaults.
OPENAI_API_KEYis the only required input during deployment. The admin keyOPENVIKING_ROOT_API_KEYis generated automatically and viewable in the Variables tab.
Quick Start (Web Studio)
Initial bootstrap can be completed entirely within the browser:
- Set Admin Key: Copy
OPENVIKING_ROOT_API_KEYfrom Railway Variables, openhttps://<your-domain>/studio/settings, and save it. - Create User: Navigate to
https://<your-domain>/studio/usersto create your initial account and user. The user API key will be displayed immediately. - Start Using: Use this user API key for subsequent access via Web Studio, the
ovCLI, and SDKs.
Configuration Management
- Initial Configuration: The template pre-populates
OPENVIKING_CONF_CONTENTwith a complete configuration referencing${OPENAI_API_KEY}. This variable is used only on the first startup, whenov.confdoes not yet exist. - Later Changes: After the first startup, edit the volume-backed
ov.confdirectly using the commands supported by your installed Railway CLI. To regenerate it, first back up the old configuration and verifyOPENVIKING_CONF_CONTENT, then move the old file aside and redeploy. Check storage and authentication settings afterward.
Pricing & Resource Sizing
- Estimate costs: Check Railway pricing for the current plan and resource billing rules. Test with your document volume and request rate, then estimate costs from the usage dashboard.
- Trial and retention: Check Railway trial rules and your account for credits, expiration, and volume retention. Back up data before the applicable retention deadline.
Security Note: The service is publicly accessible by default. Keep
OPENVIKING_ROOT_API_KEYconfidential and consult the public access guide before production rollout.
Multi-instance notes
With an embedded vector backend (local or cuvs), OpenViking holds an exclusive OS file lock on storage.workspace by default. The .openviking.lock file remains on disk; its presence does not mean a server is running. The OS releases the lock when the server closes it or the process terminates. Do not manually delete a running server's lock file.
Remote vector backends (http, volcengine, vikingdb) do not acquire this workspace lock, including when files are stored on a shared NAS. They do not require storage.skip_process_lock=true. Placing an embedded vector database on NAS does not make it safe to share between processes.
For embedded vector backends, when upgrading from a version that uses .openviking.pid, stop all older servers using the workspace before starting the new version. The new version does not use leftover PIDs to determine ownership; the two locking protocols cannot be mixed.
For multi-instance deployments, prefer these settings:
- Set
server.temp_upload.default_modeto"shared"so uploaded temporary files can be consumed by a different replica. - Use a remote vector backend for shared storage. The existing
storage.skip_process_lockoption only disables the embedded-backend startup guard; it does not add multi-process support to embedded vector storage. - For QueueFS, prefer an explicit per-instance local SQLite path via
storage.agfs.queuefs.db_path. If usage audit is enabled, prefer an explicit per-instance local SQLite path viaserver.observability.usage_audit.sqlite_pathinstead of mixing these files into a shared workspace volume.
Example:
{
"server": {
"temp_upload": {
"default_mode": "shared"
}
},
"storage": {
"vectordb": {
"backend": "http",
"url": "http://vector-db:5000"
}
}
}This example uses a remote HTTP vector service. Replace its URL with your deployment's vector-service address, or configure a volcengine or vikingdb backend.
Example with explicit local SQLite paths for QueueFS and usage audit:
{
"server": {
"temp_upload": {
"default_mode": "shared"
},
"observability": {
"usage_audit": {
"sqlite_path": "/var/lib/openviking-local/usage_audit.sqlite3"
}
}
},
"storage": {
"vectordb": {
"backend": "http",
"url": "http://vector-db:5000"
},
"agfs": {
"queuefs": {
"db_path": "/var/lib/openviking-local/queue.db"
}
}
}
}This variant is useful when multiple instances share the same workspace, but QueueFS and usage audit SQLite files still need per-instance local paths.
For public HTTPS access, see the Public Access Guide.
To build the image yourself, pass an explicit OpenViking version. Replace <VERSION> with a release number: docker build --build-arg OPENVIKING_VERSION=<VERSION> -t openviking:latest .
Kubernetes + Helm
This chart deploys the open-source service and is separate from the private delivery ovadmin / Operator workflow. See the Helm README for chart parameters.
The project provides a Helm chart located at deploy/helm/openviking/:
helm install openviking ./deploy/helm/openviking \
--set-string config.server.root_api_key="YOUR_ROOT_API_KEY" \
--set-string config.embedding.dense.api_key="YOUR_API_KEY" \
--set-string config.vlm.api_key="YOUR_API_KEY"For a detailed cloud deployment guide (including Volcengine TOS + VikingDB + Ark configuration), see the Cloud Deployment Guide.
Health Checks
| Endpoint | Auth | Purpose |
|---|---|---|
GET /health | No | Process liveness; normally returns status: ok and healthy: true, without verifying model credentials |
GET /ready | No | Readiness probe — checks AGFS, VectorDB, APIKeyManager, Embedding, Ollama |
# Liveness
curl http://localhost:1933/health
# Readiness
curl http://localhost:1933/ready
# {"status":"ready","checks":{"agfs":{"status":"ok","checks":{"filesystem":"ok","multiwrite_sync":"not_supported"}},"vectordb":"ok","api_key_manager":"ok","embedding":"ok","ollama":"not_configured"}}Use /health for Kubernetes liveness probes and /ready for readiness probes. See the System API for the individual checks.
Related Documentation
- Public Access & Reverse Proxy - HTTPS, Caddy, nginx
- Authentication - API key setup
- OAuth Guide - OAuth 2.1 for MCP clients
- Observability & Diagnostics - Health checks, tracing, and debugging
- API Overview - Complete API reference