Example configuration files

Examples of various configuration possibilities to help you get started. The source scripts are available too.

Projects configuration

This file includes the configration of which hooks are available.

 1example1:
 2  app_key: c202217f7bba73a73cce17794f79be6672d89450a3b7895d
 3  triggers:
 4    trigger1:
 5      trigger_key: c633c360800fb7e0126fd123ecaed1500c125d29625e5896
 6      repo: git@github.com:aquatix/webhaak.git
 7      command: sudo supervisorctl restart webhaak
 8    trigger2:
 9      trigger_key: 33b3506bc8496bdcd1b155756b7e9a01acc76f6e83e3c60f
10      repo: ...
11      command: bash /home/myuser/bin/update_all_the_things.sh
12
13aquariusoft.org:
14  app_key: c202217f7bba73a73cce17794f79be6672d89450a3b7895d
15  triggers:
16    trigger1:
17      trigger_key: c633c360800fb7e0126fd123ecaed1500c125d29625e5896
18      repo: git@github.com:aquatix/aquariusoft.org.git
19      command: update_aquariusoft.sh
20    trigger2:
21      trigger_key: 33b3506bc8496bdcd1b155756b7e9a01acc76f6e83e3c60f
22      repo: git@github.com:aquatix/paragoo.git
23      branch: develop
24      command: |
25          bash /home/myuser/bin/update_all_the_things.sh REPOVERSION
26    sentry:
27      trigger_key: 7c6bd635948eea920fc15df87400a45b056c9779f4305bf0
28      notify: false
29      command: /srv/scripts/sentry_to_telegram.sh "PROJECT_NAME" "CULPRIT" "URL" "TITLE" "STACKTRACE"
30
31flask_webapp:
32  app_key: 175cc847f608840815d741070d114f3aac35243b4f7e501c
33  triggers:
34    update:
35      trigger_key: bde96f31cf248fd980ce3878942e8df66ae775a9da378c6d
36      repo: git@github.com:YOU/yourflaskwebapp.git
37      repo_parent: /srv/www/flaskwebapp.example.com
38      command: /srv/www/hook.example.com/scripts/update_flask.sh flaskwebapp REPODIR
39
40paragoo:
41  app_key: 6fa726e09524c41e5ff0751a811d34f5dac81cf23d6b5fb4
42  triggers:
43    update:
44      trigger_key: 613b285e72f654b7b7957e5562f5728fbb9049b3d7c58d7d
45      repo: git@github.com:aquatix/paragoo.git
46      command: |
47          bash /home/myuser/bin/update_all_the_things.sh
48    update_theme:
49      trigger_key: 67a729b6cbfaa78075925631552f4eec29938f7a5a19f908
50      repo: git@github.com:aquatix/paragoo-theme-material.git
51      command: python REPODIR/generate_variants.py
52    flake8:
53      trigger_key: 181bd69f610e8544ffa4092b487658636388f7444cb4238f
54      command: /srv/www/hook.example.com/scripts/flake8diff.sh /srv/www/hook.example.com/venvtests/bin/activate paragoo "REPODIR" "EMAIL" COMMIT_BEFORE COMMIT_AFTER "COMPARE_URL"
55
56webhaak:
57  app_key: bdbff089697cb6d07f12498a905a76454ba5467f8b2d5197
58  triggers:
59    update:
60      trigger_key: 9bc193c48b8927d97e35ed7f85181c8305f2f5bb3011c3a8
61      repo: git@github.com:aquatix/webhaak.git
62      repo_parent: /srv/www/hook.example.com
63      command: /srv/www/hook.example.com/scripts/update_webapp.sh webhaak REPODIR /srv/www/hook.example.com/venvs/webhaak
64    flake8:
65      trigger_key: 92a78e26514dc3089b95b49bcc0865fefb7d14dd43c51542
66      notify: false
67      command: /srv/www/hook.example.com/scripts/flake8diff.sh /srv/www/hook.example.com/venvtests/bin/activate webhaak /srv/www/hook.example.com/webhaak "EMAIL" COMMIT_BEFORE COMMIT_AFTER "COMPARE_URL"
68    bitbucket:
69      trigger_key: 0865fefb7d14dd43c515420865fefb7d14dd43c51542bdea
70      notify: false
71      repo: git@bitbucket.org:aquatix/webhaak.git
72      repo_parent: /srv/www/_tests
73      command: /srv/www/hook.example.com/scripts/flake8diff.sh /srv/www/hook.example.com/venvtests/bin/activate webhaak "REPODIR" "EMAIL" COMMIT_BEFORE COMMIT_AFTER "COMPARE_URL"
74      authors:
75        aquatix: itsme@example.com
76        another: mario@example.com

systemd unit file for webhaak webservice

 1[Unit]
 2Description=Gunicorn Daemon for webhaak FastAPI
 3After=network.target
 4
 5[Service]
 6User=change_into_the_correct_username
 7Group=change_into_the_correct_username
 8WorkingDirectory=/srv/www/hook.example.com/webhaak/src
 9
10Environment="SECRETKEY=ABCDEFG"
11Environment="LOG_DIR=/var/log/webhaak"
12Environment="EVENTLOG_DIR=/var/log/webhaak/events"
13Environment="PROJECTS_FILE=/srv/www/hook.example.com/projects.yaml"
14#Environment="REPOS_CACHE_DIR=/srv/www/hook.example.com/_cache"
15# Like in the supervisord config, but make sure it's writable for the user webhaak is running as:
16Environment="REPOS_CACHE_DIR=/var/cache/webhaak"
17Environment="PUSHOVER_USERKEY=your_user_key_here"
18Environment="PUSHOVER_APPTOKEN=your_app_token_here"
19
20ExecStart=/srv/www/hook.example.com/venv/bin/gunicorn -c /srv/www/hook.example.com/gunicorn_webhaak_conf.py webhaak.main:app
21
22[Install]
23WantedBy=multi-user.target

This uses a Gunicorn configuration file:

 1# gunicorn_conf.py
 2from multiprocessing import cpu_count
 3
 4bind = "127.0.0.1:8888"
 5
 6# Worker Options
 7workers = cpu_count() + 1
 8worker_class = 'uvicorn.workers.UvicornWorker'
 9
10# Logging Options
11loglevel = 'debug'
12accesslog = '/var/log/webhaak/access_log'
13errorlog = '/var/log/webhaak/error_log'

Supervisord for RQ worker

 1[program:webhaak_rq_worker]
 2environment=SECRETKEY="ABCDEFG",LOG_DIR="/var/log/webhaak",EVENTLOG_DIR="/var/log/webhaak/events",PROJECTS_FILE="/srv/www/hook.example.com/projects.yaml"REPOS_CACHE_DIR="/var/cache/webhaak",PUSHOVER_USERKEY="your_userkey",PUSHOVER_APPTOKEN="your_apptoken"
 3command = /srv/www/hook.example.com/venv/bin/rq worker --url redis://localhost:6379/0 webhaak --with-scheduler
 4user = change_into_the_correct_username
 5autostart = true
 6autorestart = true
 7stdout_logfile = /var/log/supervisor/webhaak_rq_worker.log
 8redirect_stderr = true
 9#environment = LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8
10
11; process_num is required if you specify >1 numprocs
12; process_name=%(program_name)s-%(process_num)s
13
14; If you want to run more than one worker instance, increase this
15numprocs=1
16
17; This is the directory from which RQ is ran. Be sure to point this to the
18; directory where your source code is importable from
19directory=/srv/www/hook.example.com/webhaak/src
20
21; RQ requires the TERM signal to perform a warm shutdown. If RQ does not die
22; within 10 seconds, supervisor will forcefully kill it
23stopsignal=TERM

nginx vhost

nxing configuration to serve the web application with; the application itself runs under systemd for example

 1server {
 2    listen [::]:443 ssl http2;
 3    listen 443 ssl http2;
 4    server_name hook.example.com;
 5
 6    real_ip_header      X-Forwarded-For;
 7
 8    access_log  /var/log/nginx/access_hook.example.com.log;
 9    error_log  /var/log/nginx/error_hook.example.com.log  warn;
10
11    location / {
12        proxy_pass             http://127.0.0.1:8888;
13        proxy_read_timeout     60;
14        proxy_connect_timeout  60;
15        proxy_redirect         off;
16
17        # Allow the use of websockets
18        proxy_http_version 1.1;
19        proxy_set_header Upgrade $http_upgrade;
20        proxy_set_header Connection 'upgrade';
21        proxy_set_header Host $host;
22        proxy_cache_bypass $http_upgrade;
23    }
24
25    location /ui/ {
26        alias /srv/www/hook.example.com/webhaak-ui/webhaak-ui/;
27        try_files $uri /index.html =404;
28        index index.html;
29    }
30
31    ssl_certificate /etc/letsencrypt/live/hook.example.com/fullchain.pem; # managed by Certbot
32    ssl_certificate_key /etc/letsencrypt/live/hook.example.com/privkey.pem; # managed by Certbot
33}

Environment file

The various environment variables have to be put in the supervisord config and systemd unit file like described above; they can also be put in a .env file.

1SECRETKEY=abc123
2LOG_DIR=/var/log/webhaak
3EVENTLOG_DIR=/var/log/webhaak/events
4PROJECTS_FILE=/srv/www/hook.example.com/projects.yaml
5
6REPOS_CACHE_DIR=/srv/www/hook.example.com/_cache
7
8PUSHOVER_USERKEY=your_user_key_here
9PUSHOVER_APPTOKEN=your_app_token_here

Helper scripts

Updating a webapp project (like a FastAPI one):

 1#!/bin/bash
 2set -e
 3# Any subsequent(*) commands which fail will cause the shell script to exit immediately
 4
 5if [ "$#" -ne 3 ]; then
 6    echo "USAGE: update_webapp.sh [projectname] [repodir] [venvdir]"
 7    exit 1
 8fi
 9
10PROJECTNAME="${1}"
11REPODIR="${2}"
12VENVDIR="${3}"
13
14DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
15
16# Assume update_virtualenv.sh lives in the same directory as this one
17$DIR/update_virtualenv.sh "${VENVDIR}" "${REPODIR}/requirements-server.txt"
18
19# Restart the project
20sudo /usr/bin/systemctl restart "${PROJECTNAME}.service"
21sudo /usr/bin/supervisorctl restart "${PROJECTNAME}_rq_worker"

Updating a Flask project:

 1#!/bin/bash
 2set -e
 3# Any subsequent(*) commands which fail will cause the shell script to exit immediately
 4
 5if [ "$#" -ne 2 ]; then
 6    echo "USAGE: update_flask.sh [projectname] [repodir]"
 7    exit 1
 8fi
 9
10PROJECTNAME="${1}"
11REPODIR="${2}"
12# Convention of having the virtualenv under the same parent dir as the project
13VENVDIR="${2}/../venv/"
14
15DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
16
17# Assume update_virtualenv.sh lives in the same directory as this one
18$DIR/update_virtualenv.sh "${VENVDIR}" "${REPODIR}/requirements.txt"
19
20# Restart the project
21sudo /usr/bin/supervisorctl restart "${PROJECTNAME}"

Updating a Python virtualenv (also used by the Flask update script):

 1#!/bin/bash
 2set -e
 3# Any subsequent(*) commands which fail will cause the shell script to exit immediately
 4
 5if [ "$#" -ne 2 ]; then
 6    echo "USAGE: update_virtualenv.sh [virtualenv_path] [requirements_file]"
 7    exit 1
 8fi
 9
10if [ ! -f "$2" ]; then
11    echo "requirements file '$2' not found"
12    exit 2
13fi
14
15VIRTUALENVDIR="${1}"
16REQUIREMENTSFILE="${2}"
17
18if [ ! -d "${VIRTUALENVDIR}" ]; then
19    echo "Creating virtualenv $1"
20    mkdir -p "${VIRTUALENVDIR}"
21    cd "${VIRTUALENVDIR}"
22    virtualenv -p python3 .
23    # python3 -m venv .
24fi
25
26if [[ -z ${VIRTUAL_ENV} ]]; then
27    # Only activate the virtualenv if we aren't in one already
28    source ${VIRTUALENVDIR}/bin/activate
29    REQUIREMENTSDIR=$(dirname "${REQUIREMENTSFILE}")
30
31    cd "$REQUIREMENTSDIR"
32
33    # Make sure to run the latest pip and pip-tools
34    pip install pip --upgrade
35    pip install pip-tools --upgrade
36
37    pip-sync "${REQUIREMENTSFILE}"
38else
39    echo "A virtualenv is already activated: $VIRTUAL_ENV"
40    exit 3
41fi

Running flake8 linter and isort checker over a directory with Python files:

 1#!/bin/bash
 2
 3MAIL_FROM="CHANGEME@example.com"
 4
 5VENVDIR="${1}"
 6PROJECTNAME="${2}"
 7REPODIR="${3}"
 8EMAIL="${4}"
 9COMMIT="${5}"
10
11source "${VENVDIR}"
12
13cd "${REPODIR}"
14
15echo
16echo "== flake8 ======"
17echo "Checking changes for ${PROJECTNAME}"
18echo "Changes by ${EMAIL}"
19echo "${COMMIT}"
20echo
21
22FLAKE8RESULT=$(git -c advice.detachedHead=false checkout "${COMMIT}" && flake8 --config tox.ini)
23
24echo "${FLAKE8RESULT}"
25
26ISORTRESULT=$(isort -c . | grep -v Skipped)
27
28if [ ! -z "${FLAKE8RESULT}${ISORTRESULT}" ]; then
29    echo "Sending email"
30    TEXT="Changes by ${EMAIL}\nDetails: ${COMMIT}\n\nflake8:\n\n${FLAKE8RESULT}\n\nisort:\n\n${ISORTRESULT}"
31    echo -e "${TEXT}" | /usr/bin/mail -s "flake8 and isort results for ${PROJECTNAME}" -a "From: ${MAIL_FROM}" ${EMAIL}
32else
33    echo "Nothing to mail"
34fi
35echo "== Done with flake8 ======"

Apache

Not officially supported anymore since the rewrite with FastAPI.

uWSGI

Not officially supported anymore since the rewrite with FastAPI.