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.
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.
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 đ
user
directory to something like user_backup
$ cd my-fancy-site
$ mv user user_backup
user
$ git clone git@github.com:my-account/my-user-directory-repo.git user
user_backup
into the newly created directory/repo$ cd user_backup
$ cp -R * ../user/.
.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.$ 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.
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.
bin/grav install
). It is done into the user
directory and we need to prepare it first.user
directoryuser
data repository. Remember that has to be named user
$ git clone git@github.com:my-account/my-user-directory-repo.git user
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.bin/grav install
)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)
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)
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.
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
www-data
user)$ chown www-data:www-data git-pull.sh
$ chmod 755 git-pull.sh
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!