Skip to content

elsenormanzana/openweb

Repository files navigation

OpenWeb

OpenWeb is a monorepo CMS platform with:

  • apps/web: React + Vite admin/public frontend
  • apps/api: Fastify + Drizzle API
  • Postgres for persistence
  • NGINX reverse proxy in Docker deployment

1) Repository Structure

  • apps/web/ frontend app
  • apps/api/ backend API
  • apps/api/drizzle/ SQL migrations
  • apps/api/uploads/ uploaded media in local/dev runtime
  • deploy/ Docker Compose/Swarm deployment assets
  • setup-deploy.sh interactive production setup script (root)

2) Production Deployment (Recommended)

Use the interactive root script:

./setup-deploy.sh

This script handles environment setup, Docker deployment, migrations, and optional restore from backup ZIP.

2.1 Prerequisites

Install and verify:

docker --version
docker compose version
unzip -v

Recommended host requirements:

  • Linux server or VM
  • Docker Engine 24+
  • Port 80 open
  • Sufficient disk space for Postgres, uploads, and backups

2.2 What setup-deploy.sh asks

When you run the script, it prompts for:

  1. Postgres database name
  2. Postgres username
  3. Postgres password
  4. Docker type (deployment mode):
    • 1 = Docker Compose
    • 2 = Docker Swarm (autoscaler enabled)
  5. If Docker Swarm chosen: stack name
  6. Whether you have a backup ZIP to restore now
  7. Backup ZIP path (if you answered yes)

JWT_SECRET is auto-generated by the script.

2.3 Docker Type: Compose vs Swarm

Docker Compose (1)

Use this for single-server deployments.

Script behavior:

  • Writes deploy/.env
  • Runs:
    • docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d --build
  • Applies all SQL files in apps/api/drizzle/*.sql in order
  • If backup ZIP provided:
    • Restores database.sql
    • Restores uploads/ contents

Docker Swarm (2)

Use this when you want autoscaling of API/Web.

Script behavior:

  • Builds required images:
    • openweb-api:latest
    • openweb-web:latest
    • openweb-autoscaler:latest
  • Initializes swarm if needed (docker swarm init)
  • Deploys stack from deploy/docker-stack.yml
  • Applies all SQL migrations
  • If backup ZIP provided:
    • Restores database.sql
    • Restores uploads/

Autoscaling runs only in Swarm mode.

2.4 After Script Completes

The script prints URLs:

  • App entry: http://localhost
  • First-time setup: http://localhost/setup
  • Admin: http://localhost/admin

If this is a fresh install:

  1. Open /setup
  2. Create initial admin user
  3. Login and configure site

2.5 Backup During Setup

If you choose to restore a backup ZIP during setup, the ZIP must contain at least:

  • database.sql
  • optional uploads/ directory

Restore behavior:

  • Drops and recreates public schema
  • Imports database.sql
  • Replaces uploads content if provided

2.6 Production Operations

Compose operations

# status
docker compose -f deploy/docker-compose.yml --env-file deploy/.env ps

# logs
docker compose -f deploy/docker-compose.yml --env-file deploy/.env logs -f

# stop
docker compose -f deploy/docker-compose.yml --env-file deploy/.env down

# scale manually
docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d --scale api=3 --scale web=3

Swarm operations

# list services
docker stack services openweb

# service logs
docker service logs -f openweb_api
docker service logs -f openweb_web
docker service logs -f openweb_autoscaler

# manual scale override
docker service scale openweb_api=4
docker service scale openweb_web=4

# remove stack
docker stack rm openweb

If you selected a different stack name in setup, replace openweb accordingly.

2.7 Admin Panel Backup Management

In admin: System -> Backups

  • Create ZIP backup
  • Download backup ZIP
  • Restore by uploading ZIP

2.8 SSO (Google, Microsoft, Custom OIDC/LDAP via IdP)

OpenWeb supports:

  • local email/password login
  • Google OAuth login
  • Microsoft Entra ID (Azure AD) login
  • custom OIDC IdP login (Okta/Auth0/Keycloak/etc.)

The login page automatically shows only SSO providers that are configured.

First time? Run setup is only shown when /api/setup/needed returns needed: true.

2.8.1 How SSO works in OpenWeb

  1. User opens login page.
  2. Web app calls GET /api/auth/sso/providers.
  3. User clicks Sign in with <provider>.
  4. Browser is redirected to /api/auth/sso/:provider/start.
  5. API sends user to provider authorization URL.
  6. Provider redirects back to /api/auth/sso/:provider/callback.
  7. API exchanges code for tokens, fetches profile, upserts the user, issues OpenWeb JWT.
  8. Callback writes openweb_token and openweb_user to localStorage and redirects to /admin (or requested redirect path).

Notes on account mapping:

  • Existing email: account is linked to that SSO provider.
  • New email: a new user is created.
  • First user ever created via SSO becomes admin; next users default to subscriber.

2.8.2 Required API environment variables

Set these in your API env:

  • Production Docker: deploy/.env (used by setup-deploy.sh)
  • Dev run: apps/api/.env

Common:

  • JWT_SECRET (already auto-generated in setup-deploy.sh for production)

Google:

  • SSO_GOOGLE_CLIENT_ID
  • SSO_GOOGLE_CLIENT_SECRET

Microsoft:

  • SSO_MICROSOFT_CLIENT_ID
  • SSO_MICROSOFT_CLIENT_SECRET
  • SSO_MICROSOFT_TENANT_ID (optional, defaults to common)

Custom OIDC:

  • SSO_OIDC_LABEL (button label, default SSO)
  • SSO_OIDC_CLIENT_ID
  • SSO_OIDC_CLIENT_SECRET
  • SSO_OIDC_AUTH_URL
  • SSO_OIDC_TOKEN_URL
  • SSO_OIDC_USERINFO_URL
  • SSO_OIDC_SCOPES (default openid profile email)

2.8.3 Redirect URI / callback URL configuration

You must register these callback URLs in each provider app:

  • Google callback:
    • https://YOUR_DOMAIN/api/auth/sso/google/callback
  • Microsoft callback:
    • https://YOUR_DOMAIN/api/auth/sso/microsoft/callback
  • OIDC callback:
    • https://YOUR_DOMAIN/api/auth/sso/oidc/callback

For local development (Vite + API):

  • http://localhost:3000/api/auth/sso/google/callback
  • http://localhost:3000/api/auth/sso/microsoft/callback
  • http://localhost:3000/api/auth/sso/oidc/callback

Important:

  • Callback host/protocol must match the real public URL seen by users/proxy.
  • If using reverse proxy/TLS termination, ensure forwarded host/proto headers are correct.

2.8.4 Google setup

  1. Create OAuth credentials in Google Cloud Console.
  2. Add authorized redirect URI:
    • https://YOUR_DOMAIN/api/auth/sso/google/callback
  3. Add credentials to env:
    • SSO_GOOGLE_CLIENT_ID
    • SSO_GOOGLE_CLIENT_SECRET
  4. Restart API service.
  5. Verify login page shows Sign in with Google.

2.8.5 Microsoft setup (Entra ID / Azure AD)

  1. Register app in Microsoft Entra admin center.
  2. Add redirect URI:
    • https://YOUR_DOMAIN/api/auth/sso/microsoft/callback
  3. Create client secret.
  4. Set env:
    • SSO_MICROSOFT_CLIENT_ID
    • SSO_MICROSOFT_CLIENT_SECRET
    • SSO_MICROSOFT_TENANT_ID (optional; keep common for multi-tenant)
  5. Restart API service.
  6. Verify login page shows Sign in with Microsoft.

2.8.6 Custom OIDC / LDAP IdP setup

If your organization uses LDAP, expose it via an IdP that supports OIDC (for example Keycloak, Authentik, Okta, Auth0, etc.). OpenWeb integrates via OIDC endpoints.

  1. In your IdP, create an OIDC client.
  2. Configure callback:
    • https://YOUR_DOMAIN/api/auth/sso/oidc/callback
  3. Ensure email and subject (sub) claims are returned by userinfo.
  4. Set env:
    • SSO_OIDC_LABEL=Your Company SSO
    • SSO_OIDC_CLIENT_ID
    • SSO_OIDC_CLIENT_SECRET
    • SSO_OIDC_AUTH_URL
    • SSO_OIDC_TOKEN_URL
    • SSO_OIDC_USERINFO_URL
    • SSO_OIDC_SCOPES=openid profile email
  5. Restart API service.
  6. Verify login page shows your custom button label.

2.8.7 Security and operations guidance

  • Always use HTTPS in production.
  • Use strong, rotated client secrets.
  • Keep JWT_SECRET long and random.
  • Restrict who can create users in external IdP if needed (group policy/tenant policy).
  • Back up database regularly; SSO user links are stored in users table.

2.8.8 Troubleshooting

  • SSO button not visible:
    • missing or empty SSO env vars
    • API not restarted after env update
  • Provider says redirect URI mismatch:
    • callback URL in provider does not exactly match OpenWeb callback
  • Login returns 400 Provider did not return required account data:
    • provider userinfo is missing email or sub
  • Login returns 502 token/userinfo errors:
    • invalid client secret/ID, wrong token URL/userinfo URL, or provider-side issue
  • User can’t access admin:
    • role is subscriber; promote user role in admin/users data

3) Developer Run (Local Development)

Use this mode when coding locally with hot reload.

3.1 Prerequisites

  • Node.js 22+
  • npm 10+
  • Postgres running locally (or remote instance)

3.2 Install Dependencies

From repository root:

npm install

3.3 API Environment

Create API env file:

cp apps/api/.env.example apps/api/.env

Edit apps/api/.env and set:

  • PORT (default 3000)
  • DATABASE_URL
  • JWT_SECRET
  • Optional SSO vars (SSO_GOOGLE_*, SSO_MICROSOFT_*, SSO_OIDC_*)

Example:

PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/openweb
JWT_SECRET=dev-secret-change-me

3.4 Run Database Migrations

From repo root:

npm run db:migrate

When schema changes are introduced:

npm run db:generate
npm run db:migrate

3.5 Start Developer Servers

Run API and web in separate terminals:

npm run dev:api
npm run dev:web

Defaults:

  • API: http://localhost:3000
  • Web: http://localhost:5173

Vite proxies /api, /uploads, /health, /robots.txt, and /sitemap.xml to API.

3.6 Dev URLs

  • Public: http://localhost:5173
  • Admin: http://localhost:5173/admin
  • Setup: http://localhost:5173/setup

3.7 Build Checks

Before committing/deploying:

npm run build:api
npm run build:web

Plugins

Detailed plugin documentation is available in PLUGINS.md.

  • Template ZIP: hello-world-plugin-template.zip
  • Template source: templates/plugins/hello-world/
  • Recommended: test plugins locally from your GitHub clone before production install.

4) Useful Commands

From root:

# dev
npm run dev:api
npm run dev:web

# build
npm run build:api
npm run build:web

# db
npm run db:generate
npm run db:migrate

5) Notes

  • Persistent Docker volumes include database, uploads, and backups.
  • Never commit secrets (deploy/.env, apps/api/.env).

For low-level deployment internals, see deploy/README.md.

About

OpenWeb tries to be a lightweight CMS written in NodeJS and TypeScript.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages