Apache HTTP Server (한국어)
Apache HTTP Server(생략해서 Apache라고도 한다)는 아파치 소프트웨어 재단에서 개발된 유명한 웹 서버이다.
아파치는 보통 MySQL 같은 데이터베이스와 PHP 등의 스크립트 언어와 함께 사용된다. 이러ᅟ한 아파치와의 연동을 흔히 LAMP stack (Linux, Apache, MySQL, PHP)이라고 불린다. 이 문서에서는 아파치 서버 구축 방법과 PHP, MySQL 연동 방법에 대해서 설명한다.
설치
설정
아파치 설정 파일들은 /etc/httpd/conf
에 위치한다. 주(主) 파일은 /etc/httpd/conf/httpd.conf
로서 다른 설정파일들을 포함한다.
기본 설정파일은 아파치 설치 과정에서 자동으로 생성되며 정상적으로 동작하는 설정 파일이다. 기본 설정파일은 /srv/http
디렉토리를 서버의 웹페이지에 접속한 사용자에게 제공한다.
아파치 서버 서비스를 시작하기 위해서는 systemd를 이용하여 httpd.service
를 시작한다.
서비스 시작 후에는 아파치 서버가 정상적으로 동작하고 있을 것이다. 서버의 동작여부를 확인하기 위해서는 웹 브라우저에서 http://localhost/로 접속한다. 접속하면 간단한 인덱스 페이지가 출력될 것이다.
아파치 설정에 관련된 자세한 정보는 이어지는 절을 참고한다.
고급 옵션
아래에 열거된 옵션들은 /etc/httpd/conf/httpd.conf
파일 내에 정의되어 있는 것으로서, 서버를 구축하고자 하는 사용자에게 유용한 옵션들이다.
User http
- 아파치는 보안 문제 때문에 root 관리자에 의해 시작된 뒤 곧바로 http UID로 전환된다. 설정파일에 기본으로 등록되는 사용자는 http이며 해당 사용자는 아파치 설치 과정에서 자동으로 생성된다.
Listen 80
- 아파치 서버에서 열어 놓을 포트를 설정한다. 라우터를 이용한 인터넷 접근을 위해서는 반드시 포트포워딩을 설정해주어야 한다.
- 만일 아파치 서버를 로컬에서만 접속이 허용되도록 설정하고 싶다면, 해당 줄 내용을
Listen 127.0.0.1:80
으로 변경한다.
ServerAdmin you@example.com
- 관리자의 이메일 주소를 설정한다. 설정된 이메일 주소는 에러 페이지에서 관리자 메일로 표시된다.
DocumentRoot "/srv/http"
- 호스팅할 웹 페이지들이 위치하는 디렉토리 위치
- DocumentRoot를 변경하면
<Directory "/srv/http">
도 변경해야한다. 그렇지 않으면 변경된 DocumentRoot에 접근할 때 403 에러(권한 부족 에러)가 발생한다. 또한,Require all denied
부분을Require all granted
으로 변경해야 한다. 해당 라인을 바꾸지 않는 경우에도 403 에러가 발생할 수 있다. 언급한 두 가지 경우 외에, DocumentRoot 디텍토리와 그 부모 디렉토리의 권한 문제가 있는 경우에도 403 에러가 발생될 수 있다.
두 개의 디렉토리(DocumentRoot, DocumentRoot의 부모 디렉토리)는 반드시 다른 사용자들에게도 실행권한이 부여되어야 한다. (chmod o+x /path/to/DocumentRoot
를 통해 설정할 수 있다)
위에서 언급된 권한관련 해결방법에는 몇 가지 논란이 있다. 반드시 모든 사용자들에게 실행 권한을 줄 필요가 없고 ACL을 통해 웹서버에만 실행 권한을 줄 수 있는 방법이 있기 때문이다. 자세한 내용은 다음 링크를 살펴보자. Access Control Lists#Granting execution permissions for private files to a web server[broken link: invalid section], Talk:Apache HTTP Server
AllowOverride None
-
<Directory>
섹션 안의 위 디렉티브는 아파치가.htaccess
파일을 완전하게 무시하도록 설정해준다. 하지만 아피치 2.4버전 이후부터 해당 옵션은 기본으로 되어있기 때문에.htaccess
파일을 사용하고 싶다면 명시적으로 허용해주어야 한다..htaccess
에서mod_rewrite
혹은 다른 설정들을 사용하고 싶다면 .htaccess파일에 관련 디렉티브를 선언함으로써 서버 설정을 오버라이딩 해야 한다. 이에 관련된 자세한 내용은 다음 링크를 참고한다. Apache documentation.
apachectl configtest
더 많은 설정 옵션들은 다음 파일에서 확인할 수 있다: /etc/httpd/conf/extra/httpd-default.conf
:
서버 서명을 비활성화하려면 다음 라인을 추가한다:
ServerSignature Off
아파치와 PHP 버전과 같은 서버 정보를 숨기려면 다음 라인을 추가한다:
ServerTokens Prod
사용자 디렉토리
사용자 디렉토리는 기본적으로 http://localhost/~yourusername/를 통해서 접근 가능하며, ~/public_html
의 내용을 표시한다. (/etc/httpd/conf/extra/httpd-userdir.conf
에서 변경이 가능하다).
만일 유저 디렉토리를 원하지 않는 경우에는 /etc/httpd/conf/httpd.conf
파일에서 다음 라인을 주석처리한다:
Include conf/extra/httpd-userdir.conf
아파치가 사용자의 홈디렉토리에 접근하기 위해서는 반드시 디렉토리의 권한을 적절하게 설정해 주어야 한다. 홈 디렉토리와 ~/public_html
은 반드시 다른 사용자들이 실행권한을 갖고 있어야 한다. (혹은 ACL을 통해 아파치 사용자 http에 한해서만 허용하도록 한다.)
$ chmod o+x ~ $ chmod o+x ~/public_html $ chmod -R o+r ~/public_html
권한 설정이 완료되면 httpd.service
를 재시작한다. Umask#Set the mask value 참고.
TLS/SSL
openssl는 TLS/SSL을 지원하고 아치에서 기본으로 설치된다.
/etc/httpd/conf/httpd.conf
파일에서 다음 세 개의 라인의 주석처리를 해제한다:
LoadModule ssl_module modules/mod_ssl.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so Include conf/extra/httpd-ssl.conf
TLS/SSL를 위해서는 키와 인증이 필요하다. 만약 공공 도메인을 가지고 있다면 무료로 인증을 받기 위해 Let's Encrypt를 사용할 수 있다. 공공 도메인을 가지고 있지 않다면 #키 생성과 자체 서명 인증 방법방법을 참고한다.
키와 인증을 얻고 나서는 /etc/httpd/conf/extra/httpd-ssl.conf
파일 내의 SSLCertificateFile
, SSLCertificateKeyFile
라인에서 해당 키와 인증을 가리키도록 설정한다.
마지막으로 변경 사항 적용을 위해 httpd.service
를 재시작한다.
키 생성과 자체 서명 인증 방법
개인키와 자체 서명 인증을 생성한다. 이것은 CSR가 요구되지 않는 대부분의 설치로는 적절하다.
# cd /etc/httpd/conf # openssl req -new -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 1095 # chmod 400 server.key
만약 CSR의 생성이 필요하다면, 위의 방법 대신 아래의 키 생성 방법을 따르도록 한다.
# openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out server.key # chmod 400 server.key # openssl req -new -sha256 -key server.key -out server.csr # openssl x509 -req -days 1095 -in server.csr -signkey server.key -out server.crt
가상 호스트
한 개 이상의 호스트를 원하는 경우에 /etc/httpd/conf/httpd.conf
설정 파일에서 아래 기술된 부분의 주석을 해제한다.
Include conf/extra/httpd-vhosts.conf
또한, /etc/httpd/conf/extra/httpd-vhosts.conf
파일에서 가상 호스트를 설정할 수 있다. 제공되는 기본 설정파일에는 자세한 예제가 많기 때문에 호스트 설정을 위해 참고하기에 유용하다.
로컬 머신에서 가상 호스트를 테스트하고 싶다면, /etc/hosts
파일에 가상 도메인명을 다음과 같이 등록한다:
127.0.0.1 domainname1.dom 127.0.0.1 domainname2.dom
파일 변경 후, 설정 적용을 위해 httpd.service
를 재시작한다.
가상 호스트 관리
이 절에서는 엄청나게 많은 가상 호스트를 가지고 있는 경우에 가상 호스트들을 관리하는 방법에 대하여 기술한다. 이러한 경우에는 가상 호스트별로 설정 파일을 만들고 이를 하나의 디렉토리(예: /etc/httpd/conf/vhosts
)에 저장하는 것을 권장한다.
먼저 디렉토리를 하나 생성한다:
# mkdir /etc/httpd/conf/vhosts
각 가상 호스트별 설정 파일을 생성한 디렉토리 안에 생성한다:
# nano /etc/httpd/conf/vhosts/domainname1.dom # nano /etc/httpd/conf/vhosts/domainname2.dom ...
마지막으로 아파치 메인 설정파일인 /etc/httpd/conf/httpd.conf
안에 Include
를 사용하서 가상 호스트별로 생성해둔 설정 파일들을 포함시킨다:
#Enabled Vhosts: Include conf/vhosts/domainname1.dom Include conf/vhosts/domainname2.dom
위처럼 각각의 가상 호스트를 주석처리를 통해 간단하게 활성화/비활성화할 수 있다.
다음은 각 가상 호스트별 파일의 예제이다:
/etc/httpd/conf/vhosts/domainname1.dom
<VirtualHost domainname1.dom:80> ServerAdmin webmaster@domainname1.dom DocumentRoot "/home/user/http/domainname1.dom" ServerName domainname1.dom ServerAlias domainname1.dom ErrorLog "/var/log/httpd/domainname1.dom-error_log" CustomLog "/var/log/httpd/domainname1.dom-access_log" common <Directory "/home/user/http/domainname1.dom"> Require all granted </Directory> </VirtualHost> <VirtualHost domainname1.dom:443> ServerAdmin webmaster@domainname1.dom DocumentRoot "/home/user/http/domainname1.dom" ServerName domainname1.dom:443 ServerAlias domainname1.dom:443 ErrorLog "/var/log/httpd/domainname1.dom-error_log" CustomLog "/var/log/httpd/domainname1.dom-access_log" common <Directory "/home/user/http/domainname1.dom"> Require all granted </Directory> SSLEngine on SSLCertificateFile "/etc/httpd/conf/apache.crt" SSLCertificateKeyFile "/etc/httpd/conf/apache.key" </VirtualHost>
확장 모듈(Extensions)
PHP
PHP 설치를 위해서는 php, php-apache 패키지를 설치한다.
/etc/httpd/conf/httpd.conf
파일에서 아래의 줄을 주석처리 한다:
#LoadModule mpm_event_module modules/mod_mpm_event.so
그리고 아래의 줄의 주석을 해제한다:
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
libphp7.so
이 mod_mpm_event
와는 제대로 동작하지 않고 mod_mpm_prefork
에서만 정상적으로 동작하기 때문에 위에서 기술된 것처럼 설정해주어야 한다.(참고: FS#39218)
위의 처리를 해주지 않는 경우 다음과 같은 에러 메세지가 출력된다:
Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP. AH00013: Pre-configuration failed httpd.service: control process exited, code=exited status=1또 다른 해결 방법으로,
mod_proxy_fcgi
를 사용하는 방법이 있다. 자세한 방법은 이하 절의 #php-fpm, mod_proxy_fcgi 사용하기를 참고한다.PHP를 활성화하기 위해서 /etc/httpd/conf/httpd.conf
파일에 아래 코드를 추가해준다:
-
LoadModule
리스트에서,LoadModule dir_module modules/mod_dir.so
다음의 원하는 곳에 아래 코드를 추가한다:
LoadModule php7_module modules/libphp7.so
-
Include
리스트 마지막 부분에 다음을 추가한다:
Include conf/extra/php7_module.conf
설정을 완료한 후, systemd를 사용하여 httpd.service
를 재시작한다.
PHP가 올바르게 설정되었는지 확인하려면 아파치 DocumentRoot
디렉토리(예. /srv/http/
혹은 ~/public_html
)에 test.php
파일을 생성하여 다음 코드를 해당 파일에 추가한다:
<?php phpinfo(); ?>
파일을 저장한 뒤, PHP가 제대로 작동하는지 확인하기 위하여 브라우저를 통해 다음 URL을 연다: http://localhost/test.php 또는 http://localhost/~myname/test.php
더 많은 설정 옵션과 확장 모듈(extensions)에 대한 정보는 PHP를 참고한다.
php-fpm, mod_proxy_fcgi 사용하기
ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php-fpm/php-fpm.sock|fcgi://localhost/srv/http/$1
php-fpm 패키지를 설치한다.
아래의 내용으로 /etc/httpd/conf/extra/php-fpm.conf
파일을 생성한다:
/etc/httpd/conf/extra/php-fpm.conf
<FilesMatch \.php$> SetHandler "proxy:unix:/run/php-fpm/php-fpm.sock|fcgi://localhost/" </FilesMatch> <Proxy "fcgi://localhost/" enablereuse=on max=10> </Proxy> <IfModule dir_module> DirectoryIndex index.php index.html </IfModule>
그리고 나서 /etc/httpd/conf/httpd.conf
파일의 최하단에 include 코드를 추가한다:
Include conf/extra/php-fpm.conf
sock
과 fcgi
사이의 파이프 좌우로 빈칸은 허용되지 않는 점에 유의해야 한다. localhost
는 다른 문자열로 치환될 수 있으며, 치환된 문자열은 반드시 SetHandler
와 Proxy
디렉티브에서도 일치해야 한다. 더 자세한 정보는 이곳에서 확인할 수 있다. SetHandler
와 Proxy
는 가상 호스트 설정 파일별로 사용가능하지만 fcgi://
이후의 이름은 반드시 가상 호스트들끼리 서로 달라야 한다./etc/php/php-fpm.d/www.conf
에서 PHP-FPM을 설정할 수 있지만 기본 설정으로도 정상적으로 동작한다.
아래 코드는 더이상 필요하지 않기 때문에 만약 httpd.conf
파일에 추가했다면 삭제하도록 한다.
LoadModule php7_module modules/libphp7.so Include conf/extra/php7_module.conf
httpd.service
와 php-fpm.service
를 재시작한다.
apache2-mpm-worker, mod_fcgid 사용하기
PHP wrapper를 위해 필요한 디렉토리와 심볼릭 링크를 만들어준다:
# mkdir /srv/http/fcgid-bin # ln -s /usr/bin/php-cgi /srv/http/fcgid-bin/php-fcgid-wrapper
다음 내용으로 /etc/httpd/conf/extra/php-fcgid.conf
파일을 생성한다:
/etc/httpd/conf/extra/php-fcgid.conf
# Required modules: fcgid_module <IfModule fcgid_module> AddHandler php-fcgid .php AddType application/x-httpd-php .php Action php-fcgid /fcgid-bin/php-fcgid-wrapper ScriptAlias /fcgid-bin/ /srv/http/fcgid-bin/ SocketPath /var/run/httpd/fcgidsock SharememPath /var/run/httpd/fcgid_shm # If you don't allow bigger requests many applications may fail (such as WordPress login) FcgidMaxRequestLen 536870912 # Path to php.ini – defaults to /etc/phpX/cgi DefaultInitEnv PHPRC=/etc/php/ # Number of PHP childs that will be launched. Leave undefined to let PHP decide. #DefaultInitEnv PHP_FCGI_CHILDREN 3 # Maximum requests before a process is stopped and a new one is launched #DefaultInitEnv PHP_FCGI_MAX_REQUESTS 5000 <Location /fcgid-bin/> SetHandler fcgid-script Options +ExecCGI </Location> </IfModule>
/etc/httpd/conf/httpd.conf
파일을 편집하여 actions 모듈을 활성화한다:
LoadModule actions_module modules/mod_actions.so
다음을 추가해준다.
LoadModule fcgid_module modules/mod_fcgid.so Include conf/extra/httpd-mpm.conf Include conf/extra/php-fcgid.conf
아래 코드는 더이상 필요하지 않기 때문에 만약 httpd.conf
파일에 추가했다면 삭제하도록 한다.
LoadModule php7_module modules/libphp7.so Include conf/extra/php7_module.conf
httpd.service
을 재시작한다.
MySQL/MariaDB
PHP#MySQL/MariaDB 위키페이지의 설명서를 따른다.
설정이 완료되면 httpd.service
를 재시작한다.
HTTP2
HTTP/2 지원을 위해서는 nghttp2 패키지를 설치해야 한다.
설치 후에 httpd.conf
파일에서 다음 줄의 주석을 해제한다:
LoadModule http2_module modules/mod_http2.so
다음 줄을 추가한다:
Protocols h2 http/1.1
더 자세한 내용은 mod_http2 문서를 참고한다.
문제 해결
아파치 서버 상태와 로그
systemctl를 통해 아파치 데몬의 현재 상태를 확인할 수 있다.
아파치 로그파일은 /var/log/httpd/
에서 찾을 수 있다.
Error: PID file /run/httpd/httpd.pid not readable (yet?) after start
httpd.conf
파일에서 unique_id_module
부분을 주석처리한다: #LoadModule unique_id_module modules/mod_unique_id.so
Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe.
httpd.service
가 php7_module
을 로딩할 때 다음과 같은 에러메세지가 출력되는 경우:
Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.
설정파일에서 다음과 같이 mpm_event_module
를 mpm_prefork_module
로 바꿔준다:
/etc/httpd/conf/httpd.conf
LoadModule mpm_event_module modules/mod_mpm_event.soLoadModule mpm_prefork_module modules/mod_mpm_prefork.so
그리고나서, httpd.service
를 재시작한다.
AH00534: httpd: Configuration error: No MPM loaded.
아파치를 최신 버전으로 업그레이드하면서 나타나는 문제다. 이는 최신 아파치 설정 부분에서 변경된 부분이 이전의 설정파일에 반영되지 않았기 때문에 생기는 문제로서 다음 부분의 주석을 해제해주면 해결이 가능하다.
/etc/httpd/conf/httpd.conf
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
이 후에도 계속해서 에러메세지가 출력된다면 위에서 언급된 부분을 참고한다.
Changing the max_execution_time in php.ini has no effect
php.ini
파일에서 max_execution_time
의 값을 30(초)보다 큰 값으로 변경하면 30초 후에 아파치로부터 503 Service Unavailable
라는 응답을 받게 된다. 이를 해결하기 위해서는 http 설정에서 <FilesMatch \.php$>
부분 이전에 ProxyTimeout
디렉티브를 추가해주면 해결 가능하다:
/etc/httpd/conf/httpd.conf
ProxyTimeout 300
변경 후에는 httpd.service
를 재시작한다.