Skip to content

Deploy Markdawn On A Fedora VPS

This guide documents the maintained deployment path for one Fedora VPS with Caddy, rootless Podman, and PostgreSQL.

Follow this guide when you want a documented first installation. It assumes you can manage DNS, open firewall ports, edit environment values, and use sudo on the server.

Prepare:

  • A Fedora 44 VPS with at least 4 GB of RAM.
  • A domain or subdomain pointing to the VPS IP address.
  • A deployment user with sudo access.
  • Google and GitHub OAuth applications if you want social login.

Open ports 80 and 443 so Caddy can receive web traffic and obtain a certificate.

Other Linux Distributions And Docker Compose

Section titled “Other Linux Distributions And Docker Compose”

The setup script targets Fedora and Podman. It is not a requirement imposed by the application.

An adapted deployment needs to provide:

  • PostgreSQL with persistent storage.
  • The Markdawn API.
  • The collaboration service with WebSocket support.
  • The built web application.
  • A reverse proxy for the public origin, API routes, and /collab WebSocket traffic.
  • The environment variables from .env.production.
  • Persistent storage for the database and uploads.
  • db:migrate before the application accepts traffic.

The included scripts do not manage every alternative environment. If you use Docker Compose or Ubuntu, adapt the service definitions and maintain the deployment yourself.

Run these commands on the documented Fedora server as a non-root user:

Terminal window
curl -fsSL https://raw.githubusercontent.com/atharva-again/Markdawn/master/deploy/setup.sh -o setup.sh
chmod +x setup.sh
./setup.sh

The script prompts you to edit .env, installs required tools, creates persistent storage, builds the services, applies database migrations, and starts the application.

The checked-in Caddy configuration currently uses markdawn.space as its site address. The setup script copies that file to /etc/caddy/Caddyfile; setting FRONTEND_URL does not change the Caddy hostname automatically. Custom domains therefore require a manual Caddyfile edit.

For a custom deployment, replace the first line of deploy/Caddyfile before running the setup script when using an existing checkout, or edit the installed file after setup:

Terminal window
sudoedit /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Replace markdawn.space with the domain that points to the VPS. Use the same domain in FRONTEND_URL, CORS_ORIGINS, VITE_API_URL, and the OAuth redirect URLs below. Caddy must be able to resolve the domain and reach ports 80 and 443 to obtain its certificate.

At minimum, review:

POSTGRES_USER
POSTGRES_PASSWORD
POSTGRES_DB
DATABASE_URL
BETTER_AUTH_SECRET
FRONTEND_URL
GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET
GITHUB_CLIENT_ID
GITHUB_CLIENT_SECRET
CORS_ORIGINS
NODE_ENV
PORT
COLLAB_PORT
VITE_API_URL

Use a secret of at least 32 characters for BETTER_AUTH_SECRET. Create a unique COLLAB_INTERNAL_SECRET of at least 32 characters. Do not reuse example passwords or commit .env.

Register these redirect URLs for your domain:

https://your-domain.example/api/auth/callback/google
https://your-domain.example/api/auth/callback/github

The URLs must match the provider configuration exactly.

Terminal window
curl https://your-domain.example/api/health

A healthy service returns a JSON response with status set to ok. Then open the domain and sign in.

After signing in, verify one page can be created and edited in the browser. If you use collaborative editing, open a second browser session and confirm that changes appear in both sessions.

Terminal window
journalctl --user -u markdawn-postgres.service --no-pager
journalctl --user -u markdawn-api.service --no-pager
journalctl --user -u markdawn-collab.service --no-pager

For later updates and migration safety, see Maintain a Self-Hosted Markdawn. To move the installation, see Move a Markdawn Deployment.