Skip to content

Commit db4e6c2

Browse files
committed
Docs: manual DigitalOcean Droplet setup
1 parent 028d56c commit db4e6c2

4 files changed

Lines changed: 298 additions & 4 deletions

File tree

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ Credentials: `docs/deploy/aws.md#retrieving-credentials`
5656
[![Deploy on DigitalOcean](https://img.shields.io/badge/Deploy-DigitalOcean-0080FF?logo=digitalocean&logoColor=white)](https://marketplace.digitalocean.com/apps/opencode-cloud)
5757

5858
Marketplace one-click deploy provisions a Droplet that bootstraps opencode-cloud
59-
on first boot.
59+
on first boot (listing pending).
6060

61-
Docs: `docs/deploy/digitalocean-marketplace.md`
61+
Manual Droplet setup: `docs/deploy/digitalocean-droplet.md`
62+
Marketplace docs: `docs/deploy/digitalocean-marketplace.md`
6263

6364
## Features
6465

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
# DigitalOcean Droplet (Manual Setup)
2+
3+
Manual deployment instructions for running opencode-cloud on a DigitalOcean
4+
Droplet before the Marketplace 1-click image is available.
5+
6+
## Overview
7+
8+
What you get:
9+
10+
- **Persistence**: your workspace, config, and PAM users persist on the Droplet disk.
11+
- **Sandboxing**: opencode runs inside `prizz/opencode-cloud-sandbox` (Docker).
12+
13+
Security posture (recommended):
14+
15+
- Keep the service **bound to localhost**.
16+
- Access it via an **SSH tunnel** (`ssh -L ...`).
17+
- Do **not** expose port `3000` publicly until you have a user, and a firewall/TLS plan.
18+
19+
## Prereqs
20+
21+
- Droplet: **Ubuntu 24.04 LTS**.
22+
- Disk: **50GB+** recommended (Docker images + workspace can grow).
23+
- SSH key added during Droplet creation.
24+
25+
## Path 1 (Recommended): Install `occ` on the Droplet
26+
27+
### 1) Create the Droplet
28+
29+
In the DigitalOcean UI:
30+
31+
- Choose **Ubuntu 24.04 LTS**
32+
- Add your **SSH key**
33+
- Optional: attach a **Cloud Firewall** that only allows inbound `22/tcp` from your IP
34+
35+
### 2) SSH into the Droplet
36+
37+
```bash
38+
ssh root@<droplet-ip>
39+
```
40+
41+
### 3) Install Docker + deps
42+
43+
```bash
44+
apt-get update -y
45+
apt-get install -y docker.io curl jq
46+
systemctl enable --now docker
47+
docker --version
48+
```
49+
50+
If `cargo install` fails later due to missing build dependencies, install:
51+
52+
```bash
53+
apt-get install -y build-essential pkg-config libssl-dev
54+
```
55+
56+
### 4) Install Rust (rustup) + `opencode-cloud`
57+
58+
```bash
59+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y --profile minimal
60+
. "$HOME/.cargo/env"
61+
cargo install opencode-cloud
62+
occ --version
63+
```
64+
65+
### 5) Start the service (localhost-only default)
66+
67+
Pull and start the sandbox image:
68+
69+
```bash
70+
occ start --pull-sandbox-image
71+
```
72+
73+
### 6) Create the first PAM user
74+
75+
Recommended: generate a strong password:
76+
77+
```bash
78+
occ user add admin --generate
79+
```
80+
81+
Scripting mode:
82+
83+
```bash
84+
occ user add admin --generate --print-password-only
85+
```
86+
87+
### 7) Access via SSH tunnel (recommended default)
88+
89+
From your laptop:
90+
91+
```bash
92+
ssh -L 3000:localhost:3000 root@<droplet-ip>
93+
```
94+
95+
Then open:
96+
97+
- `http://localhost:3000`
98+
99+
Log in with the user you created.
100+
101+
### 8) Enable reboot persistence via systemd (system-level)
102+
103+
```bash
104+
occ config set boot_mode system
105+
occ install
106+
systemctl status opencode-cloud --no-pager
107+
```
108+
109+
View logs:
110+
111+
```bash
112+
journalctl -u opencode-cloud -f
113+
```
114+
115+
### 9) Optional: expose port 3000 publicly (only after user + firewall)
116+
117+
Bind to all interfaces:
118+
119+
```bash
120+
occ config set bind_address 0.0.0.0
121+
occ restart
122+
```
123+
124+
Firewall recommendations:
125+
126+
- Allow inbound `3000/tcp` **only** from your IP (or office/VPN CIDR).
127+
- Keep inbound `22/tcp` restricted.
128+
129+
Confirm unauthenticated access is disabled:
130+
131+
```bash
132+
occ config get allow_unauthenticated_network
133+
```
134+
135+
It should be `false`.
136+
137+
## Optional HTTPS (Caddy)
138+
139+
Goal: keep opencode on localhost, expose only `80/443` publicly.
140+
141+
### 1) Ensure opencode binds to localhost
142+
143+
```bash
144+
occ config set bind_address 127.0.0.1
145+
occ restart
146+
```
147+
148+
### 2) Install Caddy
149+
150+
```bash
151+
apt-get update -y
152+
apt-get install -y caddy
153+
systemctl enable --now caddy
154+
```
155+
156+
If `apt-get install caddy` fails, install from the official Caddy repo instead.
157+
158+
### 3) Configure Caddy
159+
160+
Edit `/etc/caddy/Caddyfile`:
161+
162+
```caddyfile
163+
your-domain.example.com {
164+
reverse_proxy 127.0.0.1:3000
165+
}
166+
```
167+
168+
Reload Caddy:
169+
170+
```bash
171+
systemctl reload caddy
172+
```
173+
174+
### 4) DigitalOcean firewall
175+
176+
- Allow inbound `80/tcp` and `443/tcp` from `0.0.0.0/0`
177+
- Keep inbound `3000/tcp` **closed**
178+
179+
### 5) Proxy headers note (trustProxy)
180+
181+
If you are running behind a reverse proxy and need opencode to trust
182+
`X-Forwarded-*` headers, you may need to set `trustProxy` in opencode config
183+
and restart.
184+
185+
This file lives on the host bind-mount. If you ran `occ` as `root`, it is
186+
typically:
187+
188+
- `/root/.config/opencode/opencode.jsonc`
189+
190+
Example config:
191+
192+
```jsonc
193+
{
194+
"auth": {
195+
"enabled": true,
196+
"trustProxy": true
197+
}
198+
}
199+
```
200+
201+
Then restart:
202+
203+
```bash
204+
occ restart
205+
```
206+
207+
## Path 2: Docker-only (Image Direct)
208+
209+
Use this if you don’t want `occ` installed on the Droplet.
210+
211+
### 1) Install Docker
212+
213+
```bash
214+
apt-get update -y
215+
apt-get install -y docker.io curl jq
216+
systemctl enable --now docker
217+
docker --version
218+
```
219+
220+
### 2) Create Docker volumes
221+
222+
```bash
223+
docker volume create opencode-data
224+
docker volume create opencode-state
225+
docker volume create opencode-cache
226+
docker volume create opencode-workspace
227+
docker volume create opencode-config
228+
docker volume create opencode-users
229+
```
230+
231+
### 3) Run the container (SSH tunnel default: bind host port to localhost)
232+
233+
```bash
234+
docker run -d --name opencode-cloud-sandbox \
235+
--restart unless-stopped \
236+
-p 127.0.0.1:3000:3000 \
237+
-v opencode-data:/home/opencode/.local/share/opencode \
238+
-v opencode-state:/home/opencode/.local/state/opencode \
239+
-v opencode-cache:/home/opencode/.cache/opencode \
240+
-v opencode-workspace:/home/opencode/workspace \
241+
-v opencode-config:/home/opencode/.config/opencode \
242+
-v opencode-users:/var/lib/opencode-users \
243+
-e OPENCODE_BOOTSTRAP_USER=admin \
244+
-e OPENCODE_BOOTSTRAP_PASSWORD='change-me' \
245+
prizz/opencode-cloud-sandbox:15.2.0
246+
```
247+
248+
Notes:
249+
250+
- Prefer a **pinned tag** (like `15.2.0`) for reproducible deployments.
251+
- See Docker Hub for tags: https://hub.docker.com/r/prizz/opencode-cloud-sandbox
252+
253+
### 4) Access via SSH tunnel
254+
255+
From your laptop:
256+
257+
```bash
258+
ssh -L 3000:localhost:3000 root@<droplet-ip>
259+
```
260+
261+
Then open `http://localhost:3000`.
262+
263+
### 5) Expose publicly (optional)
264+
265+
- Change to `-p 0.0.0.0:3000:3000` (or `-p 3000:3000`)
266+
- Apply a DigitalOcean firewall allowlist (recommended)
267+
268+
## Troubleshooting
269+
270+
Container status/logs:
271+
272+
```bash
273+
docker ps
274+
docker logs opencode-cloud-sandbox
275+
```
276+
277+
CLI status/logs (if using `occ`):
278+
279+
```bash
280+
occ status
281+
occ logs
282+
```
283+
284+
systemd logs (if installed via `occ install`):
285+
286+
```bash
287+
journalctl -u opencode-cloud -f
288+
```
289+

docs/deploy/digitalocean-marketplace.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ This deployment path packages opencode-cloud as a DigitalOcean Marketplace 1-cli
44
Droplet image. Users deploy from the Marketplace listing and the instance
55
bootstraps itself on first boot.
66

7+
> Note: Marketplace listing pending. For manual Droplet setup now, see
8+
> `docs/deploy/digitalocean-droplet.md`.
9+
710
## Deploy from the Marketplace
811

912
1. Click the **Deploy on DigitalOcean** button in the root README.

packages/core/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ Credentials: `docs/deploy/aws.md#retrieving-credentials`
5656
[![Deploy on DigitalOcean](https://img.shields.io/badge/Deploy-DigitalOcean-0080FF?logo=digitalocean&logoColor=white)](https://marketplace.digitalocean.com/apps/opencode-cloud)
5757

5858
Marketplace one-click deploy provisions a Droplet that bootstraps opencode-cloud
59-
on first boot.
59+
on first boot (listing pending).
6060

61-
Docs: `docs/deploy/digitalocean-marketplace.md`
61+
Manual Droplet setup: `docs/deploy/digitalocean-droplet.md`
62+
Marketplace docs: `docs/deploy/digitalocean-marketplace.md`
6263

6364
## Features
6465

0 commit comments

Comments
 (0)