한 대의 httpd 로 서로 다른 디렉터리를 서비스해야 한다. DocumentRoot 를 두 번 적으면 뒤엣것만 먹는다. 포트별로 나누고 싶은데 Listen 을 어떻게 맞춰야 하는지, 잘 갈렸는지 어떻게 확인하는지가 문제다.
DocumentRoot 는 서버 전역에 하나, 그리고 <VirtualHost> 블록마다 하나씩 둘 수 있다. 전역에 두 번 적으면 나중 것이 앞의 것을 덮는다. 여러 개를 두려면 가상 호스트를 그 수만큼 만든다.
가르는 기준은 두 가지다. 포트로 가르거나, 같은 포트에서 호스트 이름으로 가른다.
듣는 포트를 먼저 모두 열어야 한다. Listen 이 없으면 그 포트의 가상 호스트는 아무 일도 하지 않는다.
Listen 80
Listen 8080
<VirtualHost *:80>
ServerName site-a.example.com
DocumentRoot /var/www/site-a
ErrorLog /var/log/httpd/site-a_error.log
CustomLog /var/log/httpd/site-a_access.log combined
<Directory /var/www/site-a>
Require all granted
Options -Indexes +FollowSymLinks
AllowOverride None
</Directory>
</VirtualHost>
<VirtualHost *:8080>
ServerName site-b.example.com
DocumentRoot /var/www/site-b
ErrorLog /var/log/httpd/site-b_error.log
CustomLog /var/log/httpd/site-b_access.log combined
<Directory /var/www/site-b>
Require all granted
Options -Indexes +FollowSymLinks
</Directory>
</VirtualHost>
<Directory> 블록을 빼면 기본 거부 정책에 걸려 403 이 난다. DocumentRoot 만 바꾸고 끝내지 않는다.
포트를 늘리지 않아도 된다면 이쪽이 낫다. 방화벽을 더 열 필요가 없다.
<VirtualHost *:80>
ServerName a.example.com
DocumentRoot /var/www/site-a
</VirtualHost>
<VirtualHost *:80>
ServerName b.example.com
ServerAlias www.b.example.com
DocumentRoot /var/www/site-b
</VirtualHost>
같은 주소·포트에 가상 호스트가 여럿이면, 요청의 Host 헤더와 맞는 것이 없을 때 맨 처음 정의된 블록이 기본값으로 쓰인다. 의도치 않은 사이트가 기본이 되지 않게 순서에 유의한다.
문법을 먼저 본다. 이 단계에서 걸리면 재기동해도 소용없다.
sudo apachectl configtest
포트를 새로 열었으면 reload 로는 반영되지 않는 경우가 있다. Listen 을 바꿨다면 restart 한다.
sudo systemctl restart httpd
어떤 가상 호스트가 어떤 파일에서 읽혔는지 그대로 보여 주는 명령이 있다. 설정이 여러 파일로 흩어졌을 때 가장 유용하다.
httpd -S
apachectl -S
출력에 포트별·이름별 가상 호스트와 그 정의 위치가 줄줄이 나온다. 여기에 안 보이면 설정 파일이 아예 안 읽힌 것이다.
실제로 어느 디렉터리가 서비스되는지는 요청으로 확인한다.
ss -lntp | grep httpd
curl -I http://127.0.0.1:8080/
curl -s -H 'Host: b.example.com' http://127.0.0.1/ | head
각 디렉터리에 구분되는 파일을 하나씩 두고 받아 보는 것이 가장 확실하다.
echo 'site-a' | sudo tee /var/www/site-a/whoami.txt
echo 'site-b' | sudo tee /var/www/site-b/whoami.txt
curl -s http://127.0.0.1/whoami.txt
curl -s http://127.0.0.1:8080/whoami.txt
새 포트를 방화벽이 막고 있다.
sudo firewall-cmd --add-port=8080/tcp --permanent && sudo firewall-cmd --reload
SELinux 가 비표준 포트 바인드를 막는다. httpd 가 쓸 수 있는 포트 목록에 추가한다.
sudo semanage port -a -t http_port_t -p tcp 8080
문서 디렉터리의 SELinux 문맥이 다르다. /var/www 밖에 디렉터리를 두면 거의 항상 이 문제가 난다.
sudo semanage fcontext -a -t httpd_sys_content_t '/data/web(/.*)?'
sudo restorecon -Rv /data/web