How to Deploy OpenSEO Using Docker for Local Testing
TLDR: OpenSEO runs locally via Docker Compose using a pre-built GHCR image, a PostgreSQL container, and a .env file that defaults to AUTH_MODE=local_noauth for instant access at http://localhost:3001.
OpenSEO is a full-stack SEO analytics application designed for self-hosting. You can deploy OpenSEO using Docker for local testing in minutes by combining the official [compose.yaml](https://github.com/every-app/open-seo/blob/main/compose.yaml), a published container image, and a few environment variables. This guide walks through the architecture, configuration files, and commands needed to get the stack running on your machine.
Understanding the Docker Architecture
OpenSEO's Docker setup is optimized for quick local evaluation. The stack intentionally disables internal authentication and bundles the front-end, server functions, and database into a single Compose project.
The Container Image and Compose Stack
By default, the stack pulls ghcr.io/every-app/open-seo:latest as documented in the project's Docker guide. The root-level [compose.yaml](https://github.com/every-app/open-seo/blob/main/compose.yaml) orchestrates two primary services:
- The OpenSEO web container, which packages the compiled Next.js / Vite front-end and Cloudflare-compatible server code.
- A PostgreSQL database using the
postgres:15-alpineimage to persist projects, keywords, and audits.
Environment and Security Defaults
When running under Docker, the application automatically sets AUTH_MODE=local_noauth. This disables the built-in authentication flow and creates a default admin user (admin@localhost) so you can access the dashboard immediately.
You supply core settings through an .env file copied from .env.example. Critical variables include:
DATAFORSEO_API_KEY– Required to fetch SEO data.OPEN_SEO_IMAGE– Overrides the default image tag (e.g., pin to a specific release).ALLOWED_HOST– Whitelists your external domain when running behind a reverse proxy.PORT– Defaults to3001.
Telemetry and Server Functions
Anonymized usage metrics are collected by default via the logic in [src/server/lib/self-host-telemetry.ts](https://github.com/every-app/open-seo/blob/main/src/server/lib/self-host-telemetry.ts). You can opt out by setting OPENSEO_TELEMETRY_DISABLED=1 or DO_NOT_TRACK=1 in your .env file.
All server-side API endpoints—such as project creation, keyword tracking, and site audits—live under src/serverFunctions/ and execute inside the running container.
Step-by-Step Local Deployment
Follow these steps to start OpenSEO on your local machine.
Clone the Repository and Configure the Environment
First, clone the repository and prepare your environment file:
git clone https://github.com/every-app/open-seo.git
cd open-seo
cp .env.example .env
Open .env and add your DATAFORSEO_API_KEY. Verify that AUTH_MODE=local_noauth is present or leave it unset to accept the Compose default.
Start the Stack
Run the following command to pull the image, build if necessary, and start all services:
docker compose up -d
The first start may take one to two minutes while the application compiles and runs database migrations.
Verify the Deployment
Check that the containers are healthy:
docker compose ps
Then open your browser to http://localhost:3001 (or the custom PORT you defined). You can also verify the backend status by querying the health endpoint:
curl http://localhost:3001/api/health
Custom Builds and Advanced Configuration
If you want to modify the source code or pin to a specific release, you can build locally or override the Compose environment.
Build a Local Image with Dockerfile.selfhost
The repository includes a Dockerfile.selfhost for creating your own image. This is useful when testing local changes:
docker build -f Dockerfile.selfhost -t open-seo:local .
OPEN_SEO_IMAGE=open-seo:local docker compose up -d
Update and Restart Commands
To pull the latest published image and recreate the container:
docker compose pull && docker compose up -d
If you change environment variables, force a fresh recreate:
docker compose up -d --force-recreate open-seo
Alternatively, restart only the application service:
docker compose up -d open-seo
Disable Telemetry
Add one of the following lines to your .env file before starting the stack:
OPENSEO_TELEMETRY_DISABLED=1
Or:
DO_NOT_TRACK=1
Common Docker Commands for OpenSEO
Keep these commands handy for day-to-day management:
- View running services:
docker compose ps - Inspect effective configuration:
docker compose config - View logs:
docker compose logs -f open-seo - Stop the stack:
docker compose down - Stop and remove volumes:
docker compose down -v
Summary
- OpenSEO is deployed locally via the root-level [
compose.yaml](https://github.com/every-app/open-seo/blob/main/compose.yaml) and a pre-built GHCR image. - The Docker stack defaults to
AUTH_MODE=local_noauthwith an automaticadmin@localhostuser. - You must copy
.env.exampleto.envand supply yourDATAFORSEO_API_KEY. - Use
Dockerfile.selfhostto build custom images for development. - Telemetry can be disabled with
OPENSEO_TELEMETRY_DISABLED=1orDO_NOT_TRACK=1. - Always verify the deployment with
docker compose psand the/api/healthendpoint.
Frequently Asked Questions
What authentication mode does OpenSEO use in Docker?
OpenSEO uses AUTH_MODE=local_noauth when deployed through Docker Compose. This mode disables the internal authentication system and creates a default admin user at admin@localhost, allowing immediate access to the dashboard for local testing.
How do I update to the latest OpenSEO Docker image?
Run docker compose pull && docker compose up -d from the repository root. This fetches the latest ghcr.io/every-app/open-seo:latest tag—or the tag specified by OPEN_SEO_IMAGE in your .env file—and recreates the container.
Can I build my own OpenSEO image instead of using GHCR?
Yes. Use the provided Dockerfile.selfhost to build a local image, then set OPEN_SEO_IMAGE=your-tag in .env before running docker compose up -d. This workflow is ideal for testing source code modifications.
Is it safe to expose the OpenSEO Docker container directly to the internet?
No. The Docker documentation recommends placing the container behind your own reverse proxy, tunnel, or private network. If you use a reverse proxy, set the ALLOWED_HOST environment variable to your external domain so the application correctly validates incoming requests.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →