Change

Time
2026-05-31 10:17:29
User
York-Simon Johannsen (YoSiJo)
Action
Created
Object type
Virtualization | virtual machine
Object
Message
telnorran.anoxinon.de nach dokumentiert
Request ID

Difference

Object Created

Pre-Change Data

None

Post-Change Data

disk: 40960name: "telnorran.anoxinon.de"role: 4site: 1tags: []owner: 1vcpus: "2"device: nullmemory: 4serial: ""status: "active"tenant: 1cluster: 3comments: "# telnorran.anoxinon.de\r\n\r\ntelnorran.anoxinon.de ist der CICD server (Continuous Integration / Continuous Delivery) von Anoxinone.V.\r\nEr reagiert auf Änderungen an den Codeberg-Webseiten-Repositories, baut die neuen Versionen und lädt sie hoch.\r\n\r\n## 0. Konzept\r\n\r\nAuf telnorran gibt es ein Skript, dass die aktuellen Seiten herunterlädt, baut und an den Webserver schickt.\r\nDieses Skript wird per Webhook bei Commits auf Codeberg ausgeführt und einmal stündlich.\r\n\r\n## 1. Altlasten deaktivieren\r\n\r\nAuf dem Server lief früher Drone ... daher gibt es noch Reste davon. Der Drone-Dienst wurde beendet mittels:\r\n\r\n```\r\ndocker ps\r\n# die folgenden IDs sind abgelesen von docker ps\r\ndocker stop d52a62f0af5a\r\ndocker stop 129780181b8b\r\n```\r\n\r\nAnmerkung: Alle anderen Spuren von drone auf argos und telnorran sind geblieben.\r\n\r\n## 2. git installieren\r\n\r\nAls ich nachgesehen habe, war es schon installiert.\r\nFalls es nicht installiert ist reicht ein ``apt install git``.\r\n\r\n## 3. Buildbot-Benutzer erstellen\r\n\r\nDas Bauen von Webseiten braucht keine root-Rechte. Daher wird dafür der Benutzer ``buildbot``\r\nmit Home-Ordner erstellt. Der Nutzer bekommt kein Passwort, man kann sich also nicht direkt\r\nals dieser Benutzer anmelden.\r\n\r\n``useradd --create-home buildbot``\r\n\r\n## 4. Start-Hugo-Hilfsskript erstellen\r\n\r\nAb jetzt wird mit dem Buildbot-Benutzer gearbeitet - ``sudo --user=buildbot --shell``.\r\nDann bleibt man im root-Ordner, aber das kann ``cd`` ändern.\r\n\r\nAls 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:\r\n\r\n```\r\ntee start-hugo.sh <<\"EOF\"\r\n#! /bin/bash\r\n#\r\n# hugo utils - helper scripts for using (Go) hugo\r\n# Copyright (C) 2020 Jonas Lochmann\r\n#\r\n# This program is free software: you can redistribute it and/or modify\r\n# it under the terms of the GNU General Public License as published by\r\n# the Free Software Foundation, either version 3 of the License, or\r\n# (at your option) any later version.\r\n#\r\n# This program is distributed in the hope that it will be useful,\r\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n# GNU General Public License for more details.\r\n#\r\n# You should have received a copy of the GNU General Public License\r\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n#\r\n#\r\n#\r\n# This scripts uses the FORCE_HUGO_VERSION environment variable or the\r\n# hugo-version.txt file of the current directory to download and launch\r\n# the specified hugo version. All parameters are passed dirctly to hugo.\r\n#\r\n# This script downloads the offical binaries from GitHub.\r\n\r\n# START OF CONFIGURATION\r\nARCH=\"Linux-64bit\"\r\nHUGO_DOWNLOAD_DIR=\"${XDG_CACHE_HOME:-$HOME/.cache}/hugo-utils/hugo-binaries\"\r\n# END OF CONFIGURATION\r\n\r\nset -e\r\n\r\nif [ \"$FORCE_HUGO_VERSION\" == \"\" ]; then\r\n  if [ -f \"./hugo-version.txt\" ]; then\r\n    FORCE_HUGO_VERSION=\"$(cat \"./hugo-version.txt\")\"\r\n  else\r\n    echo \"I don't know which hugo version you want to run\"\r\n    echo \"Please set FORCE_HUGO_VERSION or create a hugo-version.txt\"\r\n    exit 1\r\n  fi\r\nfi\r\n\r\nif [[ ! \"$FORCE_HUGO_VERSION\" =~ ^[0-9]+\\.[0-9]+\\.[0-9]+$ ]]; then\r\n  echo \"The specified version number does not look like a hugo version number\"\r\n  exit 1\r\nfi\r\n\r\nHUGO_BINARY_PATH=\"$HUGO_DOWNLOAD_DIR/hugo-$FORCE_HUGO_VERSION-$ARCH\"\r\nLOCKFILE=\"$HUGO_DOWNLOAD_DIR/download-lock\"\r\n\r\nmkdir -p \"$HUGO_DOWNLOAD_DIR\"\r\n\r\nif [ ! -d \"$HUGO_DOWNLOAD_DIR\" ]; then\r\n  echo \"Could not create the hugo download directory\"\r\n  exit 1\r\nfi\r\n\r\nif [ ! -f \"$HUGO_BINARY_PATH\" ]; then\r\n  echo \"The specified hugo version is not yet downloaded\"\r\n\r\n  echo \"waiting for the lock\"\r\n  exec {LOCKFILE_FD}>\"$LOCKFILE\"\r\n  flock \"$LOCKFILE_FD\"\r\n\r\n  if [ -f \"$HUGO_BINARY_PATH\" ]; then\r\n    echo \"The hugo version was downloaded already\"\r\n  else\r\n    DOWNLOAD_URL=\"https://github.com/gohugoio/hugo/releases/download/v${FORCE_HUGO_VERSION}/hugo_${FORCE_HUGO_VERSION}_${ARCH}.tar.gz\"\r\n    echo \"downloading hugo $DOWNLOAD_URL\"\r\n\r\n    rm -f \"$HUGO_BINARY_PATH.tmp\"\r\n    wget \"$DOWNLOAD_URL\" -qO - | tar -xzO hugo > \"$HUGO_BINARY_PATH.tmp\"\r\n    chmod u+x \"$HUGO_BINARY_PATH.tmp\"\r\n    mv \"$HUGO_BINARY_PATH.tmp\" \"$HUGO_BINARY_PATH\"\r\n  fi\r\n\r\n  flock -u \"$LOCKFILE_FD\"\r\nfi\r\n\r\n\"$HUGO_BINARY_PATH\" \"$@\"\r\nEOF\r\nchmod u+x start-hugo.sh\r\n```\r\n\r\n## 5. SSH-Key erstellen\r\n\r\nNun 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\r\nden öffentlichen Schlüssel.\r\n\r\n## 6. Webserver (argos.anoxinon.de) vorbereiten\r\n\r\n**Achtung: Das Folgende läuft auf argos.anoxinon.de ab** - einfach ein weiteres Terminal öffnen ...\r\n\r\nDie Seiten liegen unter ``/var/www/[domain]`` - siehe ``ls -la /var/www``.\r\nDamit beim \"Basteln\" Nichts verloren geht, werden für das CI neue Unterordner angelegt:\r\n\r\n```\r\nmkdir /var/www/ci.anoxinon.de\r\nmkdir /var/www/ci.anoxinon.media\r\n```\r\n\r\nDie Ordner gehören root, was ungeeignet ist. Das braucht wieder einen Hilfsbenutzer, der dann der Besitzer wird.\r\n\r\n```\r\nuseradd -m buildbot\r\nchown buildbot:nginx /var/www/ci.anoxinon.de /var/www/ci.anoxinon.media\r\n```\r\n\r\nDann muss sich der buildbot noch anmelden können (weiterhin auf argos). Dort gibt es kein sudo,\r\ndaher wird su verwendet.\r\n\r\n```\r\nsu buildbot\r\ncd\r\nmkdir .ssh\r\nnano .ssh/authorized_keys\r\n```\r\n\r\nDa muss dann der SSH-Key vom Buildbot von telnorran rein.\r\nTesten kann man das mit ``ssh argos.anoxinon.de -- echo test`` vom **telnorran** aus.\r\nDieser Test ist erforderlich, weil man dann gleich den SSH-Key autorisiert.\r\n\r\nDann kann man beim **argos** wieder zum root zurückkehren: ``exit``.\r\n\r\n## 7. Buildskripte erstellen\r\n\r\nEs folgt ein Copy-and-Paste-Block für den Benutzer **buildbot** auf dem **telnorran**:\r\n\r\n```\r\ncd\r\ntee base-git-building.shf <<\"EOF\"\r\n# this script can be sourced, it needs the following:\r\n# - the environment variables GIT_REPO, WORKDIR and BUILD_SEED\r\n#   - the GIT_REPO is a url for git clone\r\n#   - the WORKDIR is a directory for storing the clone of the repo\r\n#     and temporarily files; it could be a good idea to put it in the home directory\r\n#   - the same commits are built again if the BUILD_SEED was changed\r\n# - a function \"hookBranchProcessing\" with 3 parameters\r\n#   - directory which is equal to the current working directory when starting it; this\r\n#     directory is the git working directory\r\n#   - the branch name\r\n#   - the commit id\r\n# - a function \"hookBranchRemoval\" with 1 parameter\r\n#   - the branch name\r\n\r\n# check if the variables are set\r\nif [ -z ${GIT_REPO+x} ]; then echo \"GIT_REPO is unset\"; exit 1; fi\r\nif [ -z ${WORKDIR+x} ]; then echo \"WORKDIR is unset\"; exit 1; fi\r\nif [ -z ${BUILD_SEED+x} ]; then echo \"BUILD_SEED is unset\"; exit 1; fi\r\n\r\n# $1 = message\r\nwriteHeader() {\r\n  echo \"\"\r\n  echo \"###${1//?/#}###\"  \r\n  echo \"## $1 ##\"\r\n  echo \"###${1//?/#}###\"  \r\n  echo \"\"\r\n}\r\n\r\nset -e\r\nLOCKFILE=\"$WORKDIR/lock\"\r\nGIT_REPO_DIR=\"$WORKDIR/repo\"\r\nREF_STORAGE_DIR=\"$WORKDIR/last-handled-ref-storage\"\r\n\r\n# create the directory and make sure it exists\r\nmkdir -p \"$WORKDIR\"\r\ntest -d \"$WORKDIR\"\r\n\r\n# get a lock\r\necho \"waiting for the lock\"\r\nexec {LOCKFILE_FD}>\"$LOCKFILE\"\r\nflock \"$LOCKFILE_FD\"\r\necho \"got lock\"\r\n\r\nif [ ! -d \"$GIT_REPO_DIR\" ]; then\r\n  echo \"cloning repo\"\r\n  git clone \"$GIT_REPO\" \"$GIT_REPO_DIR\"\r\nfi\r\n\r\n# get the remote status\r\necho \"get the remote status\"\r\ncd \"$GIT_REPO_DIR\"\r\ngit fetch -p\r\n\r\n# handle all branches\r\necho \"iterate over the remote branches\"\r\ngit \"for-each-ref\" refs/remotes/origin/ --format \"%(refname)\" | while read BRANCH_REF; do\r\n  cd \"$GIT_REPO_DIR\"\r\n  BRANCH_REF_RESOLVED=\"$(git rev-parse \"$BRANCH_REF\")\"\r\n  BRANCH_NAME=\"${BRANCH_REF:20}\"\r\n  SAFE_BRANCH_NAME=\"\"${BRANCH_NAME//[^a-z0-9]/}\"-$(echo \"$BRANCH_NAME\" | base64 --wrap 0 | tr '/+' '_-')\"\r\n\r\n  # skip the remote head\r\n  [ \"$BRANCH_NAME\" = \"HEAD\" ] && continue\r\n  \r\n  writeHeader \"$BRANCH_NAME\"\r\n  \r\n  # check if it was already handled\r\n  if [ -f \"$REF_STORAGE_DIR/$SAFE_BRANCH_NAME\" ]; then\r\n    if [ \"$(cat \"$REF_STORAGE_DIR/$SAFE_BRANCH_NAME\")\" == \"$BRANCH_REF_RESOLVED-$BUILD_SEED\" ]; then\r\n      echo \"current ref already handled\"\r\n      continue\r\n    fi\r\n  fi\r\n\r\n  git checkout -f \"$BRANCH_REF_RESOLVED\"\r\n  git clean -f\r\n  \r\n  # the echo prevents the hook from consuming anything from the list\r\n  if ! true | hookBranchProcessing \"$GIT_REPO_DIR\" \"$BRANCH_NAME\" \"$BRANCH_REF_RESOLVED\"; then\r\n    echo \"error during processing $BRANCH_NAME\"\r\n    continue\r\n  fi\r\n  \r\n  echo \"save new ref\"\r\n  mkdir -p \"$REF_STORAGE_DIR\"\r\n  echo \"$BRANCH_REF_RESOLVED-$BUILD_SEED\" > \"$REF_STORAGE_DIR/$SAFE_BRANCH_NAME\"\r\n  echo \"finished branch\"\r\ndone\r\n\r\nwriteHeader \"finished all branches\"\r\n\r\n# remove old branches\r\necho \"check for removed branches\"\r\n\r\nfor REF_FILE in $REF_STORAGE_DIR/*-*; do\r\n  # for the case that there are no ref files\r\n  if [ ! -f \"$REF_FILE\" ]; then\r\n    continue\r\n  fi\r\n  \r\n  REF_FILE_NAME=\"$(basename \"$REF_FILE\")\"\r\n  REF_FILE_BASE64=\"${REF_FILE_NAME/[a-z0-9]*-/}\"\r\n  BRANCH_NAME=\"$(echo \"$REF_FILE_BASE64\" | base64 --decode)\"\r\n  \r\n  if [ \"$(git for-each-ref -- \"refs/remotes/origin/$BRANCH_NAME\" | wc -l)\" -eq 0 ]; then\r\n    echo \"$BRANCH_NAME was removed\"\r\n\r\n    # the echo prevents the hook from consuming anything from the list\r\n    if ! true | hookBranchRemoval \"$BRANCH_NAME\" ; then\r\n      echo \"failed to execute hook\"\r\n      continue\r\n    fi\r\n    \r\n    rm \"$REF_FILE\"\r\n  fi\r\ndone\r\n\r\n# done\r\nrm \"$LOCKFILE\"\r\necho \"done\"\r\nEOF\r\ntee website-git-building.shf <<\"EOF\"\r\n# this script can be sourced, it needs the following:\r\n# - the environment variables GIT_REPO and WORKDIR\r\n#   - the GIT_REPO is a url for git clone\r\n#   - the WORKDIR is a directory for storing the clone of the repo\r\n#     and temporarily files; it could be a good idea to put it in the home directory\r\n# - the environemt variables DEPLOY_TARGET_HOST, DEPLOY_TARGET_DIR and DEV_DOMAIN\r\n#   - example for host: argos.anoxinon.de\r\n#   - example for dir: /var/www/ci.anoxinon.media\r\n#   - example for dev domain: dev.anoxinon.de\r\n\r\n# check if the variables are set\r\nif [ -z ${DEPLOY_TARGET_HOST+x} ]; then echo \"DEPLOY_TARGET_HOST is unset\"; exit 1; fi\r\nif [ -z ${DEPLOY_TARGET_DIR+x} ]; then echo \"DEPLOY_TARGET_DIR is unset\"; exit 1; fi\r\nif [ -z ${DEV_DOMAIN+x} ]; then echo \"DEV_DOMAIN is unset\"; exit 1; fi\r\n# the other variables are checked by base-git-building.shf\r\n\r\nBUILD_SEED=\"v1\"\r\n\r\n# $1: directory which is equal to the current working directory when starting it; this\r\n#     directory is the git working directory\r\n# $2: the branch name\r\n# $3: the commit id\r\nhookBranchProcessing() {\r\n  if [[ ! \"$2\" =~ ^[0-9a-z-]*$ ]]; then\r\n    echo \"the branch name is not safe\"\r\n    return 1\r\n  fi\r\n  \r\n  rm -rf public || return 1\r\n  mkdir public || return 1\r\n\r\n  echo \"$3\" > public/commit.txt\r\n  \r\n  if [ \"$2\" == \"master\" ]; then\r\n    \"$HOME/start-hugo.sh\" --buildFuture --minify || return 1\r\n  else\r\n    \"$HOME/start-hugo.sh\" --buildFuture --minify --baseUrl \"https://$2.$DEV_DOMAIN/\" || return 1\r\n  fi\r\n\r\n  ssh \"$DEPLOY_TARGET_HOST\" -- mkdir -p \"$DEPLOY_TARGET_DIR/$2\" || return 1\r\n  rsync -rc --delete ./public/ \"$DEPLOY_TARGET_HOST:$DEPLOY_TARGET_DIR/$2/\" || return 1\r\n}\r\n\r\n# $1: the branch name\r\nhookBranchRemoval() {\r\n  if [[ ! \"$1\" =~ ^[0-9a-z-]*$ ]]; then\r\n    echo \"the branch name is not safe => no need to remove it\"\r\n    return 0\r\n  fi\r\n\r\n  ssh \"$DEPLOY_TARGET_HOST\" -- rm -rf \"$DEPLOY_TARGET_DIR/$1\" || return 1\r\n}\r\n\r\n. \"${BASH_SOURCE%/*}/base-git-building.shf\"\r\nEOF\r\ntee buildjob-media.sh <<\"EOF\"\r\n#! /bin/bash\r\nGIT_REPO=\"https://codeberg.org/Anoxinon_e.V./anoxinon-web-media.git\"\r\nWORKDIR=\"$HOME/build-data/web-media\"\r\nDEPLOY_TARGET_HOST=\"argos.anoxinon.de\"\r\nDEPLOY_TARGET_DIR=\"/var/www/ci.anoxinon.media\"\r\nDEV_DOMAIN=\"media.dev.anoxinon.de\"\r\n\r\n. \"${BASH_SOURCE%/*}/website-git-building.shf\"\r\nEOF\r\ntee buildjob-main.sh <<\"EOF\"\r\n#! /bin/bash\r\nGIT_REPO=\"https://codeberg.org/Anoxinon_e.V./anoxinon-web-main.git\"\r\nWORKDIR=\"$HOME/build-data/web-main\"\r\nDEPLOY_TARGET_HOST=\"argos.anoxinon.de\"\r\nDEPLOY_TARGET_DIR=\"/var/www/ci.anoxinon.de\"\r\nDEV_DOMAIN=\"dev.anoxinon.de\"\r\n\r\n. \"${BASH_SOURCE%/*}/website-git-building.shf\"\r\nEOF\r\nchmod u+x buildjob-media.sh buildjob-main.sh\r\n```\r\n\r\nEinen Testlauf kann man per ``./buildjob-media.sh`` starten.\r\nDann kann man den buildbot-Benutzer per ``exit``verlassen.\r\n\r\n## 8. Webserver konfigurieren\r\n\r\nJa, die Seite möchte ausgeliefert werden ... dafür muss die Nginx-Konfiguration auf argos noch angepasst werden.\r\n\r\n### 8.1 neue Zertifikate\r\n\r\nacme.sh war schon passend eingerichtet - ``acme.sh --issue --dns dns_servercow -d '*.media.dev.anoxinon.de'`` hat gereicht.\r\n\r\n### 8.2 /etc/nginx/sites-enabled/anoxinon.media\r\n\r\n```\r\nserver {\r\n    listen 443 ssl http2;\r\n    listen [::]:443 ssl http2;\r\n    server_name anoxinon.media www.anoxinon.media;\r\n\r\n    ssl_stapling on;\r\n    ssl_stapling_verify on;\r\n    ssl_certificate /etc/letsencrypt/live/anoxinon.media/fullchain.pem;\r\n    ssl_certificate_key /etc/letsencrypt/live/anoxinon.media/privkey.pem;\r\n    ssl_dhparam /etc/letsencrypt/live/anoxinon.media/dhparam.pem;\r\n    ssl_trusted_certificate /etc/letsencrypt/live/anoxinon.media/chain.pem;\r\n\r\n    keepalive_timeout 70;\r\n\r\n    root /var/www/ci.anoxinon.media/master;\r\n\r\n    error_page 404 /404.html;\r\n    \r\n    add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains; preload\" always;\r\n    add_header Referrer-Policy \"no-referrer\" always;\r\n    add_header X-Frame-Options \"deny\" always;\r\n    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;\r\n    add_header X-Content-Type-Options \"nosniff\" always;\r\n    add_header X-XSS-Protection \"1; mode=block\";\r\n\r\n    location /suche {\r\n        proxy_pass http://unix:/var/run/anoxinon-suche/server:/media/;\r\n    }\r\n\r\n    # redirect from the old urls to the wiki\r\n    location /downloads { return 301 $scheme://$host/wiki/; }\r\n    location /empfohleneprogramme { return 301 $scheme://$host/wiki/programme/; }\r\n    location /empfohlenedienste { return 301 $scheme://$host/wiki/dienste/; }\r\n    location /weitereempfehlungen { return 301 $scheme://$host/wiki/infoquellen/; }\r\n    location /extras { return 301 $scheme://$host/wiki/; }\r\n}\r\n\r\nserver {\r\n    listen 443 http2 ssl;\r\n    listen [::]:443 http2 ssl;\r\n\r\n    ssl_certificate /root/.acme.sh/*.media.dev.anoxinon.de/fullchain.cer;\r\n    ssl_certificate_key /root/.acme.sh/*.media.dev.anoxinon.de/*.media.dev.anoxinon.de.key;\r\n\r\n    server_name ~^(.*)\\.media\\.dev\\.anoxinon\\.de$;\r\n    root /var/www/ci.anoxinon.media/$1/;\r\n\r\n    error_page 404 /404.html;\r\n\r\n    add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains; preload\" always;\r\n    add_header Referrer-Policy \"no-referrer\" always;\r\n    add_header X-Frame-Options \"deny\" always;\r\n    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;\r\n    add_header X-Content-Type-Options \"nosniff\" always;\r\n    add_header X-XSS-Protection \"1; mode=block\";\r\n\r\n    location /suche {\r\n        proxy_pass http://unix:/var/run/anoxinon-suche/server:/media/;\r\n    }\r\n\r\n    # redirect from the old urls to the wiki\r\n    location /downloads { return 301 $scheme://$host/wiki/; }\r\n    location /empfohleneprogramme { return 301 $scheme://$host/wiki/programme/; }\r\n    location /empfohlenedienste { return 301 $scheme://$host/wiki/dienste/; }\r\n    location /weitereempfehlungen { return 301 $scheme://$host/wiki/infoquellen/; }\r\n    location /extras { return 301 $scheme://$host/wiki/; }\r\n}\r\n\r\n```\r\n\r\n### 8.3 /etc/nginx/sites-enabled/anoxinon.de\r\n\r\n```\r\nserver {\r\n    listen 443 ssl http2;\r\n    listen [::]:443 ssl http2;\r\n    server_name anoxinon.de www.anoxinon.de;\r\n\r\n    ssl_stapling on;\r\n    ssl_stapling_verify on;\r\n    ssl_certificate /etc/letsencrypt/live/anoxinon.de/fullchain.pem; # managed by Certbot\r\n    ssl_certificate_key /etc/letsencrypt/live/anoxinon.de/privkey.pem; # managed by Certbot\r\n    ssl_dhparam /etc/letsencrypt/live/anoxinon.de/dhparam.pem;\r\n    ssl_trusted_certificate /etc/letsencrypt/live/anoxinon.de/chain.pem;\r\n\r\n    add_header X-Permitted-Cross-Domain-Policies none;\r\n    add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains; preload\" always;\r\n    add_header Referrer-Policy \"no-referrer\" always;\r\n    add_header X-Frame-Options \"deny\" always;\r\n    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;\r\n    add_header X-Content-Type-Options \"nosniff\" always;\r\n    add_header X-XSS-Protection \"1; mode=block\";\r\n\r\n    keepalive_timeout 70;\r\n \r\n    root /var/www/ci.anoxinon.de/master;\r\n\r\n    error_page 404 /404.html;\r\n\r\n    location /suche {\r\n        proxy_pass http://unix:/var/run/anoxinon-suche/server:/main/;\r\n    }\r\n}\r\n\r\n\r\n\r\n##\r\n## Wildcard vhost for dev.anoxinon.de\r\n## This is for serving all the Git branches which were build be CI/CD\r\n## (telnorran.anoxinon.de)\r\n## Ask Thomas Leister about this. <thomas.leister@anoxinon.de>\r\n##\r\n\r\nserver {\r\n    listen 443 http2 ssl;\r\n    listen [::]:443 http2 ssl;\r\n\r\n    ssl_certificate /etc/acme.sh/dev.anoxinon.de/fullchain.pem;\r\n    ssl_certificate_key /etc/acme.sh/dev.anoxinon.de/privkey.pem;\r\n\r\n    server_name ~^(([a-zA-Z0-9]|-)*)\\.dev\\.anoxinon\\.de$;\r\n    root /var/www/ci.anoxinon.de/$1/;\r\n\r\n    error_page 404 /404.html;\r\n    \r\n    add_header X-Permitted-Cross-Domain-Policies none;\r\n    add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains; preload\" always;\r\n    add_header Referrer-Policy \"no-referrer\" always;\r\n    add_header X-Frame-Options \"deny\" always;\r\n    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;\r\n    add_header X-Content-Type-Options \"nosniff\" always;\r\n    add_header X-XSS-Protection \"1; mode=block\";\r\n\r\n    location /suche {\r\n        proxy_pass http://unix:/var/run/anoxinon-suche/server:/main/;\r\n    }\r\n}\r\n```\r\n\r\n### 8.4 nginx Konfiguration neu laden\r\n\r\n``systemctl reload nginx`` sollte man nicht vergessen.\r\n\r\n## 9. Webhook\r\n\r\nJetzt gibt es Skripte, die alles machen, aber Niemanden, der diese startet. Das kann man aber ändern.\r\nDamit nicht jeder den Hook auslösen kann, braucht man Secrets, die man z.B. von ``openssl rand -hex 32`` bekommt.\r\n\r\nWeil die unkritisch sind/man damit keinen Schaden anrichten kann, stehen sie hier:\r\n\r\n- media: a3570dce8af7d2ae5a31a4bb5d4a7fcef964edc95fc3ee0061743c2234a3403f\r\n- main: 9b8d3feb4c0352dac2687192f5f2e23f9fa52482d91ae340e298d400126cff90\r\n\r\nDas Folgende läuft auf telnorran als root ab:\r\n\r\n```\r\napt install apache2 certbot python3-certbot-apache\r\na2enmod cgi\r\nsystemctl restart apache2\r\ntee /etc/apache2/sites-available/100-ci-system.conf <<\"EOF\"\r\n<VirtualHost *:80>\r\n  ServerName telnorran.anoxinon.de\r\n  Include conf-available/serve-cgi-bin.conf\r\n</VirtualHost>\r\nEOF\r\nln -s /etc/apache2/sites-available/100-ci-system.conf /etc/apache2/sites-enabled/\r\nrm /etc/apache2/sites-enabled/000-default.conf\r\nsystemctl reload apache2\r\ncertbot --apache\r\n```\r\n\r\n- E-Mail-Adresse gemäß <https://doku.anoxinon.de/books/general-tooling/page/lets-encrypt-tls-zertifikate> angeben\r\n- Domain: telnorran.anoxinon.de\r\n- HTTPS-Weiterleitung nicht aktivieren\r\n- Certbot hat bei Debian eine SystemD-Timer-Unit => es ist nichts zu beachten\r\n- Certbot legt eine SSL-Variante der Seite an (``100-ci-system-le-ssl.conf``)\r\n\r\nDann sollte <https://telnorran.anoxinon.de/> funktionieren.\r\n\r\n### 9.1 Webhook-Skripte\r\n\r\nBereit für Copy and Paste:\r\n\r\n```\r\ntee /usr/lib/cgi-bin/build-media.sh <<\"EOF\"\r\n#! /bin/bash\r\nSECRET=\"a3570dce8af7d2ae5a31a4bb5d4a7fcef964edc95fc3ee0061743c2234a3403f\"\r\nHASH=\"$(openssl sha256 -hmac \"$SECRET\" | sed \"s/(stdin)= //\")\"\r\n\r\nif [ \"$HASH\" = \"$HTTP_X_GITEA_SIGNATURE\" ]; then\r\n  echo \"Content-Type: text/plain\"\r\n  echo \"\"\r\n  echo \"signature valid\"\r\n\r\n  sudo -u buildbot /home/buildbot/buildjob-media.sh 2>&1\r\nelse\r\n  echo \"Status: 401\"\r\n  echo \"Content-Type: text/plain\"\r\n  echo \"\"\r\n  echo \"signature invalid\"\r\n  exit 1\r\nfi\r\nEOF\r\ntee /usr/lib/cgi-bin/build-main.sh <<\"EOF\"\r\n#! /bin/bash\r\nSECRET=\"9b8d3feb4c0352dac2687192f5f2e23f9fa52482d91ae340e298d400126cff90\"\r\nHASH=\"$(openssl sha256 -hmac \"$SECRET\" | sed \"s/(stdin)= //\")\"\r\n\r\nif [ \"$HASH\" = \"$HTTP_X_GITEA_SIGNATURE\" ]; then\r\n  echo \"Content-Type: text/plain\"\r\n  echo \"\"\r\n  echo \"signature valid\"\r\n\r\n  sudo -u buildbot /home/buildbot/buildjob-main.sh 2>&1\r\nelse\r\n  echo \"Status: 401\"\r\n  echo \"Content-Type: text/plain\"\r\n  echo \"\"\r\n  echo \"signature invalid\"\r\n  exit 1\r\nfi\r\nEOF\r\nchmod u=rw,g=rx,o= /usr/lib/cgi-bin/build-media.sh /usr/lib/cgi-bin/build-main.sh\r\nchown root:www-data /usr/lib/cgi-bin/build-media.sh /usr/lib/cgi-bin/build-main.sh\r\n```\r\n\r\nTesten kann man das Ganze **lokal** mittels:\r\n\r\n```\r\n# media\r\nRQC=\"{}\"\r\nSECRET=\"a3570dce8af7d2ae5a31a4bb5d4a7fcef964edc95fc3ee0061743c2234a3403f\"\r\nHASH=\"$(echo -n \"$RQC\" | openssl sha256 -hmac \"$SECRET\" | sed \"s/(stdin)= //\")\"\r\ncurl --header \"X-Gitea-Signature: $HASH\" -X POST --data \"$RQC\"  https://telnorran.anoxinon.de/cgi-bin/build-media.sh\r\n\r\n# main\r\nRQC=\"{}\"\r\nSECRET=\"9b8d3feb4c0352dac2687192f5f2e23f9fa52482d91ae340e298d400126cff90\"\r\nHASH=\"$(echo -n \"$RQC\" | openssl sha256 -hmac \"$SECRET\" | sed \"s/(stdin)= //\")\"\r\ncurl --header \"X-Gitea-Signature: $HASH\" -X POST --data \"$RQC\"  https://telnorran.anoxinon.de/cgi-bin/build-main.sh\r\n```\r\n\r\nNatürlich fehlt da noch etwas - man sollte einen Fehler von sudo angezeigt bekommen.\r\n\r\n### 9.2 Berechtigungen erteilen\r\n\r\nHier erlaubt man dem Webserver, die entsprechenden Skripte auszuführen.\r\n\r\n```visudo --file=/etc/sudoers.d/buildbot```\r\n\r\nDie Datei braucht zwei Zeilen:\r\n\r\n```\r\nwww-data ALL=(buildbot) NOPASSWD: /home/buildbot/buildjob-media.sh\r\nwww-data ALL=(buildbot) NOPASSWD: /home/buildbot/buildjob-main.sh\r\n```\r\n\r\nwww-data darf damit unabhängig vom Hostnamen als buildbot ohne Eingabe eines Passwortes die Skripte ausführen.\r\n\r\n### 9.3 Webserver reduzieren\r\n\r\nUnter ```telnorran.anoxinon.de``` gibt es noch Inhalte, die dort nicht passen.\r\n\r\nDafür ruft man ```nano /etc/apache2/apache2.conf``` auf. Dann sucht man nach ```<Directory /var/www/>``` und kommentiert es aus.\r\nDann noch am Ende das hier ergänzen:\r\n\r\n```\r\nServerSignature Off\r\nServerTokens Prod\r\n```\r\n\r\nNach einem ```systemctl reload apache2``` gibt es ein Forbidden und die Header enthalten nicht mehr die Server-Version.\r\n\r\n### 9.4 Hooks bei Codeberg eintragen\r\n\r\nIn den Repository-Einstellungen bei Codeberg gibt es den Abschnitt Webhooks. Alte Einträge von Drone können dort\r\ndeaktiviert werden.\r\n\r\nBeim Hinzufügen ist der Typ \"Gitea\" passend. Die Target-URLs und Secrets stehen am Ende vom Abschnitt 9.1.\r\nAls HTTP-Methode passt POST, als Content-Type JSON, getriggert werden soll nur bei Push Events, der Branchfilter kann\r\nauf ``*`` bleiben, damit alle Branches den Trigger auslösen.\r\n\r\nBei den beiden Webseiten-Repositories muss jeweils der Hook eingetragen werden.\r\n\r\n### 10. Cronjobs\r\n\r\nDamit es auch ohne Webhook läuft:\r\n\r\n```\r\nsudo -s -u buildbot\r\ncrontab -e\r\n```\r\n\r\nDann zwei Zeilen:\r\n\r\n```\r\n13 * * * * /home/buildbot/buildjob-media.sh &> /dev/null\r\n47 * * * * /home/buildbot/buildjob-main.sh &> /dev/null\r\n```\r\n\r\n### 11. weitere Altlasten entfernen\r\n\r\n#### 11.1 argos.anoxinon.de\r\n\r\nDie 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.\r\n\r\nDann gibt es noch den Hilfsbenutzer für Drone, den man mit ``deluser --remove-home drone`` entfernen kann.\r\n\r\n#### 11.2 telnorran.anoxinon.de\r\n\r\n```\r\ncd\r\nrm -rf buildcontainer-hugo drone-ssh-keys run-drone-agent.sh run-drone-master.sh\r\nyes | docker system prune\r\nrm -rf /var/lib/drone/\r\napt remove -y docker-ce\r\napt autoremove -y\r\n# sudo was indirectly installed, but it is needed\r\napt install -y sudo\r\napt-mark showmanual\r\n# remove more unused things\r\napt remove -y containerd.io docker-ce-cli\r\n```\r\n\r\n#### 11.3 Codeberg\r\n\r\n- die alten Webhooks bei Codeberg können entfernt werden\r\n- der Account ``anoxinon.cicd`` bei Codeberg wird nicht mehr benötigt und kann entfernt werden"platform: nulldescription: "CICD Server (Continuous Integration / Continuous Delivery)"primary_ip4: nullprimary_ip6: nullcustom_fields: {}start_on_boot: "off"config_template: nullinterface_count: 0local_context_data: nullvirtual_disk_count: 0
Documents
None

Related Changes

None