LAMP-Server für InstaHub aufsetzen

13. Februar 2022 - Lesezeit: 14 Minuten

Dokumentation zum Aufsetzen eines LAMP-Servers auf Debian 11 mit dem Ziel InstaHub zu betreiben. Nicht unbedingt nachmachen, ich bin kein Profi.

Die Dokumentation dient hauptsächlich dazu, dass ich beim nächsten Mal nicht wieder einen Ferientag opfern muss, um einen LAMP Server aufzusetzen.

Genutzt wird ein Debian 11 mit der Minimal Ausführung. Das Image gibt es meist beim vHoster-Betreiber des Vertrauens zum Hosting mit dazu. Sonst entweder mit einem anderen Image sein Glück probieren oder hoffen, dass man ein virtuelles CD-Laufwerk hat (Download).

Als erstes ändern wir das root-Passwort.

passwd root

Dateien lassen sich entweder mit einem graphischen Werkzeug oder direkt in der Konsole mit nano etwa nano /etc/fail2ban/jail.local bearbeitet werden.

Teilweise fehlen noch andere wichtige Befehle wie apt-get install unzip und apt-get install curl

Firewall installieren

apt install ufw
ufw allow OpenSSH
sudo ufw allow 9090
sudo ufw allow in "WWW Full"
ufw enable

Mit ufw app list kann man sich vordefinierte Filter auflisten lassen und mit ufw app info "SMTP" die damit verknüpften Ports ansehen. ufw deny SMTP sorgt dafür, dass Regeln wieder entfernt werden.

fail2ban installieren

apt install fail2ban
systemctl enable fail2ban
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Dann müssen wir noch auf unsere Firewall anpassen indem wir in der jail.local noch die Zeilen so anpassen:

banaction = ufw
banaction_allports = ufw

Und neustarten:

systemctl restart fail2ban.service

Cockpit installieren

Cockpit ist ein Dashboard, womit man auch von unterwegs den Server administrieren und die Auslastung prüfen kann.

apt-get install cockpit

Fehlt der Menüeintrag "Software Updates" kann dieser über apt-get install cockpit-packagekit nachgeladen werden.

Die Seite ist dann über Port 9090 erreichbar. Login ist wie auf dem vServer selbst. Hierüber lassen sich etwa Sicherheitsupdates schnell installieren.

Apache installieren

sudo apt install apache2
a2enmod rewrite # add rewrite
a2enmod ssl #enable ssl
a2ensite default-ssl # enable default page also in ssl
systemctl restart apache2

Datenbank installieren

apt install mariadb-server
mysql_secure_installation
mariadb
MariaDB [(none)]> GRANT ALL ON *.* TO 'admin_xskBTs'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> exit

Bei mysql_secure_installation kein Passwort für root vergeben und allen anderen Maßnahmen zustimmen. Eigenen Benutzer ausdenken und password ersetzen 😉.

PHP installieren

PHP 8.3 installieren (Debian bringt aktuell nur 7.4 mit):

echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/sury-php.list
apt install wget
apt install apt-transport-https software-properties-common
wget -qO - https://packages.sury.org/php/apt.gpg | sudo apt-key add -
apt update
apt install php8.3
apt install php8.3-common php8.3-gd php8.3-ldap php8.3-odbc php8.3-xsl php8.3-apcu php8.3-curl php8.3-gmp php8.3-opcache php8.3-mbstring php8.3-pgsql php8.3-imagick php8.3-memcached php8.3-bz2 php8.3-ds php8.3-imap php8.3-cgi php8.3-mysql php8.3-cli php8.3-fpm php8.3-xml php8.3-gettext php8.3-bcmath

Test ist mit php -v möglich. Die Version kann auch später noch über update-alternatives --config php geändert werden.

phpMyAdmin installieren

apt install phpmyadmin

Unbedingt bei der Installation beachten, dass die Frage an der Integration in apache2 zwar hervorgehoben aber nicht ausgewählt ist. Das unbedingt noch setzen.

In phpMyAdmin kannst du dich nur mit dem admin_xskBTs und nicht mit dem root Benutzer anmelden. Soll eigentlich die Sicherheit erhöhen, aber das haben wir gerade überbrückt. 😊

Jetzt lässt er sich an jedem Virtual Host mit /phpmyadmin/ aufrufen. Das wollen wir aber nicht, daher in /etc/phpmyadmin/apache.conf die Zeile

Alias /phpmyadmin /usr/share/phpmyadmin

mit # auskommentieren. Nun in die gewünschten Virtual Hosts (etwa default) gehen und dort die Zeile in den Virtual Host einfügen. Und neustarten nicht vergessen:

systemctl restart apache2

Ausführungszeit auf Datenbank beschränken

Nutzen wir gleich unseren admin-Benutzer und schränken die Ausführungszeit für alle ein. Das ist sehr wichtig, da CROSS JOINs sonst unsere Datenbank lahm legen können. PHP bricht zwar nach 30 Sekunden ab, aber die Datenbank läuft fröhlich weiter.

Folgende Befehle schränken ganz gut ein:

SET GLOBAL max_join_size=10000;
SET GLOBAL sql_select_limit=10000;
SET GLOBAL max_statement_time=20;

Da diese aber in jeder Datenbank gesetzt werden müssten, beschränken wir uns auf eine Änderung der /etc/mysql/mariadb.cnf und fügen dort ein:

max_join_size = 10000
max_statement_time = 20

Speicherbelegung

Die mögliche Speicherbelegung der Datenbank im Arbeitsspeicher ist in fast allen Fällen zu klein. Der Default ist 128MB, während meist 70% des verfügbaren Arbeitsspeichers empfohlen wird. Hier in Byte der Speicherplatz für 3GB verfügbare Speicher:

innodb_buffer_pool_size = 3221225472

Node zum Übersetzen der JS-Bibliotheken installieren

sudo apt install -y ca-certificates curl gnupg
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

Let's Encrypt installieren

Fürst du die Befehle nach dem Login aus bist du im Verzeichnie /root

curl https://get.acme.sh | sh

Jetzt unbedingt das Terminal neu starten und danach Let's Encrypt als CA auswählen:

acme.sh --set-default-ca --server letsencrypt

Anschließend stellen wir ein Zertifikat für die interne Server-URL aus:

acme.sh --issue --apache -d v220220282479179029.bestsrv.de

Jetzt müssen wir das Zertifikat in /etc/apache2/sites-available/000-default.conf eintragen. Dabei sind die Zeilen schon im Text, aber mit # auskommentiert:

SSLCertificateFile /root/.acme.sh/v220220282479179029.bestsrv.de/v220220282479179029.bestsrv.de.cer
SSLCertificateKeyFile /root/.acme.sh/v220220282479179029.bestsrv.de/v220220282479179029.bestsrv.de.key

Die Dateien nicht zu kopieren, sondern aus dem Arbeitsverzeichnis zu verwenden wird vom Entwickler explizit nicht gutgeheißen, da sich die Ordnerstruktur ändern könnte.

Mit crontab -l kannst du prüfen, ob der Cronjob zum automatischen erneuern des Zertifikats gesetzt wurde. Das Zertifikat ist 90 Tage gültig und wird aller 60 Tage ersetzt.

Alternativ kann man auch die bestehenden Zeilen auskommentieren und ein selbst signiertes Zertifikat verwenden (besser als keins). Dafür muss noch das Zertifikat erstellt werden:

make-ssl-cert generate-default-snakeoil --force-overwrite

Virtual Hosts für die Webseiten anlegen

Im Ordner /etc/apache2/sites-available/ die Datei instahub.yak9.de.conf anlegen:

<VirtualHost *:80>
    ServerName instahub.yak9.de
    ServerAlias *.instahub.yak9.de
    ServerAdmin webmaster@instahub.org
    DocumentRoot /var/www/instahub.yak9.de/public

    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^(?!/\.well-known/acme-challenge/)(.*)$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]

    ServerAdmin webmaster@localhost

    ErrorLog ${APACHE_LOG_DIR}/instahub.yak9.de.error.log
    CustomLog ${APACHE_LOG_DIR}/instahub.yak9.de.access.log combined
</VirtualHost>

Der obige Virtual Host lässt eigentlich nur Let's Encrypt passieren und verweist alle anderen auf die SSL-Verbindung.

Anschließend den eigentlichen Host für instahub.yak9.de-ssl.conf anlegen:

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerName instahub.yak9.de
        ServerAlias *.instahub.yak9.de
        ServerAdmin webmaster@instahub.org
        DocumentRoot /var/www/instahub.yak9.de/public

        <Directory />
            Options FollowSymLinks
            AllowOverride None
        </Directory>
        <Directory /var/www/instahub.yak9.de/public>
                AllowOverride All
        </Directory>

        LogLevel warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SSLEngine on

        SSLCertificateFile /root/.acme.sh/instahub.yak9.de/instahub.yak9.de.cer
        SSLCertificateKeyFile /root/.acme.sh/instahub.yak9.de/instahub.yak9.de.key

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
                SSLOptions +StdEnvVars
        </Directory>
    </VirtualHost>
</IfModule>

Und aktivieren:

a2ensite instahub.yak9.de.conf
a2ensite instahub.yak9.de-ssl.conf
systemctl reload apache2

InstaHub installieren

Zuerst installieren wir das Kommandozeilenwerkzeug Composer:

apt install wget php-cli php-zip unzip
wget -O composer-setup.php https://getcomposer.org/installer
php composer-setup.php --install-dir=/usr/local/bin --filename=composer

Nun laden wir den Branch beta herunter.

apt install git
cd /var/www
git clone -b beta git://github.com/wi-wissen/instahub.git instahub.yak9.de

Und das SSL-Wildcard-Zertifikat erstellen:

acme.sh --issue -d instahub.yak9.de -d *.instahub.yak9.de --dns --force --yes-I-know-dns-manual-mode-enough-go-ahead-please

Jetzt müssen die entsprechenden TXT-Einträge im DNS der Domain vorgenommen werden. Je nachdem wie schnell euer DNS-Server verbunden ist, muss man noch warten.

acme.sh --renew -d instahub.yak9.de -d *.instahub.yak9.de --dns --force --yes-I-know-dns-manual-mode-enough-go-ahead-please

Und nicht vergessen, wie oben geschrieben die SSL-Zertifikate im Virtual Host verlinken und den Apache neu starten mit systemctl restart apache2.

Jetzt (oder während man auf den DNS-Server wartet), InstaHub nach der Anleitung installieren: https://github.com/wi-wissen/instahub

Wenn man als root unterwegs ist muss man mit den Rechten besonders aufpassen, die müssen insbesondere bei storage rekursiv gesetzt werden. Etwa so:

usermod -a -G www-data root
chown -R www-data:www-data "/var/www/instahub.yak9.de/"

cd "/var/www/instahub.yak9.de/"
chgrp -R www-data storage bootstrap/cache
chmod -R ug+rwx storage bootstrap/cache

Noch den Storage-Ordner mit Hardlink versehen:

php artisan storage:link

Ab 2024 noch den Java-Skript übersetzen:

npm install
npm run build

Wer das versehentlich als root gemacht hat muss unbedingt sudo chown -R www-data:www-data . ausführen, damit der Apache sich austoben kann

kein Mailserver

Mailserver betreibe ich sehr ungern selber, da ich hier nicht aus Versehen ein Spam-Bot werden möchte. Daher schalte ich meine Domain entweder für die Mails auf ein Shared-Hosting oder Mailpaket auf bzw. nutze folgende Dienste:

mailtrap.io - Während der Entwicklung spielt der Dienst Mailserver, aber anstelle die Mails auszuliefern bewahrt er sie auf, sodass man sich in Ruhe ansehen kann, was gesendet wurden wäre. So benötigt man keine zig Dummy-Mailadressen.

TEMPMAIL - Für Tests auf dem Produktivsystem (ja, ich weiß, ganz schlechter Stil), mal schnell einen neuen Nutzer mit "eigenem" Mailkonto erstellen.

Abschließende Worte

Jetzt hast du vielleicht zwischendurch echt schlecht Luft bekommen oder dir mit der Hand gegen die Stirn geschlagen. Ja, ging mir auch so. Ich gebe gern zu, dass ich kein Serveradmin bin.

Also falls du dich besser auskennst oder mithelfen möchtest. Ich würde mich freuen. 🙂