Rocky www: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(39 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 49: Zeile 49:
 
;PHP-FPM starten – httpd übergibt PHP-Anfragen an diesen Prozess
 
;PHP-FPM starten – httpd übergibt PHP-Anfragen an diesen Prozess
 
* systemctl enable --now php-fpm
 
* systemctl enable --now php-fpm
 +
 +
{{Hinweis|
 +
;mod_php: Läuft als Apache-Modul direkt im httpd-Prozess – jeder Apache-Worker hat einen eigenen PHP-Interpreter im Speicher, was bei prefork/MPM viel RAM frisst und PHP fest an Apache bindet.
 +
;PHP-FPM: Läuft als eigenständiger Prozess-Pool außerhalb von httpd, der über FastCGI (Unix-Socket oder TCP) angesprochen wird – dadurch kann Apache mit dem schlankeren event/worker-MPM laufen, PHP-Prozesse lassen sich unabhängig skalieren/neustarten, und derselbe FPM-Pool ist auch von nginx oder mehreren vhosts mit unterschiedlichen PHP-Versionen nutzbar.}}
  
 
= VirtualHost konfigurieren =
 
= VirtualHost konfigurieren =
;Wir legen eine eigene Konfigurationsdatei an – nicht die default ssl.conf anfassen
+
;Die mitgelieferte ssl.conf wird ersetzt mit dem notwendigsten
* vi /etc/httpd/conf.d/www.it2XX.int.conf
+
* echo Listen 443 https > /etc/httpd/conf.d/ssl.conf
 +
;Die Welcome Seite wir vaborisiert
 +
* rm /etc/httpd/conf.d/welcome.conf
 +
;Wir legen unsere Seite an
 +
* vi /etc/httpd/conf.d/www.conf
 
<pre>
 
<pre>
# HTTP → HTTPS Redirect
 
<VirtualHost *:80>
 
    ServerName www.it2XX.int
 
    Redirect permanent / https://www.it2XX.int/
 
</VirtualHost>
 
  
 
# HTTPS VirtualHost
 
# HTTPS VirtualHost
 
<VirtualHost *:443>
 
<VirtualHost *:443>
 
     ServerName www.it2XX.int
 
     ServerName www.it2XX.int
     DocumentRoot /var/www/it2XX
+
     DocumentRoot /var/repo
 
 
 
     SSLEngine on
 
     SSLEngine on
 
     SSLCertificateFile    /etc/ssl/own.crt
 
     SSLCertificateFile    /etc/ssl/own.crt
 
     SSLCertificateKeyFile /etc/ssl/own.key
 
     SSLCertificateKeyFile /etc/ssl/own.key
  
     <Directory /var/www/it2XX>
+
     <Directory /var/repo>
 +
        Options +Indexes
 
         AllowOverride None
 
         AllowOverride None
 
         Require all granted
 
         Require all granted
Zeile 82: Zeile 85:
 
     CustomLog /var/log/httpd/www.it2XX.int_access.log combined
 
     CustomLog /var/log/httpd/www.it2XX.int_access.log combined
 
</VirtualHost>
 
</VirtualHost>
 +
 +
 
</pre>
 
</pre>
 
= Verzeichnis anlegen =
 
;DocumentRoot erstellen
 
* mkdir -p /var/www/it2XX
 
  
 
= Beispielseite =
 
= Beispielseite =
;Eine einfache PHP-Seite die den Hostnamen und die aktuelle Zeit anzeigt
+
;Eine einfache PHP-Seite die den Hostnamen und die aktuelle Zeit anzeigt. /var/www/html ist die Standard-DocumentRoot von httpd – existiert bereits, kein eigenes Verzeichnis und kein eigener SELinux-Kontext nötig
* vi /var/www/it2XX/index.php
+
* vi /var/repo/index.php
 
<pre>
 
<pre>
 
<!DOCTYPE html>
 
<!DOCTYPE html>
Zeile 117: Zeile 118:
 
  Syntax OK
 
  Syntax OK
  
= Dienst starten =
+
= Dienst Testweise starten =
* systemctl enable --now httpd
 
 
* systemctl restart httpd
 
* systemctl restart httpd
 +
 +
= SELinux =
 +
;SELinux läuft auf Rocky standardmäßig im enforcing-Modus. /var/www/html ist bereits korrekt mit httpd_sys_content_t gelabelt – nur die Zertifikate unter /etc/ssl brauchen einen eigenen Kontext
 +
 +
== Fehleranalyse ==
 +
;Falls der Zugriff trotzdem fehlschlägt – SELinux-Blockaden anzeigen
 +
* ausearch -m avc -ts recent
 +
 +
== Kontext setzen ==
 +
*semanage fcontext -a -t httpd_sys_content_t "/etc/ssl/own\.(crt|key)"
 +
*restorecon -Rv /etc/ssl/
 +
 +
;Kontext prüfen
 +
* ls -Z /etc/ssl/own.crt /etc/ssl/own.key
  
 
= Firewall =
 
= Firewall =
Zeile 126: Zeile 140:
 
* firewall-cmd --permanent --zone=public --add-service=https
 
* firewall-cmd --permanent --zone=public --add-service=https
 
* firewall-cmd --reload
 
* firewall-cmd --reload
 +
= Test =
 +
;Im Browser aufrufen
 +
*https://www.it2XX.int
 +
Wir bekommen ein Forbidden
 +
 +
You don't have the permission to access this resource
  
= SELinux =
+
= Wieder zu Ausearch=
;SELinux läuft auf Rocky standardmäßig im enforcing-Modus. Auch wenn die Dateiberechtigungen stimmen, blockiert SELinux den Zugriff wenn der Sicherheitskontext falsch ist.
+
*ausearch -m avc -ts recent
 +
<pre>
 +
time->Tue Jul  7 23:59:32 2026
 +
type=PROCTITLE msg=audit(1783461572.080:196): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44
 +
type=SYSCALL msg=audit(1783461572.080:196): arch=c000003e syscall=262 success=no exit=-13 a0=ffffff9c a1=7fb4c400bd08 a2=7fb4d1de37c0 a3=100 items=0 ppid=3347 pid=3350 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
 +
type=AVC msg=audit(1783461572.080:196): avc:  denied  { getattr } for  pid=3350 comm="httpd" path="/var/repo/index.html" dev="dm-0" ino=67781042 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0
 +
</pre>
 +
*semanage fcontext -a -t httpd_sys_content_t "/var/repo(/.*)?"
 +
*restorecon -Rv /var/repo
 +
;Erklärung der Regex "/var/repo(/.*)?"
 +
{| class="wikitable"
 +
! Teil !! Bedeutung
 +
|-
 +
| <code>/var/repo</code> || literaler, fester Text – muss genau so vorkommen
 +
|-
 +
| <code>( )</code> || Gruppierung – fasst den eingeschlossenen Ausdruck zusammen
 +
|-
 +
| <code>/</code> || literales Zeichen – ein fester Slash
 +
|-
 +
| <code>.</code> || beliebiges einzelnes Zeichen (Wildcard)
 +
|-
 +
| <code>*</code> || 0 bis unendlich Wiederholungen des davorstehenden Elements (hier: <code>.</code>)
 +
|-
 +
| <code>.*</code> || zusammen: beliebig viele beliebige Zeichen (auch keins)
 +
|-
 +
| <code>(/.*)</code> || Gruppe: ein <code>/</code> gefolgt von beliebig vielem Inhalt
 +
|-
 +
| <code>?</code> || macht die davorstehende Gruppe optional (0 oder 1 mal)
 +
|-
 +
| <code>(/.*)?</code> || die ganze Gruppe "/ + beliebiger Inhalt" ist optional
 +
|}
  
== Kontext setzen ==
+
'''Matched:'''
;Das Verzeichnis muss als Webinhalt markiert sein damit httpd darauf zugreifen darf
+
* <code>/var/repo</code>
* semanage fcontext -a -t httpd_sys_content_t "/var/www/it2XX(/.*)?"
+
* <code>/var/repo/</code>
* restorecon -Rv /var/www/it2XX
+
* <code>/var/repo/index.html</code>
 +
* <code>/var/repo/sub/dir/datei.txt</code> (beliebige Tiefe)
  
;Kontext prüfen
+
'''Matched nicht:'''
* ls -Zd /var/www/it2XX
+
* <code>/var/repository</code>
 +
* <code>/var/repo2</code>
  
== Fehleranalyse ==
+
= Test =
;Falls der Zugriff trotzdem fehlschlägt – SELinux-Blockaden anzeigen
+
;Im Browser aufrufen
* ausearch -m avc -ts recent
+
*https://www.it2XX.int
 +
;Jetzt klappt es
  
 
= Logs =
 
= Logs =
Zeile 146: Zeile 199:
 
* tail -f /var/log/httpd/www.it2XX.int_error.log
 
* tail -f /var/log/httpd/www.it2XX.int_error.log
 
* tail -f /var/log/httpd/www.it2XX.int_access.log
 
* tail -f /var/log/httpd/www.it2XX.int_access.log
 
= Test =
 
;Im Browser aufrufen – HTTP muss automatisch auf HTTPS umleiten
 
http://www.it2XX.int
 
https://www.it2XX.int
 
  
 
;Zertifikat prüfen
 
;Zertifikat prüfen
 
* openssl s_client -connect www.it2XX.int:443 -showcerts
 
* openssl s_client -connect www.it2XX.int:443 -showcerts

Aktuelle Version vom 8. Juli 2026, 16:17 Uhr

Installation

DATEN

Parameter Wert Erläuterung
VM Name www Name der VM
Disk 20GB Vorgabe übernehmen
CPU 4 Cores Kerne
Ram 4 GB Speicher
Netzwerk (NIC) DMZ Interface-Zuweisung in VirtualBox
Admin root Passwort: radler
User kit Passwort: kit
IP 10.88.2XX.11/24 Statische IP
CIDR 24 Classless Inter-Domain Routing Präfixlänge
GW 10.88.2XX.1 GATEWAY
NS 10.88.2XX.21 Resolver
FQDN www.it2XX.int Fully Qualified Domain Name
DOM it2XX.int Domain Name

Hostname

  • hostnamectl set-hostname FQDN

Netzwerk

  • nmcli con mod enp0s3 ipv4.addresses IP/CIDR
  • nmcli con mod enp0s3 ipv4.gateway GW
  • nmcli con mod enp0s3 ipv4.dns NS
  • nmcli con mod enp0s3 ipv4.method manual
  • nmcli con mod enp0s3 ipv4.dns-search DOM
  • nmcli con mod enp0s3 connection.autoconnect yes
  • nmcli con up enp0s3

Hintergrund

Die Verbindungen findet ihr hier
  • DIR: /etc/NetworkManager/system-connections/
In unserem Fall
  • cat /etc/NetworkManager/system-connections/enp0s3.nmconnection
[connection]
id=enp0s3
uuid=40ff96e5-0c0d-31de-9bf0-f75da265425b
type=ethernet
autoconnect-priority=-999
interface-name=enp0s3
timestamp=1784278716

[ethernet]

[ipv4]
address1=192.168.3.127/24
dns=192.168.20.1;
dns-search=it.int;
gateway=192.168.3.254
method=manual

[ipv6]
addr-gen-mode=eui64
method=auto

[proxy]

Apache Webserver auf Rocky Linux

Der Webserver läuft in der DMZ und stellt Webinhalte über HTTP und HTTPS bereit. HTTP-Anfragen werden automatisch auf HTTPS umgeleitet. Das Zertifikat kommt von web.samogo.de und liegt unter /etc/ssl/.

Installation

  • dnf install -y httpd mod_ssl

Zertifikat holen

  • get-cert.sh

PHP installieren

PHP wird über das dnf-Modul installiert – so lässt sich später auch eine andere Version aktivieren
  • dnf install -y php php-fpm php-mysqlnd php-json php-mbstring
PHP-FPM starten – httpd übergibt PHP-Anfragen an diesen Prozess
  • systemctl enable --now php-fpm

ℹ️ Hinweis:

mod_php
Läuft als Apache-Modul direkt im httpd-Prozess – jeder Apache-Worker hat einen eigenen PHP-Interpreter im Speicher, was bei prefork/MPM viel RAM frisst und PHP fest an Apache bindet.
PHP-FPM
Läuft als eigenständiger Prozess-Pool außerhalb von httpd, der über FastCGI (Unix-Socket oder TCP) angesprochen wird – dadurch kann Apache mit dem schlankeren event/worker-MPM laufen, PHP-Prozesse lassen sich unabhängig skalieren/neustarten, und derselbe FPM-Pool ist auch von nginx oder mehreren vhosts mit unterschiedlichen PHP-Versionen nutzbar.

VirtualHost konfigurieren

Die mitgelieferte ssl.conf wird ersetzt mit dem notwendigsten
  • echo Listen 443 https > /etc/httpd/conf.d/ssl.conf
Die Welcome Seite wir vaborisiert
  • rm /etc/httpd/conf.d/welcome.conf
Wir legen unsere Seite an
  • vi /etc/httpd/conf.d/www.conf

# HTTPS VirtualHost
<VirtualHost *:443>
    ServerName www.it2XX.int
    DocumentRoot /var/repo
    SSLEngine on
    SSLCertificateFile    /etc/ssl/own.crt
    SSLCertificateKeyFile /etc/ssl/own.key

    <Directory /var/repo>
        Options +Indexes
        AllowOverride None
        Require all granted
    </Directory>

    # PHP über FPM
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
    </FilesMatch>

    ErrorLog  /var/log/httpd/www.it2XX.int_error.log
    CustomLog /var/log/httpd/www.it2XX.int_access.log combined
</VirtualHost>


Beispielseite

Eine einfache PHP-Seite die den Hostnamen und die aktuelle Zeit anzeigt. /var/www/html ist die Standard-DocumentRoot von httpd – existiert bereits, kein eigenes Verzeichnis und kein eigener SELinux-Kontext nötig
  • vi /var/repo/index.php
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>Willkommen auf <?= gethostname() ?></title>
    <style>
        body { font-family: sans-serif; max-width: 600px; margin: 4em auto; }
        h1   { color: #c0392b; }
        p    { color: #333; }
    </style>
</head>
<body>
    <h1>Willkommen auf <?= gethostname() ?></h1>
    <p>Server: <strong><?= $_SERVER['SERVER_NAME'] ?></strong></p>
    <p>Zeit:   <strong><?= date('d.m.Y H:i:s') ?></strong></p>
    <p>PHP:    <strong><?= phpversion() ?></strong></p>
</body>
</html>

Konfiguration prüfen

Syntaxfehler erkennen bevor httpd neu gestartet wird
  • apachectl configtest
Syntax OK

Dienst Testweise starten

  • systemctl restart httpd

SELinux

SELinux läuft auf Rocky standardmäßig im enforcing-Modus. /var/www/html ist bereits korrekt mit httpd_sys_content_t gelabelt – nur die Zertifikate unter /etc/ssl brauchen einen eigenen Kontext

Fehleranalyse

Falls der Zugriff trotzdem fehlschlägt – SELinux-Blockaden anzeigen
  • ausearch -m avc -ts recent

Kontext setzen

  • semanage fcontext -a -t httpd_sys_content_t "/etc/ssl/own\.(crt|key)"
  • restorecon -Rv /etc/ssl/
Kontext prüfen
  • ls -Z /etc/ssl/own.crt /etc/ssl/own.key

Firewall

HTTP und HTTPS auf dem www-Server freigeben
  • firewall-cmd --permanent --zone=public --add-service=http
  • firewall-cmd --permanent --zone=public --add-service=https
  • firewall-cmd --reload

Test

Im Browser aufrufen

Wir bekommen ein Forbidden

You don't have the permission to access this resource

Wieder zu Ausearch

  • ausearch -m avc -ts recent
time->Tue Jul  7 23:59:32 2026
type=PROCTITLE msg=audit(1783461572.080:196): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44
type=SYSCALL msg=audit(1783461572.080:196): arch=c000003e syscall=262 success=no exit=-13 a0=ffffff9c a1=7fb4c400bd08 a2=7fb4d1de37c0 a3=100 items=0 ppid=3347 pid=3350 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1783461572.080:196): avc:  denied  { getattr } for  pid=3350 comm="httpd" path="/var/repo/index.html" dev="dm-0" ino=67781042 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0
  • semanage fcontext -a -t httpd_sys_content_t "/var/repo(/.*)?"
  • restorecon -Rv /var/repo
Erklärung der Regex "/var/repo(/.*)?"
Teil Bedeutung
/var/repo literaler, fester Text – muss genau so vorkommen
( ) Gruppierung – fasst den eingeschlossenen Ausdruck zusammen
/ literales Zeichen – ein fester Slash
. beliebiges einzelnes Zeichen (Wildcard)
* 0 bis unendlich Wiederholungen des davorstehenden Elements (hier: .)
.* zusammen: beliebig viele beliebige Zeichen (auch keins)
(/.*) Gruppe: ein / gefolgt von beliebig vielem Inhalt
? macht die davorstehende Gruppe optional (0 oder 1 mal)
(/.*)? die ganze Gruppe "/ + beliebiger Inhalt" ist optional

Matched:

  • /var/repo
  • /var/repo/
  • /var/repo/index.html
  • /var/repo/sub/dir/datei.txt (beliebige Tiefe)

Matched nicht:

  • /var/repository
  • /var/repo2

Test

Im Browser aufrufen
Jetzt klappt es

Logs

  • journalctl -fu httpd
  • tail -f /var/log/httpd/www.it2XX.int_error.log
  • tail -f /var/log/httpd/www.it2XX.int_access.log
Zertifikat prüfen
  • openssl s_client -connect www.it2XX.int:443 -showcerts