From b77ef80b5692721e18fc46cedaec60ad35267c07 Mon Sep 17 00:00:00 2001 From: Daniel Maksymilian Syrnicki Date: Sat, 18 Apr 2026 12:10:06 +0200 Subject: [PATCH] feat(website): legal pages (Impressum/Datenschutz) + auto-deploy on push-to-main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two coupled changes that make sense to land together: 1. Legal pages required under German law - /imprint/ + /de/impressum/ — §5 DDG disclosure (contact is email plus Forgejo-Issues as the second quick-contact channel, per ECJ C-298/07 no phone number required) - /privacy/ + /de/datenschutz/ — Art. 13 GDPR minimum: server-log processing (IP, UA, URL, retention ≤30 days), no cookies, no tracking, no third-party embeds. RLP Landesbeauftragter as the competent supervisory authority. - Footer partial linked from every page, localized per language. - DE versions are legally binding; EN versions are courtesy translations noting that. 2. Auto-deploy wired up - New workflow .forgejo/workflows/deploy-site.yml fires on push-to-main with paths under website/**. Runs on the self-hosted runner, which *is* forge-runner-01 — so "deploy" is just a local rsync into /srv/furtka-site and a hugo build into /var/www/furtka.org. No SSH, no secrets. - website/deploy-ci.sh is the SSH-free counterpart of deploy.sh, invoked by the workflow. - compose.yml bind-mounts /srv/furtka-site and /var/www/furtka.org into the runner container at matching paths so the workflow can reach them. Requires a one-time `docker compose up -d` on the runner host to pick the mounts up. - deploy.sh is kept for out-of-band manual deploys (testing from a local branch, CI outage) but gets a header comment pointing at the CI path as the normal flow. Co-Authored-By: Claude Opus 4.7 (1M context) --- .forgejo/workflows/deploy-site.yml | 39 ++++++++++++++ ops/forgejo-runner/compose.yml | 7 +++ website/content/datenschutz.de.md | 79 +++++++++++++++++++++++++++ website/content/datenschutz.md | 80 ++++++++++++++++++++++++++++ website/content/impressum.de.md | 26 +++++++++ website/content/impressum.md | 29 ++++++++++ website/deploy-ci.sh | 27 ++++++++++ website/deploy.sh | 8 ++- website/layouts/partials/footer.html | 7 +++ 9 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 .forgejo/workflows/deploy-site.yml create mode 100644 website/content/datenschutz.de.md create mode 100644 website/content/datenschutz.md create mode 100644 website/content/impressum.de.md create mode 100644 website/content/impressum.md create mode 100755 website/deploy-ci.sh diff --git a/.forgejo/workflows/deploy-site.yml b/.forgejo/workflows/deploy-site.yml new file mode 100644 index 0000000..a50b69d --- /dev/null +++ b/.forgejo/workflows/deploy-site.yml @@ -0,0 +1,39 @@ +name: Deploy site + +# Auto-deploy the Hugo site to /var/www/furtka.org on push-to-main. +# Only fires when content under website/ changes — everything else +# (Python code, ISO build, runbook docs) is unaffected. +# +# Runs on the self-hosted runner, which is forge-runner-01 — the same +# host that serves furtka.org. So the "deploy" is just a local rsync +# of the Hugo source into /srv/furtka-site and a `hugo` build into +# /var/www/furtka.org. No SSH, no secrets, no cross-host anything. +# +# Requires two bind-mounts on the runner container (/srv/furtka-site +# and /var/www/furtka.org → same paths inside). See compose.yml. +on: + push: + branches: [main] + paths: + - 'website/**' + +concurrency: + group: deploy-site + cancel-in-progress: true + +jobs: + deploy: + runs-on: self-hosted + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + + - name: Install hugo + rsync + # Runner image is alpine-based; apk is fast and cached. + # Pinning is intentionally skipped — alpine:latest moves hugo + # forward in lockstep with upstream, and the site only uses + # baseline features. + run: apk add --no-cache hugo rsync + + - name: Deploy + run: ./website/deploy-ci.sh diff --git a/ops/forgejo-runner/compose.yml b/ops/forgejo-runner/compose.yml index 7f33e71..76e71ba 100644 --- a/ops/forgejo-runner/compose.yml +++ b/ops/forgejo-runner/compose.yml @@ -19,6 +19,13 @@ services: volumes: - ./data:/data - /var/run/docker.sock:/var/run/docker.sock + # Auto-deploy of furtka.org runs inside this container — the + # runner host *is* the web server. Bind these at matching paths + # so rsync/hugo just see plain local filesystem. Without these + # mounts, .forgejo/workflows/deploy-site.yml can't reach the + # source tree or the webroot. + - /srv/furtka-site:/srv/furtka-site + - /var/www/furtka.org:/var/www/furtka.org command: >- /bin/sh -c "apk add --no-cache nodejs docker-cli && sleep 5 && forgejo-runner daemon --config /data/config.yml" diff --git a/website/content/datenschutz.de.md b/website/content/datenschutz.de.md new file mode 100644 index 0000000..7de6dfd --- /dev/null +++ b/website/content/datenschutz.de.md @@ -0,0 +1,79 @@ +--- +title: "Datenschutzerklärung" +translationKey: "privacy" +sitemap: + priority: 0.2 +--- + +### Kurzfassung + +Diese Website setzt **keine Cookies**, lädt **keine Schriften oder +Skripte von Drittanbietern**, bindet **keine Analyse- oder +Tracking-Dienste** ein und enthält **keine externen Einbettungen** +(YouTube, Maps, Social-Media-Buttons, …). Technisch anfallend sind +ausschließlich kurzfristige Server-Zugriffsprotokolle. + +### Verantwortlicher + +
+Daniel Maksymilian Syrnicki
+Hauptstraße 35
+55569 Monzingen
+Deutschland
+E-Mail: hallo@furtka.org +
+ +### Server-Logfiles + +Beim Aufruf der Website werden technisch notwendige Daten vom Browser an +den Server übermittelt und dort in Logdateien gespeichert: + +- Datum und Uhrzeit des Aufrufs +- IP-Adresse (in gekürzter Form) +- aufgerufene URL +- HTTP-Statuscode und übertragene Datenmenge +- Referrer (falls vom Browser gesendet) +- User-Agent-Kennung des Browsers + +**Zweck:** Auslieferung der Website und Abwehr missbräuchlicher Zugriffe. +**Rechtsgrundlage:** Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse +an Betrieb und Sicherheit). +**Speicherdauer:** maximal 30 Tage, danach automatische Löschung. +**Empfänger:** keine Weitergabe. Die Website läuft auf eigener +Infrastruktur; es gibt keinen externen Auftragsverarbeiter. +**Drittlandübermittlung:** keine. + +### Cookies und Tracking + +Keine. Es werden keine Cookies gesetzt, kein LocalStorage oder +SessionStorage verwendet und keine Tracking- oder Analyse-Dienste +eingebunden. Eine Einwilligung nach § 25 TDDDG ist daher nicht +erforderlich. + +### Ihre Rechte + +Sie haben jederzeit das Recht auf: + +- Auskunft über die zu Ihrer Person gespeicherten Daten (Art. 15 DSGVO) +- Berichtigung unrichtiger Daten (Art. 16 DSGVO) +- Löschung (Art. 17 DSGVO) +- Einschränkung der Verarbeitung (Art. 18 DSGVO) +- Datenübertragbarkeit (Art. 20 DSGVO) +- Widerspruch gegen die Verarbeitung (Art. 21 DSGVO) + +Anfragen hierzu richten Sie bitte per E-Mail an hallo@furtka.org. + +### Beschwerderecht + +Sie haben das Recht, sich bei einer Datenschutz-Aufsichtsbehörde zu +beschweren. Zuständig ist: + +**Der Landesbeauftragte für den Datenschutz und die Informationsfreiheit +Rheinland-Pfalz** +Hintere Bleiche 34, 55116 Mainz +Website: + +### Stand + +Diese Erklärung ist aktuell gültig und wurde zuletzt am 18.04.2026 +aktualisiert. diff --git a/website/content/datenschutz.md b/website/content/datenschutz.md new file mode 100644 index 0000000..4c88952 --- /dev/null +++ b/website/content/datenschutz.md @@ -0,0 +1,80 @@ +--- +title: "Privacy" +translationKey: "privacy" +url: /privacy/ +sitemap: + priority: 0.2 +--- + +### In short + +This website sets **no cookies**, loads **no third-party fonts or +scripts**, embeds **no analytics or tracking services**, and contains +**no external embeds** (YouTube, Maps, social buttons, …). The only +technical data collected is short-lived server access logs. + +### Controller + +
+Daniel Maksymilian Syrnicki
+Hauptstraße 35
+55569 Monzingen
+Germany
+Email: hallo@furtka.org +
+ +### Server logs + +When you load a page, your browser sends technically necessary data to +the server, which stores it in log files: + +- Date and time of the request +- IP address (in shortened form) +- Requested URL +- HTTP status code and bytes transferred +- Referrer (if sent by the browser) +- User-agent string + +**Purpose:** serving the website and defending against abusive traffic. +**Legal basis:** Art. 6(1)(f) GDPR — legitimate interest in operation +and security. +**Retention:** up to 30 days, then automatically deleted. +**Recipients:** none. The site runs on our own infrastructure; no +external processor is involved. +**Transfers outside the EU/EEA:** none. + +### Cookies and tracking + +None. No cookies are set, no localStorage or sessionStorage is used, and +no tracking or analytics services are embedded. Because of this, no +consent under § 25 TDDDG (German implementation of the ePrivacy +directive) is required. + +### Your rights + +You have the right at any time to: + +- Information about the data stored about you (Art. 15 GDPR) +- Correction of inaccurate data (Art. 16 GDPR) +- Erasure (Art. 17 GDPR) +- Restriction of processing (Art. 18 GDPR) +- Data portability (Art. 20 GDPR) +- Object to processing (Art. 21 GDPR) + +Send requests to hallo@furtka.org. + +### Right to complain + +You have the right to file a complaint with a data protection +supervisory authority. The competent one is: + +**Der Landesbeauftragte für den Datenschutz und die Informationsfreiheit +Rheinland-Pfalz** +Hintere Bleiche 34, 55116 Mainz, Germany +Website: + +### Last updated + +This statement was last updated on 2026-04-18. + +The German version of this privacy statement is the legally binding one. diff --git a/website/content/impressum.de.md b/website/content/impressum.de.md new file mode 100644 index 0000000..4d17140 --- /dev/null +++ b/website/content/impressum.de.md @@ -0,0 +1,26 @@ +--- +title: "Impressum" +translationKey: "imprint" +sitemap: + priority: 0.2 +--- + +Angaben gemäß § 5 DDG. + +
+Daniel Maksymilian Syrnicki
+Hauptstraße 35
+55569 Monzingen
+Deutschland +
+ +### Kontakt + +- E-Mail: hallo@furtka.org +- Forgejo-Issues: + +### Hinweis zum Projekt + +Furtka ist ein privates Open-Source-Projekt. Es ist kein Unternehmen, +bietet keine kostenpflichtigen Leistungen an und nimmt keine Zahlungen +entgegen. Der Quelltext steht unter der AGPL-3.0. diff --git a/website/content/impressum.md b/website/content/impressum.md new file mode 100644 index 0000000..1d9c50c --- /dev/null +++ b/website/content/impressum.md @@ -0,0 +1,29 @@ +--- +title: "Imprint" +translationKey: "imprint" +url: /imprint/ +sitemap: + priority: 0.2 +--- + +Information pursuant to § 5 DDG (German Digital Services Act). + +
+Daniel Maksymilian Syrnicki
+Hauptstraße 35
+55569 Monzingen
+Germany +
+ +### Contact + +- Email: hallo@furtka.org +- Forgejo issues: + +### Project note + +Furtka is a private open-source project. It is not a company, offers no +paid services, and does not accept payments. The source code is licensed +under AGPL-3.0. + +The German version of this imprint is the legally binding one. diff --git a/website/deploy-ci.sh b/website/deploy-ci.sh new file mode 100755 index 0000000..454622b --- /dev/null +++ b/website/deploy-ci.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Auto-deploy path run by .forgejo/workflows/deploy-site.yml inside the +# self-hosted runner — which is forge-runner-01, the actual web server. +# Same effect as deploy.sh but without the SSH hop: everything is local. +# +# Requires `rsync` and `hugo` on PATH. The workflow apk-installs both +# before invoking this script. +set -euo pipefail + +HERE="$(cd "$(dirname "$0")" && pwd)" +SRCROOT="${FURTKA_SRCROOT:-/srv/furtka-site}" +WEBROOT="${FURTKA_WEBROOT:-/var/www/furtka.org}" + +echo "==> rsync website/ → $SRCROOT" +rsync -az --delete \ + --exclude='.hugo_build.lock' \ + --exclude='public/' \ + --exclude='resources/' \ + --exclude='deploy.sh' \ + --exclude='deploy-ci.sh' \ + "$HERE/" "$SRCROOT/" + +echo "==> hugo build → $WEBROOT" +cd "$SRCROOT" +hugo --minify --cleanDestinationDir -d "$WEBROOT" + +echo "OK: deployed to https://furtka.org/" diff --git a/website/deploy.sh b/website/deploy.sh index 04a5cea..9ef1b17 100755 --- a/website/deploy.sh +++ b/website/deploy.sh @@ -1,6 +1,12 @@ #!/usr/bin/env bash -# Deploy furtka.org to forge-runner-01. +# Manual deploy of furtka.org to forge-runner-01. # Rsyncs the Hugo source up to the VM and builds it in-place. +# +# Normal path is now the `Deploy site` Forgejo workflow, which auto-fires +# on every push-to-main that touches website/** — see +# .forgejo/workflows/deploy-site.yml. Keep this script for out-of-band +# pushes (testing from a local branch, recovering from a CI outage, +# whatever). The in-CI equivalent that skips the SSH hop is deploy-ci.sh. set -euo pipefail HOST="${FURTKA_HOST:-forge-runner}" diff --git a/website/layouts/partials/footer.html b/website/layouts/partials/footer.html index 48af58b..4b62096 100644 --- a/website/layouts/partials/footer.html +++ b/website/layouts/partials/footer.html @@ -5,5 +5,12 @@ · AGPL-3.0 · {{ site.Params.contactEmail }}

+

+ {{ if eq site.Language.Lang "de" -}} + Impressum · Datenschutz + {{- else -}} + Imprint · Privacy + {{- end }} +