Datenschutz-freundliche Website

Inhaltsverzeichnis:


🛡️ Eigener datensparsamer Webserver mit Caddy, Docker und OpenSSH (ohne Plesk, ohne Logs)

Du möchtest eine Website hosten, aber ohne unnötige Server-Logs, ohne Drittanbieter, ohne FTP und ohne Plesk? Dann bist du hier richtig.

Wenn du in Richtung Hoster etwas suchst, dann bist du falsch, da ChrootDirectory bei sFTP nicht dafür angelegt ist / wurde, da sind Änderungen nötig, da jeder User sieht, welche User angelegt sind. anders wäre das viel mehr Aufwand.

In dieser Anleitung erfährst du Schritt für Schritt, wie du:

  • einen eigenen V-Server aufsetzt,
  • SFTP-Zugriff mit OpenSSH einrichtest,
  • Docker und Caddy verwendest, um eine statische Website bereitzustellen,
  • alle Logs deaktivierst,
  • und automatische Updates per Watchtower einrichtest.

🔁 Hinweis: Überall, wo example.com oder examplecom steht, musst du deinenr kommagetren echten Domainnamen einsetzen (z. B. simon99.de oder simon99de).
Wir legen für jede Website einen eigenen User an, damit man die Webseiten dann einfacher ist, für verschiedene Webseiten zu nutzen.

Überall wo webadmin steht, kann man es lassen oder überall auch ändern in etwas anderes. das ist ein 2. Benutzer für die Docker user Umgebung, da Docker keinChrootDirectory root mag.


Sichere SSH Verbindung (Linux Desktop)

Für dein Linux-Setup (z. B. Publii-Upload, SSH-Zugang, SFTP) ist es am besten, wenn du einen ganz normalen OpenSSH-Schlüssel nutzt anstatt ein Passwort:

ssh-keygen -t ed25519 -C "user@deine.server.ip.adresse"

Das erstellt automatisch:

  • ~/.ssh/id_ed25519 (privater Schlüssel)

  • ~/.ssh/id_ed25519.pub (öffentlicher Schlüssel)

Dann einfach den Public Key auf dem Server in ~/.ssh/authorized_keys eintragen.

Abschließend SSH / Server neu starten (Auf dem Server):

sudo systemctl restart ssh

🔧 SSH-Konfiguration (empfohlen):

Bearbeite (Linux Desktop):

nano ~/.ssh/config

Trage z. B. ein:

Host vserver1
   HostName deine.server.ip.adresse
   User root
   IdentityFile ~/.ssh/private-schlüssel-datei
Port 22

Dann kannst du dich ganz einfach verbinden mit:

ssh vserver1

🔐 Vergiss nicht (wenn nicht bereits so erstellt wurde):

chmod 600 ~/.ssh/private-schlüssel-datei
 

🔧 V-Server vorbereiten (Debian 13)

Installiere ein frisches Debian 13-Image auf deinem V-Server. Dadurch wird sichergestellt, dass keinerlei Altlasten oder Logdateien vorhanden sind.

Als Root-Nutzer einmal updaten und Werkzeuge installieren:

apt update && apt upgrade -y
apt install -y curl nano ufw gnupg2 ca-certificates lsb-release apt-transport-https unattended-upgrades needrestart

Firewall konfigurieren:

Firewall absichern (nur 22, 80, 443):
Nur nötig, wenn du deine Ports schützen willst. Kann optional übersprungen werden.

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

🧰 Sicherheitsupdates aktivieren:

sudo dpkg-reconfigure --priority=low unattended-upgrades

Wähle „Yes“, um automatische Sicherheitsupdates zu aktivieren.

Updates anpassen:

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

🧹 Automatische Bereinigung (optional)
Damit bleiben keine alten Kernel oder Bibliotheken übrig.
// entfernen:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";

Suche und ersetze die zeile für automatische neustarts (etwar mittig in der datei):
// entfernen und auf true setzen:
Unattended-Upgrade::Automatic-Reboot "true";

Hier stellt man ein, wann der neustart gemacht werden soll:
// entfernen und eine Uhrzeit deiner Wahl wählen:
Unattended-Upgrade::Automatic-Reboot-Time "03:30";

und das noch ganz am ende einfügen:
// Das sorgt dafür, dass Sicherheitsupdates erst nach 14 Tagen Wartezeit installiert werden  
// damit sie nicht sofort eingespielt werden, falls sie fehlerhaft sind.
Unattended-Upgrade::MinimumAge "14";

Update häufigkeit anpassen:

sudo nano /etc/apt/apt.conf.d/10periodic

hier kommt der Inhalt rein:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";

🧪 Testen: (optional)

Zum Test, ob alles funktioniert:

sudo unattended-upgrades --dry-run --debug
➡️ Zeigt an, welche Updates jetzt installiert würden,
ohne sie wirklich zu installieren.

🔐 OpenSSH mit SFTP einrichten (statt FTP oder SFTPGo)

Benutzer Anlegen:

Erstelle einen Benutzer für z. B. Publii, deine Website zum hochladen – z. B. examplecom:

sudo adduser examplecom

sshd_config anpassen:

Dann mit sudo nano /etc/ssh/sshd_config folgende Zeilen am Ende einfügen:
das bewirkt, dass der User nur die SFTP Verbindung ohne SSH nutzen kann. 

Match User examplecom
  ChrootDirectory /home
  ForceCommand internal-sftp -d /%u
  AllowTcpForwarding no X11Forwarding no

Mit STRG + O und dann Enter Speichert man dann die Datei.
Mit STRG + X verlässt man die Datei / den nano Editor dann

Kann mehrere user aufnehmen mit zb.:

Match User examplecom,examplede,exampleorg
  ...

Abschließend SSH neu starten:

sudo systemctl restart ssh

Jetzt kann Publii via SFTP (OpenSSH) direkt in /home/ bzw. in /home/examplecom/ Webseiten hochladen.


📦 Docker und Docker Compose installieren

Jetzt erstelle einen Benutzer für deine Website / Docker-Umgebung, wenn du als root user eingeloggt bist. da gebe ich dir 2 Möglichkeiten. einmal ohne ssh + passwort und einmal mit (A und B)

A: ohne Passwort / Login – z. B. webadmin:

adduser --disabled-password --gecos "" webadmin

Login über den befehl möglich als zb. root oder ein anderer Nutzer:

su - webadmin

B: mit Passwort / Login – z. B. webadmin:

adduser webadmin


Den aktuellen Benutzer der Docker-Gruppe hinzufügen:

getent group docker || sudo groupadd docker
sudo usermod -aG docker webadmin

(Danach ggf. einmal neu einloggen)

Docker-Repository hinzufügen:

docs.docker.com (Offizielle Anleitung)

1. Docker einrichten aptRepository. 

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Docker installieren & starten:

2. Installieren Sie die Docker-Pakete. 

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Docker starten & prüfen:

Docker beim Boot starten
Meist schon aktiv, aber sicherheitshalber:

sudo systemctl enable --now docker

Der Docker-Dienst startet nach der Installation automatisch. Um zu überprüfen, ob Docker läuft, verwenden Sie:

sudo systemctl status docker

Bei einigen Systemen ist dieses Verhalten möglicherweise deaktiviert und erfordert einen manuellen Start:

sudo systemctl start docker

3. Überprüfen Sie, ob die Installation erfolgreich war, indem Sie den hello-world Bild: 

sudo docker run hello-world

 


🌐 Website per Docker + Caddy bereitstellen (ohne Logs, mit HTTPS)

Login über den befehl möglich als zb. root oder als Nutzer einloggen:

su - webadmin

Erstelle ein Arbeitsverzeichnis (z. B. /home/webadmin/docker) und wechsle hinein:

mkdir -p ~/docker
cd ~/docker

📄 Caddyfile anlegen

Erstelle eine Datei namens Caddyfile mit folgendem Inhalt – angepasst an deinen Domainnamen:

nano Caddyfile
# Catch-All fuer unbekannte Domains oder direkte IP-Aufrufe. Nur http / 80 moeglich, https funktioniert nicht.
:80 {
  redir https://example.com/
    log {
        output discard
    }
}

# www Redirect, Weiterleitung an "redir ..."
www.example.com,
wwww.example.com,
ww.example.com,
w.example.com {
  redir https://example.com{uri}
    log {
        output discard
    }
}

# Hauptdomain
example.com {
  root * /srv/www/examplecom
    file_server

    handle_errors {
        @404 {
            expression {http.error.status_code} == 404
        }
        rewrite @404 /404.html
        file_server
    }
    log {
        output discard
    }
}

Diese Konfiguration sorgt für:

  • 📦 HTTPS + automatische Zertifikate über Let's Encrypt
  • 🔁 Weiterleitung von www.example.com → example.com
  • ❌ Keine Logs durch output discard
  • 🧭 Eine eigene 404.html-Seite bei Fehlern

Mit STRG + O und dann Enter Speichert man dann die Datei.
Mit STRG + X verlässt man die Datei / den nano Editor dann

🛠️ Docker Compose-Datei erstellen

Lege die Datei docker-compose.yml im selben Verzeichnis an:

nano docker-compose.yml
services:
  caddy:
    image: caddy:alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
    - ./Caddyfile:///etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    - /home/examplecom:/srv/www/examplecom
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_LABEL_ENABLE=true
      - WATCHTOWER_POLL_INTERVAL=1209600 # 14 Tage in Sekunden

volumes:
  caddy_data:
  caddy_config:

hier muss man etwas ändern und zwar darf hier keine 3 /// sondern nur eines stehen!: - ./Caddyfile:///etc/caddy/Caddyfile also: ...:/etc/caddy/Caddyfile
(ist ein Bug bei der Website bei mir)

  • 📂 Caddyfile: definiert alle Domains, Weiterleitungen, Dateipfade und Einstellungen.
  • 📁 /home/examplecom/: dort liegen die von Publii erzeugten Website-Dateien.
  • 🔁 Watchtower: aktualisiert automatisch alle Container alle 14 Tage (1209600 Sekunden).

🚀 Container starten

Starte jetzt Caddy + Watchtower:

docker compose up -d

Die Website ist danach per https://example.com erreichbar – mit automatischem HTTPS und ohne jegliche Logs.


🧱 Hinweis für Publii: Remote-Pfad korrekt einstellen

Publii lädt standardmäßig in einen Ordner namens examplecom/ hoch. Genau dieser Ordner wird im Container als Website-Wurzel verwendet.

Wichtig: Da du dich per SFTP direkt in /home/examplecom/ befindest, trägst du bei Publii einfach nur ein: 

  • Remote-Pfad: /examplecom/ (vor und nach Domain ein "/")
  • (wird normalerweise nicht benötigt, dank d /%u in sshd config/ sFTP, aber kann zu Probleme kommen, wenn nichts eingetragen ist, muss es aber nicht)

Die Dateien landen dann exakt dort, wo Caddy sie erwartet.


🔐 Datenschutz & rechtlicher Hinweis

Mit der hier beschriebenen Konfiguration ist deine Website besonders datenschutzfreundlich:

  • Es werden keinerlei Besucher-Logs oder IP-Adressen gespeichert (output discard in Caddy).
  • Es gibt keine Cookies, da keine Benutzerdaten verarbeitet werden.
  • Keine externen Tracker oder Skripte eingebunden.
  • Keine Fonts von Google oder anderen Anbietern eingebunden.

Datenschutzfreundliche Konfiguration:

Achtung: Wenn du externe Inhalte wie YouTube-Videos, Karten (z. B. Google Maps) oder andere eingebettete Dienste verwendest, musst du diese ggf. blockieren, bis der Besucher zugestimmt hat (Cookiebanner / Consent-Tool). Zudem musst du sie im Datenschutz erwähnen und anpassen.

Die hier bereitgestellten Informationen stellen keine Rechtsberatung dar. Datenschutzgesetze (wie die DSGVO) ändern sich, daher übernehme ich keine Haftung für die rechtliche Vollständigkeit oder Aktualität. Im Zweifel solltest du rechtlichen Rat einholen.

📄 Beispielabschnitt für deine Datenschutzerklärung

3. Hosting und Server-Log-Dateien

Der Webserver dieser Website wird vollständig selbst betrieben (Selfhosting). Dabei kommen keine externen Hostingdienste, Content Delivery Networks (CDNs) oder Drittanbieter-Tools zum Einsatz. Es erfolgt keine Auswertung des Nutzerverhaltens, keine Speicherung von IP-Adressen und keine Erstellung von Server-Log-Dateien auf dem Server selbst. Auch auf das Setzen von Cookies wird verzichtet.

Zur Auslieferung der Inhalte wird der Webserver „Caddy“ verwendet. Dieser wurde so konfiguriert, dass keine Protokolle gespeichert werden („output discard“).

Die Datenübertragung erfolgt ausschließlich über verschlüsselte HTTPS-Verbindungen (TLS/SSL), um die Vertraulichkeit und Integrität der übertragenen Daten zu gewährleisten.

Hinweis: Bei einigen Hosting-Anbietern (z. B. V-Server oder Root-Server) kann es sein, dass im Rahmen der Infrastrukturüberwachung – etwa bei Angriffen wie DDoS – bestimmte Verbindungsdaten wie IP-Adresse und Port temporär und automatisiert erfasst und geloggt werden. Diese Vorgänge erfolgen außerhalb des eigenen Servers und liegen in der Verantwortung des Hosting-Anbieters. In der Regel werden diese Daten nur im Angriffsfall analysiert und anschließend gelöscht.

Hier wurde Teilweise bei der Anleitung mit KI Zusammengearbeitet und teilweise aus eigener Hand geschrieben, da KI die Anleitung () nicht gut genug geschrieben hat, habe ich sie verändert / neu geschrieben und aktualisiert auf Debian 13