Ubuntu24, MariaDB, Nginx, PHP‐FPM 설정으로 고성능 웹 서버 구축 - ohipark/btstack GitHub Wiki
- Nginx와 PHP-FPM 설정으로 고성능 웹 서버 구축
- Installing LEMP Stack (Nginx, MariaDB, PHP8.1) on Ubuntu 22.04
- How to Install Nginx, MariaDB, and PHP (LEMP) on Ubuntu 22.04 LTS
- How To Install Linux, Nginx, MariaDB, PHP (LEMP stack) on Debian 10
ubuntu-24.04.1-live-server-amd64.iso
- minimum server로 설치
- user : mcq / mcq***
$ sudo apt-get update
$ sudo apt-get install iputils-ping
$ sudo apt-get install net-tools
$ sudo apt-get install vim
$ sudo apt install vi
Nginx를 설치하고 기본적인 설정을 하는 것부터 시작하겠습니다. 여기서는 Ubuntu 기반 시스템을 예로 사용한다.
먼저 터미널을 열고 다음 명령어를 실행하여 Nginx를 설치
sudo apt update
sudo apt install nginx
sudo apt install apt-utils nginx-common fcgiwrap nginx-doc ssl-cert
설치가 완료되면 다음 명령어로 Nginx 서비스를 시작하고 부팅 시 자동으로 실행되도록 설정
sudo systemctl start nginx
sudo systemctl enable nginx
Nginx의 주요 설정 파일들은 다음과 같은 위치에 있음
- /etc/nginx/nginx.conf: 메인 설정 파일
- /etc/nginx/sites-available/: 사이트 설정 파일들이 위치한 디렉토리
- /etc/nginx/sites-enabled/: 활성화된 사이트 설정 파일들의 심볼릭 링크가 위치한 디렉토리
nginx.conf
파일은 전역 설정을 포함하고 있으며, 개별 사이트의 설정은 sites-available
디렉토리에 저장
사이트를 활성화하려면 해당 설정 파일의 심볼릭 링크를 sites-enabled
디렉토리에 생성
기본 서버 블록을 설정하여 웹사이트를 호스팅할 준비
/etc/nginx/sites-available/default 파일을 열어 다음과 같이 수정
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
이 설정은 기본적인 정적 파일 서빙을 위한 것이며, 나중에 PHP 지원을 추가할 때 이 설정을 더 수정해야 함
설정을 변경한 후에는 항상 구문 오류를 체크하고 Nginx를 재시작
sudo nginx -t
sudo systemctl restart nginx
apt install mariadb-server mariadb-client
systemctl start mariadb
systemctl enable mariadb
systemctl status mariadb
systemctl status mariadb
mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
Enter current password for root (enter for none):
OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.
Set root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!
mysql -e "SHOW DATABASES;" -p
$ sudo mariadb
MariaDB [(none)]> CREATE DATABASE example_database;
MariaDB [(none)]> GRANT ALL ON example_database.* TO 'test'@'localhost' IDENTIFIED BY 'test123' WITH GRANT OPTION;
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit
$ mariadb -u test -p
Enter password: test123
MariaDB [(none)]> SHOW DATABASES;
MariaDB [(none)]> exit
이제 기본적인 Nginx 및 MariaDB 설치와 설정이 완료되었으며, 다음 단계에서는 PHP-FPM을 설치하고 Nginx와 연동
PHP-FPM(FastCGI Process Manager)은 PHP 스크립트를 효율적으로 처리하기 위한 FastCGI 구현체임
Nginx와 함께 사용하면 동적 콘텐츠를 빠르게 처리할 수 있음..
PHP-FPM을 설치하고 Nginx와 연동하는 과정 처리
Ubuntu 시스템에서 PHP-FPM을 설치하려면 다음 명령어를 실행
sudo apt update
sudo apt install php-fpm php-mysql
이 명령어는 PHP-FPM과 MySQL 데이터베이스와의 연동을 위한 PHP 모듈을 함께 설치함.
프로젝트의 요구사항에 따라 추가적인 PHP 모듈을 설치할 수 있음
PHP-FPM의 주요 설정 파일은 다음 위치에 있음
- /etc/php/8.3/fpm/php.ini: PHP 전역 설정 파일 (버전 번호는 설치된 PHP 버전에 따라 다를 수 있음)
- /etc/php/8.3/fpm/pool.d/www.conf: PHP-FPM 풀 설정 파일
www.conf
파일에서 PHP-FPM 프로세스의 수, 사용자 및 그룹, 소켓 위치 등을 설정할 수 있음
Nginx가 PHP 파일을 처리할 수 있도록 설정을 변경
/etc/nginx/sites-available/default
파일을 열어 다음과 같이 수정
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
#fastcgi_index index.php;
#include fastcgi_params;
}
}
이 설정에서 주목할 점은 다음과 같음
-
index
지시자에index.php
를 추가하여 PHP 파일도 인덱스 파일로 사용할 수 있게 함 -
location ~ \.php$
블록은 .php로 끝나는 모든 요청을 PHP-FPM으로 전달함 -
fastcgi_pass
지시자는 PHP-FPM 소켓의 위치를 지정합니다. 설치된 PHP 버전에 따라 소켓 경로가 다를 수 있으므로 주의해야 함
설정을 변경한 후에는 Nginx 설정을 테스트하고 서비스를 재시작
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl restart php8.3-fpm
HP가 제대로 작동하는지 확인하기 위해 간단한 PHP 파일을 생성
/var/www/html/info.php
파일을 만들고 다음 내용을 작성하여 실행
<?php
phpinfo();
?>
웹 브라우저에서 http://your_server_ip/info.php
에 접속하여 PHP 정보 페이지가 표시되는지 확인함(확인 후에는 보안을 위해 이 파일을 삭제해야 함)
$ mariadb -u test -p
Enter password: test123
MariaDB [(none)]> CREATE TABLE example_database.todo_list (
item_id INT AUTO_INCREMENT,
content VARCHAR(255),
PRIMARY KEY(item_id)
);
MariaDB [(none)]> INSERT INTO example_database.todo_list (content) VALUES ("My first important item");
MariaDB [(none)]> INSERT INTO example_database.todo_list (content) VALUES ("My second important ite");
MariaDB [(none)]> INSERT INTO example_database.todo_list (content) VALUES ("My third important item");
MariaDB [(none)]> INSERT INTO example_database.todo_list (content) VALUES ("and this one more thing");
MariaDB [(none)]> SELECT * FROM example_database.todo_list;
nano /var/www/your_domain/todo_list.php
<?php
$user = "test";
$password = "test123";
$database = "example_database";
$table = "todo_list";
try {
$db = new PDO("mysql:host=localhost;dbname=$database", $user, $password);
echo "<h2>TODO</h2><ol>";
foreach($db->query("SELECT content FROM $table") as $row) {
echo "<li>" . $row['content'] . "</li>";
}
echo "</ol>";
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>
http://192.168.10.77/todo_list.php
Nginx의 성능을 최적화하는 것은 웹 서버의 전반적인 성능 향상에 큰 영향을 미치므로, 여기서는 Nginx의 주요 성능 최적화 기법들을 검토함
Nginx의 워커 프로세스 수를 조정하여 서버 리소스를 효율적으로 사용
/etc/nginx/nginx.conf 파일을 열어 다음 설정을 확인하고 수정
worker_processes auto;
worker_rlimit_nofile 65535;
worker_processes
를 auto
로 설정하면 Nginx가 자동으로 CPU 코어 수에 맞춰 워커 프로세스 수를 조정
worker_rlimit_nofile
은 각 워커 프로세스가 동시에 열 수 있는 파일 수를 제한
이벤트 모듈 설정을 통해 연결 처리 방식을 최적화할 수 있음
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
-
worker_connections
: 각 워커 프로세스가 동시에 처리할 수 있는 최대 연결 수 -
use epoll: Linux
시스템에서 가장 효율적인 이벤트 처리 방식 -
multi_accept
: 한 번에 여러 개의 새로운 연결을 수락
Keepalive 연결을 최적화하여 클라이언트와 서버 간의 연결을 효율적으로 유지함
http {
keepalive_timeout 65;
keepalive_requests 100;
}
Keepalive 연결을 최적화하여 클라이언트와 서버 간의 연결을 효율적으로 유지
http {
keepalive_timeout 65;
keepalive_requests 100;
}
keepalive_timeout
은 Keepalive 연결을 유지하는 시간을, keepalive_requests
는 하나의 Keepalive 연결로 처리할 수 있는 최대 요청 수를 지정
버퍼 크기를 조정하여 메모리 사용을 최적화하고 성능을 향상시킬 수 있음
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
이러한 설정은 클라이언트 요청 처리에 사용되는 버퍼의 크기를 조정하며, 서버의 메모리 용량과 일반적인 요청 크기를 고려하여 적절히 조정해야 함.
정적 파일에 대한 캐싱을 설정하여 반복적인 요청에 대한 처리 속도를 높일 수 있음
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
이 설정은 이미지, CSS, JavaScript 파일 등의 정적 리소스에 대해 30일간의 캐시 기간을 설정함.
Gzip 압축을 활성화하여 전송되는 데이터의 크기를 줄일 수 있음
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;
이 설정은 다양한 타입의 파일에 대해 Gzip 압축을 적용함
압축 레벨은 1(최소 압축)부터 9(최대 압축)까지 설정할 수 있으며, 여기서는 중간 수준인 5로 설정함.
오픈 파일 캐시를 설정하여 자주 사용되는 파일의 디스크립터를 메모리에 유지할 수 있음
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
이 설정은 최대 1000개의 파일 디스크립터를 캐시하며, 20초 동안 사용되지 않은 항목은 캐시에서 제거
로깅 설정을 최적화하여 디스크 I/O를 줄일 수 있음
access_log /var/log/nginx/access.log combined buffer=16k;
error_log /var/log/nginx/error.log warn;
액세스 로그에 버퍼를 사용하고, 에러 로그 레벨을 조정하여 로깅으로 인한 성능 저하를 최소화함
이러한 최적화 설정들을 적용한 후에는 반드시 Nginx 설정을 테스트하고 서비스를 재시작해야 함
sudo nginx -t
sudo systemctl restart nginx
이러한 최적화 설정들은 Nginx의 성능을 크게 향상시킬 수 있으나, 각 설정의 효과는 서버의 하드웨어 사양, 트래픽 패턴, 애플리케이션의 특성 등에 따라 달라질 수 있으므로, 실제 환경에서 테스트를 통해 최적의 설정을 찾는 것이 중요함
PHP-FPM(FastCGI Process Manager)의 성능을 최적화하는 것은 동적 콘텐츠를 효율적으로 처리하는 데 매우 중요함.
PHP-FPM의 프로세스 관리 설정을 최적화하여 서버 리소스를 효율적으로 사용할 수 있음
/etc/php/8.3/fpm/pool.d/www.conf
파일(PHP 버전에 따라 경로가 다를 수 있음)을 열어 다음 설정을 확인하고 수정함
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
-
pm = dynamic
: 동적으로 프로세스 수를 조절 -
pm.max_children
: 최대 자식 프로세스 수를 설정 -
pm.start_servers
: 시작 시 생성할 자식 프로세스 수 -
pm.min_spare_servers
와pm.max_spare_servers
: 유휴 상태의 최소 및 최대 프로세스 수를 지정 -
pm.max_requests
: 각 자식 프로세스가 재시작되기 전에 처리할 수 있는 최대 요청 수
이 값들은 서버의 CPU 코어 수와 가용 메모리에 따라 조정해야 함
예를 들어, 4코어 8GB RAM 서버의 경우 다음과 같이 설정할 수 있음
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
OpCache는 PHP 스크립트를 컴파일된 상태로 메모리에 저장하여 실행 속도를 높임.
/etc/php/8.3/fpm/php.ini
파일에서 다음 설정을 확인하고 수정해야 함
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_ freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1
-
opcache.enable=1
: OpCache를 활성화함 -
opcache.memory_consumption=128
: OpCache가 사용할 메모리 크기를 MB 단위로 지정 -
opcache.interned_strings_buffer=8
: 문자열 버퍼 크기를 MB 단위로 설정 -
opcache.max_accelerated_files=4000
: 캐시할 수 있는 최대 파일 수를 지정 -
opcache.revalidate_freq=60
: 캐시된 파일의 유효성을 검사하는 주기를 초 단위로 설정 -
opcache.fast_shutdown=1
: 빠른 종료 기능을 활성화 -
opcache.enable_cli=1
: CLI 모드에서도 OpCache를 사용
PHP 스크립트가 사용할 수 있는 최대 메모리 양을 조정
/etc/php/8.3/fpm/php.ini
파일에서 다음 설정을 수정
memory_limit = 256M
이 값은 애플리케이션의 요구사항에 따라 적절히 조정해야 함.
PHP 스크립트의 최대 실행 시간을 설정하여 서버 리소스를 보호
max_execution_time = 30
max_input_time = 60
이 값들은 일반적인 웹 애플리케이션에 적합한 설정이지만, 복잡한 작업을 수행하는 스크립트의 경우 더 높은 값이 필요할 수 있음
세션 데이터를 파일 시스템 대신 메모리에 저장하여 성능을 향상시킬 수 있음
php.ini
파일에서 다음 설정을 수정함
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
이 설정은 Redis를 세션 저장소로 사용하는 예시이며, Redis를 사용하려면 별도로 설치하고 설정해야 함
Realpath Cache를 최적화하여 파일 시스템 접근을 줄일 수 있음
realpath_cache_size = 4096k
realpath_cache_ttl = 600
이 설정은 파일 경로 확인 작업의 결과를 캐시하여 성능을 향상시킴.
PHP 8.0 이상에서는 JIT(Just-In-Time) 컴파일러를 활성화하여 성능을 더욱 향상시킬 수 있음
opcache.jit_buffer_size=100M
opcache.jit=1235
JIT 설정은 신중하게 테스트해야 하며, 모든 애플리케이션에 이점을 제공하지 않을 수 있음
로깅 설정을 최적화하여 디스크 I/O를 줄임.
www.conf
파일에서 다음 설정을 확인하고 수정
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
catch_workers_output = yes
이 설정은 에러 로깅을 활성화하고 워커 프로세스의 출력을 캡처함.
모든 설정을 변경한 후에는 PHP-FPM 서비스를 재시작하고 설정이 제대로 적용되었는지 확인해야 함
sudo systemctl restart php8.3-fpm
sudo systemctl status php8.3-fpm
또한, PHP 정보 페이지를 통해 변경된 설정이 적용되었는지 확인할 수 있음
<?php phpinfo(); ?>
이 코드를 포함한 PHP 파일을 웹 서버 루트 디렉토리에 생성하고 브라우저에서 접속하여 설정을 확인함.
이러한 PHP-FPM 최적화 설정들은 동적 콘텐츠 처리 성능을 크게 향상시킬 수 있으나, 각 설정의 효과는 서버 환경과 애플리케이션의 특성에 따라 달라질 수 있으므로, 실제 환경에서 충분한 테스트를 거쳐 최적의 설정을 찾는 것이 중요함
Nginx와 PHP-FPM을 함께 사용할 때 추가적인 최적화와 보안 강화 방법을 적용하면 더욱 안정적이고 효율적인 웹 서버 환경을 구축할 수 있음
Nginx의 FastCGI 캐시를 활용하여 동적 콘텐츠의 응답 속도를 높일 수 있음
Nginx 설정 파일에 다음과 같은 내용을 추가함
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
server {
# ... 기존 서버 설정 ...
location ~ \.php$ {
fastcgi_cache MYAPP;
fastcgi_cache_valid 200 60m;
fastcgi_cache_use_stale error timeout invalid_header updating http_500;
fastcgi_cache_lock on;
fastcgi_cache_bypass $query_string;
fastcgi_no_cache $query_string;
# ... 기존 FastCGI 설정 ...
}
}
이 설정은 PHP 스크립트의 출력을 캐시하여 반복적인 요청에 대한 응답 시간을 크게 줄일 수 있음..
PHP-FPM의 상태를 모니터링할 수 있는 페이지를 설정하고, www.conf 파일에 다음 설정을 추가함
pm.status_path = /status
그리고 Nginx 설정에 다음과 같은 location 블록을 추가함.
location /status {
access_log off;
allow 127.0.0.1;
deny all;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
}
이 설정은 로컬호스트에서만 접근 가능한 PHP-FPM 상태 페이지를 생성함
보안을 강화하기 위해 Nginx 설정에 다음과 같은 보안 헤더를 추가함
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
이러한 헤더들은 클릭재킹, XSS 공격, MIME 타입 스니핑 등 다양한 웹 보안 위협을 방지하는 데 도움을 제공함.
HTTPS를 사용하는 경우, SSL/TLS 설정을 최적화하여 보안과 성능을 향상시킬 수 있음
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
이 설정은 최신의 안전한 프로토콜과 암호화 스위트를 사용하며, OCSP 스테이플링을 활성화하여 SSL/TLS 연결의 성능을 개선함
PHP-FPM 소켓의 권한을 적절히 설정하여 보안을 강화함.
www.conf 파일에서 다음 설정을 확인하고 수정
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
이 설정은 웹 서버 사용자만 PHP-FPM 소켓에 접근할 수 있도록 제한함.
PHP-FPM이 실행되는 사용자와 그룹을 제한하여 보안을 강화
www.conf
파일에서 다음 설정을 확인
user = www-data
group = www-data
이 설정은 PHP-FPM 프로세스가 제한된 권한으로 실행되도록 함.
프로덕션 환경에서는 상세한 오류 메시지가 표시되지 않도록 설정
php.ini
파일에서 다음 설정을 확인하고 수정합니다:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
이 설정은 사용자에게 민감한 오류 정보가 노출되는 것을 방지함
파일 업로드 크기를 제한하여 잠재적인 공격을 방지할 수 있음
php.ini
파일에서 다음 설정을 확인하고 수정
upload_max_filesize = 2M
post_max_size = 8M
이 값은 애플리케이션의 요구사항에 따라 적절히 조정해야 함
Nginx, PHP, 그리고 관련 모듈들을 정기적으로 업데이트하여 최신 보안 패치를 적용하는 것이 중요함.
Ubuntu 시스템에서는 다음 명령어를 사용하여 업데이트를 수행할 수 있음
sudo apt update
sudo apt upgrade
이러한 통합 최적화 및 보안 강화 설정들을 적용하면 Nginx와 PHP-FPM을 사용하는 웹 서버의 성능과 안정성, 그리고 보안성을 크게 향상시킬 수 있으나, 각 설정의 영향을 충분히 이해하고, 실제 환경에서 테스트를 거친 후 적용하는 것이 중요함. 또한, 보안은 지속적인 과정이므로 정기적인 검토와 업데이트가 필요합니다. 🛡️🚀