Quick Deploy Solution
1135 words, ~ 6 min reading time
Quick Deploy - a possibly hacky way to deploy a Git repository without much overload and fast setup.
From time to time I work on some TYPO3 Site Packages (mostly design work) where seeing the changes is quite important to me. Since TYPO3 needs a web server and a Database server running (well yes, it can be set up locally, but I had some database errors last time I tried). I prefer running it on a virtual private server (VPS) over trashing my computer. So I need to somehow deliver locally made changes to this development server.
In the past I had different approaches for solving this problem. Once I think I had a quite similar (but more dirty) approach for this problem (I don’t remember exactly what it was since this was some time ago). The last few times I had a script running locally which mirrored the changes using rsync to the development server. If your interested you can find it in the uulm_hackathon Site Package repository.
For now and future projects (not necessary limited to TYPO3) I wanted another solution which works with the git repository. A few words about my setup: I have a Gitea server (a simple but powerful self-hosted Git server) running on one server and a TYPO3 Development instance running on another one. But this solution should also work on just a bare Git repository and separate server also are not necessary.
The basic idea
The basic idea is that we have some kind of a Git server (GitLab, Gitea, Phabricator, Gitolite, just a bare Git repo on a server) on the one hand which is capable of setting a post-receive Git hook. On the other hand we have a web server with PHP capabilities, e.g. for developing a TYPO3 Site Package in my case. On the web server we have a PHP script (see below) running which gets called by the post-receive Git hook. If the script gets called, it pulls the latest changes from out Git server.
OK, so what I want is some kind of continuous delivering tool. Of course there are already many different solutions available that perfectly fit my purpose. But after some search what I did not find was a tool that is quick and easy to setup. Most of them require docker, which I don’t want to setup for various reasons. I simply want something that can be setup and working in a few minutes.
Technical details and setup
As already mentioned in the above section, we have a Git repository or server where we can define a Git post-receive hook and a web server with PHP capabilities. On the Git server / repository we define the post-receive Git hook like in following example.
#!/bin/bash curl https://dev.your-server.rocks/quick-deploy.php?secret=YOUR-SECRET
As you can see it is just a one line bash script which executes
curl running a GET request to the given URL. The URL is your domain name (of course) and the
quick-deploy.php script as path. We also give the script a
secret parameter. The secret (in the example
YOUR-SECRET) should only be known to you, the Git hook and the development server. You can create such a secret for example with
openssl rand -base64 42. This is all we need to do in our Git repository / server.
On the development server we now need to setup the
quick-deploy.php script. The source code for the script with a README and short setup instructions is available in my corresponding “scripts” GitLab repository. We download the script and the example config file on our server and move it to the correct location. Finally we need to adjust the configuration. For that we rename the example config
config.json and adjust the values. If not otherwise noted, the variables are required.
remote-path: The path or URL where the Git repository is hosted. You have to make sure, that the development server with the user running the script can access the repository. Gitea for example offers to add a “deploy key” which can pull but not push to the repository. The script currently offers no option to define which SSH key it should use.
branch: This is the only optional variable. With it you can choose with branch the script should track. If it is not set, it will default to
local-path: The path where the script can find the local repository on the development server. Make sure that this directory (and if a initial
git cloneshould work also the parent directory) is writable by the user which the script runs (presumably
secret: This is the secret that we created and set earlier in the post-receive Git hook.
Since we enter the secret as plain text in the configuration we have to make sure, that the configuration file is not accessible from outside the server. So we set the correct permission. A
chmod 600 config.example should do the job, but make sure that the script is now owned by the user running the config script. You can check if the permissions are correct by trying to access
https://dev.your-server.rocks/config.json. This is of course no high-end security, but it should be sufficient. An attacker knowing the secret key cannot gain any sensible information but just trigger a pull.
That is it. Now the system should work as intended.
Writing the script was for me a one-day-task (it would have been much faster, but I didn’t write and PHP code in the last time). So there is still much room for improvement. If I find the time, I may improve the script.
For me the most wanted feature is a ability to define in the configuration which SSH key should be used. This could be quite particularly interesting if you have a specific key just for one repository and/or multiple repositories you want to track.
The tracking of multiple repositories cloud be another very interesting feature. So the configuration could contain multiple blocks (one for each repository) with the values as described above. Then the pull for a specific repository cloud be triggered with another URL parameter.
It cloud also be possible to write an administration frontend for managing the configuration file over the web, but this is not planned because of its complexity.
Nevertheless how much features will be added in the future, the main goal is, to keep a simple and quick setup. This includes that this script will always be in one file and will not require any software that can not be easily installed (this is the reason, why I use JSON and not YAML).
If you are interested in the project and would like to contribute, feel free to do so. I appreciate any help. Bug reports and code contributions are both very welcome.