webfluence hat 5 von 5 Sternen bei 11 Bewertungen auf Google My Business.

WordPress Entwicklungsumgebung auf Linux einrichten

Eine kleine Dokumentation, wie ich meine lokale WordPress Entwicklungs­umgebung auf Linux umgesetzt habe

Dieser Artikel hält die Entstehung meiner lokalen WordPress Entwicklungsumgebung auf Linux fest.

Ziel ist eine Struktur, die mehrere WordPress Projekte auf einem Rechner erlaubt. Jedes Projekt soll automatisch über eine (lokale) Adresse nach dem Muster https://[projektordner-name].dev.localhost via Browser erreichbar sein.

Der Prozess kann vermutlich mindestens auf alle auf Ubuntu basierenden Systeme übertragen werden.

Robert Rosanke

Webentwickler

Vorwort

Dieser Artikel dient hauptsächlich als Notizzettel, wenn ich mal einen neuen PC einrichten muss.

Beschriebene Methoden sind vielleicht nicht »best practise«.

Auf meinem aktuellen System läuft die Entwicklungsumgebung nun über 3 Monate stabil. Für den Start mehr als zufriedenstellend, finde ich.

Apache Server & PHP installieren

Apache installieren

sudo apt-get install apache2

PHP 7.4 installieren

sudo apt-get install libapache2-mod-php7.4

MySQL-Modul für PHP installieren

sudo apt-get install php7.4-mysql

php -m für Info der installierten Module

Wenn die imagick Erweiterung nicht in der Liste ist, dann manuell installieren. WordPress mag die Erweiterung für Fotos.

sudo apt-get install php-imagick

Server neu starten, um Änderungen zu aktualisieren

sudo service apache2 restart

MySQL installieren

MySQL Server installieren

sudo apt-get install mysql-server

Sicherheit

(Vermutlich nicht relevant für lokale Installationen. Nehmen wir trotzdem mit.)

sudo mysql_secure_installation

Löst Fragenhagel zur Konfiguration aus:

  1. Validate Password Component installieren? Yes | level: strong
    • dictionary bedeutet, dass keine Wörter darin vorkommen dürfen
  2. root passwort festlegen (ungleich dem Linux-User)
  3. Anonyme User entfernen? yes
  4. disallow remote login? yes
  5. remove test database? yes
  6. reload privilege tables now? yes

Datenbank für WordPress anlegen

Mit root Nutzer einloggen

mysql -u root -p

Passworteingabe schlägt fehl.

Ansatz nach kurzer Recherche: root könnte auth_socket nutzen. auth_socket speichert angeblich kein Passwort für den User, sodass der Login mit Passwort natürlich nicht hinhaut. Dementsprechend kurz mit Adminrechten einloggen und schauen, ob auth_socket in Verwendung ist.

sudo mysql -u root
mysql> USE mysql;
mysql> SELECT User, Host, plugin FROM mysql.user;

Ergebnis ist eine Tabelle

+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| debian-sys-maint | localhost | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | auth_socket           |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)

Diese zeigt, dass der root Nutzer tatsächlich auth_socket nutzt.

Ziel ist es jetzt also die Methode zu ändern und dann das Passwort nochmal anzupassen.

Lösung nach ewigem Probieren: https://askubuntu.com/a/1033750

Anschließend

Datenbank erstellen

create database wptest1;

DB User erstelle ich nicht, weil ich den root Nutzer nutzen werde – nur für lokale Umgebung nutzen.

WordPress herunterladen

  1. WordPress herunterladen
  2. im home-Ordner ein Verzeichnis für WordPress Seiten erstellen /Entwicklung/dev_env/
    • auf einem echten Webserver würden die Dateien vermutlich unter /var/www/html/ abgelegt.
    • Ist mir zu nervig auf meiner lokalen Maschine in solch versteckten Territorien zu arbeiten. Darum ein Ordner in meinem Verzeichnis.
  3. WordPress unzippen und in einen eigenen Ordner innerhalb des Entwicklungsverzeichnis legen – z.B. /Entwicklung/dev_env/wptest1/

Ordner on the fly als Subdomain nutzen

hosts file bearbeiten

sudo nano /etc/hosts

Domain in der Datei festlegen, die für Entwicklungsumgebung genutzt werden soll

127.0.0.1	dev.localhost

Speichern: STRG+X , ja, Enter

Tipp

Besser eigene, ausgedachte TLD nutzen, um die Unterscheidung von echten Websites von der lokalen Entwicklungsumgebung zu erleichtern.

VirtualHost anlegen

sudo a2enmod vhost_alias
sudo nano /etc/apache2/sites-available/dev_env.conf

Folgendes in die Datei eintragen

<Directory "/home/MEIN_USERNAME/Entwicklung/dev_env">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
    Require all granted
</Directory>

<Virtualhost *:80>
    VirtualDocumentRoot "/home/MEIN_USERNAME/Entwicklung/dev_env/%1"
    ServerAlias *.dev.localhost
    UseCanonicalName Off
</Virtualhost>
        
<Virtualhost *:80>
    VirtualDocumentRoot "/home/MEIN_USERNAME/Entwicklung/dev_env"
    ServerName localhost
    UseCanonicalName Off
</Virtualhost>

Gedanke: Order, Allow und Deny sind vermutlich nicht einmal notwendig, da der Router in der Regel keine Verbindungen von außen Richtung der Geräte innerhalb des normalen Heimnetzwerkes durchlassen sollte. Wenn doch, dann könnte Listen „auf globaler Ebene“ nützlich sein.

Tipp

Warum 2 Blöcke für Port 80? Eine Anweisung für die normale Domain und eine für alle Subdomains.

anschließend:

sudo a2ensite dev_env.conf

und Server neu starten

systemctl reload apache2

Zwischenergebnis

  • Testordner nun erreichbar unter http://wptest1.dev.localhost/wp-admin/install.php
  • lose Dateien nun erreichbar unter http://localhost/[filename].php

Da mich diese ganzen „Verbindung ist nicht sicher“ Warnungen nerven, braucht es noch eine Lösung dafür.

Von HTTP nach HTTPS weiterleiten

VirtualHost bearbeiten: zurück ins config file

sudo nano /etc/apache2/sites-available/dev_env.conf

VirtualHost abändern

  • Port 80 – HTTP – soll automatisch zu HTTPS weiterleiten
  • Port 443 – HTTPS – soll Inhalte ganz normal ausspielen

Am Ende schaut die Datei wie folgt aus:

<Directory "/home/MEIN_USERNAME/Entwicklung/dev_env">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride All
    Order deny,allow
    Deny from all
    Allow from 127.0.0. ::1
    Allow from localhost
    Satisfy Any
</Directory>

<VirtualHost *:80> 
  ServerAlias *.dev.localhost
  #  Redirect permanent / https://%1.dev.localhost/
   <Location "/">
     Redirect permanent "https://%{HTTP_HOST}%{REQUEST_URI}"
   </Location>
</VirtualHost>

<VirtualHost *:80>
  ServerAlias dev.localhost
  Redirect permanent / https://dev.localhost/
</VirtualHost>

<Virtualhost *:443>
    VirtualDocumentRoot "/home/MEIN_USERNAME/Entwicklung/dev_env/%1"
    ServerAlias *.dev.localhost
    UseCanonicalName Off
</Virtualhost>
        
<Virtualhost *:443>
    VirtualDocumentRoot "/home/MEIN_USERNAME/Entwicklung/dev_env"
    ServerName dev.localhost
    UseCanonicalName Off
</Virtualhost>

SSL einrichten – Wildcard für alle Subdomains

sudo a2enmod ssl

Server neu starten

sudo service apache2 restart

Zertifikate und Schlüssel erstellen

Ansatz Zertifikat erstellen und vertrauen: https://gist.github.com/cecilemuller/9492b848eb8fe46d462abeb26656c4f8

sudo mkdir /etc/apache2/ssl

CA erstellen

openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=DE/CN=Beispiel-Root-CA"
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt

Domain name certificate

sudo touch domains.ext
sudo nano domains.ext

in die Datei eintragen:

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = dev.localhost
DNS.2 = *.dev.localhost

dann:

openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=DE/ST=Deutschland/L=Berlin/O=Beispiel-Certificates/CN=dev.localhost"

Tipp

common name (CN) muss die spätere Domain sein: dev.localhost

openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt

Tipp

Zertifikate müssen ab und zu erneuert werden. Wenn es also mal eine „diese Verbindung ist nicht sicher“-Warnung gibt, dann ist es vermutlich soweit.

Server-Einstellungen aktualisieren (VirtualHost bearbeiten)

sudo nano /etc/apache2/sites-available/dev_env.conf

Ans Ende der beiden :443-Blöcke einfügen

SSLEngine on
SSLCertificateFile /etc/apache2/ssl/localhost.crt
SSLCertificateKeyFile /etc/apache2/ssl/localhost.key

Am Ende schaut die gesamte Datei nun so aus:

<Directory "/home/MEIN_USERNAME/Entwicklung/dev_env">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride All
    Order deny,allow
    Deny from all
    Allow from 127.0.0. ::1
    Allow from localhost
    Satisfy Any
</Directory>

<VirtualHost *:80> 
  ServerAlias *.dev.localhost
  #  Redirect permanent / https://%1.dev.localhost/
   <Location "/">
     Redirect permanent "https://%{HTTP_HOST}%{REQUEST_URI}"
   </Location>
</VirtualHost>

<VirtualHost *:80>
  ServerAlias dev.localhost
  Redirect permanent / https://dev.localhost/
</VirtualHost>

<Virtualhost *:443>
    VirtualDocumentRoot "/home/MEIN_USERNAME/Entwicklung/dev_env/%1"
    ServerAlias *.dev.localhost
    UseCanonicalName Off
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/localhost.crt
    SSLCertificateKeyFile /etc/apache2/ssl/localhost.key
</Virtualhost>
        
<Virtualhost *:443>
    VirtualDocumentRoot "/home/MEIN_USERNAME/Entwicklung/dev_env"
    ServerName dev.localhost
    UseCanonicalName Off
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/localhost.crt
    SSLCertificateKeyFile /etc/apache2/ssl/localhost.key
</Virtualhost>

Zertifikat vertrauen

Firefox: Einstellungen → Datenschutz und Sicherheit → Überschrift „Zertifikate“ → Button: Zertifikate anzeigen → Zertifizierungsstellen → RootCA.pem file importieren

Zu Chrome habe ich keine Notizen. Muss also intuitiv sein, dem Firefox-Muster folgen oder automatisch hinhauen. Keine Ahnung mehr.

WordPress mit Datenbank verbinden

mysql -u root -p

root Passwort eingeben

SHOW DATABASES;

Ergebnis:

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wptest1            |
+--------------------+
5 rows in set (0.01 sec)

wptest1 existiert ja schon

exit;

Also WordPress Installationsassistent durchgehen und Datenbank-Zugang hinterlegen: https://wptest1.dev.localhost/wp-admin/install.php

Fehlermeldung im Website-Zustand

Deine WordPress-Installation benötigt FTP-Zugangsdaten, um Aktualisierungen durchzuführen. (Deine Website führt aufgrund des Dateibesitzes Aktualisierungen über FTP durch. Kontaktiere diesbzgl. deinen Provider.)

WordPress während der Installation

Problem: WordPress-Dateien liegen in meinem Verzeichnis. Der Server – Apache – hat keine Berechtigungen, um an Dateien in „meinen“ Ordnern zu werkeln.

Lösungsansatz: Apache Server mindestens als Gruppe angeben, damit Schreibrechte da sind

Ergebnis: Apache (www-data) als owner nutzen und meinen User als Gruppe

sudo chown -R www-data:MEIN_USERNAME /home/MEIN_USERNAME/Entwicklung/dev_env

Anschließend Besitzrechte fixen, damit Server und ich die gleichen Rechte haben

Ordner 775

sudo find /home/MEIN_USERNAME/Entwicklung/dev_env -type d -exec chmod 775 {} \;

Files 664

sudo find /home/MEIN_USERNAME/Entwicklung/dev_env -type f -exec chmod 664 {} \;

Installer unter https://wptest1.dev.localhost/wp-admin/install.php neu durchlaufen lassen.

wp-config.php nach Abschluss des Installers auf 660 stellen

sudo chmod o-rwx /home/MEIN_USERNAME/Entwicklung/dev_env/wptest1/wp-config.php

660 ist vermutlich nicht notwendig für lokale Umgebungen. Aber gut. Ein bisschen Spielerei muss erlaubt sein.

Fehlende PHP-Module für WordPress nachinstallieren

WordPress Installation unter Werkzeuge → Website-Zustand prüfen und fehlende Module anzeigen lassen → curl, dom, mbstring, zip

Nach den Bezeichnungen der Pakete suchen

apt-cache seach [modulname]

Anschließend alle mit einmal installieren

sudo apt-get install php-curl php-xml php-mbstring php-zip
sudo a2enmod rewrite
sudo service apache2 restart

WP-CLI installieren

phar-datei herunterladen

wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar

Test, ob es geht

php wp-cli.phar --info

ausführbar machen

chmod +x wp-cli.phar

verschieben

sudo mv wp-cli.phar /usr/local/bin/wp

Tipp

Ab und zu WP-CLI aktualisieren: sudo wp cli update

Nun kann WP-CLI entspannt genutzt werden.

Skript erstellen, dass die Dateiberechtigungen aktualisiert

Problem: neue Dateien in Entwicklung/dev_env/ übernehmen leider nicht die einmal festgelegte owner/group Einstellung.

Check: kurze Testdatei hallo.php in Entwicklungsordner erstellen, um „default“ Rechte neuer Dateien zu prüfen.

dann:

stat /home/MEIN_USERNAME/Entwicklung/dev_env/hallo.php

Ergebnis

Zugriff: (0664/-rw-rw-r--)  Uid: ( 1000/  MEIN_USERNAME)   Gid: ( 1000/  MEIN_USERNAME)

Scheinbar gelten die vorher festgelegten owner/group-einstellungen nicht automatisch für neu erstellte Inhalte innerhalb der Entwicklungsumgebung.

Deshalb: Skript erstellen, mit dem die Rechte bei Bedarf künftig einfach mit einem Kommando für alle Projekte in der Entwicklungsumgebung gefixt werden.

cd /usr/local/bin
touch update-dev-env.sh
chmod +x update-dev-env.sh
nano update-dev-env.sh

In die Datei einfügen

#!/bin/bash
# update ownership for files and folders in ~/Entwicklung/dev_env
# set apache as owner and MEIN_USERNAME as group
# 


update_owner=0;
update_permissions=0;
secure_config_files=0;
show_help_message=0;
show_insecure_message=0;

while test $# -gt 0; do
    case $1 in
	--help)
	  show_help_message=1
	  shift
	  ;;
        --ownership)
	  update_owner=1
	  shift
	  ;;
        --permissions)
	  update_permissions=1
	  shift
	  ;;
	--secure)
	  secure_config_files=1
	  shift
	  ;;
        *)
	  echo "Unknown parameter passed: $1"
	  return 1;
	  ;;
    esac
done

dev_env_path='/home/MEIN_USERNAME/Entwicklung/dev_env';

if [ $update_owner = 1  ]; then
  sudo chown -R www-data:MEIN_USERNAME $dev_env_path
  echo "owner and group updated"
fi

if [ $update_permissions = 1  ]; then
  sudo find $dev_env_path -type d -exec chmod 775 {} \;
  sudo find $dev_env_path -type f -exec chmod 664 {} \;
  echo "permissions updated"
fi

if [ $secure_config_files = 1  ]; then
  sudo find $dev_env_path -type f -name "wp-config.php" -exec chmod 660 {} \;
  sudo find $dev_env_path -type f -name ".htaccess" -exec chmod 660 {} \;
  echo "wp-config and .htaccess files are not accessible to anonymous users anymore"
  echo "happy coding!"
fi

if [ $show_help_message = 1  ]; then
  echo "availible flags:"
  echo "--ownership & --permissions enable access for the Apache server"
  echo "--secure after initial WordPress setup"
fi

if [ $show_help_message = 0  ]; then
  while read line; do
    files_chmod=$(stat -c '%a' $line);
    if [ $files_chmod != 660 ]; then
      show_insecure_message=1
    fi
  done < <(sudo find $dev_env_path -type f \( -name "wp-config.php" -o -name ".htaccess" \))
fi

if [ $show_insecure_message = 1  ]; then
  echo "---"
  echo "Please set wp-config.php and .htaccess files to 660 after initial WordPress setup."
  echo "use --secure to update chmod"
fi


# Idee: wenn alle Variablen null, dann Hilfetext mit möglichen Parametern anzeigen
  • sudo /usr/local/bin/update-dev-env.sh --ownership --permissions nun nach dem unzippen der WordPress-Dateien in einen neuen Ordner der Entwicklungsumgebung durchlaufen lassen
  • sudo /usr/local/bin/update-dev-env.sh --secure nach dem durchlaufen des WordPress Installationsassistenten

Wenn neben WordPress auch noch andere Projekte betreut werden, die auf nginx-Server oder anderes setzen, dann diese vielleicht in einem anderen Ordner ablegen.

Reine Node.js Projekte funktionieren nach meinen ersten Tests auch mit diesem Setup und ohne extra Aufwand, weil der User die gleichen Rechte wie per default hat. Sehr angenehm.

Node.js/npm installieren

Benötigt zur Entwicklung von Blöcken für den Gutenberg-Editor.

sudo apt-get install nodejs npm

Tipp

Nachtrag: Globale Paketinstallationen sind mit diesem Setup ein Krampf. Besser ist es den Node Version Manager zu installieren. Deutlich angenehmer, wenn beispielsweise mal ein Vue.js Projekt ansteht und Vue-CLI benötigt wird. npx haut mit Vue-CLI einfach nicht zuverlässig hin und bereitet nur Kopfschmerzen.

Erfolgreiche Installation checken mit node -v und npm -v

Um damit zu arbeiten, kann die Konfiguration aus dem Artikel WordPress Block entwickeln genutzt werden.

Mail-Server aufsetzen

Ziel: Kontaktformulare in der Entwicklungsumgebung einrichten und direkt mit den richtigen Ziel-Mail-Adressen der späteren Live-Umgebung testen, um zu vermeiden, dass Seiten mal mit falscher Mail live geschalten werden und Inhaber keine Anfragen erhalten.

Ansatz 1 – Mails von lokal an einen echten Mail-Server zu senden – schlug fehl. Gmail wies in einem Test jede Mail ab. Anforderungen schienen nicht ohne signifikanten Aufwand zu erfüllen.

Darum neuer Ansatz: Alle Mails, die von lokal versendet werden, abfangen und direkt auf der Entwicklungsmaschine ansehen. Dann kann, beispielsweise in Contact Form 7, auch direkt die echte Mail das späteren Seitenbetreibers hinterlegt werden.

Haut komplett hin. Mails, die an eine externe Domain geschickt werden, werden abgefangen und in einem Thunderbird Mailfach angezeigt. Ist vielleicht nicht super schön, jetzt extra noch Thunderbird installieren zu müssen, doch erfüllt den Zweck.

Zusammenfassung: neues Projekt anlegen

Falls doch ein Mensch diese Anleitung durchgespielt hat, hier noch einmal die wichtigsten Schritte zum erstellen eines neuen WordPress Projekts in der Entwicklungsumgebung.

  1. neuen Ordner in /Entwicklung/dev_env/ anlegen – z.B. testseite
  2. WordPress herunterladen, unzippen und im neu angelegten Ordner ablegen
  3. neue Tabelle in der MySQL-Datenbank anlegen, z.B. mit dem gleichen Namen des Projektordners (testseite)
  4. Apache Zugriff auf den Ordner und die Dateien geben
    • sudo /usr/local/bin/update-dev-env.sh --ownership --permissions
  5. WordPress Installationsassistent aufrufen und Seite mit Datenbank verbinden
    • https://testseite.dev.localhost/wp-admin/install.php
  6. Optional: wp-config.php und .htaccess auf 660 setzen
    • sudo /usr/local/bin/update-dev-env.sh --secure

Verbesserungsmöglichkeiten

Wenn mal wieder Zeit und Lust zum basteln ist:

  • /usr/local/bin/update-dev-env.sh eliminieren und ein Skript bauen, dass einen Projektnamen entgegennimmt und daraufhin automatisch
    • einen Ordner anlegt
    • die benötigte Datenbanktabelle erstellt
    • Apache die Rechte gibt
    • mir den WordPress Installationsassistent im Browser öffnet
  • Nach durchlaufen des Installationsassistenten sollen wp-config.php und .htaccess auf 660 gesetzt werden

Außerdem könnte die Entwicklungsumgebung auf HTTP/2 – oder später mal HTTP/3 – setzen. Umsetzung frisst Zeit. Zugewinn ist gering, da eh kaum jemand Server Push und sonstige Features mit WordPress wirklich nutzt. Dementsprechend kein Umsetzungswille.

Diesen Artikel in sozialen Netzwerken teilen: