Grav Deployment & Maintenance — Going Live and Staying Safe
In this tutorial, you'll deploy your Grav site to production and set up a maintenance routine.
What You'll Learn
- How to deploy Grav to production servers
- Git-based deployment workflow
- Backup strategies for flat-file sites
- Updating Grav core, plugins, and themes
- Monitoring and troubleshooting production issues
Why It Matters
A local Grav site is just practice. A live site delivers value. But deploying a CMS means considering server requirements, security, backups, and updates. Grav's flat-file architecture makes deployment simpler than database-driven CMS platforms — but you still need a plan.
Real-World Use
DodaTech deploys Grav documentation sites using a Git workflow: git push to a private repository, a webhook triggers git pull on the production server, followed by bin/grav cache. No database migrations, no sync jobs, no downtime.
Hosting Options
Shared Hosting
Most shared hosting supports Grav with PHP 8.0+.
Requirements:
- PHP 8.0 or higher
- PHP extensions: curl, mbstring, xml, zip, json
- Apache with mod_rewrite (or Nginx)
Upload steps:
- Zip your Grav folder (excluding
user/data/cache/) - Upload via cPanel File Manager or FTP
- Unzip in the web root
- Set permissions:
chmod -R 755 user/ - Clear cache:
php bin/grav cache
VPS / Dedicated Server
Full control, best performance.
Nginx config:
server {
listen 80;
server_name example.com;
root /var/www/grav;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\. {
deny all;
}
location ~ \.(yaml|twig|md)$ {
deny all;
}
}
Cloud Platform
Platforms like DigitalOcean App Platform, Railway, or Render can run Grav:
- Push your Grav site to a Git repository
- Set the build command:
composer install --no-dev - Set the start command:
cp -r user /app/ && php -S 0.0.0.0:8080 index.php - Set environment variable:
GRAV_ENV=production
Git-Based Deployment
The most common workflow for Grav teams.
Step 1: Initialize Git
cd grav-site
git init
git add .
git commit -m "Initial Grav site"
Step 2: Add .gitignore
user/data/cache/*
user/data/logs/*
user/data/sessions/*
vendor/
.env
This excludes cache and vendor files — they're regenerated on the server.
Step 3: Set Up a Remote
git remote add origin https://github.com/yourorg/grav-site.git
git push -u origin main
Step 4: Deploy on the Server
# On the production server
git clone https://github.com/yourorg/grav-site.git
cd grav-site
composer install --no-dev
bin/grav cache --all
Step 5: Automate with a Webhook
For automatic deployment on push, create a deploy script:
#!/bin/bash
# /var/www/deploy.sh
cd /var/www/grav
git pull origin main
composer install --no-dev
bin/grav cache --all
Then set up a webhook that triggers this script when you push to the repository.
Backup Strategies
Grav's flat-file structure makes backups simple.
Full Backup (Files Only)
# Backup everything except cache and vendor
tar -czf grav-backup-$(date +%Y-%m-%d).tar.gz \
--exclude="user/data/cache" \
--exclude="vendor" \
grav-site/
Incremental Backup with Git
git add .
git commit -m "Backup $(date +%Y-%m-%d)"
git push
Your entire site (content, config, themes) is backed up with full version history.
Selective Backups
| What | Where | Backup Command |
|---|---|---|
| Content | user/pages/ |
tar -czf pages-backup.tar.gz user/pages/ |
| Configuration | user/config/ |
tar -czf config-backup.tar.gz user/config/ |
| Themes | user/themes/ |
tar -czf themes-backup.tar.gz user/themes/ |
| Plugins | user/plugins/ |
tar -czf plugins-backup.tar.gz user/plugins/ |
Restore from Backup
# Restore full site
tar -xzf grav-backup-2026-06-27.tar.gz
cd grav-site
composer install --no-dev
bin/grav cache --all
Updating Grav
Check for Updates
bin/gpm version
Update Core
bin/grav selfupgrade
Update All Plugins and Themes
bin/gpm update
Safe Update Process
# 1. Backup
tar -czf pre-update-backup.tar.gz user/
# 2. Update
bin/grav selfupgrade
bin/gpm update
# 3. Clear cache
bin/grav cache --all
# 4. Verify
curl -I http://yoursite.com
Always test updates on a local copy first. Grav is stable, but plugin compatibility issues can occur. The Admin plugin and Login plugin versions must match the Grav core version.
Maintenance Routine
Daily
# Check error logs
tail -f user/data/logs/grav.log
# Monitor disk usage
du -sh user/data/cache/
Weekly
# Git commit and push
git add user/pages/ user/config/
git commit -m "Weekly backup $(date +%Y-%m-%d)"
git push
# Check for updates
bin/gpm version
Monthly
# Full backup
tar -czf monthly-backup-$(date +%Y-%m).tar.gz grav-site/
# Clear old cache
bin/grav cache --all
# Review security
bin/grav security
# Update dependencies
composer update --no-dev
Troubleshooting Production Issues
| Problem | Likely Cause | Fix |
|---|---|---|
| White screen | PHP error or permission issue | Check user/data/logs/grav.log, set permissions |
| 404 on pages | .htaccess or Nginx config missing | Ensure rewrite rules are configured |
| Admin login loops | Session directory not writable | chmod 755 user/data/sessions/ |
| Styles missing | Asset pipeline broken | Clear cache, disable pipeline temporarily |
| Slow page loads | Cache disabled in production | Enable Caching in system.yaml |
| Forms not emailing | SMTP credentials wrong | Check user/config/plugins/email.yaml |
Learning Path
flowchart LR A["What is Grav?"] --> B["Installation"] B --> C["Pages & Content"] C --> D["Navigation"] D --> E["Twig Templating"] E --> F["Themes"] F --> G["Taxonomy & Blog"] G --> H["Plugins & Admin"] H --> I["Configuration & Caching"] I --> J["Deployment & Maintenance
← You are here"]:::current classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px
What You Built
Over 10 lessons, you built a complete Grav documentation site:
| Lesson | What You Did |
|---|---|
| 1 | Learned the flat-file CMS concept |
| 2 | Installed Grav and explored the folder structure |
| 3 | Created pages with Markdown and frontmatter |
| 4 | Organized navigation and menus |
| 5 | Built Twig templates with inheritance |
| 6 | Customized themes with branding |
| 7 | Set up blog with taxonomy and tags |
| 8 | Extended with plugins and Admin panel |
| 9 | Optimized caching for production |
| 10 | Deployed to production and set up maintenance |
Practice Questions
What's the simplest way to back up a Grav site? Answer: Git.
git add . && git commit -m "backup" && git pushbacks up content, config, and themes with full version history.How do you deploy Grav to a production server? Answer: Clone the Git repo on the server, run
composer install --no-dev, clear cache. Alternatively, upload files via FTP.How do you update Grav core and plugins safely? Answer: Backup first, then run
bin/grav selfupgradeandbin/gpm update, then clear cache and verify.Why is Git-based deployment easier with Grav than WordPress? Answer: No database. Content is files that can be version-controlled, merged, and deployed like any codebase. WordPress requires database syncing between environments.
Challenge: Deploy your Grav site to a production server. Set up automated daily Git backups. Configure a weekly cron job for updates. Test a restore from your backup.
Final Words
You started with "what is a flat-file CMS" and ended with a fully deployed Grav site. Here's what makes Grav special in the CMS landscape:
- No database — Setup takes 2 minutes, backups are file copies
- Git-native — The entire site is version controllable
- Fast by default — File reads beat database queries
- Twig templates — Clean, secure, maintainable
- Developer-friendly — Edit in any text editor, deploy with git pull
Your Grav site is ready. Add more content, refine your theme, and keep learning. Every expert was once a beginner — and you're no longer a beginner.
Continue exploring other tutorials:
- Drupal CMS Guide — Enterprise content management
- Joomla CMS Guide — Social networks and portals
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro