Zum Inhalt

Domain, DNS und Reverse Proxy einrichten

Ziel

Diese Seite dokumentiert, wie eine Domain gekauft, per DNS auf einen Server geleitet und anschließend mit Nginx als Reverse Proxy auf einzelne Docker-Dienste verteilt wird.

Die Anleitung ist projektübergreifend gedacht und gehört zum Developer Playbook. Immohai dient als konkretes Praxisbeispiel.

Die beschriebenen Schritte können später für weitere Apps wiederverwendet werden.


Grundprinzip

Eine Domain zeigt per DNS auf die öffentliche IP-Adresse eines Servers.

Der Server nimmt eingehende HTTP- und HTTPS-Anfragen über Nginx entgegen und leitet sie intern an die passenden Docker-Container weiter.

Browser
↓
Domain / Subdomain
↓
DNS A-Record
↓
Server
↓
Nginx Reverse Proxy
↓
lokaler Docker-Dienst

Warum ist das sinnvoll?

  • Die Docker-Container müssen nicht direkt öffentlich erreichbar sein.
  • Nginx kann mehrere Subdomains auf verschiedene lokale Dienste verteilen.
  • HTTPS-Zertifikate können zentral über Nginx und Certbot verwaltet werden.
  • Das Setup ist auf mehrere Apps übertragbar.
  • Die öffentliche Serverstruktur bleibt sauber und wartbar.

Allgemeine Zielstruktur

Für ein Setup mit Developer Playbook und mehreren Apps wird eine Hauptdomain verwendet.

Beispiel:

example.com

Darunter werden Subdomains verwendet:

playbook.example.com
app1.example.com
docs.app1.example.com
app2.example.com
docs.app2.example.com

Es muss nicht für jede App eine eigene Domain gekauft werden. Eine Hauptdomain reicht.


Praxisbeispiel: Immohai

Für das Praxisbeispiel Immohai wurde folgende Domain registriert:

ohaisoft.com

Der Server läuft bei Hetzner Cloud.

Eigenschaft Wert
Hetzner-Projekt AppsOhai
Servername bei Hetzner ubuntu-4gb-nbg1-1
Öffentliche IPv4-Adresse 46.225.28.194
Standort Nürnberg
Server-Typ CPX22
Architektur x86
Speicher 80 GB
Server-Benutzer fober
App Immohai
Domain ohaisoft.com

Zielstruktur für Immohai:

ohaisoft.com                    → optionale Hauptseite / Übersicht
www.ohaisoft.com                → optionale Hauptseite / Übersicht
playbook.ohaisoft.com           → Developer Playbook
immohai.ohaisoft.com            → Immohai App
docs.immohai.ohaisoft.com       → Immohai Projektdokumentation

Aktueller Stand:

https://immohai.ohaisoft.com          → Immohai App
https://docs.immohai.ohaisoft.com     → Immohai Dokumentation

Das Developer Playbook wird später ergänzt:

https://playbook.ohaisoft.com

1. Domain kaufen

Allgemein

Eine Domain kann bei einem Domainanbieter registriert werden.

Der Domainanbieter muss nicht derselbe Anbieter sein wie der Serveranbieter.

Beispiel:

Server: Hetzner Cloud
Domain: IONOS
DNS: IONOS

Das ist technisch vollständig in Ordnung.

Für kleine private oder professionelle Projekte reicht am Anfang normalerweise eine einzelne Hauptdomain.


Worauf beim Domainkauf zu achten ist

Beim Domainkauf sollte bewusst geprüft werden:

Punkt Bedeutung
Domainname Sollte langfristig passen und nicht zu eng auf eine einzelne App begrenzt sein
Preis ab dem zweiten Jahr Einstiegspreise sind oft stark reduziert
Mindestlaufzeit Viele Anbieter verkaufen Domains mit 12 oder 24 Monaten Laufzeit
Zusatzprodukte Webhosting, E-Mail oder Website-Baukasten sind oft nicht erforderlich
DNS-Verwaltung Der Anbieter sollte einfache DNS-Records ermöglichen
Eigentümerdaten Domaininhaber-Daten müssen korrekt sein

Für ein Setup mit eigenem Server werden normalerweise keine zusätzlichen Webhosting-Pakete benötigt.


Praxisbeispiel: Domain bei IONOS kaufen

Die Domain wurde bei IONOS gekauft:

ohaisoft.com

Beim Kauf wurde nur die Domain benötigt.

Nicht erforderlich waren:

Zusatzprodukt Warum nicht erforderlich
Webhosting Die Website läuft auf dem eigenen Server
MyWebsite / Website-Baukasten Die App wird selbst entwickelt
E-Mail-Paket E-Mail ist für die App zunächst nicht erforderlich
Domain Guard Optionales Zusatzprodukt, nicht zwingend nötig

Empfehlung:

Nur Domain kaufen.
Keine zusätzlichen Hosting-, Website- oder Mailpakete buchen, wenn diese nicht bewusst benötigt werden.

2. DNS-Einträge einrichten

Allgemein

DNS verbindet Domainnamen mit IP-Adressen.

Für Web-Apps wird meistens ein A-Record verwendet.

A-Record = Domain oder Subdomain zeigt auf eine IPv4-Adresse

Beispiel:

app.example.com → 123.123.123.123

Für Subdomains muss keine neue Domain gekauft werden. Die Subdomains werden kostenlos über DNS-Einträge angelegt.


Typische DNS-Records

Record-Typ Zweck
A Verweist eine Domain oder Subdomain auf eine IPv4-Adresse
AAAA Verweist eine Domain oder Subdomain auf eine IPv6-Adresse
CNAME Verweist eine Subdomain auf einen anderen Domainnamen
MX Mailserver für eine Domain
TXT Textbasierte Nachweise, z. B. SPF, DKIM oder Domain-Verifikation

Für einfache Web-Apps reicht zu Beginn meistens ein A-Record.


Empfohlene Subdomain-Struktur

Für mehrere Apps empfiehlt sich folgende Struktur:

playbook.example.com          → Developer Playbook
app1.example.com              → App 1
docs.app1.example.com         → Dokumentation App 1
app2.example.com              → App 2
docs.app2.example.com         → Dokumentation App 2

Vorteile:

  • Eine Hauptdomain reicht für mehrere Apps.
  • Apps und Dokumentationen bleiben klar getrennt.
  • Nginx kann anhand der Subdomain auf verschiedene lokale Dienste weiterleiten.
  • Neue Apps können später einfach ergänzt werden.

Praxisbeispiel: DNS bei IONOS

Bei IONOS wurden für ohaisoft.com folgende DNS-Einträge gesetzt.

Typ Hostname Ziel
A @ 46.225.28.194
A www 46.225.28.194
A playbook 46.225.28.194
A immohai 46.225.28.194
A docs.immohai 46.225.28.194

Ergebnis:

ohaisoft.com                    → 46.225.28.194
www.ohaisoft.com                → 46.225.28.194
playbook.ohaisoft.com           → 46.225.28.194
immohai.ohaisoft.com            → 46.225.28.194
docs.immohai.ohaisoft.com       → 46.225.28.194

DNS prüfen

Auf dem Server oder lokal:

nslookup ohaisoft.com
nslookup playbook.ohaisoft.com
nslookup immohai.ohaisoft.com
nslookup docs.immohai.ohaisoft.com

Erwartetes Ergebnis:

Address: 46.225.28.194

Im Praxisbeispiel wurden alle vier Domains korrekt aufgelöst:

ohaisoft.com                  → 46.225.28.194
playbook.ohaisoft.com         → 46.225.28.194
immohai.ohaisoft.com          → 46.225.28.194
docs.immohai.ohaisoft.com     → 46.225.28.194

Damit war die DNS-Einrichtung abgeschlossen.


3. Docker-Container auf lokale Ports umstellen

Warum?

Wenn Nginx als Reverse Proxy verwendet wird, soll Nginx die öffentlichen Ports 80 und 443 belegen.

Die Docker-Container sollen diese Ports nicht direkt öffentlich belegen.

Falsch für Reverse-Proxy-Betrieb:

ports:
  - "80:80"

Besser:

ports:
  - "127.0.0.1:8200:80"

Damit ist der Container nur lokal auf dem Server erreichbar.


Port-Strategie

Für mehrere Apps sollte eine klare Port-Strategie verwendet werden.

Beispiel:

Bereich Zweck
8100–8199 Developer Playbook
8200–8299 App 1
8300–8399 App 2
8400–8499 App 3

Beispielstruktur:

127.0.0.1:8100 → Developer Playbook
127.0.0.1:8200 → App 1
127.0.0.1:8201 → Dokumentation App 1
127.0.0.1:8300 → App 2
127.0.0.1:8301 → Dokumentation App 2

Praxisbeispiel: Immohai Docker Compose

Datei:

/home/fober/projects/immohai/docker-compose.yml

Zielkonfiguration:

services:
  web:
    image: nginx:latest
    container_name: immohai-web
    restart: always
    ports:
      - "127.0.0.1:8200:80"
    volumes:
      - ./frontend:/usr/share/nginx/html:ro

  docs:
    image: squidfunk/mkdocs-material:latest
    container_name: immohai-docs
    restart: always
    ports:
      - "127.0.0.1:8201:8000"
    volumes:
      - ./:/docs
    command: serve -a 0.0.0.0:8000

Bedeutung:

Dienst Lokaler Port Container-Port Zweck
immohai-web 127.0.0.1:8200 80 Immohai App
immohai-docs 127.0.0.1:8201 8000 Immohai Doku

Docker Compose prüfen

docker compose config

Danach Container neu starten:

docker compose down
docker compose up -d

Container prüfen:

docker ps --format "table {{.Names}}\t{{.Ports}}"

Erwartung:

immohai-web     127.0.0.1:8200->80/tcp
immohai-docs    127.0.0.1:8201->8000/tcp

Lokalen Zugriff testen:

curl http://127.0.0.1:8200
curl http://127.0.0.1:8201

4. Nginx installieren und starten

Allgemein

Nginx übernimmt die öffentlichen Ports:

Port Zweck
80 HTTP
443 HTTPS

Nginx entscheidet anhand des angefragten Domainnamens, welcher lokale Dienst angesprochen wird.


Installation

sudo apt update
sudo apt install nginx -y

Status prüfen:

sudo systemctl status nginx

Nginx starten:

sudo systemctl start nginx

Bei erfolgreichem Start:

nginx.service → active (running)

Prüfen, ob Nginx auf Port 80 hört

sudo ss -ltnp | grep ':80'

Erwartung:

LISTEN ... 0.0.0.0:80 ... nginx
LISTEN ... [::]:80 ... nginx

5. Port-80-Konflikt lösen

Problem

Beim Start von Nginx kann folgende Fehlermeldung auftreten:

bind() to 0.0.0.0:80 failed (98: Address already in use)

Das bedeutet:

Port 80 ist bereits belegt.

Typische Ursache:

Ein Docker-Container läuft direkt auf 0.0.0.0:80.

Prüfen, wer Port 80 belegt

sudo ss -ltnp | grep ':80'

Zusätzlich:

docker ps --format "table {{.Names}}\t{{.Ports}}"

Praxisbeispiel: alter Container blockiert Port 80

Im Praxisbeispiel war noch ein alter Docker-Container aktiv:

atlas-web    0.0.0.0:80->80/tcp

Dieser Container blockierte Nginx.

Lösung:

docker stop atlas-web
docker rm atlas-web

Danach erneut prüfen:

sudo ss -ltnp | grep ':80'
docker ps --format "table {{.Names}}\t{{.Ports}}"

Port 80 muss für Nginx frei sein.


6. Nginx Reverse Proxy einrichten

Allgemein

Nginx nimmt Anfragen für verschiedene Domains entgegen und leitet sie intern weiter.

Beispiel:

app.example.com       → 127.0.0.1:8200
docs.app.example.com  → 127.0.0.1:8201

Für jede Subdomain wird eine eigene Nginx-Konfigurationsdatei empfohlen.


Empfohlenes Schema

Dateien unter:

/etc/nginx/sites-available/

werden vorbereitet.

Aktive Seiten werden dann nach:

/etc/nginx/sites-enabled/

verlinkt.

Beispiel:

sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/

Praxisbeispiel: Immohai App

Datei erstellen:

sudo nano /etc/nginx/sites-available/immohai.ohaisoft.com

Inhalt:

server {
    listen 80;
    server_name immohai.ohaisoft.com;

    location / {
        proxy_pass http://127.0.0.1:8200;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Aktivieren:

sudo ln -s /etc/nginx/sites-available/immohai.ohaisoft.com /etc/nginx/sites-enabled/

Praxisbeispiel: Immohai Doku

Datei erstellen:

sudo nano /etc/nginx/sites-available/docs.immohai.ohaisoft.com

Inhalt:

server {
    listen 80;
    server_name docs.immohai.ohaisoft.com;

    location / {
        proxy_pass http://127.0.0.1:8201;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Aktivieren:

sudo ln -s /etc/nginx/sites-available/docs.immohai.ohaisoft.com /etc/nginx/sites-enabled/

Nginx-Konfiguration prüfen

sudo nginx -t

Erwartung:

syntax is ok
test is successful

Danach Nginx neu laden:

sudo systemctl reload nginx

HTTP testen

curl -I http://immohai.ohaisoft.com
curl -I http://docs.immohai.ohaisoft.com

Erwartung:

HTTP/1.1 200 OK

Im Praxisbeispiel funktionierten beide Subdomains:

immohai.ohaisoft.com          → HTTP 200 OK
docs.immohai.ohaisoft.com     → HTTP 200 OK

7. Firewall prüfen

Ubuntu Firewall prüfen

sudo ufw status verbose

Erwartung:

22/tcp          ALLOW IN
80,443/tcp      ALLOW IN

oder:

OpenSSH         ALLOW IN
Nginx Full      ALLOW IN

Falls HTTP/HTTPS noch nicht freigegeben sind:

sudo ufw allow 'Nginx Full'
sudo ufw reload

Von außen testen

Vom lokalen Rechner, zum Beispiel unter Windows PowerShell:

curl.exe -I http://immohai.ohaisoft.com
curl.exe -I http://docs.immohai.ohaisoft.com

Zusätzlich:

Test-NetConnection immohai.ohaisoft.com -Port 80
Test-NetConnection docs.immohai.ohaisoft.com -Port 80

Erwartung:

TcpTestSucceeded : True

Im Praxisbeispiel war Port 80 von außen erreichbar.


8. HTTPS mit Certbot einrichten

Warum?

HTTP ist unverschlüsselt. Für produktive Webdienste sollte HTTPS verwendet werden.

Für Nginx kann Certbot automatisch kostenlose Let's-Encrypt-Zertifikate einrichten.


Certbot installieren

sudo apt update
sudo apt install certbot python3-certbot-nginx -y

Zertifikat für App und Doku erstellen

Mehrere Subdomains können gemeinsam in ein Zertifikat aufgenommen werden.

Allgemeines Muster:

sudo certbot --nginx -d app.example.com -d docs.app.example.com

Praxisbeispiel Immohai:

sudo certbot --nginx -d immohai.ohaisoft.com -d docs.immohai.ohaisoft.com

Bei der Einrichtung:

Frage Empfehlung
E-Mail-Adresse echte E-Mail-Adresse verwenden
Terms of Service akzeptieren
Newsletter optional
HTTP auf HTTPS umleiten ja

Im Praxisbeispiel wurde das Zertifikat erfolgreich erstellt und automatisch in die Nginx-Konfiguration eingebunden.

Certbot meldete:

Successfully received certificate.
Successfully deployed certificate for immohai.ohaisoft.com.
Successfully deployed certificate for docs.immohai.ohaisoft.com.

Wichtig: Private Keys niemals kopieren, veröffentlichen oder in Git speichern.


HTTPS testen

curl -I https://immohai.ohaisoft.com
curl -I https://docs.immohai.ohaisoft.com

Erwartung:

HTTP/1.1 200 OK

Im Praxisbeispiel funktionierten beide HTTPS-Aufrufe:

https://immohai.ohaisoft.com          → HTTP 200 OK
https://docs.immohai.ohaisoft.com     → HTTP 200 OK

HTTP-Weiterleitung testen

curl -I http://immohai.ohaisoft.com
curl -I http://docs.immohai.ohaisoft.com

Erwartung:

301 Moved Permanently

oder eine andere permanente Weiterleitung auf HTTPS.


Automatische Zertifikatserneuerung testen

sudo certbot renew --dry-run

Erwartung:

Congratulations, all simulated renewals succeeded

Im Praxisbeispiel war die Simulation erfolgreich:

/etc/letsencrypt/live/immohai.ohaisoft.com/fullchain.pem (success)

Damit ist HTTPS vollständig eingerichtet.


9. Developer Playbook vorbereiten

Die DNS-Einrichtung für das Developer Playbook ist bereits vorbereitet:

playbook.ohaisoft.com → 46.225.28.194

Der Nginx-Proxy für das Developer Playbook wird später ergänzt, sobald das Repository und der Container existieren.

Geplantes Ziel:

playbook.ohaisoft.com → 127.0.0.1:8100

Geplante Serverstruktur:

/home/fober/workspace/
├── developer-playbook/
└── apps/
    └── Immohai/

10. Typische Fehler

Fehler Ursache Lösung
Domain zeigt nicht auf Server DNS noch nicht propagiert oder A-Record falsch nslookup prüfen
Nginx startet nicht Port 80 ist bereits belegt sudo ss -ltnp \| grep ':80'
Docker blockiert Port 80 Container läuft mit 0.0.0.0:80->80/tcp Container auf lokalen Port umstellen
Subdomain zeigt falschen Inhalt Nginx server_name oder proxy_pass falsch Nginx-Dateien prüfen
nginx -t schlägt fehl Syntaxfehler in Konfigurationsdatei Fehlermeldung lesen und Datei korrigieren
Certbot Timeout Port 80 nicht von außen erreichbar Firewall, DNS und Nginx prüfen
IONOS SSL-Warnung IONOS verwaltet kein SSL für den eigenen Server SSL auf dem Server mit Certbot einrichten
Browser meldet Nur-HTTPS-Warnung HTTPS ist noch nicht eingerichtet Certbot ausführen
Container ist öffentlich erreichbar Port-Mapping auf 0.0.0.0 gesetzt Port auf 127.0.0.1 beschränken

11. Allgemeine Checkliste

Domain und DNS

  • [ ] Hauptdomain festgelegt
  • [ ] Domain gekauft
  • [ ] DNS-Verwaltung gefunden
  • [ ] A-Record für Hauptdomain gesetzt
  • [ ] A-Record für App-Subdomain gesetzt
  • [ ] A-Record für Doku-Subdomain gesetzt
  • [ ] Optionaler A-Record für www gesetzt
  • [ ] DNS mit nslookup geprüft

Docker

  • [ ] App-Container auf lokalen Port umgestellt
  • [ ] Doku-Container auf lokalen Port umgestellt
  • [ ] Keine Container direkt auf 0.0.0.0:80
  • [ ] Docker Compose geprüft
  • [ ] Container neu gestartet
  • [ ] Lokaler Zugriff per curl geprüft

Nginx

  • [ ] Nginx installiert
  • [ ] Port 80 ist frei
  • [ ] Reverse Proxy für App eingerichtet
  • [ ] Reverse Proxy für Doku eingerichtet
  • [ ] Nginx-Konfiguration geprüft
  • [ ] HTTP-Zugriff erfolgreich getestet

HTTPS

  • [ ] Certbot installiert
  • [ ] HTTPS für App eingerichtet
  • [ ] HTTPS für Doku eingerichtet
  • [ ] HTTP-Weiterleitung auf HTTPS geprüft
  • [ ] Automatische Zertifikatserneuerung getestet

12. Checkliste Praxisbeispiel Immohai

Domain und DNS

  • [x] Domain gekauft: ohaisoft.com
  • [x] A-Record für @ gesetzt
  • [x] A-Record für www gesetzt
  • [x] A-Record für playbook gesetzt
  • [x] A-Record für immohai gesetzt
  • [x] A-Record für docs.immohai gesetzt
  • [x] DNS mit nslookup geprüft

Docker

  • [x] Immohai App auf lokalen Port 127.0.0.1:8200 umgestellt
  • [x] Immohai Doku auf lokalen Port 127.0.0.1:8201 umgestellt
  • [x] Docker Compose mit docker compose config geprüft
  • [x] Container neu gestartet
  • [x] Lokaler Zugriff per curl geprüft

Nginx

  • [x] Nginx installiert
  • [x] Port-80-Konflikt mit altem Container atlas-web gelöst
  • [x] Nginx gestartet
  • [x] Reverse Proxy für immohai.ohaisoft.com eingerichtet
  • [x] Reverse Proxy für docs.immohai.ohaisoft.com eingerichtet
  • [x] Nginx-Konfiguration geprüft
  • [x] HTTP-Zugriff erfolgreich getestet

HTTPS

  • [x] Certbot installiert
  • [x] HTTPS für immohai.ohaisoft.com eingerichtet
  • [x] HTTPS für docs.immohai.ohaisoft.com eingerichtet
  • [x] Automatische Zertifikatserneuerung getestet

Developer Playbook

  • [ ] Repository developer-playbook erstellt
  • [ ] Container für Developer Playbook eingerichtet
  • [ ] Reverse Proxy für playbook.ohaisoft.com eingerichtet
  • [ ] HTTPS für playbook.ohaisoft.com eingerichtet

Ergebnis

Die allgemeine Struktur ist für weitere Apps wiederverwendbar:

app2.example.com
docs.app2.example.com
app3.example.com
docs.app3.example.com

Im Praxisbeispiel Immohai ist der aktuelle Stand:

https://immohai.ohaisoft.com
https://docs.immohai.ohaisoft.com

Das Developer Playbook wird später ergänzt:

https://playbook.ohaisoft.com