Deployment
OwnDocs ships as source code you own, so deploying starts with your copy of it rather than with someone else's repository. Push that copy to a Git repository you control, then point a host at it. By the end you'll have a live documentation site answering on a public URL, or on port 3000 of your own host.
Prerequisites
- Your copy of the OwnDocs source, and a Git repository you control to push it to. A private repository is fine, and is the usual choice.
- Node.js 20.9.0 or newer and npm 10 or newer, for a manual build. Node.js 24 is the tested version.
- Docker with the Compose plugin, for the self-hosted container path
- Values ready for the environment variables listed below; run
bash scripts/setup-env.shto generate the secret ones
Steps
Put the source in your own repository
OwnDocs is a commercial product, and the repository it ships from is private. A hosting platform cannot clone that repository on your behalf, so a deploy button pointing at it would fail every time. That is why there isn't one. What you deploy is your own copy of the source.
Create an empty repository on GitHub, GitLab, or Bitbucket, then push the source you received into it:
git init
git add .
git commit -m "Initial OwnDocs site"
git remote add origin git@github.com:your-org/your-docs.git
git push -u origin mainKeep that repository private. The host you connect it to authenticates as you, so it can read a private repository of your own without the source becoming public.
Everything below assumes your repository exists and holds the source.
Vercel
Vercel is Next.js's native host. In the Vercel dashboard choose Add New →
Project, pick your repository, and let it import. The bundled vercel.json
sets the framework to nextjs and the build command to npm run build, so
there is nothing else to configure.
Add the environment variables under Project → Settings → Environment
Variables before the first build, then deploy. The finished site answers on a
.vercel.app URL until you attach your own domain.
Netlify
Netlify runs Next.js through the OpenNext adapter, which it installs during the
build. Choose Add new site → Import an existing project, pick your
repository, and Netlify reads the build command from the bundled netlify.toml.
Set the environment variables under Site configuration → Environment
variables. The finished site answers on a .netlify.app URL.
Render
Render reads the bundled render.yaml, which defines the whole service, so use
the Blueprint flow rather than creating a web service by hand. Choose New →
Blueprint, pick your repository, and Render creates the service from that
file.
The blueprint does more of the work than the other two. It pins Node.js 24, runs
npm ci && npm run build, starts with npm start, and generates
APP_PASSWORD, JWT_SECRET, and COOKIE_SALT for you, so you never type those
three. It ships with ACCESS_MODE set to public and THEME_VARIANT set to
violet; change either in the blueprint or in the dashboard before you go live.
The finished site answers on an .onrender.com URL.
Environment Variables
All three platforms read the same variables. scripts/setup-env.sh generates
them for local development; for a cloud deploy, set them in the platform's
dashboard.
Five matter on a first deploy:
ACCESS_MODE:publicunless you set it toprivate. Anything other than the exact valueprivatekeeps the site open.APP_PASSWORD,JWT_SECRET, andCOOKIE_SALT: required whenever the site is private. Render generates all three from its blueprint.THEME_VARIANT: the color theme, defaulting toviolet.
Configuration documents every variable with its exact default, including the optional footer links and the site URL used for the sitemap and OpenGraph tags.
Manual Deployment
For any Node.js hosting provider, build and start OwnDocs with:
npm install
npm run build
npm startThe production server starts on port 3000 by default. Set environment variables
through your hosting provider's dashboard or a .env.local file before
building.
Docker Self-Host
OwnDocs ships a Dockerfile and a docker-compose.yml so you can run it as a
container on your own infrastructure. This is the recommended self-hosted path
when you want a single isolated service without installing a Node toolchain on
the host.
-
Prepare environment variables
The compose file reads secrets from
.env.local. Generate them first:BashBashbash scripts/setup-env.sh -
Build and start the container
BashBashdocker compose up --build -dIf you are on an older Docker installation, the legacy spelling works the same way:
BashBashdocker-compose up --build -d -
Open the site
The container publishes port 3000, so the site is at
http://localhost:3000. -
Stop the container
BashBashdocker compose down
The compose file maps 3000:3000, loads environment variables from
.env.local, and restarts the container automatically with
restart: unless-stopped. The Dockerfile builds a production image with a
non-root user and runs npm start on port 3000. The image copies the docs
content into the runtime, so on-demand revalidation and the MCP fetch_page
tool work inside the container. It also sets FEEDBACK_DIR=/app/data/feedback,
a writable directory owned by the non-root user where the daily feedback files
land. The compose file maps no volume, so votes are lost on rebuild or recreate:
mount a volume at /app/data/feedback to keep them. See
Configuration for the full environment
variable reference.
Result
Open the deployed URL. On Vercel it ends in .vercel.app, on Netlify
.netlify.app, on Render .onrender.com, and on a manual or Docker host it is
http://localhost:3000. You should land on the OwnDocs home page with the
sidebar, the theme toggle, and working search. Two checks confirm the deploy
took your configuration:
GET /api/healthreturns{"status":"pass"}.- With
ACCESS_MODEset toprivate, any page redirects you to/loginuntil you enterAPP_PASSWORD.
If either check fails, the environment variables didn't reach the running process. Re-check them against Configuration.