# How to Update Open-SEO: Complete Self-Hosted Upgrade Guide

> Update Open-SEO easily with this self-hosted upgrade guide. Learn to pull code, refresh dependencies, apply migrations, and rebuild Docker for a seamless update.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-08-06

---

**Updating Open-SEO requires pulling the latest code from the `main` branch, refreshing Node.js dependencies with `pnpm`, applying database migrations via Drizzle-ORM, and rebuilding the Docker image using `Dockerfile.selfhost`.**

Open-SEO is an open-source SEO platform maintained by every-app. Keeping your instance current ensures you receive the latest features, security patches, and database schema updates. This guide walks through the exact commands and configuration files—located in the `every-app/open-seo` repository—required to update open-seo safely.

## Step 1: Pull the Latest Source Code

Start by fetching the newest commit from the repository. This brings in updated source files, migration scripts, and dependency manifests.

```bash
git checkout main
git pull origin main

```

This updates your local working directory to match the current state of the `main` branch on GitHub.

## Step 2: Refresh Node.js Dependencies

Open-SEO uses `pnpm` for reproducible installs locked by [`pnpm-lock.yaml`](https://github.com/every-app/open-seo/blob/main/pnpm-lock.yaml). After pulling new code, reinstall dependencies to align with the versions specified in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json).

```bash
pnpm install

```

This command reads the lock file and installs the exact dependency tree required by the new release, including updates to **TanStack Server Functions** and **Drizzle-ORM**.

## Step 3: Rebuild the Frontend Bundle

If you serve the web UI, compile the optimized static assets using the Vite configuration defined in [`web/vite.config.ts`](https://github.com/every-app/open-seo/blob/main/web/vite.config.ts).

```bash

# Production build

pnpm run build

# Or for local development

pnpm run dev

```

The build process generates optimized assets based on the current TypeScript types in `src/types/schemas/*.ts`, which are updated automatically when backend query shapes change.

## Step 4: Apply Database Migrations

Schema changes ship with migration metadata in `drizzle-pg/meta/*.json`. Apply these using the built-in migration script or the D1-to-Postgres helper.

**Standard migration:**

```bash
pnpm run migrate

```

**Migrating from legacy D1 to Postgres:**

```bash
node scripts/migrate-d1-to-postgres.ts

```

These commands reference [`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts) (for SQLite/D1) and [`drizzle-pg.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-pg.config.ts) (for Postgres) to execute schema changes safely.

## Step 5: Rebuild and Redeploy the Docker Image

For self-hosted deployments, recreate the container image using the definitions in `Dockerfile.selfhost` and the orchestration in [`compose.yaml`](https://github.com/every-app/open-seo/blob/main/compose.yaml).

```bash
docker compose build
docker compose up -d

```

This rebuilds the application with the latest code, dependencies, and compiled assets, then restarts the service without destroying persistent volumes.

## Step 6: Verify the Update

Confirm the deployment health by running the Playwright end-to-end test suite and checking the application URL.

```bash
pnpm run test:e2e

```

The test files in [`e2e/keyword-research-navigation.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/keyword-research-navigation.spec.ts) validate critical user flows. Additionally, open `http://localhost:3000` (or your configured host) to verify the UI loads without runtime errors.

## Summary

- **Source control:** Always pull the latest `main` branch before updating.
- **Dependencies:** Run `pnpm install` to sync with [`pnpm-lock.yaml`](https://github.com/every-app/open-seo/blob/main/pnpm-lock.yaml).
- **Database:** Execute `pnpm run migrate` or `node scripts/migrate-d1-to-postgres.ts` to apply schema changes tracked in [`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts).
- **Deployment:** Rebuild the Docker image using `docker compose build` and restart with `docker compose up -d`.
- **Validation:** Use `pnpm run test:e2e` to confirm the upgrade succeeded.

## Frequently Asked Questions

### What should I do if database migrations fail?

Check that your [`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts) points to the correct database URL and that you have Postgres running. If migrating from Cloudflare D1, use the [`scripts/migrate-d1-to-postgres.ts`](https://github.com/every-app/open-seo/blob/main/scripts/migrate-d1-to-postgres.ts) helper script specifically designed to port legacy data to the new schema.

### Do I need to rebuild the frontend every time I update?

Yes, if you are serving the web UI in production. Run `pnpm run build` to regenerate static assets via [`web/vite.config.ts`](https://github.com/every-app/open-seo/blob/main/web/vite.config.ts). The build process bundles the latest TypeScript types from `src/types/schemas/` and optimizes the output for deployment.

### Can I update Open-SEO without using Docker?

While the repository provides `Dockerfile.selfhost` and [`compose.yaml`](https://github.com/every-app/open-seo/blob/main/compose.yaml) for containerized deployments, you can run the update manually by executing `pnpm install`, `pnpm run build`, `pnpm run migrate`, and starting the Node.js process directly. However, you must ensure your environment matches the Node version specified in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json).

### How do I verify that the update was successful?

Run the end-to-end test suite with `pnpm run test:e2e`, which executes Playwright tests including [`e2e/keyword-research-navigation.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/keyword-research-navigation.spec.ts). Additionally, manually verify that `http://localhost:3000` loads without errors and that core features like keyword research function correctly.