Apache VirtualHost — konfiguracja wielu domen na jednym serwerze
Opublikowano: 9 kwietnia 2026 · Kategoria: VPS, Serwer
VirtualHost to mechanizm Apache pozwalający obsługiwać wiele domen z jednego serwera i jednego adresu IP. Każda domena ma własny katalog główny, własne logi i własną konfigurację. W tym artykule pokażemy jak stworzyć VirtualHost dla HTTP i HTTPS, aktywować go za pomocą a2ensite i przetestować konfigurację bez restartu serwera.
Jak działa Name-Based Virtual Hosting
Gdy przeglądarka wysyła żądanie HTTP, w nagłówku Host: przekazuje nazwę domeny (np.
mojastrona.pl). Apache sprawdza wszystkie aktywne VirtualHosty i dopasowuje ten
z pasującym ServerName lub ServerAlias. Dzięki temu jeden serwer z
jednym IP może obsługiwać setki domen.
Struktura katalogów dla wielu domen
# Utwórz katalogi dla każdej domeny sudo mkdir -p /var/www/mojastrona.pl/public_html sudo mkdir -p /var/www/innadomena.pl/public_html # Ustaw właściciela (www-data = użytkownik Apache) sudo chown -R www-data:www-data /var/www/mojastrona.pl sudo chown -R www-data:www-data /var/www/innadomena.pl # Uprawnienia sudo chmod -R 755 /var/www/mojastrona.pl
VirtualHost HTTP (port 80)
Stwórz plik konfiguracyjny w /etc/apache2/sites-available/:
# /etc/apache2/sites-available/mojastrona.pl.conf
<VirtualHost *:80>
ServerName mojastrona.pl
ServerAlias www.mojastrona.pl
DocumentRoot /var/www/mojastrona.pl/public_html
# Logi per domena
ErrorLog ${APACHE_LOG_DIR}/mojastrona.pl-error.log
CustomLog ${APACHE_LOG_DIR}/mojastrona.pl-access.log combined
# Opcje katalogu
<Directory /var/www/mojastrona.pl/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All # Pozwala na .htaccess
Require all granted
</Directory>
# Przekierowanie HTTP -> HTTPS (po instalacji certyfikatu SSL)
# Redirect permanent / https://mojastrona.pl/
</VirtualHost> VirtualHost HTTPS (port 443)
# /etc/apache2/sites-available/mojastrona.pl-ssl.conf
<VirtualHost *:443>
ServerName mojastrona.pl
ServerAlias www.mojastrona.pl
DocumentRoot /var/www/mojastrona.pl/public_html
# Certyfikat SSL (Let's Encrypt)
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/mojastrona.pl/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mojastrona.pl/privkey.pem
# Nowoczesne protokoły SSL
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder off
SSLSessionTickets off
# Nagłówki bezpieczeństwa
Header always set Strict-Transport-Security "max-age=63072000"
# Logi per domena
ErrorLog ${APACHE_LOG_DIR}/mojastrona.pl-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/mojastrona.pl-ssl-access.log combined
<Directory /var/www/mojastrona.pl/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost> Aktywacja: a2ensite i a2dissite
# Aktywuj moduł SSL (potrzebny dla HTTPS) sudo a2enmod ssl sudo a2enmod headers sudo a2enmod rewrite # Potrzebny dla .htaccess RewriteRule # Aktywuj VirtualHosty (tworzy symlink sites-available → sites-enabled) sudo a2ensite mojastrona.pl.conf sudo a2ensite mojastrona.pl-ssl.conf # Dezaktywuj domyślny VirtualHost (opcjonalne) sudo a2dissite 000-default.conf # Przetestuj konfigurację (BEZ restartu!) sudo apache2ctl configtest # Oczekiwany wynik: Syntax OK # Przeładuj Apache (zero downtime) sudo systemctl reload apache2 # Lub pełny restart (krótka przerwa) sudo systemctl restart apache2
Przykład: VirtualHost dla WordPress
# /etc/apache2/sites-available/wordpress.pl.conf
# Przekierowanie HTTP → HTTPS
<VirtualHost *:80>
ServerName wordpress.pl
ServerAlias www.wordpress.pl
Redirect permanent / https://wordpress.pl/
</VirtualHost>
<VirtualHost *:443>
ServerName wordpress.pl
ServerAlias www.wordpress.pl
DocumentRoot /var/www/wordpress.pl/public_html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/wordpress.pl/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/wordpress.pl/privkey.pem
# WordPress wymaga AllowOverride All dla permalink
<Directory /var/www/wordpress.pl/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# Ochrona pliku konfiguracyjnego
<FilesMatch "^wp-config\.php$">
Require all denied
</FilesMatch>
</Directory>
# Blokada dostępu do ukrytych plików
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/wordpress.pl-error.log
CustomLog ${APACHE_LOG_DIR}/wordpress.pl-access.log combined
</VirtualHost> Testowanie i debugowanie konfiguracji
# Sprawdź składnię konfiguracji sudo apache2ctl configtest # Wylistuj aktywne VirtualHosty sudo apache2ctl -S # Pokazuje: port, ServerName, DocumentRoot, plik konfiguracyjny # Sprawdź status Apache sudo systemctl status apache2 # Obejrzyj logi w czasie rzeczywistym sudo tail -f /var/log/apache2/error.log sudo tail -f /var/log/apache2/mojastrona.pl-error.log # Test połączenia (bez DNS) curl -H "Host: mojastrona.pl" http://127.0.0.1/
Typowe błędy i ich rozwiązania
- AH00558: Could not reliably determine server's FQDN — dodaj
ServerName localhostdo/etc/apache2/apache2.conf - 403 Forbidden — sprawdź uprawnienia katalogów (
chmod 755) iRequire all grantedw Directory - SSL_ERROR_RX_RECORD_TOO_LONG — port 443 nie ma SSL, brakuje
SSLEngine onlub moduł ssl nie jest aktywny (a2enmod ssl) - Permalinki WordPress nie działają — brak
AllowOverride Alllub moduł rewrite nie aktywny (a2enmod rewrite)