No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Christian Säum 982388aae6
All checks were successful
CI – Validate & Release / mirror (push) Successful in 2s
CI – Validate & Release / validate (push) Successful in 10s
CI – Validate & Release / release (push) Has been skipped
Merge pull request 'chore(license): AGPL-3.0-or-later + Copyright-Hinweis' (#1) from chore/add-license into main
2026-09-02 19:47:33 +00:00
.forgejo/workflows fix(ci): retry Codeberg pushes on 502/504, prefer compose v2 (dockerfile_inline) 2026-06-21 18:13:19 +02:00
.idea refactor(gtm-sstm): clean up stack to reusable template 2026-06-13 13:59:52 +02:00
.env refactor(gtm-sstm): clean up stack to reusable template 2026-06-13 13:59:52 +02:00
.gitignore chore(gitignore): ignore dist/ (CI build artifacts) 2026-06-21 14:30:14 +02:00
AGENTS.md refactor(gtm-sstm): clean up stack to reusable template 2026-06-13 13:59:52 +02:00
CICD-Actions.md docs(ci): align docs with hardened pipeline (compose v2 runner image, Codeberg 502/504 retry) 2026-06-21 18:57:47 +02:00
CLAUDE.md refactor(gtm-sstm): clean up stack to reusable template 2026-06-13 13:59:52 +02:00
docker-compose.yml Healthcheck entfernt - Autoheal reagiert auf den internen Healthcheck und Network auf Variable geändert 2026-06-14 13:03:14 +02:00
LICENSE chore(license): add AGPL-3.0-or-later license and copyright notice 2026-09-02 21:32:41 +02:00
Projekt.md refactor(gtm-sstm): clean up stack to reusable template 2026-06-13 13:59:52 +02:00
README.md chore(license): add AGPL-3.0-or-later license and copyright notice 2026-09-02 21:32:41 +02:00

Google Tag Manager – Server-Side Tagging Stack

Dieser Stack betreibt Google Tag Manager (GTM) als selbst gehostete Server-Side-Tagging-Lösung. Er besteht aus zwei Containern: einem Tag-Server (produktiver Endpunkt) und einem Preview-Server (Debugging & Vorschau).


Voraussetzungen

  • Docker & Docker Compose
  • Laufender [Traefik] Reverse Proxy mit dem externen Netzwerk traefik_proxy_network
  • Zwei DNS-Einträge auf den Server (je einen für Tag-Server und Preview-Server)
  • Laufender [Autoheal] Stack auf dem Server

Verzeichnisstruktur

GTM/
├── docker-compose.yml           ← Haupt-Stack (Tag-Server + Preview-Server)
├── .env                         ← Konfiguration (Template mit Platzhaltern)
├── README.md                    ← Diese Datei

Einrichtung

1. Google Tag Manager Container-Konfiguration holen

  1. Auf tagmanager.google.com einloggen
  2. Einen neuen Server-Container anlegen (Typ: Server)
  3. In den Container-Einstellungen den Wert unter „Container-Konfiguration" kopieren — dieser Base64-kodierte String ist der Wert für CONTAINER_CONFIG

2. .env Datei anlegen

COMPOSE_PROJECT_NAME=mein-gtm-stack

# Base64-kodierter String aus den GTM Container-Einstellungen
CONTAINER_CONFIG=aWQ9R1RNLVhYWFhYWFhYJmVudj0xJmF1dGg9XXXXXXXXXX==

# Traefik Host-Regeln
HOSTRULEGTM=Host(`gtm.domain.de`)
HOSTRULEPREVIEW=Host(`gtm-preview.domain.de`)

# URL des Preview-Servers (ohne https://)
PREVIEW_SERVER_URL=gtm-preview.domain.de

# Name des externen Traefik-Netzwerks
PROXY_NETWORK=traefik_proxy_network

TIMEZONE=Europe/Berlin

3. GTM Container-URLs eintragen

Nach dem ersten Start müssen die URLs in GTM hinterlegt werden:

  1. In GTM die Container-Einstellungen öffnen
  2. Unter „Server-Container-URLs" beide Domains eintragen:
    • Tag-Server: https://gtm.domain.de
    • Preview-Server: https://gtm-preview.domain.de
  3. Speichern

4. Stack starten

docker compose up -d

Healthcheck

Beide Container prüfen regelmäßig den Endpoint /healthy auf Port 8080:

Container Healthcheck-URL (intern) Öffentliche URL
Tag-Server http://localhost:8080/healthy https://gtm.domain.de/healthy
Preview-Server http://localhost:8080/healthy https://gtm-preview.domain.de/healthy

Gibt der Endpoint HTTP 200 zurück, ist der Container healthy. Bei einem Fehler wird der Container nach 3 fehlgeschlagenen Versuchen als unhealthy markiert und von Autoheal neugestartet.

Healthcheck-Parameter:

Parameter Wert Bedeutung
interval 30s Prüfintervall
timeout 10s Maximale Antwortzeit pro Prüfung
retries 3 Fehlversuche bis Status unhealthy
start_period 60s Wartezeit nach Container-Start (GTM lädt Konfiguration von Google)

Autoheal-Integration

Die GTM-Container sind für den zentralen Autoheal-Stack vorkonfiguriert:

labels:
  - autoheal=true                # Markiert den Container zur Überwachung
  - autoheal.stop.timeout=10     # Wartezeit in Sekunden vor SIGKILL beim Neustart

Autoheal startet den Container automatisch neu sobald der Status unhealthy ist. Der Autoheal-Stack muss separat auf dem Server laufen (Stack docker-autoheal-neustart).


Nützliche Befehle

# Stack starten
docker compose up -d

# Stack stoppen
docker compose down

# Logs ansehen
docker compose logs -f

# Logs eines einzelnen Containers
docker compose logs -f gtm-tag-server
docker compose logs -f gtm-preview-server

# Healthcheck-Status prüfen
docker inspect --format='{{.State.Health.Status}}' <container-name>

# Alle Container-Status auf einmal
docker ps --format "table {{.Names}}\t{{.Status}}"

Troubleshooting

Container bleibt auf starting / wird nicht healthy:

  • GTM braucht beim Start bis zu 60 Sekunden um die Konfiguration von Google zu laden
  • Logs prüfen: docker compose logs -f gtm-tag-server
  • Sicherstellen dass CONTAINER_CONFIG in der .env korrekt ist

/healthy gibt keinen 200 zurück:

  • Prüfen ob CONTAINER_CONFIG gültig und vollständig ist
  • In GTM unter Container-Einstellungen den Base64-String neu kopieren

Preview-Server nicht erreichbar:

  • PREVIEW_SERVER_URL in der .env darf kein https:// enthalten, nur die Domain
  • In den GTM Container-Einstellungen muss die Preview-URL korrekt eingetragen sein

Traefik routet nicht:

  • Sicherstellen dass das Netzwerk traefik_proxy_network existiert: docker network ls
  • Traefik-Dashboard prüfen ob der Router registriert ist

CI/CD & Spiegelung

Die Pipeline (.forgejo/workflows/ci.yml) läuft self-hosted auf Forgejo, ganz ohne externe Actions (Checkout per git clone):

  • validate (jeder Push/PR auf main + Tags): docker compose config -q, yamllint (relaxed) und gitleaks (nur Working-Tree). Es wird docker compose v2 genutzt (Runner-Image catthehacker/ubuntu:act-latest; nötig u. a. für v2-Keys wie dockerfile_inline), apt nur als Fallback – kein 64-MB-github-Download.
  • mirror (nur Push, needs: validate): spiegelt main + Tags erst nach grünen Checks nach Codeberg (Org Docker-Stacks), mit Retry gegen transiente 502/504. Forgejos eingebauten Push-Mirror dafür nicht zusätzlich aktivieren.
  • release (nur Tag v*): baut ein schlankes Deploy-ZIP und hängt es an ein Forgejo-Release und – als Backup – an ein Codeberg-Release (die Releases-Unit am Codeberg-Repo wird dabei automatisch aktiviert).

Release auslösen:

git tag v1.1
git push origin v1.1

Details siehe CICD-Actions.md.

Lizenz

Copyright (C) 2026 Christian Säum – web-seo-consulting.eu

Dieses Projekt steht unter der GNU Affero General Public License, Version 3 oder (nach deiner Wahl) einer späteren Version (AGPL-3.0-or-later). Der vollständige Lizenztext steht in der Datei LICENSE.

Du darfst die Software nutzen, weitergeben und – auch kommerziell – verkaufen. Gibst du eine veränderte Fassung weiter oder betreibst du sie über ein Netzwerk (z. B. als Dienst), muss deren vollständiger Quellcode ebenfalls unter der AGPL-3.0-or-later verfügbar sein. Der Copyright-Hinweis und die Nennung des ursprünglichen Autors dürfen nicht entfernt werden.

Diese Angabe betrifft nur die in diesem Repository enthaltenen eigenen Dateien (Konfiguration, Skripte, Anpassungen). Eingebundene Fremdsoftware und Container-Images unterliegen weiterhin ihren eigenen Lizenzen.