Virtual Machine

Name
telnorran.anoxinon.de
Status
Active
Start on boot
Off
Role
Platform
Description
CICD Server (Continuous Integration / Continuous Delivery)
Serial number
Tenant
Config template
Primary IPv4
Primary IPv6

Tags

No tags assigned

Comments

telnorran.anoxinon.de

telnorran.anoxinon.de ist der CICD server (Continuous Integration / Continuous Delivery) von Anoxinone.V. Er reagiert auf Änderungen an den Codeberg-Webseiten-Repositories, baut die neuen Versionen und lädt sie hoch.

0. Konzept

Auf telnorran gibt es ein Skript, dass die aktuellen Seiten herunterlädt, baut und an den Webserver schickt. Dieses Skript wird per Webhook bei Commits auf Codeberg ausgeführt und einmal stündlich.

1. Altlasten deaktivieren

Auf dem Server lief früher Drone ... daher gibt es noch Reste davon. Der Drone-Dienst wurde beendet mittels:

docker ps
# die folgenden IDs sind abgelesen von docker ps
docker stop d52a62f0af5a
docker stop 129780181b8b

Anmerkung: Alle anderen Spuren von drone auf argos und telnorran sind geblieben.

2. git installieren

Als ich nachgesehen habe, war es schon installiert. Falls es nicht installiert ist reicht ein apt install git.

3. Buildbot-Benutzer erstellen

Das Bauen von Webseiten braucht keine root-Rechte. Daher wird dafür der Benutzer buildbot mit Home-Ordner erstellt. Der Nutzer bekommt kein Passwort, man kann sich also nicht direkt als dieser Benutzer anmelden.

useradd --create-home buildbot

4. Start-Hugo-Hilfsskript erstellen

Ab jetzt wird mit dem Buildbot-Benutzer gearbeitet - sudo --user=buildbot --shell. Dann bleibt man im root-Ordner, aber das kann cd ändern.

Als Hilfsmittel zum Ausführen von Hugo kommt https://codeberg.org/jonas-l/hugo-utils/src/branch/master/start-hugo.sh zum Einsatz. Damit es nicht verloren geht, wird es auch gleich hier in die Dokumentation gepackt:

tee start-hugo.sh <<"EOF"
#! /bin/bash
#
# hugo utils - helper scripts for using (Go) hugo
# Copyright (C) 2020 Jonas Lochmann
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
#
#
# This scripts uses the FORCE_HUGO_VERSION environment variable or the
# hugo-version.txt file of the current directory to download and launch
# the specified hugo version. All parameters are passed dirctly to hugo.
#
# This script downloads the offical binaries from GitHub.

# START OF CONFIGURATION
ARCH="Linux-64bit"
HUGO_DOWNLOAD_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/hugo-utils/hugo-binaries"
# END OF CONFIGURATION

set -e

if [ "$FORCE_HUGO_VERSION" == "" ]; then
  if [ -f "./hugo-version.txt" ]; then
    FORCE_HUGO_VERSION="$(cat "./hugo-version.txt")"
  else
    echo "I don't know which hugo version you want to run"
    echo "Please set FORCE_HUGO_VERSION or create a hugo-version.txt"
    exit 1
  fi
fi

if [[ ! "$FORCE_HUGO_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "The specified version number does not look like a hugo version number"
  exit 1
fi

HUGO_BINARY_PATH="$HUGO_DOWNLOAD_DIR/hugo-$FORCE_HUGO_VERSION-$ARCH"
LOCKFILE="$HUGO_DOWNLOAD_DIR/download-lock"

mkdir -p "$HUGO_DOWNLOAD_DIR"

if [ ! -d "$HUGO_DOWNLOAD_DIR" ]; then
  echo "Could not create the hugo download directory"
  exit 1
fi

if [ ! -f "$HUGO_BINARY_PATH" ]; then
  echo "The specified hugo version is not yet downloaded"

  echo "waiting for the lock"
  exec {LOCKFILE_FD}>"$LOCKFILE"
  flock "$LOCKFILE_FD"

  if [ -f "$HUGO_BINARY_PATH" ]; then
    echo "The hugo version was downloaded already"
  else
    DOWNLOAD_URL="https://github.com/gohugoio/hugo/releases/download/v${FORCE_HUGO_VERSION}/hugo_${FORCE_HUGO_VERSION}_${ARCH}.tar.gz"
    echo "downloading hugo $DOWNLOAD_URL"

    rm -f "$HUGO_BINARY_PATH.tmp"
    wget "$DOWNLOAD_URL" -qO - | tar -xzO hugo > "$HUGO_BINARY_PATH.tmp"
    chmod u+x "$HUGO_BINARY_PATH.tmp"
    mv "$HUGO_BINARY_PATH.tmp" "$HUGO_BINARY_PATH"
  fi

  flock -u "$LOCKFILE_FD"
fi

"$HUGO_BINARY_PATH" "$@"
EOF
chmod u+x start-hugo.sh

5. SSH-Key erstellen

Nun braucht der Bot auch noch eine Möglichkeit, um die Seite hochzuladen. Da wird ein SSH-Schlüssel benötigt. Das wird mit ssh-keygen erledigt. Mit cat ~/.ssh/id_rsa.pub bekommt man den den öffentlichen Schlüssel.

6. Webserver (argos.anoxinon.de) vorbereiten

Achtung: Das Folgende läuft auf argos.anoxinon.de ab - einfach ein weiteres Terminal öffnen ...

Die Seiten liegen unter /var/www/[domain] - siehe ls -la /var/www. Damit beim "Basteln" Nichts verloren geht, werden für das CI neue Unterordner angelegt:

mkdir /var/www/ci.anoxinon.de
mkdir /var/www/ci.anoxinon.media

Die Ordner gehören root, was ungeeignet ist. Das braucht wieder einen Hilfsbenutzer, der dann der Besitzer wird.

useradd -m buildbot
chown buildbot:nginx /var/www/ci.anoxinon.de /var/www/ci.anoxinon.media

Dann muss sich der buildbot noch anmelden können (weiterhin auf argos). Dort gibt es kein sudo, daher wird su verwendet.

su buildbot
cd
mkdir .ssh
nano .ssh/authorized_keys

Da muss dann der SSH-Key vom Buildbot von telnorran rein. Testen kann man das mit ssh argos.anoxinon.de -- echo test vom telnorran aus. Dieser Test ist erforderlich, weil man dann gleich den SSH-Key autorisiert.

Dann kann man beim argos wieder zum root zurückkehren: exit.

7. Buildskripte erstellen

Es folgt ein Copy-and-Paste-Block für den Benutzer buildbot auf dem telnorran:

cd
tee base-git-building.shf <<"EOF"
# this script can be sourced, it needs the following:
# - the environment variables GIT_REPO, WORKDIR and BUILD_SEED
#   - the GIT_REPO is a url for git clone
#   - the WORKDIR is a directory for storing the clone of the repo
#     and temporarily files; it could be a good idea to put it in the home directory
#   - the same commits are built again if the BUILD_SEED was changed
# - a function "hookBranchProcessing" with 3 parameters
#   - directory which is equal to the current working directory when starting it; this
#     directory is the git working directory
#   - the branch name
#   - the commit id
# - a function "hookBranchRemoval" with 1 parameter
#   - the branch name

# check if the variables are set
if [ -z ${GIT_REPO+x} ]; then echo "GIT_REPO is unset"; exit 1; fi
if [ -z ${WORKDIR+x} ]; then echo "WORKDIR is unset"; exit 1; fi
if [ -z ${BUILD_SEED+x} ]; then echo "BUILD_SEED is unset"; exit 1; fi

# $1 = message
writeHeader() {
  echo ""
  echo "###${1//?/#}###"  
  echo "## $1 ##"
  echo "###${1//?/#}###"  
  echo ""
}

set -e
LOCKFILE="$WORKDIR/lock"
GIT_REPO_DIR="$WORKDIR/repo"
REF_STORAGE_DIR="$WORKDIR/last-handled-ref-storage"

# create the directory and make sure it exists
mkdir -p "$WORKDIR"
test -d "$WORKDIR"

# get a lock
echo "waiting for the lock"
exec {LOCKFILE_FD}>"$LOCKFILE"
flock "$LOCKFILE_FD"
echo "got lock"

if [ ! -d "$GIT_REPO_DIR" ]; then
  echo "cloning repo"
  git clone "$GIT_REPO" "$GIT_REPO_DIR"
fi

# get the remote status
echo "get the remote status"
cd "$GIT_REPO_DIR"
git fetch -p

# handle all branches
echo "iterate over the remote branches"
git "for-each-ref" refs/remotes/origin/ --format "%(refname)" | while read BRANCH_REF; do
  cd "$GIT_REPO_DIR"
  BRANCH_REF_RESOLVED="$(git rev-parse "$BRANCH_REF")"
  BRANCH_NAME="${BRANCH_REF:20}"
  SAFE_BRANCH_NAME=""${BRANCH_NAME//[^a-z0-9]/}"-$(echo "$BRANCH_NAME" | base64 --wrap 0 | tr '/+' '_-')"

  # skip the remote head
  [ "$BRANCH_NAME" = "HEAD" ] && continue

  writeHeader "$BRANCH_NAME"

  # check if it was already handled
  if [ -f "$REF_STORAGE_DIR/$SAFE_BRANCH_NAME" ]; then
    if [ "$(cat "$REF_STORAGE_DIR/$SAFE_BRANCH_NAME")" == "$BRANCH_REF_RESOLVED-$BUILD_SEED" ]; then
      echo "current ref already handled"
      continue
    fi
  fi

  git checkout -f "$BRANCH_REF_RESOLVED"
  git clean -f

  # the echo prevents the hook from consuming anything from the list
  if ! true | hookBranchProcessing "$GIT_REPO_DIR" "$BRANCH_NAME" "$BRANCH_REF_RESOLVED"; then
    echo "error during processing $BRANCH_NAME"
    continue
  fi

  echo "save new ref"
  mkdir -p "$REF_STORAGE_DIR"
  echo "$BRANCH_REF_RESOLVED-$BUILD_SEED" > "$REF_STORAGE_DIR/$SAFE_BRANCH_NAME"
  echo "finished branch"
done

writeHeader "finished all branches"

# remove old branches
echo "check for removed branches"

for REF_FILE in $REF_STORAGE_DIR/*-*; do
  # for the case that there are no ref files
  if [ ! -f "$REF_FILE" ]; then
    continue
  fi

  REF_FILE_NAME="$(basename "$REF_FILE")"
  REF_FILE_BASE64="${REF_FILE_NAME/[a-z0-9]*-/}"
  BRANCH_NAME="$(echo "$REF_FILE_BASE64" | base64 --decode)"

  if [ "$(git for-each-ref -- "refs/remotes/origin/$BRANCH_NAME" | wc -l)" -eq 0 ]; then
    echo "$BRANCH_NAME was removed"

    # the echo prevents the hook from consuming anything from the list
    if ! true | hookBranchRemoval "$BRANCH_NAME" ; then
      echo "failed to execute hook"
      continue
    fi

    rm "$REF_FILE"
  fi
done

# done
rm "$LOCKFILE"
echo "done"
EOF
tee website-git-building.shf <<"EOF"
# this script can be sourced, it needs the following:
# - the environment variables GIT_REPO and WORKDIR
#   - the GIT_REPO is a url for git clone
#   - the WORKDIR is a directory for storing the clone of the repo
#     and temporarily files; it could be a good idea to put it in the home directory
# - the environemt variables DEPLOY_TARGET_HOST, DEPLOY_TARGET_DIR and DEV_DOMAIN
#   - example for host: argos.anoxinon.de
#   - example for dir: /var/www/ci.anoxinon.media
#   - example for dev domain: dev.anoxinon.de

# check if the variables are set
if [ -z ${DEPLOY_TARGET_HOST+x} ]; then echo "DEPLOY_TARGET_HOST is unset"; exit 1; fi
if [ -z ${DEPLOY_TARGET_DIR+x} ]; then echo "DEPLOY_TARGET_DIR is unset"; exit 1; fi
if [ -z ${DEV_DOMAIN+x} ]; then echo "DEV_DOMAIN is unset"; exit 1; fi
# the other variables are checked by base-git-building.shf

BUILD_SEED="v1"

# $1: directory which is equal to the current working directory when starting it; this
#     directory is the git working directory
# $2: the branch name
# $3: the commit id
hookBranchProcessing() {
  if [[ ! "$2" =~ ^[0-9a-z-]*$ ]]; then
    echo "the branch name is not safe"
    return 1
  fi

  rm -rf public || return 1
  mkdir public || return 1

  echo "$3" > public/commit.txt

  if [ "$2" == "master" ]; then
    "$HOME/start-hugo.sh" --buildFuture --minify || return 1
  else
    "$HOME/start-hugo.sh" --buildFuture --minify --baseUrl "https://$2.$DEV_DOMAIN/" || return 1
  fi

  ssh "$DEPLOY_TARGET_HOST" -- mkdir -p "$DEPLOY_TARGET_DIR/$2" || return 1
  rsync -rc --delete ./public/ "$DEPLOY_TARGET_HOST:$DEPLOY_TARGET_DIR/$2/" || return 1
}

# $1: the branch name
hookBranchRemoval() {
  if [[ ! "$1" =~ ^[0-9a-z-]*$ ]]; then
    echo "the branch name is not safe => no need to remove it"
    return 0
  fi

  ssh "$DEPLOY_TARGET_HOST" -- rm -rf "$DEPLOY_TARGET_DIR/$1" || return 1
}

. "${BASH_SOURCE%/*}/base-git-building.shf"
EOF
tee buildjob-media.sh <<"EOF"
#! /bin/bash
GIT_REPO="https://codeberg.org/Anoxinon_e.V./anoxinon-web-media.git"
WORKDIR="$HOME/build-data/web-media"
DEPLOY_TARGET_HOST="argos.anoxinon.de"
DEPLOY_TARGET_DIR="/var/www/ci.anoxinon.media"
DEV_DOMAIN="media.dev.anoxinon.de"

. "${BASH_SOURCE%/*}/website-git-building.shf"
EOF
tee buildjob-main.sh <<"EOF"
#! /bin/bash
GIT_REPO="https://codeberg.org/Anoxinon_e.V./anoxinon-web-main.git"
WORKDIR="$HOME/build-data/web-main"
DEPLOY_TARGET_HOST="argos.anoxinon.de"
DEPLOY_TARGET_DIR="/var/www/ci.anoxinon.de"
DEV_DOMAIN="dev.anoxinon.de"

. "${BASH_SOURCE%/*}/website-git-building.shf"
EOF
chmod u+x buildjob-media.sh buildjob-main.sh

Einen Testlauf kann man per ./buildjob-media.sh starten. Dann kann man den buildbot-Benutzer per exitverlassen.

8. Webserver konfigurieren

Ja, die Seite möchte ausgeliefert werden ... dafür muss die Nginx-Konfiguration auf argos noch angepasst werden.

8.1 neue Zertifikate

acme.sh war schon passend eingerichtet - acme.sh --issue --dns dns_servercow -d '*.media.dev.anoxinon.de' hat gereicht.

8.2 /etc/nginx/sites-enabled/anoxinon.media

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name anoxinon.media www.anoxinon.media;

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_certificate /etc/letsencrypt/live/anoxinon.media/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/anoxinon.media/privkey.pem;
    ssl_dhparam /etc/letsencrypt/live/anoxinon.media/dhparam.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/anoxinon.media/chain.pem;

    keepalive_timeout 70;

    root /var/www/ci.anoxinon.media/master;

    error_page 404 /404.html;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Referrer-Policy "no-referrer" always;
    add_header X-Frame-Options "deny" always;
    add_header Content-Security-Policy "default-src 'none'; base-uri 'none'; block-all-mixed-content; form-action 'self'; frame-ancestors 'none'; style-src 'self'; img-src 'self'; font-src 'self'; object-src 'self';" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block";

    location /suche {
        proxy_pass http://unix:/var/run/anoxinon-suche/server:/media/;
    }

    # redirect from the old urls to the wiki
    location /downloads { return 301 $scheme://$host/wiki/; }
    location /empfohleneprogramme { return 301 $scheme://$host/wiki/programme/; }
    location /empfohlenedienste { return 301 $scheme://$host/wiki/dienste/; }
    location /weitereempfehlungen { return 301 $scheme://$host/wiki/infoquellen/; }
    location /extras { return 301 $scheme://$host/wiki/; }
}

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    ssl_certificate /root/.acme.sh/*.media.dev.anoxinon.de/fullchain.cer;
    ssl_certificate_key /root/.acme.sh/*.media.dev.anoxinon.de/*.media.dev.anoxinon.de.key;

    server_name ~^(.*)\.media\.dev\.anoxinon\.de$;
    root /var/www/ci.anoxinon.media/$1/;

    error_page 404 /404.html;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Referrer-Policy "no-referrer" always;
    add_header X-Frame-Options "deny" always;
    add_header Content-Security-Policy "default-src 'none'; base-uri 'none'; block-all-mixed-content; form-action 'self'; frame-ancestors 'none'; style-src 'self'; img-src 'self'; font-src 'self'; object-src 'self';" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block";

    location /suche {
        proxy_pass http://unix:/var/run/anoxinon-suche/server:/media/;
    }

    # redirect from the old urls to the wiki
    location /downloads { return 301 $scheme://$host/wiki/; }
    location /empfohleneprogramme { return 301 $scheme://$host/wiki/programme/; }
    location /empfohlenedienste { return 301 $scheme://$host/wiki/dienste/; }
    location /weitereempfehlungen { return 301 $scheme://$host/wiki/infoquellen/; }
    location /extras { return 301 $scheme://$host/wiki/; }
}

8.3 /etc/nginx/sites-enabled/anoxinon.de

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name anoxinon.de www.anoxinon.de;

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_certificate /etc/letsencrypt/live/anoxinon.de/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/anoxinon.de/privkey.pem; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/live/anoxinon.de/dhparam.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/anoxinon.de/chain.pem;

    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Referrer-Policy "no-referrer" always;
    add_header X-Frame-Options "deny" always;
    add_header Content-Security-Policy "default-src 'none'; base-uri 'none'; block-all-mixed-content; form-action 'self'; frame-ancestors 'none'; style-src 'self'; img-src 'self'; font-src 'self'; object-src 'self'; frame-src https://xmpp.anoxinon.me:443/; media-src 'self';" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block";

    keepalive_timeout 70;

    root /var/www/ci.anoxinon.de/master;

    error_page 404 /404.html;

    location /suche {
        proxy_pass http://unix:/var/run/anoxinon-suche/server:/main/;
    }
}



##
## Wildcard vhost for dev.anoxinon.de
## This is for serving all the Git branches which were build be CI/CD
## (telnorran.anoxinon.de)
## Ask Thomas Leister about this. <thomas.leister@anoxinon.de>
##

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    ssl_certificate /etc/acme.sh/dev.anoxinon.de/fullchain.pem;
    ssl_certificate_key /etc/acme.sh/dev.anoxinon.de/privkey.pem;

    server_name ~^(([a-zA-Z0-9]|-)*)\.dev\.anoxinon\.de$;
    root /var/www/ci.anoxinon.de/$1/;

    error_page 404 /404.html;

    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Referrer-Policy "no-referrer" always;
    add_header X-Frame-Options "deny" always;
    add_header Content-Security-Policy "default-src 'none'; base-uri 'none'; block-all-mixed-content; form-action 'self'; frame-ancestors 'none'; style-src 'self'; img-src 'self'; font-src 'self'; object-src 'self'; frame-src https://xmpp.anoxinon.me:443/; media-src 'self';" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block";

    location /suche {
        proxy_pass http://unix:/var/run/anoxinon-suche/server:/main/;
    }
}

8.4 nginx Konfiguration neu laden

systemctl reload nginx sollte man nicht vergessen.

9. Webhook

Jetzt gibt es Skripte, die alles machen, aber Niemanden, der diese startet. Das kann man aber ändern. Damit nicht jeder den Hook auslösen kann, braucht man Secrets, die man z.B. von openssl rand -hex 32 bekommt.

Weil die unkritisch sind/man damit keinen Schaden anrichten kann, stehen sie hier:

  • media: a3570dce8af7d2ae5a31a4bb5d4a7fcef964edc95fc3ee0061743c2234a3403f
  • main: 9b8d3feb4c0352dac2687192f5f2e23f9fa52482d91ae340e298d400126cff90

Das Folgende läuft auf telnorran als root ab:

apt install apache2 certbot python3-certbot-apache
a2enmod cgi
systemctl restart apache2
tee /etc/apache2/sites-available/100-ci-system.conf <<"EOF"
<VirtualHost *:80>
  ServerName telnorran.anoxinon.de
  Include conf-available/serve-cgi-bin.conf
</VirtualHost>
EOF
ln -s /etc/apache2/sites-available/100-ci-system.conf /etc/apache2/sites-enabled/
rm /etc/apache2/sites-enabled/000-default.conf
systemctl reload apache2
certbot --apache

Dann sollte https://telnorran.anoxinon.de/ funktionieren.

9.1 Webhook-Skripte

Bereit für Copy and Paste:

tee /usr/lib/cgi-bin/build-media.sh <<"EOF"
#! /bin/bash
SECRET="a3570dce8af7d2ae5a31a4bb5d4a7fcef964edc95fc3ee0061743c2234a3403f"
HASH="$(openssl sha256 -hmac "$SECRET" | sed "s/(stdin)= //")"

if [ "$HASH" = "$HTTP_X_GITEA_SIGNATURE" ]; then
  echo "Content-Type: text/plain"
  echo ""
  echo "signature valid"

  sudo -u buildbot /home/buildbot/buildjob-media.sh 2>&1
else
  echo "Status: 401"
  echo "Content-Type: text/plain"
  echo ""
  echo "signature invalid"
  exit 1
fi
EOF
tee /usr/lib/cgi-bin/build-main.sh <<"EOF"
#! /bin/bash
SECRET="9b8d3feb4c0352dac2687192f5f2e23f9fa52482d91ae340e298d400126cff90"
HASH="$(openssl sha256 -hmac "$SECRET" | sed "s/(stdin)= //")"

if [ "$HASH" = "$HTTP_X_GITEA_SIGNATURE" ]; then
  echo "Content-Type: text/plain"
  echo ""
  echo "signature valid"

  sudo -u buildbot /home/buildbot/buildjob-main.sh 2>&1
else
  echo "Status: 401"
  echo "Content-Type: text/plain"
  echo ""
  echo "signature invalid"
  exit 1
fi
EOF
chmod u=rw,g=rx,o= /usr/lib/cgi-bin/build-media.sh /usr/lib/cgi-bin/build-main.sh
chown root:www-data /usr/lib/cgi-bin/build-media.sh /usr/lib/cgi-bin/build-main.sh

Testen kann man das Ganze lokal mittels:

# media
RQC="{}"
SECRET="a3570dce8af7d2ae5a31a4bb5d4a7fcef964edc95fc3ee0061743c2234a3403f"
HASH="$(echo -n "$RQC" | openssl sha256 -hmac "$SECRET" | sed "s/(stdin)= //")"
curl --header "X-Gitea-Signature: $HASH" -X POST --data "$RQC"  https://telnorran.anoxinon.de/cgi-bin/build-media.sh

# main
RQC="{}"
SECRET="9b8d3feb4c0352dac2687192f5f2e23f9fa52482d91ae340e298d400126cff90"
HASH="$(echo -n "$RQC" | openssl sha256 -hmac "$SECRET" | sed "s/(stdin)= //")"
curl --header "X-Gitea-Signature: $HASH" -X POST --data "$RQC"  https://telnorran.anoxinon.de/cgi-bin/build-main.sh

Natürlich fehlt da noch etwas - man sollte einen Fehler von sudo angezeigt bekommen.

9.2 Berechtigungen erteilen

Hier erlaubt man dem Webserver, die entsprechenden Skripte auszuführen.

visudo --file=/etc/sudoers.d/buildbot

Die Datei braucht zwei Zeilen:

www-data ALL=(buildbot) NOPASSWD: /home/buildbot/buildjob-media.sh
www-data ALL=(buildbot) NOPASSWD: /home/buildbot/buildjob-main.sh

www-data darf damit unabhängig vom Hostnamen als buildbot ohne Eingabe eines Passwortes die Skripte ausführen.

9.3 Webserver reduzieren

Unter telnorran.anoxinon.de gibt es noch Inhalte, die dort nicht passen.

Dafür ruft man nano /etc/apache2/apache2.conf auf. Dann sucht man nach <Directory /var/www/> und kommentiert es aus. Dann noch am Ende das hier ergänzen:

ServerSignature Off
ServerTokens Prod

Nach einem systemctl reload apache2 gibt es ein Forbidden und die Header enthalten nicht mehr die Server-Version.

9.4 Hooks bei Codeberg eintragen

In den Repository-Einstellungen bei Codeberg gibt es den Abschnitt Webhooks. Alte Einträge von Drone können dort deaktiviert werden.

Beim Hinzufügen ist der Typ "Gitea" passend. Die Target-URLs und Secrets stehen am Ende vom Abschnitt 9.1. Als HTTP-Methode passt POST, als Content-Type JSON, getriggert werden soll nur bei Push Events, der Branchfilter kann auf * bleiben, damit alle Branches den Trigger auslösen.

Bei den beiden Webseiten-Repositories muss jeweils der Hook eingetragen werden.

10. Cronjobs

Damit es auch ohne Webhook läuft:

sudo -s -u buildbot
crontab -e

Dann zwei Zeilen:

13 * * * * /home/buildbot/buildjob-media.sh &> /dev/null
47 * * * * /home/buildbot/buildjob-main.sh &> /dev/null

11. weitere Altlasten entfernen

11.1 argos.anoxinon.de

Die alten Ordner, von denen die Webseite ausgeliefert wurde, werden mit rm -rf /var/www/anoxinon.de/ /var/www/anoxinon.media/ /var/www/dev.anoxinon.de/ entfernt.

Dann gibt es noch den Hilfsbenutzer für Drone, den man mit deluser --remove-home drone entfernen kann.

11.2 telnorran.anoxinon.de

cd
rm -rf buildcontainer-hugo drone-ssh-keys run-drone-agent.sh run-drone-master.sh
yes | docker system prune
rm -rf /var/lib/drone/
apt remove -y docker-ce
apt autoremove -y
# sudo was indirectly installed, but it is needed
apt install -y sudo
apt-mark showmanual
# remove more unused things
apt remove -y containerd.io docker-ce-cli

11.3 Codeberg

  • die alten Webhooks bei Codeberg können entfernt werden
  • der Account anoxinon.cicd bei Codeberg wird nicht mehr benötigt und kann entfernt werden
Documents
None

Cluster

Site
Cluster
Cluster type
Device

Resources

Virtual CPUs 2.00
Memory 4 MB
Disk Space 40.96 GB

Application Services

Image Attachments

Virtual Disks