#standwithukraine

Umzug von Bitly zu Shlink (self-hosted URL Shortener)

Um Links, die bspw. von diesem Blog auf Twitter oder sonst irgendwo auf Social Media landen, zu verkürzen, verwende ich schon ewig Bitly. Genau genommen seit 2009, anfangs noch unter der Domain bit.ly, später mit einer eigenen Domain. Schon länger will ich eigentlich weg von dem Dienst.

Shlink Logo

Nicht, dass ich unzufrieden wäre, aber nach und nach wurde der kostenlose Account immer mehr eingeschränkt und selbst die eigene Domain hat mein Account wohl nur behalten dürfen, weil diese schon ewig genutzt wurde. Wer sich heute frisch anmeldet, braucht einen bezahlten Zugang, um diese Möglichkeit nutzen zu können. Zusätzlich wurde wohl Werbung „zwischengeschaltet“. Und, bei aller Liebe, für das, was ich hier nutze (nämlich eigentlich nur die pure Weiterleitung), bin ich nicht bereit 10 Euro oder mehr im Monat zu zahlen.

Quasi als „Bonus“ kam dazu, dass ich ein wenig weg von dem ganzen US-Kram will. Nicht komplett, dafür verwende ich Google, Apple, Amazon und einige andere zu häufig. Aber wenn ich der Meinung bin, ich sollte etwas ändern, dann schaue ich mich nach einer Alternative um, die nach Möglichkeit in Europa liegt. Wenn meine Daten dann noch bei mir bleiben können, umso besser. Zum Beispiel habe erst gestern nach fast 14 Jahren mein Dropbox-Abo gekündigt. Vielleicht schreibe ich bei Gelegenheit etwas zum Umzug auf Hetzner Storage Share/Nextcloud.

Wie auch immer, ich hatte schon eine Weile die Idee, die Funktionalität von Bitly einfach selbst zu hosten. Es gibt eine ganze Reihe URL-Shortener, der bekannteste ist wahrscheinlich YOURLS. Ich habe mir ein paar angeschaut, ein wenig gelesen und mich dann für Shlink entschieden. Dieser hat die Möglichkeit, Links von Bitly zu importieren, was Grundvoraussetzung war. Immerhin will ich den Übergang 1:1 sauber abschließen und nicht noch tagelang rumfrickeln.

Was ist Shlink?

Das Schöne ist also, dass der Umzug von Bitly kein Hexenwerk ist. Aber mal kurz zu Shlink an sich:

Shlink ist open‑source (MIT License) URL-Shortener oder auf Deutsch Linkverkürzer oder Kurz-URL-Dienst. Dieser dient dazu, aus URLs wie https://github.com/shlinkio/shlink/releases/tag/v5.0.0 einen kürzeren Link wie https://mk.cx/shlink5 zu erzeugen. Zusätzlich gibt es noch (DSGVO-konforme) Statistiken, wie oft auf einen Link geklickt wurde und woher der Klicker kam. Shlink wird selbstgehostet und bietet daher natürlich die volle Kontrolle über alle Daten. Im Gegensatz zu Anbietern wie Bitly oder TinyURL gibt es keine Limits (außer hardwareseitig irgendwann). Man kann problemlos eine eigene Domain verwenden, sollte sich aber, wie bei eigentlich allem Selbstgehosteten, etwas mit Docker (compose) und DNS auskennen.

Shlink selbst besteht aus einem Server-Container, der die Weiterleitungen, die REST-API und das CLI bereitstellt und mit der Datenbank kommuniziert. Zusätzlich gibt es optional ein separates Web-Interface (shlink-web-client), das die Verwaltung im Browser ermöglicht. Es gibt auch noch ein paar andere Möglichkeiten, auf Shlink zuzugreifen.

Aber kommen wir zum Umzug. In diesem Artikel zeige ich dir Schritt für Schritt, wie ich meinen Bitly‑Account zu Shlink migriert habe, wie ich Shlink über Docker Compose installiert habe, wie ich die Web‑GUI einrichte, wie ich die Links per API importiere und wie die DNS‑Einträge aussehen müssen. Let’s Encrypt lasse ich bewusst weg, da der Artikel sonst zu ausführlich wäre und ich das einfach mal voraussetze.

Vorbereitung: Domains und DNS-Einträge

Du benötigst zwei Subdomains (oder eine Domain und eine Subdomain). Für dieses Setup verwende ich:

  • Shortlink‑Domain: Über Subdomain sh.example.com (z.B. sh.example.com/xyz123) oder example.com (example.com/xyz123)
  • GUI‑Domain: ui.example.com (z.B. ui.example.com für die Shlink‑Web‑GUI)
  • Server‑IP: 123.45.67.89

Die Domains müssen auf den Server zeigen, den du für Shlink nutzt. Bei deinem DNS‑Provider (z.B. Cloudflare, Hetzner DNS) legst du folgende Einträge an. Entweder vorab, wenn du ggf. mit ein paar Minuten Downtime leben kannst, oder wenn alles fertig ist:

  • A‑Record für example.com123.45.67.89
  • A‑Record für ui.example.com123.45.67.89
  • ggf. A‑Record für sh.example.com123.45.67.89

Shlink über Docker Compose installieren

Ich setze voraus, dass Docker und Docker Compose auf deinem Server installiert ist. Wie das geht, siehst du auf Docker.com. Ich verwende gerne ein Frontend wie Dockge, du wirst aber schon wissen, was zu tun ist, wenn du direkt auf der Shell arbeitest.

Ich habe bereits eine MariaDB-Instanz auf derselben Maschine laufen. Shlink unterstützt mehrere Datenbank-Engines, von denen du eine vorab installiert haben solltest. Des Weiteren benötigst du einen API-Key. Diesen kannst du entweder erstmal leer lassen und mit docker exec -it shlink shlink api-key:generate erzeugen, wenn der Container läuft. Alternativ geht auch vorab openssl rand -base64 32. Optional benötigst du einen Account und einen Key von Maxmind für die GeoLite2 Datenbank (Um sehen zu können, woher die Besucher deiner Links kommen).

Mein docker-compose.yml sieht wie folgt aus:

services:
  shlink:
    image: shlinkio/shlink:latest
    ports:
      - 127.0.0.1:1234:8080
    environment:
      DEFAULT_DOMAIN: example.com (oder sh.example.com)
      IS_HTTPS_ENABLED: "true"
      # DB (MariaDB on host)
      DB_DRIVER: maria
      DB_HOST: host.docker.internal
      DB_PORT: "3306"
      DB_NAME: shlink
      DB_USER: user
      DB_PASSWORD: password
      INITIAL_API_KEY: LANGERKEY
      TIMEZONE: Europe/Berlin
      GEOLITE_LICENSE_KEY: KEY
      TRUSTED_PROXIES: 127.0.0.1,172.16.0.0/12
    extra_hosts:
      - host.docker.internal:host-gateway
    restart: unless-stopped
  shlink-web:
    image: shlinkio/shlink-web-client:latest
    ports:
      - 1235:80
    environment:
      SHLINK_SERVER_URL: https://example.com (oder https://sh.example.com)
    volumes:
      - /etc/nginx/ui.conf:/etc/nginx/conf.d/default.conf:ro
    restart: unless-stopped
networks: {}

Das installiert das CLI und das Webinterface und verbindet sich mit der Datenbank. Weitere Umgebungsvariablen findest du hier. Du solltest zwei Container sehen: shlink und shlink-web. Shlink läuft auf Port 1234 und die Website auf Port 1235. Der Rest sollte eigentlich selbsterklärend sein.

Die Datei /etc/nginx/ui.conf war nötig, weil die GUI andernfalls bei mir Probleme gemacht hat. Das muss nicht zwingend bei dir auch so sein.

# /etc/nginx/ui.conf
server {                                                                                                                                                                                                                                                                                  listen 80;                                                                                                                                                                                                                                                                              listen [::]:80;                                                                                                                                                                                                                                                                         server_name _;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  root /usr/share/nginx/html;                                                                                                                                                                                                                                                             index index.html;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               location / {                                                                                                                                                                                                                                                                              try_files $uri $uri/ /index.html;                                                                                                                                                                                                                                                     }                                                                                                                                                                                                                                                                                     }                     

Reverse Proxy über Nginx

Bevor wir das Webinterface nutzen können, müssen wir für Nginx zwei Virtual Hosts anlegen.

# HTTP → HTTPS example.com (oder sh.example.com)
server {
    listen 123.45.67.89:80;
    server_name example.com; 
    return 301 https://example.com$request_uri;
}

# HTTPS example.com → Backend (oder sh.example.com)
server {
    listen 123.45.67.89:443 ssl;
    http2 on;
    server_name example.com;

    access_log /logs/example.com/access_log;
    error_log /logs/example.com/error_log;

    ssl_certificate /etc/letsencrypt/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/example.com/key.pem;
    ssl_trusted_certificate /etc/letsencrypt/example.com/ca.pem;

    location ~* \.(php|env|git|sql)$ {
        return 444;
    }

    location / {
        proxy_pass http://127.0.0.1:1234;
        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;
    }
}

# HTTP → HTTPS ui.example.com
server {
    listen 123.45.67.89:80;
    server_name ui.example.com;
    return 301 https://ui.example.com$request_uri;
}

# HTTPS ui.example.com → Backend
server {
    listen 123.45.67.89:443 ssl;
    http2 on;
    server_name ui.example.com;

    access_log /logs/ui.example.com/access_log;
    error_log /logs/ui.example.com/error_log;

    ssl_certificate /etc/letsencrypt/ui.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/ui.example.com/key.pem;
    ssl_trusted_certificate /etc/letsencrypt/ui.example.com/ca.pem;

    location ~* \.(php|env|git|sql)$ {
        return 444;
    }

    location / {
        proxy_pass http://127.0.0.1:1235;
        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;
    }
}

Das wars erstmal mit der Installation. Nachdem du Nginx neu gestartet hast, kannst du die Weboberfläche jetzt über https://ui.example.com aufrufen. Dort musst du zuerst einen Server anlegen. Die URL ist https://example.com und den API-Key hast du ja vorhin erzeugt.

Shlink Welcome

Import von Bitly

Shlink bietet nicht nur die Möglichkeit, seine Daten von Bitly zu migrieren, sondern auch von anderen Quellen. Für Bitly benötigt man ein API-Token, das man mit einem Klick in den Einstellungen erzeugen kann.

Dann öffnet man eine Shell und startet mit docker compose exec shlink shlink short-url:import bitly den Import.

Shlink Import von Bitly

Der Befehl fragt nach dem Bitly‑Token und importiert deine Links. Beachte: Klick‑Daten werden nicht importiert, nur die URLs selbst. Spätestens jetzt solltest du dafür sorgen, dass die DNS-Einträge nicht mehr auf Bitly zeigen, sondern auf deinen Server.

Fazit

Der Umzug von Bitly zu Shlink war einfacher als erwartet. Mit Docker Compose, einer sauberen Nginx‑Konfiguration und dem Import‑Tool habe ich das innerhalb weniger Stunden erledigt. Klar, Bitly ist minimal komfortabler, aber um ein paar Links zu kürzen und weiterzuleiten reicht Shlink mehr als aus.

Dynamische Benachrichtigungen für neue Geocaches mit Traccar und Project-GC

Dynamische Benachrichtigungen für neue Geocaches mit Traccar und Project-GC

Achtung, leicht technischer Nerd-Content!

Wenn du froh bist, dass du dein GPSr mit einer GPX befüllen oder Tradis mit einer App finden kannst, dann kannst du zwar gerne weiterlesen, wirst aber früher oder später nur noch Fragezeichen sehen. Wenn du aber bei Apache nicht direkt an Indianer denkst, weißt, dass es 10 Arten von Menschen gibt, über PICNIC und PEBKAC nur den Kopf schütteln kannst und Ping für dich nichts mit Tischtennis zu tun hat: Lies gerne weiter.

Um was gehts hier eigentlich?

Ja, die Überschrift klingt etwas sperrig. Um das Ganze mal etwas einfacher darzustellen: Viele Cacher haben Notifications auf Geocaching.com angestellt, um sich über die Veröffentlichung von neuen Caches oder Events informieren zu lassen.

Man gibt einen Punkt, meist die Homekoordinaten, einen Radius, einen Logtyp (normalerweise „Publish“) und eine Cacheart an und bekommt eine Email, sobald der Reviewer einen Cache freigegeben hat. Alternativ bietet Project-GC das auch für zahlende Mitglieder an.

So weit, so gut. Ein Großteil der Geocacher kann jetzt wahrscheinlich aufhören zu lesen, weil sie keine Notifications verwenden, keine FTF-Jäger sind oder zumindest außerhalb der Homezone erst gar keine FTFs versuchen. Der Teil, der übrig bleibt, erstellt sich vielleicht eine Benachrichtigung rund um seinen Urlaubsort und macht sich sonst keine weiteren Gedanken.

Und dann gibt es mich. Okay, gut, ich renne nicht grundsätzlich immer und überall einem FTF hinterher. Aber wenn ich die Chance dazu habe, sage ich selten nein. Bin ich ein paar Tage an einem Ort, ist das kein Problem, da erstelle ich mir meist auch nur eine normale Notification. Allerdings bin ich gerade mitten in der Planung für einen Roadtrip. Das bedeutet, dass man maximal 2 oder 3 Tage in derselben Gegend ist. Da wäre es super, wenn man quasi eine Benachrichtigung erstellen könnte, die sich immer auf den aktuellen Aufenthaltsort bezieht.

Einrichtung der Benachrichtigung auf Project-GC

Kann man. Von dieser Funktionalität auf Project-GC habe ich vor einigen Monaten erfahren und war sofort interessiert. Man kann eine Benachrichtigung mit „dynamischem Standort“ erstellen und sich so auch benachrichtigen lassen, wenn man nicht in der Homezone unterwegs ist.

Project-GC: Einrichtung von dynamischer Notification

Dazu erstellt man einfach über den Button „Neue Benachrichtigung hinzufügen“ einen neuen Eintrag. Man vergibt einen Namen und gibt einen Radius an. Ich habe hier 20 Kilometer genommen, schließlich will man ja meist schon „in der Nähe“ bleiben. Des Weiteren setzt man den Haken bei „Dynamischer Mittelpunkt“. Wenn man nicht bei jedem Publish, sondern nur einmal pro Tag, eine Mail bekommen will, hakt man „Tägliche Zusammenfassung“ an, der Haken bei „Logs verfolgen“ schickt einem jedes Log bis zum ersten Fundlog zu. Aktivieren braucht man die Benachrichtigung noch nicht.

Aktuellen Standort an Project-GC senden

Leider bezieht sich die Anleitung auf Project-GC auf eine Android-App, die nicht mehr weiterentwickelt wird, aber aktuell noch funktioniert. Das bringt mir allerdings überhaupt nichts, da ich ein iPhone verwende und es die App für iOS gar nicht gibt. Zwar fand ich eine ähnliche, letztendlich bietet sie aber nicht die ausreichende Funktionalität, um die API von Project-GC korrekt aufzurufen und die Standortdaten weiterzuleiten.

Ich hatte das Thema schon fast wieder vergessen, als ich in der c’t auf einen Server gestoßen bin, der GPS-Daten verwurstet und auf einer Karte anzeigt. Dachte ich zumindest. Letztendlich war das, was ich da gefunden habe, weit mächtiger, als ich annahm. Egal, die Software sieht interessant aus, ich hatte Urlaub und Lust mich damit zu beschäftigen.

    Traccar

    Traccar ist ein kostenloser Opensource GPS-Tracking-Server. Die Software kennt eine Vielzahl von Geräten (etwa 1500 verschiedene), die Updates an den Server senden können. Neben OBD-Dongles fürs Auto ist die einfachste Variante sicher, eine der Apps für iOS oder Android zu verwenden.

    Server in Docker installieren und konfigurieren

    Es gibt mehrere Möglichkeiten, den Traccar-Server zu installieren. Da ich ursprünglich ja nur etwas rumspielen wollte, habe ich die einfachste gewählt: Einen Docker-Container. Docker ist eine Virtualisierungssoftware, bei der man relativ einfach komplette Softwarepakete installieren kann.

    Mit dem folgenden Befehl wird der Container angelegt:

    mkdir -p /opt/traccar/logs
    
    docker run \
    --rm \
    --entrypoint cat \
    traccar/traccar:latest \
    /opt/traccar/conf/traccar.xml > /opt/traccar/traccar.xml

    Jetzt wäre ein guter Zeitpunkt, die vielen Optionen zumindest einmal zu überfliegen und ggf. die traccar.xml anzupassen.

    Auf der Shell sind es nur ein paar wenige Befehle:

    docker run \
    --name traccar \
    --hostname traccar \
    --detach --restart unless-stopped \
    --publish 81:8082 \
    --publish 5000-5150:5000-5150 \
    --publish 5000-5150:5000-5150/udp \
    --volume /opt/traccar/logs:/opt/traccar/logs:rw \
    --volume /opt/traccar/traccar.xml:/opt/traccar/conf/traccar.xml:ro \
    -v /var/docker/traccar/data:/opt/traccar/data:rw \
    traccar/traccar:latest

    Ich habe obigen Befehl etwas angepasst. Normalerweise wäre die Chance, dass sich nichts tut oder eine Fehlermeldung erscheint, relativ groß, wenn auf dem Server bereits ein Webserver auf Port 80 lauscht.
    Daher empfiehlt es sich, bei –publish 80:8082 die 80 durch einen anderen Port zu ersetzen. Da ich sowieso alles durch Nginx durchschleife, ist der Port egal. 81 lag nahe, letztendlich geht aber jeder freie Port. Des Weiteren habe ich das Daten-Verzeichnis installieren lassen, damit die Daten nicht verloren gehen, wenn man den Docker-Container löscht.

    Konfiguration von Nginx als Reverse Proxy

    Zur „normalen“ Konfiguration eines Virtual Hosts füge ich folgende Zeilen zum Server {}-Block hinzu:

    location /api/socket {
           include proxy_params;
           proxy_http_version 1.1;
           proxy_cache_bypass $http_upgrade;
           proxy_buffering off;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "Upgrade";
           proxy_pass http://127.0.0.1:81/api/socket;
        }
    
    location / {
    	proxy_pass http://127.0.0.1:81;
            log_not_found off;
    	proxy_set_header  Host $host;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header  X-Forwarded-Proto $scheme;
            proxy_set_header  X-Forwarded-Port $server_port;
            proxy_set_header  X-Forwarded-Host $host;
        }

    Damit ist die Weboberfläche von Traccar wie eine normale Website auf Port 443 (oder 80) erreichbar. Lässt man diesen Schritt aus, ist Traccar von extern unter Port 8082 aufrufbar. Gegebenenfalls muss dieser in der Firewall geöffnet werden.

    Ich habe die URL aufgerufen und einen Account registriert. Nach dem erfolgreichen Login habe ich unter Einstellungen -> Server die Geschwindigkeitseinheit auf km/h umgestellt, als Zeitzone „Europe/Berlin“ ausgewählt und bei Ort meinem momentanen Standort eingegeben. Dies funktioniert logischerweise erst, wenn die App einmal ihren Standort an den Server geschickt hat. Bei „Registrierung zulassen“ habe ich den Haken entfernt. Schließlich reicht es vollkommen aus, wenn ich einen Account habe.

    Auswahl der Datenbank

    Traccar verwendet die mitgelieferte H2-Datenbank. Benutzt man den Server nicht nur allein und etwas exzessiver, wird empfohlen bspw. auf MySQL bzw. MariaDB umzusteigen. Was man hier beachten muss: Läuft MySQL/MariaDB „normal“ auf dem Server, also nicht in einem Docker-Container, kann man den Datenbank-Server nicht über localhost aufrufen, sondern über die „externe“ IP-Adresse. Des Weiteren muss der User die Erlaubnis haben, von der IP des Docker-Containers auf die Datenbank zuzugreifen.

    Konfiguration der App

    Die App ist ein Selbstläufer, im wahrsten Sinne. Man kann gar nicht wahnsinnig viel einstellen, braucht man aber auch nicht. Man muss über die Weboberfläche ein neues Gerät anlegen. Dazu vergibt man einen Namen und eine ID. Diese Gerätekennung ist entweder die IMEI oder eine Nummer aus der App.

    Sobald diese auf beiden Seiten (Server und App) identisch ist, trägt man noch die URL des Servers (ggf. mit Port) ein und schaltet den Dienststatus auf an. Die Frequenz der Updates habe ich auf 300 (Sekunden, also 5 Minuten) eingestellt gelassen. Will man detailliertere Routen abrufen können, muss der Wert verkleinert werden.

    Standortdaten senden

    Ich habe die App geöffnet, konstanten Zugriff auf GPS auch im Hintergrund zugelassen, bin einmal durch die Stadt gefahren und habe mir danach die Strecke auf der Karte angeschaut. Gut, alle 5 Minuten updaten ergibt wie gesagt keine wirklich perfekte Strecke, zum Spielen (und für unsere Zwecke) ist das aber vollkommen ausreichend. Ich hatte den Server einige Tage laufen, habe mich durch die Aufbereitung der Daten geklickt und das Ganze für mich als nette Spielerei abgetan.

    Kontakt zu Project-GC

    Doch dann kam mir eine Idee: Kann der Server vielleicht die passend aufbereiteten Daten an Project-GC senden und ich komme doch noch zu dynamischen Benachrichtigungen? Jetzt wird die Sache interessant!

    Eine kurze Suche im Traccar-Forum und in der Dokumentation brachte ans Licht, dass man über die Optionen forward.enable und forward.url in der Konfigurationsdatei /opt/traccar/traccar.xml genau das einstellen kann, was ich will.

    <entry key='forward.enable'>true</entry>
    <entry key='forward.json'>false</entry>
    <entry key='forward.url'>https://URL</entry>

    Testweise habe ich mir ein PHP-Script geschrieben, um überprüfen zu können, ob die Weiterleitung fehlerfrei funktioniert. Als alles okay war, habe ich den Eintrag bei forward.url geändert und folgende URL eingetragen:

    https://project-gc.com/api/UserLocation/Update/?protocol=1&uid=UID&latitude={latitude}&longitude={longitude}&acc={accuracy}&ts={fixTime}&token=TOKEN&nid=NID&enable=1

    Die Werte für UID, TOKEN und NID holt man von Project-GC: Die User-ID und das Token findet man unter Einstellungen. Hier sollte auch eine Email-Adresse hinterlegt sein, an die die Benachrichtigungsmails gesendet werden. Die NID ist die ID der Benachrichtigung („NOTIFIER-ID“). Sie steht neben dem Namen der Benachrichtigung.

    Testen in freier Wildbahn

    Der Server läuft, die App schickt meinen Standort alle 5 Minuten, die Weiterleitung an Project-GC funktioniert auch. Zeit, das Ganze live zu testen.

    Ich war außerhalb meiner Homezone in der Nähe von Speyer cachen, als mich eine Mail von Project-GC erreichte. Der Cache, der gepublisht wurde, ist Luftlinie etwa 18 Kilometer von meinem Standort weg und weit genug entfernt zu meinen Homekoordinaten.

    Project-GC: Mail von dynamischer Notification

    Die Benachrichtigung passt! Somit scheint alles zu funktionieren, wie es soll. Dem nächsten FTF-Versuch steht also nichts mehr im Weg 🙂

    Fazit

    Ja, es ist ein bißchen wie mit den Kanonen und den Spatzen. Aber es ist eine nette Spielerei, die Ressourcen dafür sind da und es hat Spaß gemacht, den kompletten Prozess zu testen.

    Der Akku des Handys wird natürlich etwas beansprucht, allerdings funktioniert die Abfrage des Standortes im Hintergrund inzwischen einigermaßen schonend. Der Server verbraucht etwa 800 MByte RAM und unter 1% CPU.

    Nginx: Mehrere Hostnamen auf einen umleiten

    Nginx

    Das hier ist eher ein Memo für mich, als große Kunst 🙂 Ich stand vor folgendem kleinen Problem: Ich wollte mehrere Hostnamen auf einen einzigen finalen umleiten. Das wollte nicht so recht klappen.

    Nach der Umstellung auf SSL leitet http://subdomain.domain1.de auf https://subdomain.domain1.de um. Das läßt sich problemlos und einfach über folgenden Code in der Konfigurationsdatei des Vhosts einrichten.

    server {
    listen 80;
    server_name subdomain.domain1.de;
    return 301 https://$server_name$request_uri;
    }

    Als ich der Website eine eigene Domain spendiert habe, stieß ich auf ein kleines Problem:

    Ich wollte http://subdomain.domain1.de, http://www.domain2.de und https://subdomain.domain1.de auf https://www.domain2.de umleiten. Das versuchte ich wie folgt:

    server {
    listen 80;
    server_name subdomain.domain1.de www.domain2.de domain2.de;
    return 301 https://www.domain2.de$request_uri;
    }

    server {
    listen 443 ssl http2;
    server_name subdomain.domain1.de www.domain2.de domain2.de;
    […]
    }

    Soweit so gut. Oder auch nicht. Denn https://subdomain.domain1.de funktioniert zwar, leitet aber nicht auf https://www.domain2.de um. Nach etwas Knobelei hatte ich aber raus, wie das funktioniert:

    server {
    listen 80;
    server_name subdomain.domain1.de domain2.de www.domain2.de;
    return 301 https://www.domain2.de$request_uri;
    }

    server {
    listen 443 ssl http2;
    server_name subdomain.domain1.de;
    […]
    return 301 https://www.domain2.de$request_uri;
    }

    server {
    listen 443 ssl http2;
    server_name www.domain2.de domain2.de;
    […]
    }

    Man benötigt also pro SSL-Host einen eigenen server { } Abschnitt. Im Nachhinein eigentlich logisch.