Apache Httpd Configuration 정리
1. Apache Httpd
Apache Httpd 는 Apache 재단에서 제공하는 웹서버이다. Tomcat과는 달리 정적인 리소스만을 제공한다. 동적인 리소스를 처리할 수 있는 서블릿 컨테이너(Tomcat 등)과 연결하여 안정적인 웹 서비스를 제공할 수 있다.
2. Install
2.1 직접 설치
리눅스 OS를 사용한다면 패키지 관리 툴을 사용하여 Apache Httpd를 쉽게 설치할 수 있다.
apt install apache2
2.2 Docker 사용
Docker를 사용한다면 다양한 환경에서 Apache 웹서버를 쉽게 띄울 수 있다.
docker run -d --name="apache" -p 80:80 httpd
docker run -d --name="apache" -p 80:80 adoreje/httpd
httpd는 docker hub에 올라간 httpd의 공식 이미지이다. adoreje/httpd는 이미지 경량화를 위해 alpine 리눅스 기반에서 apache httpd 를 설치한 것이다. 자세한 내용은 github 을 참고한다.
3. Configuration
3.1 Apache httpd 2.4 default layout
ServerRoot :: /usr/local/apache2
DocumentRoot :: /usr/local/apache2/htdocs
Apache Config File :: /usr/local/apache2/conf/httpd.conf
Other Config Files :: /usr/local/apache2/conf/extra/
SSL Config File :: /usr/local/apache2/conf/extra/httpd-ssl.conf
ErrorLog :: /usr/local/apache2/logs/error_log
AccessLog :: /usr/local/apache2/logs/access_log
cgi-bin :: /usr/local/apache2/cgi-bin (enabled by default, but some of the bundled scripts are 644)
binaries (apachectl) :: /usr/local/apache2/bin
start/stop :: /usr/local/apache2/bin/apachectl (start|restart|graceful|graceful-stop|stop|configtest)
Apache 웹서버의 설정파일은 conf 폴더에 있다. httpd.conf 파일에서 여러가지 설정 정보를 관리하며 파일을 기능별로 여러개로 나누고 include하여 사용할 수 있다. 기능별로 나뉜 설정파일은 주로 conf/extra폴더에 위치하며 파일의 이름과 경로 등은 마음대로 설정할 수 있다.
3.2 기본 설정 정보
#### httpd.conf ####
Listen 80
# 기본으로 80포트로 들어오는 요청일 읽는다
# 다른 포트를 추가로 지정할 수 있다
ServerRoot "/usr/local/apache"
# 아파치의 홈 디렉토리, 절대경로로 설정한다. 이후에 나오는 대부분의 경로는 ServerRoot의 상대경로로 설정된다.
User apache
Group apache
# 홈페이지 서비스를 직접 담당하는 자식 프로세스들의 실행소유자와 소유 그룹에 대한 계정정보
# 보안을 위해 nobody로 설정하기도 한다.
ServerAdmin root@domain.com
# 웹 문서 로딩 중 에러 발생 시 보여지는 관리자 메일 주소
DocumentRoot "/var/www/html"
# 서버 내의 웹문서가 있는 경로
LoadModule auth_basic_module modules/mod_auth_basic.so
# /usr/local/apache/modules 에 있는 모듈을 동적으로 불러온다
Include conf.d/*.conf
# conf.d 디렉토리 내의 .conf 파일을 불러온다.
ServerName www.example.com
# 클라이언트에서 보여주는 호스트 이름
# 사용중인 도메인이 없다면 IP주소를 입력
Timeout 300
# 클라이언트에서 300초 동안 아무런 요청이 없을 때 연결을 중지
KeepAlive On
# 아파치의 한 프로세스가 특정사용자의 지속적인 요청을 처리
MaxKeepAliveRequests 100
# KeepAlive 가 on일경우에만 유효
# 사용자의 요청을 처리할 때 100이 넘어가면 프로세스를 종료하고 다른 프로세스가 사용자의 요청을 처리
# 하나의 프로세스가 지속적으로 요청을 처리하면 메모리 효율 저하 -> 시스템 성능 저하
KeepAliveTimeout 2
# KeepAlive On인 경우에만 유효
# 2초동안 요청이 없을 경우 timeout
3.3 Directives(지시어)
Related Modules | Related Directives |
---|---|
core | <Directory> |
mod_version | <DirectoryMatch> |
mod_proxy | <Files> |
<FileMatch> | |
<If> | |
<IfDefine> | |
<IfModule> | |
<IfVersion> | |
<Location> | |
<LocationMatch> | |
<DomainSet> | |
<Proxy> | |
<ProxyMatch> | |
<VirtualHost> |
<IfDefine>, <IfModule>, <IfVersion> 은 서버가 시작할 때(재시작 포함) 적용된다. 다른 지시어는 request마다 적용된다.
3.3.1 서버 전체 설정
- <IfDefine>
<IfDefine ClosedForNow>
Redirect "/" "http://otherserver.example.com/"
</IfDefine>
===========================================
서버가 httpd -DClosedForNow 명령어로 실행되어야만 적용된다.
- <IfModule>
<IfModule mod_mime_magic.c>
MimeMagicFile "conf/magic"
</IfModule>
============================================
서버에서 해당 모듈이 있을때만 적용된다. 서버 내에 모듈이 컴파일되어 있거나
<IfModule>을 호출하기 전 LoadModule을 통해 해당 모듈을 load해야 쓸 수 있다
- <IfVersion>
<IfVersion >= 2.4>
# this happens only in versions greater or
# equal 2.4.0.
</IfVersion>
===========================================
서버 버전이 2.4 이상일때만 적용된다.
3.3.2 파일 시스템
- <Directory>
<Directory "/var/www/html">
Options None
Order allow,deny
Allow from all
(Deny from all)
</Directory>
=========================================
DocumentRoot의 <Directory> 설정이다. Options 설정에 따라 DocumentRoot의파일이 목록화되어 나타날 수 있기 때문에 보안상 None으로 설정한다.
Order는 접근을 통제하는 순서를 나타낸다. allow, deny 순으로 지정하면 allow를 먼저 수행하고 deny를 나중에 수행하라는 의미이다.
Allow from(혹은 Deny from) 뒤에 쓸 수 있는 항목은 다음과 같다.
- 도메인
- 호스트 이름
- 호스트 IP 주소
- IP 주소의 A.B.C 클래스
- all (모든 주소)
- <Files>
<Files "private.html">
Require all denied
</Files>
=========================================
경로에 상관없이 private.html이라는 파일 모두에 적용된다.
3.3.3 WebSpace
클라이언트로 전송되어 화면에 보여지는 부분이다.
- <Location>, <LocationMatch>
<LocationMatch "^/private">
Require all denied
================================================
*/private이 들어간 url 요청을 모두 거부한다.
<Location "/server-status">
SetHandler server-status
</Location>
================================================
/server-status 을 호출했을 때 핸들러를 지정한다.
<Location> 지시어는 파일시스템을 따로 호출해야하는 과정이 필요 없다.
3.3.4 VirtualHost
한 서버에서 여러개의 서비스를 호스팅할 때 사용한다.
- <VirtualHost>
<VirtualHost 10.1.2.3:80>
ServerAdmin webmaster@host.example.com
DocumentRoot "/www/docs/host.example.com"
ServerName host.example.com
ErrorLog "logs/host.example.com-error_log"
TransferLog "logs/host.example.com-access_log"
</VirtualHost>
===============================================
10.1.2.3:80으로 요청이 들어올 경우 적용된다. ip뿐 만 아니라 도메인도 들어올 수 있으며 wildcard(*)를 적용할 수 있다.
<VirtualHost>마다 ServerName을 지정해주어야 하며 따로 지정해주지 않을 경우
메인 서버의 ServerName을 상속한다.
4. 주요 설정
4.1 WAS 연동
Apache Httpd와 WAS를 연동하는 방법은 3가지가 있다.
4.1.1 Tomcat connector(mod_jk)
Tomcat과 연결하기 위한 전용 모듈이다. AJP/1.3 프로토콜을 사용하며 설정이 조금 복잡하긴 하지만 JkMount 옵션을 이용하여 유연한 설정이 가능하다.
- 모듈 설치(공식 홈페이지)
# 1. 공식 홈페이지에서 최신 버전을 다운로드한다.(현재 최신버전 : 1.2.48)
wget https://mirror.navercorp.com/apache/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.48-src.tar.gz
# 2. 설치
tar zxvf tomcat-connectors-1.2.48-src.tar.gz
cd tomcat-connectors-1.2.48-src/native
./configure --with-apxs=/usr/sbin/apxs
make
make install
make install을 완료하면 apache 경로의 modules 폴더에 mod_jk.so 가 복사된다.
- httpd.conf 설정
# 모듈 load
LoadModule jk_module modules/mod_jk.so
# 설정파일 include
Include conf/extra/mod_jk.conf
================================
경로와 파일 이름은 변경할 수 있다.
- extra/mod_jk.conf 설정
폴더와 이름은 변경해도 된다.
<IfModule mod_jk.c>
# worker 설정 파일 경로
JkWorkersFile conf/workers_jk.properties
# jk 공유메모리 파일 위치
JkShmFile run/mod_jk.shm
# 로그 파일 경로
JkLogFile logs/mod_jk.log
# 로그 레벨 설정 [debug/error/info]
JkLogLevel info
# 로그 출력 시 시간 포맷 설정
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
## url pattern 에 따른 connector mapping
##JkMountFile conf/uriworkermap.properties
</IfModule>
- conf/workers_jk.properties 설정
worker.list=worker1, worker2
worker.worker1.port=8009
worker.worker1.host=server1
worker.worker1.type=ajp13
worker.worker1.lbfactor=1
## server 2
worker.worker2.port=8009
worker.worker2.host=server2
worker.worker2.type=ajp13
worker.worker2.lbfactor=1
여기서 설정하는 port는 톰캣에서 사용하는 AJP/1.3 프로토콜에서 사용하는 port를 지정한다. 관련된 설정은 톰캣의 server.xml을 확인한다.<Connector protocol="AJP/1.3" port="8009" connectionTimeout="20000" redirectPort="8443" secretRequired="false" URIEncoding="UTF-8" address="0.0.0.0"/>
- conf/uriworkermap.properties
## Mapping the URI /service1 under worker1
/service1/*.do=worker1
/service1/*.jsp=worker1
# /service2 요청으로 들어온 것은 worker2 로 mount
/service2/*=worker2
# png와 jpg 는 apache 가 처리
!/service2/*.png=worker2
!/service2/*.jpg=worker2
======================================================
uri 별로 유연한 처리가 가능하다.
- <VirtualHost> 적용
<VirtualHost *:81>
ServerName dgbp.daeguedu.com
JkMount /* worker1
</VirtualHost>
=========================================================
81번 포트로 들어오는 모든 요청을 worker1로 mount 한다.
4.1.2 mod_proxy 사용
reverse proxy로 동작하는 모듈이다.
- load module
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_module modules/mod_proxy.so
- <VirtualHost> 적용
<VirtualHost *:8080>
ServerName was2
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://10.36.25.73:8080/ retry=1 acquire=3000 timeout=600 Keepalive=On
ProxyPassReverse / http://10.36.25.73:8080/
</VirtualHost>
========================================================================
8080로 들어오는 모든 요청을 http://10.36.25.73:8080 로 전달한다.
- ProxyRequests
On : Forword proxy
Off : Reverse Proxy
- ProxyPreserveHost On
HTTP 헤더의 Host 부분을 유지한다.
4.1.3 mod_proxy_ajp 사용
AJP/1.3 프로토콜과 reverse proxy를 결합한 방식이다.
- <VirtualHost> 적용
<VirtualHost *:9090>
ServerName was2
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / ajp://10.36.25.73:8009/
ProxyPassReverse / ajp://10.36.25.73:8009/
</VirtualHost>
=============================================================================
reverse proxy와 비슷한 방식으로 적용할 수 있으며 프로토콜을 ajp로 변경하고 ajp에서 사용하는 포트를 적용한다.
4.2 SSL 적용
- extra/httpd-ssl.conf
<VirtualHost _default_:443>
DocumentRoot "/usr/local/apache2/htdocs"
ServerName www.example.com:443
ServerAdmin you@example.com
ErrorLog /proc/self/fd/2
TransferLog /proc/self/fd/1
JkMount /* worker1
SSLEngine on
SSLCertificateFile [인증서 파일 경로]
SSLCertificateKeyFile [키파일 경로]
SSLCACertificateFile [CA인증서 파일경로]
</VirtualHost>
- httpd.conf
# 모듈 load
LoadModule ssl_module modules/mod_ssl.so
- mod_proxy 에 적용
<VirtualHost *:8182>
ServerName dgbp.daeguedu.com
ServerName dgbp.daeguedu.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://10.36.3.140:8080/ retry=1 acquire=3000 timeout=600 Keepalive=On
ProxyPassReverse / http://10.36.3.140:8080/
SSLEngine on
SSLProxyEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLProxyCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateKeyFile /usr/local/apache//sslFile/server.key.pem
SSLCertificateFile /usr/local/apache//sslFile/server.crt.pem
SSLCACertificateFile /usr/local/apache//sslFile/rootca.crt.pem
</VirtualHost>
====================================================================
mod_proxy에 SSL을 적용하고자 하는 경우 SSLProxyEngine 을 활성화한다.
4.3 HTTPS Redirect
# 1. rewrite module을 로드한다.
LoadModule rewrite_module modules/mod_rewrite.so
# 2. Virtual Host에서 80으로 들어온 요청을 443으로 redirect 한다.
<VirtualHost *:80>
DocumentRoot "/www/example1"
ServerName www.example.com
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R,L]
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
DocumentRoot "/var/www/html"
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLHonorCipherOrder on
SSLCertificateFile [인증서 파일 경로]
SSLCertificateKeyFile [키파일 경로]
SSLCACertificateFile [CA인증서 파일경로]
ErrorLog logs/example.com-ssl-error_log
TransferLog logs/example.com-ssl-access_log
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
===========================================================================
- RewriteEngine
활성화 여부
- RewriteCond
조건 설정. 설정한 패턴과 일치하는 경우 RewriteRule 적용
- RewriteRule
실질적인 Rewrite 규칙을 적용하는 지시자
RewriteRule [input URL] [Return URL]
* Rewrite Subrutine 지시자
L : 뒤 구문 여부를 무시하고 그 줄에서 끝낸다.
R : 무조건 redirect를 적용한다.
P : proxy를 사용한다.