Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
2.6 KiB
Local Development Setup
This guide covers setting up the dev environment from scratch after cloning the repo.
First-time setup
user/plugins/ and user/data/ are excluded from git but Grav requires them to exist. Create them once:
mkdir -p user/plugins user/data
Then run:
make setup
make setup = build → start → install-plugins → fix-perms. This builds the Docker image (Grav 2.0 baked in), starts the container, installs all plugins from plugins.txt, and fixes file ownership.
The dev server runs at http://localhost:8081.
After any docker compose down
Always run make setup — not just make start — to ensure permissions are correct.
docker compose restart (soft restart) preserves the image and is fine for quick restarts. Only make setup is needed after docker compose down.
Fix 500 errors after plugin install
If the site returns a 500 error after plugin installation or after recreating the container:
make fix-perms
This creates uid 1000 in the container, chowns /var/www/html to 1000:1000, and reloads Apache.
Upgrading to a newer Grav RC
Grav 2.0 is baked into the custom Docker image via Dockerfile. The base getgrav/grav image ships 1.7 — the Dockerfile downloads the 2.0 RC bundle from GitHub and overwrites the core files at build time.
To upgrade:
- Update the bundle URL in
Dockerfile - Run
make setup— Docker rebuilds the image layer automatically
Required system.yaml settings (Grav 2.0)
After upgrading, verify these are set in user/config/system.yaml:
accounts:
type: flex # required for Admin2 API
pages:
type: flex # required for Admin2 pages API
Admin user API permissions
The admin user account needs api.* permissions for Admin2. In user/accounts/<username>.yaml:
access:
admin:
login: true
super: true
api:
super: true
access: true
Disable the old admin plugin
Both admin and admin2 route to /admin and conflict. After installing admin2, disable the old one:
In user/plugins/admin/admin.yaml:
enabled: false
JWT secret
Leave jwt_secret: '' in user/plugins/api/api.yaml. It works for local dev; production installs generate a secure secret automatically during make remote-install.
Language URL prefix
If Grav redirects to /en/... URLs, ensure user/config/system.yaml contains:
languages:
supported: [en]
include_default_lang: false
Without include_default_lang: false, Grav adds a language prefix to all URLs even for single-language sites.