Skip to content

Instantly share code, notes, and snippets.

@woudsma
Last active May 15, 2021 17:32
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save woudsma/df9cab0e53cf70aa31ca5b9d12fcc063 to your computer and use it in GitHub Desktop.
Save woudsma/df9cab0e53cf70aa31ca5b9d12fcc063 to your computer and use it in GitHub Desktop.
Dokku + Kirby + AutoGit

TL;DR

  • Configure Kirby for Dokku
  • Install deployment-keys and host keys Dokku plugins
  • Set up staging and production environments
  • Clone project repository into apps persistent storage folders
  • Mount desired folders including .git folder to apps
  • Add GIT_DIR and GIT_WORK_TREE environment variables to containers
  • Deploy to Dokku

Configure Kirby for Dokku

Using Kirby CLI.

# Install Kirby and AutoGit
kirby install --kit plainkit
mv kirby my-project && cd my-project
kirby plugin:install pedroborges/kirby-autogit
# Set up AutoGit in site/config/config.php
# Make sure "autogit.webhook.secret" is not set to false, create a random secret

# Bootstrap Kirby for Dokku
curl -s https://www.gitignore.io/api/node%2Csass%2Cmacos%2Clinux%2Ckirby2%2Cwindows > .gitignore
echo 'https://github.com/heroku/heroku-buildpack-php' > .buildpacks
echo 'web: vendor/bin/heroku-php-apache2 -i custom_php.ini' > Procfile
echo -e 'extension=mbstring.so \nmemory_limit=512M \ncgi.fix_pathinfo = 0;' >> custom_php.ini
echo '{"keywords":["php","kirby"]}' > app.json
echo '{}' > composer.json

Modify .htaccess to:

<IfModule mod_rewrite.c>

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)\.([0-9a-z]{32})\.(js|css)$ $1.$3 [L]

# block text files in the content folder from being accessed directly
RewriteRule ^content/(.*)\.(txt|md|mdown)$ index.php [L]

# block all files in the site folder from being accessed directly
RewriteRule ^site/(.*) index.php [L]

# block all files in the kirby folder from being accessed directly
RewriteRule ^kirby/(.*) index.php [L]

# make panel links work
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^panel/(.*) panel/index.php [L]

# make site links work
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php [L]

</IfModule>
# Set up Git
git init
git remote add origin git@gitlab.com:username/my-project.git

# Push to project repository
git add .
git commit -m 'initial'
git push origin master

Create apps

SSH into the server as root.

dokku apps:create my-app-staging
dokku apps:create my-app-production

Install the SSH Deployment Keys and HostKeys plugins for Dokku

Dokku SSH Deployment Keys Plugin
Install the deployment-keys plugin and copy/add the resulting public key to your GitHub/GitLab repository deployment keys (enable write access). The plugin will inject the deployment key in every new app container.

dokku plugin:install https://github.com/cedricziel/dokku-deployment-keys.git deployment-keys

# Show app deployment key
dokku deploymentkeys:show app-name

Dokku HostKeys Plugin
Install the host keys plugin and add your VCS provider - such as GitLab - to your shared host keys. The plugin will inject the host keys to ~/.ssh/known_hosts in new app containers.

dokku plugin:install https://github.com/cedricziel/dokku-hostkeys-plugin.git hostkeys-keys

# Add VCS provider to shared hostkeys
dokku hostkeys:shared:autoadd gitlab.com

Create persistent storage folders

mkdir -p /var/lib/dokku/data/storage/{my-app-staging,my-app-production}

Clone project git repo into app persistent storage folders

# Make sure you can clone the repository with the generated deployment key as root user
export GIT_SSH_COMMAND="ssh -i ~dokku/.deployment-keys/shared/.ssh/id_rsa -F /dev/null"

git clone git@gitlab.com:username/my-project.git /var/lib/dokku/data/storage/my-app-staging
git clone git@gitlab.com:username/my-project.git /var/lib/dokku/data/storage/my-app-production

chown -R 32767:32767 /var/lib/dokku/data/storage/my-app-staging
chown -R 32767:32767 /var/lib/dokku/data/storage/my-app-production

Mount persistent storage folders to apps

Include .git folder to enable AutoGit to commit from inside the container using the injected deployment/host keys.

dokku storage:mount my-app-staging /var/lib/dokku/data/storage/my-app-staging/.git:/app/.git
dokku storage:mount my-app-staging /var/lib/dokku/data/storage/my-app-staging/content:/app/content
dokku storage:mount my-app-staging /var/lib/dokku/data/storage/my-app-staging/site/accounts:/app/site/accounts

dokku storage:mount my-app-production /var/lib/dokku/data/storage/my-app-production/.git:/app/.git
dokku storage:mount my-app-production /var/lib/dokku/data/storage/my-app-production/content:/app/content
dokku storage:mount my-app-production /var/lib/dokku/data/storage/my-app-production/site/accounts:/app/site/accounts

Set git environment variables

Doesn't work with dokku config:set unfortunately.

dokku docker-options:add my-app-staging deploy "-e GIT_DIR=/app/.git -e GIT_WORK_TREE=/app"
dokku docker-options:add my-app-production deploy "-e GIT_DIR=/app/.git -e GIT_WORK_TREE=/app"

Exit server.

If your app container git version is <2.7 (it probably is)

Find file site/plugins/autogit/lib/autogit.php
In function hasRemote, replace:

$this->execute("remote get-url '{$remoteName}'");

With

$this->execute("config --get remote.origin.url");

Deploy app

On initial app deploy add to site/config/config.php:

c::set('panel.install', true);

Add staging/production remotes and deploy!

git remote add staging dokku@dokku.me:my-app-staging
git remote add production dokku@dokku.me:my-app-production

git add .
git commit -m 'initial deploy'
git push staging master
git push production master

# After this, you - should - not have to deploy to Dokku when changing files locally
# Make sure to "git pull" first when there have been content commits/changes
# Just push to origin and press 'Get latest changes' in the Kirby CMS panel
# Setup the correct branch when working with staging/production environments

# It is possible for AutoGit to get out of sync with the project repository
# In this case, backup your persistent folder somewhere and delete persistent storage folder
# Clone repository into app persistent storage folder again
# Set permissions again
# Rebuild the app using "dokku ps:rebuild app-name"

Versions on time of writing:

  • Dokku: v0.9.4
  • Kirby: v2.4.1
  • AutoGit: v0.5.0

Setting up HTTPS domains on staging/production apps

SSH into the server as root.

# Install Let's Encrypt plugin
sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

# Add domain to apps
dokku domains:add my-app-staging staging.my.domain
dokku domains:add my-app-production my.domain www.my.domain

# Enable SSL (make sure both apps are deployed)
dokku config:set my-app-staging --no-restart DOKKU_LETSENCRYPT_EMAIL=your@email.com
dokku config:set my-app-production --no-restart DOKKU_LETSENCRYPT_EMAIL=your@email.com
dokku letsencrypt my-app-staging
dokku letsencrypt my-app-production

# Auto-renew certificates
dokku letsencrypt:cron-job --add
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment