Replace env-var-only LIBRARY_REMOTE configuration with disk-persisted settings. The setting can now be edited in the dashboard Settings page, with LIBRARY_REMOTE env var serving as initial default when no settings file exists. Changes: - Add src/settings.rs for settings storage with JSON persistence - Add src/api/settings.rs for settings API endpoints - Update dashboard Settings page with editable library remote field - Update library-unavailable component to link to Settings page - Update documentation to recommend Settings page method
843 lines
24 KiB
Markdown
843 lines
24 KiB
Markdown
# Installing Open Agent (Ubuntu 24.04, dedicated server)
|
||
|
||
This is the installation approach currently used on a **dedicated Ubuntu 24.04 server** (OpenCode + Open Agent running on the same machine, managed by `systemd`).
|
||
|
||
Open Agent is the orchestrator/UI backend. **It does not run model inference**; it delegates execution to an **OpenCode server** running locally (default `http://127.0.0.1:4096`).
|
||
|
||
> **For AI Agents**: Before starting this installation, ask the user to provide:
|
||
> 1. **Server IP address** (e.g., `95.216.112.253`)
|
||
> 2. **Domain name** pointing to that IP (e.g., `agent.example.com`)
|
||
> 3. **SSH access** credentials or key path for the server
|
||
> 4. **Library git repo URL** (or confirm using the template)
|
||
> 5. **Dashboard password** to set for authentication (or offer to generate one)
|
||
>
|
||
> **SSH Key Setup**: Most servers require SSH key authentication. If the user doesn't have one:
|
||
> 1. Generate a key (without passphrase for easier automation):
|
||
> ```bash
|
||
> ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
|
||
> ```
|
||
> 2. Display the public key for them to copy:
|
||
> ```bash
|
||
> cat ~/.ssh/id_ed25519.pub
|
||
> ```
|
||
> 3. They need to add this key to their server. Options:
|
||
> - **Hosting provider dashboard**: Most providers (Hetzner, DigitalOcean, Vultr, etc.) have an "SSH Keys" section in their web console
|
||
> - **Existing access**: If they can already log in: `ssh-copy-id root@<server-ip>`
|
||
>
|
||
> Verify you have SSH access before proceeding: `ssh root@<server-ip> "hostname"`
|
||
>
|
||
> If connection fails, common causes:
|
||
> - The SSH key wasn't added to the server (check hosting provider's dashboard)
|
||
> - The key has a passphrase (agent tools may not handle passphrase prompts)
|
||
> - Firewall blocking port 22 (check hosting provider's firewall settings)
|
||
|
||
---
|
||
|
||
## 0) Assumptions
|
||
|
||
- Ubuntu 24.04 LTS, root SSH access
|
||
- A dedicated server (not shared hosting)
|
||
- You want:
|
||
- OpenCode server bound to localhost: `127.0.0.1:4096`
|
||
- Open Agent bound to: `0.0.0.0:3000`
|
||
- You have a Git repo for your **Library** (skills/tools/agents/rules/MCP configs)
|
||
|
||
> **Recommendation**: Unless you know exactly what you need, install **all components** in this guide:
|
||
> - **Bun** (required for OpenCode plugins and Playwright MCP)
|
||
> - **systemd-container + debootstrap** (for isolated container workspaces)
|
||
> - **Desktop automation tools** (Xvfb, i3, Chromium, xdotool, etc.)
|
||
> - **Reverse proxy with SSL** (Caddy or Nginx + Certbot)
|
||
>
|
||
> Skipping components may limit functionality. The full installation uses ~2-3 GB of disk space.
|
||
|
||
---
|
||
|
||
## 0.5) DNS & Domain Setup (before you begin)
|
||
|
||
Before starting the installation, ensure your domain is configured:
|
||
|
||
### 0.5.1 Point your domain to the server
|
||
|
||
Add an A record in your DNS provider:
|
||
|
||
```
|
||
agent.yourdomain.com → A → YOUR_SERVER_IP
|
||
```
|
||
|
||
Example with common providers:
|
||
- **Cloudflare**: DNS → Add Record → Type: A, Name: `agent`, IPv4: `YOUR_SERVER_IP`
|
||
- **Namecheap**: Advanced DNS → Add New Record → A Record
|
||
- **Route53**: Create Record → Simple routing → A record
|
||
|
||
### 0.5.2 Verify DNS propagation
|
||
|
||
Wait for DNS to propagate (usually 1-15 minutes), then verify:
|
||
|
||
```bash
|
||
# From your local machine
|
||
dig +short agent.yourdomain.com
|
||
# Should return your server IP
|
||
|
||
# Or use an online checker
|
||
curl -s "https://dns.google/resolve?name=agent.yourdomain.com&type=A" | jq .
|
||
```
|
||
|
||
### 0.5.3 SSH key for Library repo (if private)
|
||
|
||
If your Library repo is private, set up an SSH deploy key on the server:
|
||
|
||
```bash
|
||
# On the server
|
||
ssh-keygen -t ed25519 -C "openagent-server" -f /root/.ssh/openagent -N ""
|
||
cat /root/.ssh/openagent.pub
|
||
# Copy this public key
|
||
```
|
||
|
||
Add the public key as a **deploy key** in your git provider:
|
||
- **GitHub**: Repository → Settings → Deploy keys → Add deploy key
|
||
- **GitLab**: Repository → Settings → Repository → Deploy keys
|
||
|
||
Configure SSH to use the key:
|
||
|
||
```bash
|
||
cat >> /root/.ssh/config <<'EOF'
|
||
Host github.com
|
||
IdentityFile /root/.ssh/openagent
|
||
IdentitiesOnly yes
|
||
EOF
|
||
|
||
# Test the connection
|
||
ssh -T git@github.com
|
||
```
|
||
|
||
---
|
||
|
||
## 1) Install base OS dependencies
|
||
|
||
```bash
|
||
apt update
|
||
apt install -y \
|
||
ca-certificates curl git jq unzip tar \
|
||
build-essential pkg-config libssl-dev
|
||
```
|
||
|
||
**Container workspaces** (systemd-nspawn) — recommended for isolated environments:
|
||
|
||
```bash
|
||
apt install -y systemd-container debootstrap
|
||
```
|
||
|
||
**Desktop automation** (Xvfb/i3/Chromium screenshots/OCR) — recommended for browser control:
|
||
|
||
```bash
|
||
apt install -y xvfb i3 x11-utils xdotool scrot imagemagick chromium chromium-sandbox tesseract-ocr
|
||
```
|
||
|
||
See `docs/DESKTOP_SETUP.md` for i3 config and additional setup after installation.
|
||
|
||
---
|
||
|
||
## 2) Install Bun (for bunx + Playwright MCP)
|
||
|
||
OpenCode is distributed as a binary, but:
|
||
- OpenCode plugins are installed internally via Bun
|
||
- Open Agent’s default Playwright MCP runner prefers `bunx`
|
||
|
||
Install Bun:
|
||
|
||
```bash
|
||
curl -fsSL https://bun.sh/install | bash
|
||
|
||
# Make bun/bunx available to systemd services
|
||
install -m 0755 /root/.bun/bin/bun /usr/local/bin/bun
|
||
install -m 0755 /root/.bun/bin/bunx /usr/local/bin/bunx
|
||
|
||
bun --version
|
||
bunx --version
|
||
```
|
||
|
||
---
|
||
|
||
## 3) Install OpenCode (server backend)
|
||
|
||
### 3.1 Install/Update the OpenCode binary
|
||
|
||
This installs the latest release into `~/.opencode/bin/opencode`:
|
||
|
||
```bash
|
||
curl -fsSL https://opencode.ai/install | bash -s -- --no-modify-path
|
||
```
|
||
|
||
Optional: pin a version (recommended for servers):
|
||
|
||
```bash
|
||
curl -fsSL https://opencode.ai/install | bash -s -- --version 1.1.8 --no-modify-path
|
||
```
|
||
|
||
Copy the binary into a stable system location used by `systemd`:
|
||
|
||
```bash
|
||
install -m 0755 /root/.opencode/bin/opencode /usr/local/bin/opencode
|
||
opencode --version
|
||
```
|
||
|
||
### 3.2 Create `systemd` unit for OpenCode
|
||
|
||
Create `/etc/systemd/system/opencode.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=OpenCode Server
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=/usr/local/bin/opencode serve --port 4096 --hostname 127.0.0.1
|
||
WorkingDirectory=/root
|
||
Restart=always
|
||
RestartSec=10
|
||
Environment=HOME=/root
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
Enable + start:
|
||
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl enable --now opencode.service
|
||
```
|
||
|
||
Test:
|
||
|
||
```bash
|
||
curl -fsSL http://127.0.0.1:4096/global/health | jq .
|
||
```
|
||
|
||
Note: Open Agent will also keep OpenCode's global config updated (MCP + tool allowlist) in:
|
||
`~/.config/opencode/opencode.json`.
|
||
|
||
### 3.2.1 Strong workspace skill isolation (recommended)
|
||
|
||
OpenCode discovers skills from global locations (e.g. `~/.opencode/skill`, `~/.config/opencode/skill`)
|
||
*and* from the project/mission directory `.opencode/skill`. To guarantee **per‑workspace** skill usage,
|
||
run OpenCode with an isolated HOME and keep global skill dirs empty.
|
||
|
||
1) Create an isolated OpenCode home:
|
||
|
||
```bash
|
||
mkdir -p /var/lib/opencode
|
||
```
|
||
|
||
2) Update `opencode.service` to use the isolated home:
|
||
|
||
```ini
|
||
Environment=HOME=/var/lib/opencode
|
||
Environment=XDG_CONFIG_HOME=/var/lib/opencode/.config
|
||
Environment=XDG_DATA_HOME=/var/lib/opencode/.local/share
|
||
Environment=XDG_CACHE_HOME=/var/lib/opencode/.cache
|
||
```
|
||
|
||
3) Point Open Agent at the same OpenCode config dir (see section 6):
|
||
|
||
```
|
||
OPENCODE_CONFIG_DIR=/var/lib/opencode/.config/opencode
|
||
```
|
||
|
||
4) Move any old global skills out of the way (optional but recommended):
|
||
|
||
```bash
|
||
mv /root/.opencode/skill /root/.opencode/skill.bak-$(date +%F) 2>/dev/null || true
|
||
mv /root/.config/opencode/skill /root/.config/opencode/skill.bak-$(date +%F) 2>/dev/null || true
|
||
```
|
||
|
||
5) Reload services:
|
||
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl restart opencode.service
|
||
systemctl restart open_agent.service
|
||
```
|
||
|
||
Validation (on the server, from the repo root):
|
||
|
||
```bash
|
||
scripts/validate_skill_isolation.sh
|
||
```
|
||
|
||
### 3.3 Install oh-my-opencode (agent pack)
|
||
|
||
Install the default agent pack as root:
|
||
|
||
```bash
|
||
bunx oh-my-opencode install --no-tui
|
||
```
|
||
|
||
This installs the **Sisyphus** default agent (plus other personalities). To preserve plugin defaults:
|
||
Leave the Open Agent agent/model overrides unset to use the OpenCode / oh-my-opencode defaults.
|
||
|
||
Update strategy:
|
||
- Pin a version in your Library `plugins.json` (e.g., `oh-my-opencode@1.2.3`) to lock updates.
|
||
- Otherwise, the plugin can auto-update via OpenCode's install hook and Open Agent sync.
|
||
|
||
### 3.4 Install opencode-gemini-auth (optional, for Google OAuth)
|
||
|
||
If you want to authenticate with Google accounts (Gemini plans/quotas including free tier) via OAuth instead of API keys:
|
||
|
||
```bash
|
||
bunx opencode-gemini-auth install
|
||
```
|
||
|
||
This enables OAuth-based Google authentication, allowing users to leverage their existing Gemini plan directly within OpenCode. Features include:
|
||
- OAuth flow with Google accounts
|
||
- Automatic Cloud project provisioning
|
||
- Support for thinking capabilities (Gemini 2.5/3)
|
||
|
||
To authenticate via CLI (useful for testing):
|
||
|
||
```bash
|
||
opencode auth login
|
||
# Select Google provider, then "OAuth with Google (Gemini CLI)"
|
||
```
|
||
|
||
For dashboard OAuth integration, see the Settings page which handles this flow via the API.
|
||
|
||
---
|
||
|
||
## 4) Install Open Agent (Rust backend)
|
||
|
||
### 4.1 Install Rust toolchain
|
||
|
||
```bash
|
||
curl -fsSL https://sh.rustup.rs | sh -s -- -y
|
||
source /root/.cargo/env
|
||
rustc --version
|
||
cargo --version
|
||
```
|
||
|
||
### 4.2 Deploy the repository
|
||
|
||
On the server we keep the repo under `/opt/open_agent/vaduz-v1`. **This must be a git clone** (not just copied files) for the dashboard's one-click update system to work.
|
||
|
||
```bash
|
||
mkdir -p /opt/open_agent
|
||
cd /opt/open_agent
|
||
git clone <YOUR_OPEN_AGENT_REPO_URL> vaduz-v1
|
||
```
|
||
|
||
> **Important**: The update system in Settings relies on git tags to detect new releases. If you deploy via rsync without `.git`, the "Update Available" button won't work. Always use `git clone` for production deployments.
|
||
|
||
For local development, you can rsync to a *different* path (e.g., `/root/open_agent`) for rapid iteration, but keep the git clone at `/opt/open_agent/vaduz-v1` for the update system:
|
||
|
||
```bash
|
||
# Fast dev loop (to a separate path)
|
||
rsync -az --delete \
|
||
--exclude target --exclude .git --exclude dashboard/node_modules \
|
||
/path/to/local-dev/ \
|
||
root@<server-ip>:/root/open_agent/
|
||
|
||
# The git clone at /opt/open_agent/vaduz-v1 is used by the update system
|
||
```
|
||
|
||
If you need to specify a custom SSH key, add `-e "ssh -i ~/.ssh/your_key"`.
|
||
|
||
### 4.3 Build and install binaries
|
||
|
||
```bash
|
||
cd /opt/open_agent/vaduz-v1
|
||
source /root/.cargo/env
|
||
|
||
# Debug build (fast) - recommended for rapid iteration
|
||
cargo build --bin open_agent --bin workspace-mcp --bin desktop-mcp
|
||
install -m 0755 target/debug/open_agent /usr/local/bin/open_agent
|
||
install -m 0755 target/debug/workspace-mcp /usr/local/bin/workspace-mcp
|
||
install -m 0755 target/debug/desktop-mcp /usr/local/bin/desktop-mcp
|
||
|
||
# Or: Release build (slower compile, faster runtime)
|
||
# cargo build --release --bin open_agent --bin workspace-mcp --bin desktop-mcp
|
||
# install -m 0755 target/release/open_agent /usr/local/bin/open_agent
|
||
# install -m 0755 target/release/workspace-mcp /usr/local/bin/workspace-mcp
|
||
# install -m 0755 target/release/desktop-mcp /usr/local/bin/desktop-mcp
|
||
```
|
||
|
||
---
|
||
|
||
## 5) Bootstrap the Library (config repo)
|
||
|
||
Open Agent expects a git-backed **Library** repo. At runtime it will:
|
||
- clone it into `LIBRARY_PATH` (default: `{WORKING_DIR}/.openagent/library`)
|
||
- ensure the `origin` remote matches `LIBRARY_REMOTE`
|
||
- pull/sync as needed
|
||
|
||
### 5.1 Create your own library repo from the template
|
||
|
||
Template:
|
||
- https://github.com/Th0rgal/openagent-library-template
|
||
|
||
One way to bootstrap:
|
||
|
||
```bash
|
||
# On your machine
|
||
git clone git@github.com:Th0rgal/openagent-library-template.git openagent-library
|
||
cd openagent-library
|
||
|
||
# Point it at your own repo
|
||
git remote set-url origin git@github.com:<your-org>/<your-library-repo>.git
|
||
|
||
# Push to your remote (choose main/master as you prefer)
|
||
git push -u origin HEAD:main
|
||
```
|
||
|
||
### 5.2 Configure Open Agent to use it
|
||
|
||
**Option A: Via Dashboard Settings (recommended)**
|
||
|
||
After starting Open Agent, go to **Settings** in the dashboard and set the Library Remote URL.
|
||
This is the preferred method as it persists the setting to disk and allows runtime updates without restart.
|
||
|
||
**Option B: Via environment variable (initial default)**
|
||
|
||
Set in `/etc/open_agent/open_agent.env`:
|
||
- `LIBRARY_REMOTE=git@github.com:<your-org>/<your-library-repo>.git` (used as initial default if not configured in Settings)
|
||
- optional: `LIBRARY_PATH=/root/.openagent/library`
|
||
|
||
---
|
||
|
||
## 6) Configure Open Agent (env file)
|
||
|
||
Create `/etc/open_agent/open_agent.env`:
|
||
|
||
```bash
|
||
mkdir -p /etc/open_agent
|
||
chmod 700 /etc/open_agent
|
||
```
|
||
|
||
Example (fill in your real values):
|
||
|
||
```bash
|
||
cat > /etc/open_agent/open_agent.env <<'EOF'
|
||
# OpenCode backend (must match opencode.service)
|
||
OPENCODE_BASE_URL=http://127.0.0.1:4096
|
||
OPENCODE_PERMISSIVE=true
|
||
# Optional: keep Open Agent writing OpenCode global config into the isolated home
|
||
# (recommended if you enabled strong workspace skill isolation in section 3.2.1).
|
||
# OPENCODE_CONFIG_DIR=/var/lib/opencode/.config/opencode
|
||
|
||
# Server bind
|
||
HOST=0.0.0.0
|
||
PORT=3000
|
||
|
||
# Default filesystem root for Open Agent (agent still has full system access)
|
||
WORKING_DIR=/root
|
||
LIBRARY_PATH=/root/.openagent/library
|
||
# Library remote (optional, can also be set via dashboard Settings page)
|
||
LIBRARY_REMOTE=git@github.com:<your-org>/<your-library-repo>.git
|
||
|
||
# Auth (set DEV_MODE=false on real deployments)
|
||
DEV_MODE=false
|
||
DASHBOARD_PASSWORD=change-me
|
||
JWT_SECRET=change-me-to-a-long-random-string
|
||
JWT_TTL_DAYS=30
|
||
|
||
# Dashboard Console (local shell)
|
||
# No SSH configuration required.
|
||
|
||
# Default model (provider/model). If omitted or not in provider/model format,
|
||
# Open Agent won’t force a model and OpenCode will use its own defaults.
|
||
|
||
# Desktop tools (optional)
|
||
DESKTOP_ENABLED=true
|
||
DESKTOP_RESOLUTION=1920x1080
|
||
EOF
|
||
```
|
||
|
||
---
|
||
|
||
## 7) Create `systemd` unit for Open Agent
|
||
|
||
Create `/etc/systemd/system/open_agent.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=OpenAgent (managed control plane)
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
Group=root
|
||
EnvironmentFile=/etc/open_agent/open_agent.env
|
||
WorkingDirectory=/root
|
||
ExecStart=/usr/local/bin/open_agent
|
||
Restart=on-failure
|
||
RestartSec=2
|
||
|
||
# Agent needs full system access, minimal hardening
|
||
NoNewPrivileges=false
|
||
PrivateTmp=false
|
||
ProtectHome=false
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
---
|
||
|
||
## 8) Optional: Tailscale exit-node workspaces (residential IP)
|
||
|
||
If you want a **workspace** to egress via a residential IP, the recommended pattern is:
|
||
1) Run a Tailscale **exit node** at home.
|
||
2) Use a workspace template that installs and starts Tailscale inside the container.
|
||
|
||
### 8.1 Enable the exit node at home
|
||
On the home server:
|
||
|
||
```bash
|
||
tailscale up --advertise-exit-node
|
||
```
|
||
|
||
Approve it in the Tailscale admin console (Machines → your node → “Approve exit node”).
|
||
|
||
### 8.2 Use the `residential` workspace template
|
||
This repo ships a sample template at:
|
||
|
||
```
|
||
library-template/workspace-template/residential.json
|
||
```
|
||
|
||
It installs Tailscale and adds helper scripts:
|
||
- `openagent-network-up` (brings up host0 veth + DHCP + DNS)
|
||
- `openagent-tailscale-up` (starts tailscaled + sets exit node)
|
||
- `openagent-tailscale-check` (prints Tailscale status + public IP)
|
||
|
||
Set these **workspace env vars** (not global env):
|
||
- `TS_AUTHKEY` (auth key for that workspace)
|
||
- `TS_EXIT_NODE` (node name like `umbrel` or its 100.x IP)
|
||
- Optional: `TS_ACCEPT_DNS=true|false`, `TS_EXIT_NODE_ALLOW_LAN=false`, `TS_STATE_DIR=/var/lib/tailscale`
|
||
|
||
Then inside the workspace:
|
||
|
||
```bash
|
||
openagent-tailscale-up
|
||
openagent-tailscale-check
|
||
```
|
||
|
||
If the public IP matches your home ISP, the exit node is working.
|
||
|
||
### 8.3 Host NAT for veth networking (required)
|
||
`systemd-nspawn --network-veth` needs DHCP + NAT on the host. Without this, containers
|
||
won’t reach the internet or Tailscale control plane.
|
||
|
||
Create an override for `ve-*` interfaces:
|
||
|
||
```bash
|
||
cat >/etc/systemd/network/80-container-ve.network <<'EOF'
|
||
[Match]
|
||
Name=ve-*
|
||
|
||
[Network]
|
||
Address=10.88.0.1/24
|
||
DHCPServer=yes
|
||
EOF
|
||
|
||
systemctl restart systemd-networkd
|
||
```
|
||
|
||
Enable forwarding + NAT (replace `<ext_if>` with your public interface, e.g. `enp0s31f6`):
|
||
|
||
```bash
|
||
sysctl -w net.ipv4.ip_forward=1
|
||
|
||
iptables -t nat -A POSTROUTING -s 10.88.0.0/24 -o <ext_if> -j MASQUERADE
|
||
iptables -A FORWARD -s 10.88.0.0/24 -o <ext_if> -j ACCEPT
|
||
iptables -A FORWARD -d 10.88.0.0/24 -m state --state ESTABLISHED,RELATED -i <ext_if> -j ACCEPT
|
||
```
|
||
|
||
Persist the iptables rules using `iptables-persistent` (or migrate to nftables).
|
||
|
||
### 8.4 Notes for container workspaces
|
||
Tailscale inside a container requires:
|
||
- `/dev/net/tun` bound into the container
|
||
- `CAP_NET_ADMIN`
|
||
- A private network namespace (not host network)
|
||
|
||
If those aren’t enabled, Tailscale will fail or affect the host instead of the workspace.
|
||
|
||
Enable + start:
|
||
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl enable --now open_agent.service
|
||
```
|
||
|
||
Test:
|
||
|
||
```bash
|
||
curl -fsSL http://127.0.0.1:3000/api/health | jq .
|
||
```
|
||
|
||
---
|
||
|
||
## 8) Optional: Desktop automation dependencies
|
||
|
||
If you want browser/desktop automation on Ubuntu, run:
|
||
|
||
```bash
|
||
cd /opt/open_agent/vaduz-v1
|
||
bash scripts/install_desktop.sh
|
||
```
|
||
|
||
Or follow `docs/DESKTOP_SETUP.md`.
|
||
|
||
---
|
||
|
||
## 9) Updating
|
||
|
||
### 9.1 Update Open Agent via Dashboard (recommended)
|
||
|
||
The Settings page shows available updates for Open Agent, OpenCode, and oh-my-opencode. When a new version is available:
|
||
|
||
1. Go to **Settings → System Components**
|
||
2. If "Update Available" appears, click the **Update** button
|
||
3. The update will:
|
||
- Fetch the latest git tags from the repository
|
||
- Checkout the newest release tag
|
||
- Build the binaries (debug mode for faster compile)
|
||
- Install and restart the service
|
||
|
||
**Requirements for one-click updates:**
|
||
- The repository at `/opt/open_agent/vaduz-v1` must be a git clone (not rsync'd files)
|
||
- Create GitHub releases with version tags (e.g., `0.2.1` or `v0.2.1`) to trigger update detection
|
||
- The server needs SSH access to pull from GitHub (deploy key configured in section 0.5.3)
|
||
|
||
### 9.2 Update Open Agent manually (CLI)
|
||
|
||
```bash
|
||
cd /opt/open_agent/vaduz-v1
|
||
git fetch --tags origin
|
||
git checkout <version-tag> # e.g., v0.2.1
|
||
source /root/.cargo/env
|
||
cargo build --bin open_agent --bin workspace-mcp --bin desktop-mcp
|
||
install -m 0755 target/debug/open_agent /usr/local/bin/open_agent
|
||
install -m 0755 target/debug/workspace-mcp /usr/local/bin/workspace-mcp
|
||
install -m 0755 target/debug/desktop-mcp /usr/local/bin/desktop-mcp
|
||
systemctl restart open_agent.service
|
||
```
|
||
|
||
Or to follow the latest master branch:
|
||
|
||
```bash
|
||
cd /opt/open_agent/vaduz-v1
|
||
git pull origin master
|
||
# ... build and install as above
|
||
```
|
||
|
||
### 9.3 Update OpenCode (replace binary, restart service)
|
||
|
||
```bash
|
||
# Optionally pin a version
|
||
curl -fsSL https://opencode.ai/install | bash -s -- --version 1.1.8 --no-modify-path
|
||
install -m 0755 /root/.opencode/bin/opencode /usr/local/bin/opencode
|
||
systemctl restart opencode.service
|
||
curl -fsSL http://127.0.0.1:4096/global/health | jq .
|
||
```
|
||
|
||
## 10) Production Security (TLS + Reverse Proxy)
|
||
|
||
For production deployments, **always** put Open Agent behind a reverse proxy with TLS. The backend serves HTTP only and should never be exposed directly to the internet.
|
||
|
||
### 10.1 Caddy (recommended - automatic HTTPS)
|
||
|
||
Caddy automatically obtains and renews Let's Encrypt certificates.
|
||
|
||
Install Caddy:
|
||
|
||
```bash
|
||
apt install -y debian-keyring debian-archive-keyring apt-transport-https
|
||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
|
||
apt update && apt install caddy
|
||
```
|
||
|
||
Create `/etc/caddy/Caddyfile`:
|
||
|
||
```
|
||
agent.yourdomain.com {
|
||
reverse_proxy localhost:3000
|
||
}
|
||
```
|
||
|
||
Enable and start:
|
||
|
||
```bash
|
||
systemctl enable --now caddy
|
||
```
|
||
|
||
Caddy will automatically obtain TLS certificates for your domain.
|
||
|
||
### 10.2 Nginx (manual certificate setup)
|
||
|
||
Install Nginx and Certbot:
|
||
|
||
```bash
|
||
apt install -y nginx certbot python3-certbot-nginx
|
||
```
|
||
|
||
Create `/etc/nginx/sites-available/openagent`:
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name agent.yourdomain.com;
|
||
|
||
location / {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
|
||
# SSE support (for mission streaming)
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 86400s;
|
||
}
|
||
}
|
||
```
|
||
|
||
Enable the site and obtain certificates:
|
||
|
||
```bash
|
||
ln -s /etc/nginx/sites-available/openagent /etc/nginx/sites-enabled/
|
||
nginx -t && systemctl reload nginx
|
||
certbot --nginx -d agent.yourdomain.com
|
||
```
|
||
|
||
### 10.3 Firewall
|
||
|
||
Block direct access to port 3000 from the internet:
|
||
|
||
```bash
|
||
# Allow only localhost to reach Open Agent directly
|
||
iptables -A INPUT -p tcp --dport 3000 -s 127.0.0.1 -j ACCEPT
|
||
iptables -A INPUT -p tcp --dport 3000 -j DROP
|
||
```
|
||
|
||
---
|
||
|
||
## 11) Authentication Modes
|
||
|
||
Open Agent supports three authentication modes:
|
||
|
||
| Mode | Environment Variables | Use Case |
|
||
|------|----------------------|----------|
|
||
| **Disabled** | `DEV_MODE=true` | Local development only |
|
||
| **Single Tenant** | `DASHBOARD_PASSWORD`, `JWT_SECRET` | Personal server, one user |
|
||
| **Multi-User** | `OPEN_AGENT_USERS`, `JWT_SECRET` | Shared server, multiple users |
|
||
|
||
### 11.1 Single Tenant (default for production)
|
||
|
||
Set a strong password and JWT secret:
|
||
|
||
```bash
|
||
# Generate a random JWT secret
|
||
JWT_SECRET=$(openssl rand -base64 32)
|
||
|
||
# In /etc/open_agent/open_agent.env:
|
||
DEV_MODE=false
|
||
DASHBOARD_PASSWORD=your-strong-password-here
|
||
JWT_SECRET=$JWT_SECRET
|
||
JWT_TTL_DAYS=30
|
||
```
|
||
|
||
### 11.2 Multi-User Mode
|
||
|
||
For multiple users with separate credentials:
|
||
|
||
```bash
|
||
# In /etc/open_agent/open_agent.env:
|
||
DEV_MODE=false
|
||
OPEN_AGENT_USERS='[
|
||
{"username": "alice", "password": "alice-strong-password"},
|
||
{"username": "bob", "password": "bob-strong-password"}
|
||
]'
|
||
JWT_SECRET=$(openssl rand -base64 32)
|
||
```
|
||
|
||
Note: Multi-user mode provides separate login credentials but does **not** provide workspace or data isolation between users. All users see the same missions and workspaces.
|
||
|
||
---
|
||
|
||
## 12) Dashboard Configuration
|
||
|
||
This guide installs the **backend** on your server. The dashboard (frontend) is separate and you have several options:
|
||
|
||
| Option | Best For | Setup |
|
||
|--------|----------|-------|
|
||
| **Vercel** | Production, always accessible | Deploy `dashboard/` to Vercel |
|
||
| **Local** | Development, quick testing | Run `bun dev` in dashboard folder |
|
||
| **iOS App** | Mobile access | Enter backend URL in app |
|
||
|
||
### 12.1 Web Dashboard (Vercel)
|
||
|
||
Deploy the `dashboard/` folder to [Vercel](https://vercel.com):
|
||
|
||
1. Connect your repo to Vercel
|
||
2. Set the root directory to `dashboard`
|
||
3. Add environment variable: `NEXT_PUBLIC_API_URL=https://agent.yourdomain.com`
|
||
4. Deploy
|
||
|
||
The dashboard will connect to your backend server.
|
||
|
||
### 12.2 Web Dashboard (Local)
|
||
|
||
Run the dashboard locally on your machine:
|
||
|
||
```bash
|
||
cd dashboard
|
||
bun install
|
||
NEXT_PUBLIC_API_URL=https://agent.yourdomain.com bun dev
|
||
```
|
||
|
||
Then open `http://localhost:3000`.
|
||
|
||
### 12.3 iOS App
|
||
|
||
On first launch, the iOS app prompts for the server URL. Enter your backend URL (e.g., `https://agent.yourdomain.com`).
|
||
|
||
To change later: **Menu (⋮) → Settings**
|
||
|
||
---
|
||
|
||
## 13) OAuth Provider Setup
|
||
|
||
Open Agent uses OAuth for AI provider authentication. The following providers are pre-configured:
|
||
|
||
| Provider | OAuth Client | Setup Required |
|
||
|----------|-------------|----------------|
|
||
| **Anthropic** | OpenCode's client | None (works out of the box) |
|
||
| **OpenAI** | Codex CLI client | None (works out of the box) |
|
||
| **Google/Gemini** | Gemini CLI client | Install `opencode-gemini-auth` plugin |
|
||
|
||
OAuth flows use copy-paste for the authorization code. The user:
|
||
1. Clicks "Authorize" in the dashboard
|
||
2. Completes OAuth in their browser
|
||
3. Copies the redirect URL back to the dashboard
|
||
|
||
---
|
||
|
||
## Checklist for Production Deployment
|
||
|
||
- [ ] Set `DEV_MODE=false`
|
||
- [ ] Set strong `DASHBOARD_PASSWORD` and `JWT_SECRET`
|
||
- [ ] Configure reverse proxy (Caddy or Nginx) with TLS
|
||
- [ ] Firewall port 3000 (only allow localhost)
|
||
- [ ] Pin OpenCode version for stability
|
||
- [ ] Set up your Library git repo
|
||
- [ ] Test OAuth flows for AI providers
|