feat(blueprint): add orca server template

Run the headless Orca runtime (orca serve) on Dokploy. Orca publishes
no container image, so the compose builds one from the pinned upstream
release AppImage (amd64 or arm64) on Ubuntu 24.04, following the
official headless Linux server guide.

The runtime is served on one domain for both the WebSocket endpoint and
the web client. ORCA_PAIRING_ADDRESS sets the address advertised in
pairing links, and ORCA_SERVE_ARGS passes extra serve flags such as
--mobile-pairing for the Orca mobile app.
This commit is contained in:
Alexandre Blause
2026-09-19 20:32:39 +02:00
parent 830d6bbc8d
commit ea98830477
5 changed files with 150 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
version: "3.8"
services:
orca-server:
# Orca publishes no container image, so this builds one from the
# pinned upstream release AppImage, following the official headless
# Linux server guide (docs/reference/headless-linux-server.md).
build:
args:
ORCA_VERSION: v1.4.205
dockerfile_inline: |
FROM ubuntu:24.04
ARG ORCA_VERSION
ARG TARGETARCH
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
bash ca-certificates curl file git jq openssh-client procps \
xvfb zlib1g-dev libgtk-3-0t64 libpango-1.0-0 libcairo2 \
libnss3 libgbm1 libdrm2 libasound2t64 libcups2t64 libxkbcommon0 \
libatk1.0-0t64 libatk-bridge2.0-0t64 libatspi2.0-0t64 \
libx11-xcb1 libxcb-dri3-0 libxcomposite1 libxdamage1 libxfixes3 \
libxrandr2 libxrender1 libxss1 libxtst6 \
&& rm -rf /var/lib/apt/lists/*
RUN if [ "$$TARGETARCH" = arm64 ]; then asset=orca-linux-arm64.AppImage; else asset=orca-linux.AppImage; fi \
&& curl -fL --retry 3 -o /tmp/orca.AppImage \
"https://github.com/stablyai/orca/releases/download/$$ORCA_VERSION/$$asset" \
&& chmod +x /tmp/orca.AppImage \
&& cd /opt && /tmp/orca.AppImage --appimage-extract >/dev/null \
&& mv /opt/squashfs-root /opt/orca \
&& chmod -R a+rX /opt/orca \
&& rm /tmp/orca.AppImage
RUN useradd --create-home --shell /bin/bash orca
USER orca
WORKDIR /home/orca
ENV PATH=/home/orca/.local/bin:/opt/orca/resources/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LIBGL_ALWAYS_SOFTWARE=1
# Chromium cannot create its sandbox namespaces in an unprivileged
# container; the container is the isolation boundary instead.
ENTRYPOINT ["/opt/orca/AppRun", "--no-sandbox"]
restart: unless-stopped
init: true
shm_size: "1gb"
command: serve --port 6768 --pairing-address ${ORCA_PAIRING_ADDRESS} ${ORCA_SERVE_ARGS:-}
expose:
- 6768
volumes:
- orca-home:/home/orca
healthcheck:
test: ["CMD", "bash", "-c", ": > /dev/tcp/127.0.0.1/6768"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s
volumes:
orca-home: {}
+63
View File
@@ -0,0 +1,63 @@
# Orca Server
Runs `orca serve`, the headless Orca runtime, following the official
[headless Linux server guide](https://github.com/stablyai/orca/blob/main/docs/reference/headless-linux-server.md).
Orca publishes no container image, so the service is built from the pinned
upstream release AppImage (`v1.4.205`, amd64 or arm64) on the first deploy.
The first deployment therefore takes a few extra minutes.
The domain serves the runtime WebSocket and its web client. Every client,
browser included, connects with a pairing link printed in the logs.
## Pair a client
1. Open the `orca-server` service logs in Dokploy.
2. Copy the `Pairing URL: orca://pair?code=...` line printed after
`Orca server ready`. The `Web client URL` line next to it opens the same
runtime in a browser, already paired.
3. In the Orca desktop app, open **Settings > Remote Orca Servers** and paste
the link. From a CLI:
`orca environment add --name my-server --pairing-code 'orca://pair?code=...'`.
The pairing link is a credential: share it only with the client you are
pairing. Paired devices are stored in the persistent volume, so clients
reconnect after a redeploy or an upgrade without pairing again.
## Pair the Orca mobile app
The mobile app needs a mobile-scoped link, which the default link is not.
Set `ORCA_SERVE_ARGS=--mobile-pairing` in the environment and redeploy: the
logs then print a mobile pairing QR code and link instead of the desktop one.
Scan it from the app, then clear `ORCA_SERVE_ARGS` and redeploy. Devices
already paired stay paired either way. On a phone, the `Web client URL` also
works in the browser without this step.
## HTTPS
`ORCA_PAIRING_ADDRESS` is the address advertised to clients. It defaults to
`http://<your-domain>` (plain WebSocket through Traefik; the pairing channel
itself is end-to-end encrypted). Once HTTPS is enabled on the domain, set it to
`https://<your-domain>` in the environment and redeploy so clients dial
`wss://`.
## Coding agents
The image ships Orca, git and the Linux libraries it needs, but no coding
agent. Install the agents you use from an Orca terminal on this server; they
land in `/home/orca/.local/bin`, which is on `PATH` and persisted in the
`orca-home` volume together with their credentials, your repositories and
Orca's state (`/home/orca/.config`).
Example for Claude Code: `curl -fsSL https://claude.ai/install.sh | bash`.
## Upgrade
`orca serve` never updates itself. To upgrade, change the `ORCA_VERSION`
build argument in the compose file and redeploy. State lives in the
volume, not in the image, and newer releases migrate it on load.
## Logs and secrets
D-Bus and OS keyring errors at startup are expected in a container and
harmless. Without a keyring, Orca stores its secrets unencrypted in the
`orca-home` volume: treat that volume as sensitive.
+18
View File
@@ -0,0 +1,18 @@
{
"id": "orca-server",
"name": "Orca Server",
"version": "v1.4.205",
"description": "Headless Orca runtime: run a fleet of parallel coding agents in isolated git worktrees on your server and drive them from the Orca desktop, web or mobile app.",
"logo": "orca-server.png",
"links": {
"github": "https://github.com/stablyai/orca",
"website": "https://www.onorca.dev",
"docs": "https://github.com/stablyai/orca/blob/main/docs/reference/headless-linux-server.md"
},
"tags": [
"ai",
"developer-tools",
"agents",
"self-hosted"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

+14
View File
@@ -0,0 +1,14 @@
[variables]
main_domain = "${domain}"
[config]
env = [
"ORCA_PAIRING_ADDRESS=http://${main_domain}",
"ORCA_SERVE_ARGS=",
]
mounts = []
[[config.domains]]
serviceName = "orca-server"
port = 6768
host = "${main_domain}"