Skip to content

DocsRun it yourself

Self-host OpenSEO with Docker

How to self-host OpenSEO with Docker: run the open-source SEO suite on your own computer or a cloud server, with HTTPS for your own domain.

  • Docker
  • PostgreSQL
  • GitHub

OpenSEO 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.

Ways to run OpenSEO
WhereGood forYou need
Your own computerTrying it out, or using it just for yourselfDocker Desktop (Windows, macOS) or Docker (Linux)
A cloud serverUsing it from anywhere, with a team, on your own domainA server with 2 CPUs and 4 GB of memory, and a domain
From sourceChanging the codeNode.js 22, pnpm 10 and Postgres

On your own computer

  1. 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.

  2. Get the code

    Terminal
    git clone https://github.com/duckduckdeploy/openseo.git openseo
    cd openseo
  3. Set 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 32

    AUTH_SECRET signs sign-in sessions. ENCRYPTION_KEY encrypts the API keys and Google tokens 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)"
  4. Start it

    Terminal
    docker compose up -d --build

    The 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:3200, create your account and follow the setup.

Addresses on your computer
AddressWhat it is
http://localhost:3200The dashboard: where you work
http://localhost:3101This site and the docs, served locally
http://localhost:4100The API, and the MCP server at /mcp for your AI agent

These addresses are only reachable from your computer. To stop OpenSEO, 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.

  1. Point your domain at the server

    Create DNS records for your domain, app. and api. on it (for example example.com, app.example.com and api.example.com), all pointing at the server's IP address. Open ports 22, 80 and 443 in the provider's firewall, and nothing else.

  2. Install Docker and get the code

    On the server
    # Ubuntu or Debian: install Docker
    curl -fsSL https://get.docker.com | sh
    
    # Get OpenSEO
    git clone https://github.com/duckduckdeploy/openseo.git openseo
    cd openseo
    cp .env.example .env
  3. Set 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
    
    OPENSEO_DOMAIN=example.com
    APP_URL=https://app.example.com
    WEB_URL=https://example.com
    PUBLIC_API_URL=https://api.example.com

    The public addresses are built into the dashboard and the site, so set them before you start, and rebuild if you change them.

  4. Start it with HTTPS

    On the server
    docker compose --profile https up -d --build

    The https profile 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

Terminal
cd openseo
git pull
docker compose up -d --build        # add --profile https on a server

Database changes are applied automatically when the API starts. Back up first if your data matters to you.

OpenSEO keeps two Postgres databases: openseo for accounts, keys, usage and billing, and openseo_data for everything projects track and research. The second is created on first start, on the same server. To keep it elsewhere, set DATA_DATABASE_URL.

Backups

Terminal
# Back up both databases to files: accounts and keys, then project data
docker compose exec -T postgres pg_dump -U openseo openseo | gzip > openseo-$(date +%F).sql.gz
docker compose exec -T postgres pg_dump -U openseo openseo_data | gzip > openseo_data-$(date +%F).sql.gz

# Restore them into an empty install
gunzip -c openseo-2026-10-15.sql.gz | docker compose exec -T postgres psql -U openseo openseo
gunzip -c openseo_data-2026-10-15.sql.gz | docker compose exec -T postgres psql -U openseo openseo_data

Keep .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

Optional settings in .env
SettingWhat it does
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRETLets users connect Search Console and Analytics. See Set up Google sign-in.
API_BIND, APP_BIND, WEB_BINDWhich address each service listens on. 127.0.0.1 by default, so only this machine can reach them.
POSTGRES_PASSWORDThe database password. Set a long random one on a server.

After changing .env, run docker compose up -d again. See Set up Google sign-in.

From source, for development

Terminal
pnpm install
docker compose up -d postgres       # or point DATABASE_URL at your own Postgres
pnpm db:migrate
pnpm dev

pnpm dev runs the API on :4100, the dashboard on :3200 and the site on :3101 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 stand-ins for the data provider and Google.

Next

Connect your AI agent to your own install: your MCP endpoint is {API_URL}/mcp. See Connect an agent over MCP.