SETUP.md
Rama main · réplica de lectura del repositorio original.
# Setting up Ghost Browser on your own VPS
By the end of this you will have a real Chromium running on a server, that you drive from a web
console or an HTTP API — and, if you want it, **leaving through your own home internet connection
instead of the datacentre's**, so the sites it visits see a normal residential address.
It takes about ten minutes.
---
## 1. What you need
- A Linux VPS (any provider, any size from ~1 GB RAM up — a browser is memory-hungry, give it room).
- **Docker** on it. That is the whole runtime: the image already contains Chromium, the Xvfb
virtual display it needs, and Tailscale. You do not install those yourself.
- Optional, for the AI agent: an [Ollama](https://ollama.com) API key (cloud) or a self-hosted
Ollama endpoint. You can skip this and use Ghost Browser purely as a scriptable browser.
---
## 2. Run it
Build the image from this repo and start it:
```bash
git clone https://github.com/Wvdstoep/ghost-browser.git
cd ghost-browser
docker build -t ghost-browser .
docker run -d --name ghost \
-p 3000:3000 \
-e API_KEYS="pick-a-long-secret:team" \
-v ghost-profiles:/profiles \
ghost-browser
```
Two things matter here:
- **`API_KEYS`** is required — the server refuses to start without it. A session costs real memory
for its whole life, so there is no anonymous access. The format is `key:plan,key:plan`; `team` is
the highest-concurrency plan.
- **The `/profiles` volume** is where everything durable lives — logins, cookies, saved flows,
roles, the agent's model key. Mount it, or you lose all of that on every restart.
Open `http://YOUR_VPS_IP:3000`. The first visit creates the owner account. (Put it behind a reverse
proxy with TLS before you expose it to the internet — it holds live logins.)
---
## 3. Drive it
Three ways, all the same browser:
- **The console** — click into a session and use it by hand, or watch the agent work.
- **The HTTP API** — `POST /v1/sessions`, then `navigate`, `analyze`, `click`, `type`, `read`.
Auth is `Authorization: Bearer <your key>`. See the [README](README.md) for the full surface.
- **The agent** — give it a goal and let it drive, through the same numbered Set-of-Mark view a
person sees. Writes that a real person would notice (posting, following, messaging) go through an
act-gate that shows you the exact text and waits for approval.
For the agent, open **Model** in the console and point it at Ollama (cloud key, or a self-hosted
`OLLAMA_URL`). The key is stored on the `/profiles` volume and never comes back out of the API.
---
## 4. The part that makes it different: leave through your home connection
A browser running in a datacentre has a datacentre IP, and a lot of sites treat that as a red flag —
sign-ups get extra scrutiny, some content is geo- or bot-gated. Ghost Browser can route a profile's
traffic **out through a device you own at home**, so the exit address is an ordinary residential one
in your own country.
It does this with [Tailscale](https://tailscale.com) (already in the image), using a home machine as
an *exit node*. Nothing about this is a fingerprint trick — it is just choosing where your own
traffic leaves the internet.
### 4a. Turn a home device into an exit node
On any machine at home that stays on — a spare laptop, a Raspberry Pi, your desktop:
```bash
# install tailscale (see tailscale.com/download), then:
sudo tailscale up --advertise-exit-node
```
Then in the [Tailscale admin console](https://login.tailscale.com/admin/machines), open that
machine's `...` menu and **approve it as an exit node** (Tailscale requires this once, on purpose).
### 4b. Connect Ghost Browser to your tailnet
1. Create an [auth key](https://login.tailscale.com/admin/settings/keys) in the Tailscale admin
(a reusable one is convenient).
2. In the Ghost Browser console, open the **exit / network** panel and paste the auth key. The
browser joins your tailnet as a device called `ghost-browser`.
3. Choose your **home device** as the exit node. From now on, sessions leave through your home
connection by default. (A device only appears here if it is advertising itself as an exit node —
step 4a.)
### 4c. Prove it worked
Point a session at an IP-echo service and check the address:
```bash
curl -s -H "Authorization: Bearer YOUR_KEY" -X POST http://YOUR_VPS_IP:3000/v1/sessions
# then navigate that session to https://ipinfo.io/json and read it —
# the "org" and "city" should be your home ISP, not your VPS provider.
```
Per-profile control: a profile can leave through the tailnet (the default once one is connected),
or be pinned to leave straight from the server (`direct`) when a residential exit is not wanted.
---
## 5. Keep it running (production)
- **Persist `/profiles`** on a real volume. It is the whole state of the thing.
- **One browser per container.** Sessions are heavy; scale out with more containers, not more
sessions per container. Watch `GET /v1/capacity`.
- **Kubernetes:** a Helm chart is included under [`deploy/ghost-tool`](deploy/ghost-tool). It mints
an API key on first install and re-uses it on upgrades, so the key is stable across rolls.
---
## 6. Environment reference
| Variable | Default | What it does |
|---|---|---|
| `API_KEYS` | *(required)* | `key:plan,key:plan` — who may open a browser, at what concurrency |
| `PROFILE_DIR` | `/profiles` | where logins, flows, roles and the model key are stored |
| `PORT` | `3000` | HTTP port |
| `MAX_CONTEXTS` | `8` | sessions per container before it stops accepting more |
| `IDLE_MS` | `300000` | close a session after this long idle |
| `SESSION_TTL_MS` | `7200000` | absolute session lifetime |
| `MEMORY_LIMIT_PCT` | `80` | drain and recycle the container at this cgroup-memory fraction |
| `OLLAMA_URL` | — | self-hosted Ollama endpoint for the agent |
| `OLLAMA_API_KEY` | — | Ollama Cloud key for the agent (or set it in the console) |
| `TAILSCALE_HOSTNAME` | `ghost-browser` | the name this browser joins your tailnet as |
| `HEADLESS` | `false` | keep it false — a headful Chromium on Xvfb is far less detectable |
---
## Troubleshooting
- **"refuses to start"** — you did not set `API_KEYS`. That is deliberate.
- **The exit node does not appear** — the home device is not advertising itself (step 4a) or has not
been approved in the admin console (both are required, once).
- **A live view is black** — the session's page is a background tab or a nearly-blank bot wall; the
screencast only paints on change. This is one of the rough edges where **UI help is very welcome** —
see [CONTRIBUTING.md](CONTRIBUTING.md).