Just a week ago my head started again bumping with the idea of building myself a blog. Again. After so much time. I had some hard requirements, basically one: has to be a file based CMS, as I really want to move away from DBs. Long story short, I found Grav, I did some research around it, and got impressed by the features that they announce and... (dramatic pause) it's done in PHP + Twig + Markdown. I can't believe it, 2022 and something like this still exists? I have to play a bit with it.

A week after, what I expected to be a prototype of a blog system to easily place some posts became a migration from my personal site, already done, and actually having fun again with the most pure meaning of web development: place a section here, adjust the template, fight with the CSS. Lot.Of.Fun.

But here is the thing: it's file based, so it should be easy to have all the user data somewhere (let's say Git) so that I can spawn a dev and prod environment and anyhow share the data. Yes, not only can be done, it is actually designed to do so. Just take a look at their docs, here the idea is well explained.

Workflow: centralizing the user data in Git

So that's the key point, having a Git repository to pull from / push to the changes. All user data is centred in a user main directory, so the only thing we need to do is to have a Git repository that actually contains this directory.

1. Create your repository and make use of it in your local environment

Getting a git provider is out of the scope of this post. I will assume Github as the Git provider but keep in mind you have plenty of other options. Also, I assume you have some development background, so the steps here below will be a bit high level, not entering into setting up SSH keys, authentication and so on. Sorry for that 🙃

  1. Go to Github and create your own repository. I recommend that you keep it private 😉
  2. Go to your Grav instance directory and rename your user directory to something like user_backup
$ cd my-fancy-site
$ mv user user_backup
  1. Git clone your repository in your Grav instance directory making sure you call it user
$ git clone git@github.com:my-account/my-user-directory-repo.git user
  1. Copy the content of your user_backup into the newly created directory/repo
$ cd user_backup
$ cp -R * ../user/.
  1. Don't forget to add a basic .gitignore that avoids you the pain of having to handle git submodules. Below I will elaborate this a bit more. You can find a working example here in the grav docs.
  2. Now it's time to save your initial data
$ cd ../user
$ git add .
$ git commit -m "Initial commit"
$ git push

At this point you should end up with a local site that contains a git repository in the user directory that actually delivers the content to a remote server.

ℹī¸ In the point 5 above we added a .gitignore file that actually bans everything in the user directory but the pages and the config. This is because plugins and themes are git repositories themselves most of the times. I agree on not managing them, but it means that whenever you create another environment, you'll have to basically install everything from scratch, only the content is just pulled. As a tip, I pulled one of the templates and customized it enough to also wanting it to be included, so I removed the .git internal folder of the template and added an exception for it in the .gitignore file.

2. Create a production environment and pull the data

So now the magic: I want that my site is actually deployed in a public server. Again, I'm not going to enter into setting up a domain (check Directnic), a host (check DigitalOcean), the Apache site and the PHP support. I assume you have shell access to the host and the SSH keys set up between it and your Github account.

  1. Install a new Grav instance. Just follow their docs as you did locally. ⚠ī¸ Just don't do yet the plugin and dependencies installation (the bin/grav install). It is done into the user directory and we need to prepare it first.
  2. Remove completely the user directory
  3. Git clone your user data repository. Remember that has to be named user
$ git clone git@github.com:my-account/my-user-directory-repo.git user
  1. Ensure that you have the right permissions in the user directory. Won't be unusual that you run all of this in root (bad!) or in any other user, and the apache user (www-data) is not able to behave with the files there.
  2. And now just finish the Grav installation (the plugin and dependencies by the bin/grav install)
  3. Finally, install all plugins and templates that you have in the local instance.

At this point, you should end up with 2 environments: a development and a production environment, sharing a user folder that contains your content and your configuration (and in my case also the template, as I explained above)

3. Auto-synchronization dev -> prod

So here is the catch: you have 2 environments that share the content (and the config, and the template for me), but I still have to log in to the shell to push and pull the changes!

Yes, you have to do that. You're a developer, so you work in local where you can test everything you want, use branches in git, merge and/or discard your changes. You still have to access to your shell and work as usual. The pain comes by having to log into production shell every time you want to pull the changes. To avoid that you can take several routes. I studied some of them: you have the GitHub actions, also a GitSync plugin that looks promising, and some other options like custom deployment scripts. There is a guy that explored kinda all of them and got quite frustrated. Just check his adventure in his own page.

I just come with a less fancy and easier approach: schedule git pull.

Before that, just let me introduce the workflow I intend to use (Sorry Louis, I re-use your graph here from your post) diagram

So I mainly want to work locally, do all my changes and my posts in my own computer, test them, see that everything works, not only the templating but also the content, the blog posts, everything. And when I am happy, I push the changes or merge the branches, whatever, but by then the user folder repository will receive the changes in the main branch. I only need a way to automatically perform a git pull from the server side.

Grav, at least in the version I am using, has a Tool called Scheduler. It is nothing more than a handler inserted in the crontab of the Apache user, allowing the site to register jobs to be run periodically. Then, just connecting the dots, I only need to create a shell script that performs the git pull and register the job in the Scheduler.

  1. Create a file called git-pull.sh in your user directory and place the following content there (yeah, update it accordingly):
#! /bin/bash

cd /var/www/my-fancy-site/user
git pull
  1. Give the ownership and execution rights accordingly (in my case Apache runs under the www-data user)
$ chown www-data:www-data git-pull.sh
$ chmod 755 git-pull.sh
  1. Register a job into the Scheduler (I assume here that you set up the Scheduler in your system already). Here a screenshot from my Admin plugin: Screenshot%202022-11-08%20at%2008.54.25

At this point, you should now have an architecture that every 30 minutes your production environment tries to pull changes from the repository. So simply push the changes to the main branch (or merge your Pull Request) and they will appear in your public site.

I must say that this solution has been working for me pretty good until now. I am able to have a branch with new sections I am working on, while composing new posts, and I decide what and when gets merged and therefor delivered to production. I guess that I can even make it a bit more sophisticated having a specific branch called published and actually behave like Git Flow. From here on, that's up to you 😉

Salut!

Previous Post Next Post