Skip to Content
Self-Hosting

Self-Hosting

MarkDocs runs on your own infrastructure. Docker Compose for quick setups, or deploy to Railway/Render/any Node.js host.

Docker Compose

The simplest way to deploy:

git clone https://github.com/thakurkharel/markdocs.git cd markdocs

Create a .env file:

POSTGRES_PASSWORD=a-strong-random-password JWT_SECRET=another-strong-random-secret PORT=3001

Start the services:

docker compose up -d

Railway

One-click deploy with a Postgres addon:

  1. Create a new project on Railway 
  2. Add a PostgreSQL service
  3. Add a new service from your GitHub repo (fork or import thakurkharel/markdocs)
  4. Set environment variables:
DATABASE_URL → (auto-linked from the Postgres service) DIRECT_URL → (same as DATABASE_URL) JWT_SECRET → a-strong-random-secret PORT → 3001
  1. Railway auto-detects the build. The included railway.toml runs migrations on deploy.

The repo includes a railway.toml that handles the start command:

[build] builder = "nixpacks" [deploy] startCommand = "npx prisma migrate deploy && npx tsx server.ts" healthcheckPath = "/" restartPolicyType = "on_failure"

Render

Similar to Railway:

  1. Create a new Web Service on Render 
  2. Connect your repo
  3. Set build command: npm install && npx prisma generate && npm run build
  4. Set start command: npx prisma migrate deploy && npx tsx server.ts
  5. Add a PostgreSQL database and link DATABASE_URL
  6. Add JWT_SECRET and PORT=3001 as environment variables

Fly.io

fly launch fly postgres create --name markdocs-db fly postgres attach markdocs-db fly secrets set JWT_SECRET=a-strong-random-secret fly deploy

Add to your fly.toml:

[processes] app = "npx prisma migrate deploy && npx tsx server.ts"

Reverse Proxy

If running on a VPS, put MarkDocs behind a reverse proxy for HTTPS.

Caddy (automatic HTTPS):

markdocs.yourdomain.com { reverse_proxy localhost:3001 }

nginx:

server { listen 443 ssl; server_name markdocs.yourdomain.com; location / { proxy_pass http://localhost:3001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

The Upgrade and Connection headers are required for WebSocket support (real-time collaboration).

Database Backups

The PostgreSQL data is stored in a Docker volume (pgdata). Back it up regularly:

# Dump the database docker exec markdocs-db-1 pg_dump -U markdocs markdocs > backup.sql # Restore from backup cat backup.sql | docker exec -i markdocs-db-1 psql -U markdocs markdocs

For Railway/Render, use the platform’s built-in backup features.

Updating

git pull docker compose build docker compose up -d

For Railway/Render, push to your repo and the platform auto-deploys. Migrations run automatically on startup.

Environment Variables

VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string
DIRECT_URLYesSame as DATABASE_URL (for Prisma)
JWT_SECRETYesSecret for signing auth tokens
PORTNoServer port (default: 3001)
POSTGRES_PASSWORDDocker onlyPassword for the Docker Postgres instance

Resource Requirements

MarkDocs is lightweight:

  • CPU: 1 core minimum
  • RAM: 512MB minimum (1GB recommended)
  • Disk: Depends on document volume, typically under 1GB
Last updated on