Deploy Grav

Self-hosted WordPress alternative that stores content as Markdown files

Deploy Grav

Just deployed

/data

Just deployed

/var/www/html

Deploy and Host Grav on Railway

Grav is a flat-file CMS: every page is a Markdown file with YAML front matter, every setting is a YAML file, and there is no database to migrate or back up. Themes are Twig templates, plugins hook into a Symfony-based event system, and the site is a directory you edit in the admin panel or your own editor. Teams reach for it when WordPress is more machinery than the job needs but a static site generator is too little — Grav renders on request, so an editor publishes without a build step.

Self-host Grav on Railway and you get the two things a flat-file CMS still needs from a platform: somewhere durable for the files and somewhere fast for the caches. Grav serves the site through Apache and PHP 8.4, with a persistent volume at /var/www/html — pages, media, configuration, accounts and installed plugins and themes are written there and survive redeploys. Redis backs Grav's page, Twig and Flex object caches. Grav holds the public domain; Redis stays private.

Diagram of the Grav and Redis services on Railway

Getting Started with Grav on Railway

Deploy the template, set a password for the administrator account, and open the generated URL. You land on the Quark 2 theme's home page with two sample pages published. Go to /admin and sign in with the credentials you supplied at deploy — the account is created inside the container before the web server accepts a request, so nobody can claim the administrator seat first. The username defaults to admin.

Then publish something. Choose Pages → Add Page, give it a title, pick the Default template, set it Published and press Continue. You get a Markdown editor with a formatting toolbar and a media drop zone; write a paragraph, press Save, then click View site and open it from the navigation. That round trip confirms the deployment: the page is now a .md file on the volume, rendering on the public URL.

Two things are worth checking on day one. The dashboard's System panel should read Cache: redis, confirming Grav reached the Redis service rather than falling back to file caching. And Tools → Backups zips the whole site on to the volume — the backup story for a CMS with no database.

Grav admin dashboard listing pages, plugins and the Redis cache

Editing the Release Notes page in Grav's Markdown editor

The published Release Notes page on the Grav site

About Hosting Grav

Grav's design decision is that the filesystem is the database. A page lives at user/pages/01.home/default.md; the folder name sets the URL and ordering, the front matter the metadata, the body is Markdown. Configuration is the same — user/config/system.yaml is plain YAML you can read, diff and commit. Copy the directory and you have copied the site, which is not true of a database-backed CMS.

Key features:

  • Markdown pages with a rich editor, media handling and image processing built in
  • Twig theming, so a designer can build a theme without touching PHP
  • A plugin and theme marketplace installable from the panel or the bin/gpm CLI
  • Multi-language content, taxonomy, forms and a scheduler for recurring jobs
  • A REST API and a modern admin panel (Admin 2) in the box

On Railway that becomes two services. Grav renders and owns the volume — not an optimisation here, it is the site, so removing it loses everything an editor publishes. Redis is the cache tier: Grav's file cache would otherwise sit on that same volume, so moving it keeps rendering off network storage.

Why Deploy Grav on Railway

Railway removes the parts of self-hosting Grav that are not about the CMS itself:

  • A persistent volume for the whole site, provisioned and mounted for you
  • Managed Redis on a private network, with no connection strings to copy
  • HTTPS and a public domain on first deploy; custom domains are a DNS record away
  • PHP 8.4, Apache and every extension Grav needs already in the image
  • Rebuilds from a public GitHub repo, so you can fork the stack

Common Use Cases

  • Documentation and handbooks — Markdown source, Git-friendly, no database
  • Agency and brochure sites — a designer builds a Twig theme, the client edits it
  • Developer blogs and changelogs — write a post as a file, publish with no rebuild

Dependencies for Grav

  • Grav — built from gridalpha/grav-railway on the official getgrav/grav image (PHP 8.4 + Apache). The release is baked in and copied on to the volume at first boot.
  • Redis — Railway's managed Redis, wired in as system.cache.driver: redis.

Environment Variables Reference

VariablePurpose
GRAV_ADMIN_USERAdministrator username: 3–16 lowercase letters, digits, -, _
GRAV_ADMIN_PASSWORDAdministrator password: 8+ characters with an uppercase letter, a lowercase letter and a digit
GRAV_ADMIN_EMAILAddress on the administrator account, used for password recovery
GRAV_SITE_TITLESite title written into user/config/site.yaml on first boot
GRAV_REDIS_HOSTRedis host; leave the reference in place to use the Redis service
GRAV_REDIS_PORTRedis port
GRAV_REDIS_PASSWORDRedis password
GRAV_REDIS_DATABASERedis database number, 0 by default
PORTPort Apache listens on

These settings apply only while the volume has no site on it. After that the config files are yours — the admin panel writes them — so changing the variables later is intentionally a no-op. Change the password in Users and the cache driver in Configuration → System.

Deployment Dependencies

Hardware Requirements for Self-Hosting Grav

ResourceMinimumRecommended
CPU0.5 vCPU1–2 vCPU
RAM512 MB1 GB
Storage5 GB volume5–20 GB, depending on media
RuntimePHP 8.3+ with gd, intl, zipPHP 8.4 with apcu, yaml, redis

Grav is light: a site with a few hundred pages runs comfortably in 512 MB. The storage figure is really about media, since uploaded images and their derivatives are the only things that grow without bound.

Self-Hosting Grav with Docker

The official image downloads Grav on first boot into whatever you mount at /var/www/html, so a named volume is all it needs:

docker run -d --name grav \
  -p 8080:80 \
  -v grav_site:/var/www/html \
  getgrav/grav:php8.4

Open http://localhost:8080/admin and create the first account through the setup screen. To build the image this template uses — Apache on $PORT, the release baked in, the administrator created before the port opens:

git clone https://github.com/gridalpha/grav-railway.git
cd grav-railway
docker build -t grav-railway .
docker run -d -p 8080:8080 -v grav_site:/var/www/html \
  -e PORT=8080 -e GRAV_ADMIN_PASSWORD='ChangeMe123' grav-railway

Without Docker, Grav is a PHP application you unzip: download grav-admin from getgrav.org, point a PHP 8.3+ web server at the directory with AllowOverride All so its .htaccess is honoured, and make user/, cache/, logs/ and images/ writable by the web server user.

Is Grav Free to Self-Host?

Grav is open source under the MIT licence, and that covers the admin panel, the REST API and the whole plugin and theme marketplace — no paid edition, no seat count, no feature gate. Trilby Media sells optional premium plugins (a forum, collaborative editing, revision history), but nothing in the core needs them. On Railway you pay only for the compute, volume and Redis you use.

FAQ

What is Grav?

An open-source flat-file CMS written in PHP. It stores pages as Markdown and configuration as YAML, with no database, and renders through Twig on request.

What does this Railway template deploy?

Two services: Grav on Apache with PHP 8.4, holding a persistent volume at /var/www/html, and Railway's managed Redis as the cache backend. Grav gets the public domain; Redis stays private.

Why does a database-free CMS need Redis?

It does not need one, but it benefits. Grav caches parsed pages, compiled Twig templates and Flex objects, and by default those land on the same volume as the content. Redis keeps rendering off network storage and lets you flush the cache without touching files.

How do I log in to Grav for the first time?

Go to /admin with the GRAV_ADMIN_USER and GRAV_ADMIN_PASSWORD values you set at deploy. The account is created before the web server starts, so the first-run setup screen is already closed when the site becomes reachable.

How do I install plugins and themes on a self-hosted Grav?

Use Plugins → Add or Themes → Add; packages install straight on to the volume and survive redeploys. bin/gpm install does the same from a shell.

How do I upgrade Grav after deploying?

Update from Tools → Updates — Grav updates itself in place on the volume, as on any host. Rebuilding the image never overwrites an existing site: the baked release only seeds an empty volume. A custom domain needs no config change either, since the site is not pinned to a hostname.


Template Content

More templates in this category

View Template
Libredesk - Complete Setup
Complete self-hosted omnichannel customer support desk.

codestorm
1
View Template
Paperless-ngx
Paperless-ngx — document management with OCR and full-text search

INAPP
1
View Template
Instatic CMS - Postgres
Design, build and manage powerful static sites from state-of-the-art CMS

Instatic
156