navigation Navigation


WSL - Web Development mit SSL


Das Windows Subsystem für Linux (WSL) bietet eine leistungsstarke Umgebung für Webentwicklung unter Windows 11. Die Integration von SSL in lokale Entwicklungsprojekte ist dabei ein wichtiger Aspekt, um produktionsnahe Bedingungen zu simulieren. Diese Anleitung führt durch den Prozess der WSL-Installation und -Konfiguration für Webentwicklung mit funktionierender SSL-Verschlüsselung. Mit den richtigen Tools und Einstellungen lässt sich eine effiziente Linux-basierte Entwicklungsumgebung direkt unter Windows nutzen, ohne Kompromisse bei Sicherheitsfeatures eingehen zu müssen.

Inhaltsverzeichnis

    Voraussetzungen

    Damit dieser Artikel Sinn ergibt und auch hilfreich ist, sollten ein paar Annahmen erläutert bzw. ein paar Voraussetzungen erfüllt werden.

    Ich nehmen in diesem Artikel an, dass folgende Punkte gegeben sind.

    • Windows 11: Das Betriebssystem ist Windows 11
    • WSL 2: WSL in Version 2 ist bereits aktiviert und Ubuntu ist installiert

    Die Version von WSL könnt ihr wie folgt prüfen.

    Möglichkeit 1
    wsl --list --verbose

    Hierbei solltet ihr ungefähr folgendes Ergebnis erhalten. Eine Auflistung von vorhandenen WSL-Installationen mit der Version in der rechten Spalte.

    Windows 11 - WSL Version prüfen - Möglichkeit 1


    Möglichkeit 2
    wsl --status

    Bei dieser Möglichkeit erhaltet ihr die Standardversion für WLS, die verwendet wird. Und auch die Standard-Distribution.

    Windows 11 - WSL Version prüfen - Möglichkeit 2

    Installation - Apache

    Wir beginnen mit der Installation von Apache. Apache ist ein verbreiteter Web-Server. Wir werden ihn verwenden, um unsere lokale Web-Projekte auszuliefern und für unsere lokale Entwicklung einsetzen.

    Das Paket installieren.

    sudo apt install apache2

    Nach der Installation sollte beim Aufruf von http://localhost der Apache-Server mit einer Standard-Website antworten. Das ist ein Zeichen dafür, dass dieser Aktiv ist.

    Den Status von Apache kann wie folgt prüfen.

    sudo systemctl status apache2

    Ubuntu - Apache Status prüfen - Screenshot

    Hier noch ein paar wichtige Befehle, die immer wieder während der Arbeit mit Apache und eigenen lokalen Projekten benötigt werden.

    # Apache stoppen
    sudo systemctl stop apache2
    
    # Apache starten
    sudo systemctl start apache2
    
    # Apache neustarten
    sudo systemctl restart apache2

    Installation - PHP

    Im nächsten Schritt installieren wir PHP. Sehr viele Websites werden mit PHP betrieben und daher ist es nahezu unerlässlich. In diesem Beispiel (Artikel) setze ich Ubuntu 24.04 ein und diese Distribution hatte PHP in Version 8.3 als Paket.

    PHP ohne Module wird wie folgt installiert.

    sudo apt install php

    PHP mit den meisten Modulen wird wie folgt installiert.

    sudo apt install php php-mysql php-curl php-xml php-mbstring php-intl php-gd php-zip php-bcmath php-imagick

    Nach der Installation kann die aktive Version folgendermaßen geprüft werden.

    php --version

    Ubuntu - PHP Version prüfen - Screenshot


    PHP-INI Versionen

    Für spätere Anpassungen wird man ab und zu auch die INI-Konfiguration bearbeiten müssen. Hier sollte man wissen, welche die korrekte ist und wo sie sich befindet.

    Bei PHP unter einem Ubuntu-Server in Kombination mit Apache gibt es generell 2 php.ini Dateien. Je nach PHP-Version und Linux-Version kann sich der Pfad unterscheiden.

    Standardmäßig befinden sich die unterschiedlichen INI-Dateien im folgenden übergreifenden Ordner: /etc/php/8.3.

    Ubuntu - PHP INI Ordner - Screenshot

    Und in diesen Ordnern liegt jeweils eine php.ini, die bestimmte Konfiguration beinhaltet. Für Web-Development wird man in der Regel mit der Apache-Version arbeiten müssen.

    Ubuntu - PHP INI Dateien in Ordnern - Screenshot


    PHP-INI Pfad herausfinden

    Um den Pfad zu der jeweiligen PHP-INI zu finden, falls dieser von der Standard-Konfiguration abweicht, gibt es mehrere Möglichkeiten und eine Sache zu beachten.

    Wie weiter oben erwähnt, gibt es unterschiedliche Versionen von PHP-INI. Und je nach Ausführungskontext wie entweder die eine oder die andere Konfiguration geladen.

    Wenn wir also innerhalb von WSL-Terminal folgenden Befehl ausführen php --ini, erhalten wir den Pfad zu der CLI-Version, also der Terminal-Version.

    Um die Ausgabe nur auf die eine Datei zu begrenzen, verwende ich grep.

    php --ini | grep php.ini

    Als Ergebnis erhalten wir folgendes.

    Ubuntu - CLI PHP INI Pfad

    Hier haben die den Pfad zu der php.ini im Ordner CLI erhalten. Warum? Weil wir den Befehl in der Shell ausgeführt. Der Apache-Kontext war hier nicht gegeben, dafür aber der CLI-Kontext.

    Um den Pfad der Apache-Version zu erhalten, müssen wir einen anderen Weg nehmen. Dafür benötigen wir irgendeine PHP-Datei, die wir unter dem Localhost-Root platzieren und über eine URL ansprechen/ausführen. In diesem Fall würde Apache die Auslieferung übernehmen und der Apache-Kontext wäre gegeben.

    Wir erstellen im Standard-Root /var/www/html eine Datei info.php. In dieser Datei platzieren wir folgenden Inhalt.

    /var/www/html/info.php
    <?php phpinfo(); ?>

    Diese Datei können wir dann (immer noch im Terminal) folgendermaßen aufrufen. Wir verwenden hier wieder grep, um die Ausgabe auf den notwendigen Eintrag zu beschränken.

    curl http://localhost/info.php | grep "Loaded Configuration File"

    Ubuntu - Apache PHP INI Pfad

    Installation - MariaDB

    Sehr verbreit sind die MySQL und MariaDB Datenbank in der Web Entwicklung. Nahezu jedes Framework oder jedes CMS setzt irgendeine Art von SQL-Datenbank ein. Meistens entweder MySQL oder MariaDB. Ich verwende in diesem Beispiel und auch für meine lokale Entwicklungen MariaDB.

    MariaDB wird mit folgendem Befehl installiert.

    sudo apt install mariadb-server

    MariaDB - Root Passwort

    Nach der Installation empfehle ich ein Root-Passwort zu setzen. Man kann direkt nach der Installation MariaDB auch über sudo mariadb verwenden. Da viele CMS oder Frameworks neben einer SQL-Datenbank auch einen SQL-Benutzer mit einem SQL-Passwort angegeben haben möchten, müssen wir dafür sorgen, dass es diesen gibt. Da es sich hierbei um lokale Entwicklung handelt, bei der keine Notwendigkeit besteht pro CMS oder Projekt einen eigenen Benutzer mit einer eigenen Datenbank zu erstellen, verwende ich für die meisten Fälle einfach den root Benutzer.

    Direkt nach der Installation rufe ich folgendes Programm auf.

    sudo mariadb-secure-installation

    Hier startet ein Wizard, bei dem ein paar Fragen gestellt werden, die man beantworten muss.

    WSL Ubuntu - MariaDB Secure Installation - Start

    An diesem Punkt wird man noch kein Root-Passwort haben. Also klicken wir hier einfach auf “Enter” und gehen zum nächsten Punkt bzw. zur nächsten Frage.

    Hier geben wir “Y” ein.

    WSL Ubuntu - MariaDB Secure Installation - Frage 2

    Im nächsten Step wird uns die Frage gestellt, ob das Root-Passwort geändert werden soll. Selbstverständlich geben wir hier auch “Y” ein, um das Passwort zu setzen (oder zu ändern).

    WSL Ubuntu - MariaDB Secure Installation - Frage 3

    Nun werden wir aufgefordert das neue Root-Passwort zwei Mal nacheinander einzugeben.

    WSL Ubuntu - MariaDB Secure Installation - Passwort Eingabe

    Die restlichen Fragen sind für lokale Entwicklung in der Regel weniger wichtig. Ich beantworte sie immer mit “Y”. Hierbei geht es um das Entfernen der anonymen Benutzer, entfernten Zugriff und das Entfernen der Test-Datenbank. Alles Fragen, die lokal nicht von großer Bedeutung sind.


    Anmeldung mit Passwort

    Hat man nun alles korrekt eingerichtet, sollte der MariaDB-Server neugestartet werden.

    sudo systemctl restart mariadb

    Um den Status von MariaDB-Server zu prüfen, kann folgende Anweisung verwendet werden.

    sudo systemctl status mariadb

    WSL Ubuntu - MariaDB - Status prüfen

    Da jetzt alles läuft, können wir mit dem Root-Benutzer und dem gesetzten Passwort uns am MariaDB-Server anmelden.

    mariadb -u root -p

    Bei erfolgreicher Eingabe des korrekten Passworts, landen wir in der MariaDB-Shell.

    WSL Ubuntu - MariaDB - Login mit Passwort

    Installation - mkcert (Windows 11)

    Wir möchten SSL auch für unsere lokale Projekte einsetzen. Dafür verwende ich mkcert. Dieses Tool muss auf beiden Seiten installiert wird. Einmal unter Windows und einmal direkt in WSL.

    Für die Installation von mkcert unter Windows werden wir choco Paketverwaltung (Chocolatey) brauchen. Diese können wir mit folgendem Befehl installieren.

    Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

    Nachdem choco auf dem System verfügbar ist, können wir nun mkcert installieren.

    choco install mkcert

    Root-Zertifikat installieren

    Nach der Installation von mkcert muss das Root-Zertifikat installiert werden. Das erfolgt mit dem folgenden Befehl von mkcert.

    mkcert -install

    Hinweis: -install mit einem Bindestrich.

    Um sich den Pfad des Root-Zertifikats anzuzeigen, können wir folgende Anweisung verwenden.

    mkcert -CAROOT

    Windows 11 - mkcert - Ordner mit dem Root-Zertifikat

    Installation - mkcert (WSL Ubuntu)

    Im zweiten Schritt installieren wir mkcert unter Ubuntu in WSL. Für die Installation verwende ich Homebrew. Man kann allerdings mkcert auch bequem manuell installieren. In diesem Fall mache ich es mit Homebrew.

    Homebrew installieren

    Bevor man Homebrew unter Ubuntu installiert, empfiehlt es sich, folgende Pakete zu installieren, wenn sie noch nicht installiert sind.

    sudo apt install build-essential libnss3-tools curl file git

    Im Anschluss kann dann Homebrew über das offizielle Installationsskript installiert werden.

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

    Am Ende des Installationsvorgangs erhält man einen Hinweis, dass bestimmte Einträge in der .bashrc vorhanden müssen, damit Homebrew der Shell bekannt ist.

    In der Regel sollte folgende Zeile in der .bashrc vorhanden sein.

    eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"

    Um zu prüfen, ob Homebrew korrekt installiert ist, kann man den Befehl doctor verwenden. Bekommt man die Ausgabe wie Your system is ready to brew., ist alles in Ordnung und man kann Homebrew verwenden.

    brew doctor

    WSL Ubuntu - Homebrew Statusprüfung


    mkcert installieren

    Nun können wir mkcert mit Homebrew installieren.

    brew install mkcert

    Wenn alles korrekt installiert wurde, können wir prüfen, ob mkcert unserer Shell bereits bekannt ist.

    which mkcert

    WSL Ubuntu - mkcert - Pfad prüfen

    Oder, alternativ, kann man auch die Version prüfen.

    mkcert --version

    WSL Ubuntu - mkcert - Version prüfen


    Root-Zertifikat installieren

    Nun muss auch unter WSL ein Root-Zertifikat installiert werden. Der Befehl ist identisch.

    mkcert -install

    Auch in WSL kann man sich den Pfad zum Root-Zertifikat anzeigen. Diesen werden wir bald brauchen.

    mkcert -CAROOT

    WSL Ubuntu - mkcert - Pfad zum Root-Zertifikat

    Zertifikate tauschen

    WICHTIG: Dieser Schritt muss ausgeführt werden, bevor das erste Projekt-Zertifikat erstellt wird!

    Bei Verwendung von Windows mit WSL besteht die Situation, dass wir unterschiedliche Umgebungen haben. Wir werden die Websites mit einem Browser in Windows (Client) verwenden. Windows hat ein anderes Root-Zertifikat, als WSL. Mit dieser Tatsache würden unsere Zertifikate nicht funktionieren.

    Daher ist es sehr wichtig, die Zertifikate zu vereinheitlichen.. Das können wir tun, indem wir auf beiden Seiten das gleiche Root-Zertifikat haben.

    Wie kriegen wir das erreicht? Indem wir das Zertifikat unter WSL mit dem Zertifikat von Windows überschreiben. Dazu sollte man beide CAROOT Pfade öffnen. Dann löschen wir die Zertifikate unter WSL und kopieren (nicht verschieben) die Zertifikatsdateien von Windows nach WSL.

    WSL Ubuntu - mkcert - Zertifikate vereinheitlichen

    Hier nochmals die Abfolge zusammengefasst.

    1. Ordner mit Root-Zertifikatsdateien von Windows öffnen
    2. Ordner mit Root-Zertifikatsdateien von WSL öffnen
    3. Die Linux (WSL) Root-Zertifikatsdateien entfernen
    4. Die Root-Zertifikatsdateien von Windows in den Ordner (CAROOT) von Linux (WSL) kopieren

    VirtualHost erstellen

    Wir brauchen nun ein Beispiel-Projekt, das wir versuchen mit SSL-Zertifikat zum Laufen zu bringen. Hier gehen wir schrittweise vor und richten erstmal ein VirtualHost ein, damit unser lokaler Web-Server unter WSL beim Aufrufen einer Domain im Browser darauf reagiert und uns irgendwas ausliefert.

    In meinem Beispiel möchte ich die (für den Moment) neue Version des JTL-Shops installieren. Dafür verwende ich die lokale Domain jtl-550.work.

    Hosts Eintrag

    Wir starten mit einem Hosts Eintrag. In der Datei /etc/hosts fügen wir eine Domain hinzu, die von unserem Loopback (127.0.0.1) verarbeitet werden soll. Da wir aber WSL verwenden, müssen wir beachten, dass die /etc/hosts Datei durch die Windows eigene Hosts-Datei überschrieben wird. Dieser Hinweis ist ebenfalls in der /etc/hosts direkt am Anfang der Datei enthalten.

    Somit öffnen wir die Hosts-Datei in Windows direkt, um unsere Domain einzutragen, die von 127.0.0.1 verarbeitet werden soll. Diese Datei befindet sich unter dem folgenden Pfad.

    C:\Windows\System32\drivers\etc\hosts

    Diese Datei sollte mit Administrator-Rechten geöffnet werden und folgende Einträge füge ich in meinem Fall ein.

    Windows 11 - Hosts-Datei Einträge für lokale Domain

    In eurem Fall müsst ihr natürlich eure, beliebige lokale Domain eintragen.

    Wenn es getan und die Datei gespeichert hat, sollte es ausreichen, um die Domain “anpingen” zu können. Ich empfehle jedoch einen Neustart von WSL durchzuführen. Dies kann man mit dem folgenden Befehl tun. Danach WSL einfach wieder öffnen.

    wsl --shutdown

    WSL Ubuntu - Ping lokale Domain


    VirtualHost Eintrag

    An diesem Schritt registrieren wir unsere lokale Domain für Apache. Dafür erstellen wir einen neuen VirtualHost Eintrag in der Apache Sites-Konfiguration.

    Bei Apache gibt es zwei Ordner die in diesem Zusammenhang relevant sind.

    • /etc/apache2/sites-available/
    • /etc/apache2/sites-enabled/

    Im Ordner sites-available/ befinden sich die tatsächlichen Konfigurationsdateien, die Konfigurationen für die jeweilige Domain beinhalten.

    Im Ordner sites-enabled/ befinden sich symbolische Links auf die Konfigurationsdateien im Ordner sites-available/. Nur die Konfigurationen, welche nach sites-enabled/ verlinkt worden sind, gelten für Apache als aktiv.

    Man kann alle Konfigurationen aller lokaler Projekte in einer Datei führen. Ich empfehle den Ansatz die Konfigurationen auf die einzelnen Dateien aufzuteilen.

    Wir erstellen für unser Beispiel eine Datei jtl-550.conf. In dieser Datei machen wir einen neuen VirtualHost Eintrag, welcher auf den Port 80 hört.

    /etc/apache2/sites-avaiable/jtl-550.conf
    <VirtualHost *:80>
        ServerName jtl-550.work
        DocumentRoot /var/www/html/jtl_550
        <Directory /var/www/html/jtl_550>
            AllowOverride all
            Require all granted
        </Directory>
    </VirtualHost>

    Anschließend verlinken wir diese Datei im Ordner sites-enabled/.

    cd /etc/apache2/sites-enabled/
    sudo ln -s ../sites-available/jtl-550.conf .

    Und starten Apache neu.

    sudo systemctl restart apache2

    Webspace

    Nun müssen wir in unserem Web-Root (/var/www/html) einen neuen Ordner erstellen, in welchem sich unser Web-Projekt befinden wird und welcher von Apache angesteuert wird, wenn man die lokale Domain aufruft. In meinem Fall wird es der Ordner mit dem Namen jtl_550 sein und in euren Fall eben ein anderer.

    WSL Ubuntu - Datei in Webspace

    In meinem Fall platziere ich dort folgenden Inhalt.

    <?php
        echo "Hier kommt der Web-Shop";
    ?>

    Wenn wir jetzt also die Domain http://jtl-550.work im Browser aufrufen, werden wir feststellen, dass unsere Mini-Website funktioniert. Die Verbindung ist momentan noch nicht gesichert und arbeitet nur mit dem HTTP-Protokoll.

    WSL Ubuntu - Lokale Domain mit HTTP

    Projekt Zertifikat

    SSL-Zertifikate werden in der Regel pro Domain ausgestellt. Eine Domain ist in der Regel auch ein Projekt (manchmal gibt es etwas abweichende Konfigurationen). Somit werden wir auch für die lokale Entwicklung so verfahren, dass pro lokale Domain ein SSL-Zertifikat ausgestellt (generiert) wird. Dafür verwenden mkcert.

    Wenn man mkcert für die Erstellung des lokalen Zertifikats verwendet, sollte beachtet werden, in welchem Benutzer-Kontext es ausgeführt wird. Wenn wir mit unserem normalen WSL-Benutzer mkcert einsetzen, dann sollten wir darauf achten, dass wir uns in einem Ordner befinden, in welchem wir Schreibrechte haben. Dort werden nämlich die Zertifikate abgelegt.

    Ich mache es auf meinem System immer im ~/temp/ Verzeichnis.

    Das Zertifikat wird mit folgendem Befehl erzeugt.

    mkcert jtl-550.work

    Dabei erhalten wir folgende Ausgabe, wenn alles korrekt funktionierte.

    WSL Ubuntu - Lokales Zertifikat erstellt

    Es besteht auch die Möglichkeit ein Zertifikat für mehrere Domains auszustellen.

    mkcert domain-1.work domain-2.work domain-3.work

    In diesem Fall würde das erstellte Zertifikat alle drei Domains abdecken. Allerdings ist es aus meiner Sicht nicht der beste Weg, da man irgendwann nicht mehr weiß, welches Zertifikat welche Domains abdeckt, außer man bezeichnet die Zertifikatsdatei entsprechend so, dass der Name alle Domains beinhaltet. Auch das ist weniger schöne Lösung. Daher erstelle ich pro Domain ein eigenes Zertifikat. Diese Lösung ist klar, verständlich und sauber.

    Apache - SSL

    Was haben wir aktuell? Wir haben einen funktionierenden VirtualHost mit unserer eigenen lokalen Domain, wir haben auf beiden Stellen (WSL und Windows) die Zertifikate installiert und wir haben das Zertifikat für unser Beispiel-Projekt erstellt. Die Zertifikatsdateien liegen aktuell im Home-Verzeichnis, im temp Ordner.

    temp/
    ├── jtl-550.work-key.pem
    └── jtl-550.work.pem

    In diesem Schritt müssen wir SSL unter Apache aktivieren, die SSL-Zertifikate verschieben und die Konfiguration von unserem VirtualHost für die Verwendung von SSL erweitern.

    SSL-Zertifikate Speicherort

    Hier gibt es nicht wirklich eine absolut falsche oder eine absolut richtige Lösung. Jede Lösung die funktioniert, ist eigentlich richtig. Der Rest ist Geschmack- und Organisationssache. In meinem Fall möchte ich allerdings hier auch Ordnung haben.

    Die SSL-Zertifikate werden von Apache für unsere lokale Domains verwendet, die über das HTTPS-Protokoll und dem 443er Port ausgeliefert werden. Entsprechend möchte ich alle Projekt-Zertifikate irgendwo unter Apache speichern.

    Dafür erstelle ich einen Ordner unter /etc/apache2/ssl und verschiebe, nach der Erstellung, die Zertifikate in diesen Ordner.

    SSL-Ordner unter Apache
    sudo mkdir /etc/apache2/ssl

    Anschließend verschiebe ich beiden Zertifikatsdateien aus dem ~/temp/ Ordner in den ssl Ordner unter Apache.

    SSL-Ordner unter Apache
    cd ~/temp/
    sudo mv jtl-550.work* /etc/apache2/ssl/

    Somit wären jetzt die Zertifikate in diesem Ordner.

    /etc/apache2/ssl/
    ├── jtl-550.work-key.pem
    └── jtl-550.work.pem

    SSL aktivieren

    Unter Apache soll nun SSL aktiviert werden. Das kann man mit dem folgenden Befehl tun. Anschließend sollte unbedingt Apache neugestartet werden.

    sudo a2enmod ssl
    sudo systemctl restart apache2

    Das Tool a2enmod steht für Apache2 Enable Module und ist ein eigenständiges Programm, das mit Apache-Installation installiert wird. Wo es liegt kann man wie folgt herausfinden.

    which mkcert

    WSL Ubuntu - Ort von a2enmod

    Man kann das Tool auch eigenständig aufrufen. Es ist dafür zuständig, vorhandene Apache-Module zu aktivieren, indem es symbolische Links von /etc/apache2/mods-available/ nach /etc/apache2/mods-enabled/ setzt.

    Wenn man könnte also auch händisch die Apache-Module zuschalten.


    VirtualHost erweitern

    Nun haben wir unsere Zertifikatsdateien am richtigen Ort, das SSL-Module ist aktiviert und wir müssen noch unsere VirtualHost-Konfiguration entsprechend erweitern. Dabei besteht das Ziel Apache mitzuteilen, dass es auch den Port 443 für die entsprechende lokale Domain bedienen soll.

    Wir öffnen die Datei /etc/apache2/sites-available/jtl-550.conf. Und fügen folgenden Block für den 443 Port hinzu.

    <VirtualHost *:443>
        ServerName jtl-550.work
        DocumentRoot /var/www/html/jtl_550
        <Directory /var/www/html/jtl_550>
            AllowOverride all
            Require all granted
        </Directory>
    
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/jtl-550.work.pem
        SSLCertificateKeyFile /etc/apache2/ssl/jtl-550.work-key.pem
    </VirtualHost>

    Somit sieht unsere gesamte Konfiguration danach wie folgt aus.

    WSL Ubuntu - VirtualHost Konfiguration mi SSL

    Nach diesen Änderungen sollte Apache erneut neugestartet werden.

    sudo systemctl restart apache2

    Wenn wir den Cache des Browsers löschen oder unsere lokale Domain in einem Inkognito-Fenster öffnen, erhalten wir eine funktionierende SSL-Version unserer Website.

    WSL Ubuntu - Funktionierende Website mit SSL