DocsRun it yourself
Self-host OpenReach with Docker
How to self-host OpenReach with Docker: run the open-source lead generation tool on your own computer or a server, with HTTPS for your own domain.
- Docker
- PostgreSQL
- GitHub
OpenReach is open source under the MIT licence, and everything this site runs is in the repository: the dashboard, the API with its MCP server and background worker, the public site and the database schema. With Docker, one command starts all of it.
| Where | Good for | You need |
|---|---|---|
| Your own computer | Trying it out, or using it just for yourself | Docker Desktop (Windows, macOS) or Docker (Linux) |
| A cloud server | Using it from anywhere, with a team, on your own domain | A server with 2 CPUs and 4 GB of memory, and a domain |
| From source | Changing the code | Node.js 26, pnpm 10 and Postgres |
On your own computer
Install Docker
Install Docker Desktop on Windows or macOS, or Docker Engine on Linux, and start it. Give it at least 4 GB of memory: the first build compiles the dashboard and the site.
Get the code
Terminal git clone https://github.com/duckduckdeploy/openreach.git openreach cd openreachSet two secrets
Terminal cp .env.example .env # Then open .env and set these two: AUTH_SECRET= # any 32+ random characters ENCRYPTION_KEY= # the output of: openssl rand -base64 32AUTH_SECRETsigns sign-in sessions.ENCRYPTION_KEYencrypts the YepAPI keys you store; keep a copy somewhere safe, because they cannot be read without it.Terminal # Generate both with Docker if you have no openssl: docker run --rm alpine sh -c "apk add -q openssl && echo AUTH_SECRET=\$(openssl rand -hex 32) && echo ENCRYPTION_KEY=\$(openssl rand -base64 32)"Start it
Terminal docker compose up -d --buildThe first build takes a few minutes. Postgres starts, the database is set up, and then the API, dashboard and site come up. Open
http://localhost:3300, create your account and follow the setup.
| Address | What it is |
|---|---|
| http://localhost:3300 | The dashboard: where you work |
| http://localhost:3301 | This site and the docs, served locally |
| http://localhost:4300 | The API, and the MCP server at /mcp for your AI agent |
These addresses are only reachable from your computer. To stop OpenReach, run docker compose down; your data stays in a Docker volume until you remove it with docker compose down -v.
On a cloud server, with your own domain
Any provider that gives you a Linux server works: a virtual server with 2 CPUs, 4 GB of memory and 40 GB of disk is enough for one person or a small team, and costs around $10 to $25 a month. Use Ubuntu 24.04 or Debian 12.
Point your domain at the server
Create DNS records for your domain,
app.andapi.on it (for exampleexample.com,app.example.comandapi.example.com), all pointing at the server's IP address. Open ports 22, 80 and 443 in the provider's firewall, and nothing else.Install Docker and get the code
On the server # Ubuntu or Debian: install Docker curl -fsSL https://get.docker.com | sh # Get OpenReach git clone https://github.com/duckduckdeploy/openreach.git openreach cd openreach cp .env.example .envSet the secrets and your domain
.env # .env on a server with the domain example.com AUTH_SECRET=... ENCRYPTION_KEY=... POSTGRES_PASSWORD=... # a long random password OPENREACH_DOMAIN=example.com APP_URL=https://app.example.com WEB_URL=https://example.com PUBLIC_API_URL=https://api.example.comThe public addresses are built into the dashboard and the site, so set them before you start, and rebuild if you change them.
Start it with HTTPS
On the server docker compose --profile https up -d --buildThe
httpsprofile adds Caddy in front, which gets certificates from Let's Encrypt and renews them on its own. The app, site and API listen only on the server itself; Caddy is the only thing facing the internet.
Updating
cd openreach
git pull
docker compose up -d --build # add --profile https on a serverDatabase changes are applied automatically when the API starts. Back up first if your data matters to you.
OpenReach keeps two Postgres databases: openreach for accounts, keys, usage and billing, and openreach_data for projects and everything in them: creators, leads, lead searches, monitors and mentions. The second is created on first start, on the same server. To keep it elsewhere, set DATA_DATABASE_URL.
Backups
# Back up both databases to files: accounts and keys, then project data
docker compose exec -T postgres pg_dump -U openreach openreach | gzip > openreach-$(date +%F).sql.gz
docker compose exec -T postgres pg_dump -U openreach openreach_data | gzip > openreach_data-$(date +%F).sql.gz
# Restore them into an empty install
gunzip -c openreach-2026-10-15.sql.gz | docker compose exec -T postgres psql -U openreach openreach
gunzip -c openreach_data-2026-10-15.sql.gz | docker compose exec -T postgres psql -U openreach openreach_dataKeep .env with your backups: the database is useless without the same ENCRYPTION_KEY. On a server, run the backup command nightly with cron and copy the files off the machine.
Settings
| Setting | What it does |
|---|---|
| REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET | Search Reddit through its official API, for free, with an app you register at reddit.com/prefs/apps (application-only OAuth). Unset: Reddit is searched through Google results. |
| GITHUB_TOKEN | A GitHub token with no scopes, for a higher rate limit on GitHub issue search. Works without one. |
| STACKEXCHANGE_KEY | A Stack Apps key, which raises the Stack Exchange quota from 300 to 10,000 requests a day. |
| LEAD_SEARCH_MAX_CALLS | The most Google Maps calls one lead search may make. 500 by default. |
| LEAD_SEARCH_MAX_ACTIVE_PER_USER | How many lead searches one user may run at once. 2 by default. |
| PUBLIC_TOOLS_YEPAPI_KEY | Turns on the free tools on your site, paid from this key, with daily and monthly caps (PUBLIC_TOOLS_DAILY_USD, PUBLIC_TOOLS_MONTHLY_USD, PUBLIC_TOOLS_PER_DAY). |
| API_BIND, APP_BIND, WEB_BIND | Which address each service listens on. 127.0.0.1 by default, so only this machine can reach them. |
| POSTGRES_PASSWORD | The database password. Set a long random one on a server. |
After changing .env, run docker compose up -d again.
From source, for development
pnpm install
docker compose up -d postgres # or point DATABASE_URL at your own Postgres
pnpm db:migrate
pnpm devpnpm dev runs the API on :4300, the dashboard on :3300 and the site on :3301 with live reload. pnpm typecheck and pnpm test run the checks; the tests need no database or network, because they use an in-memory Postgres and a stand-in for the data provider and the community APIs.
Next
Connect your AI agent to your own install: your MCP endpoint is {API_URL}/mcp. See Connect an agent over MCP.