리눅스

우분투 서버에 NGINX, PHP-FPM, Redis, PostgreSQL을 설치하고 연동하는 방법

변군이글루 2025. 8. 8. 14:03
반응형

우분투 서버에 NGINX, PHP-FPM, Redis, PostgreSQL을 설치하고 연동하는 방법

전체 구성도

  • NGINX ↔ PHP-FPM ↔ Redis ↔ PostgreSQL 순서로 데이터가 흐르는 구조

Mermaid 코드

더보기

---

Mermaid Live Editor(Link)

graph LR
    web01[Web Server<br>web-01<br>192.168.0.101<br>NGINX]
    app01[Application Server<br>app-01<br>192.168.0.111<br>PHP-FPM]
    cache01[Cache Server<br>cache-01<br>192.168.0.121<br>Redis]
    db01[Database Server<br>db-01<br>192.168.0.131<br>PostgreSQL]

    web01 --> app01
    app01 --> cache01
    cache01 --> db01

---

Web Server - NGINX

NGINX 공식 패키지 저장소 추가

curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update

NGINX 설치

sudo apt install -y nginx
sudo systemctl enable --now nginx
$ nginx -v
nginx version: nginx/1.28.0

NGINX 기본 설정

sudo tee /etc/nginx/nginx.conf <<'EOF'
user www-data www-data;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    keepalive_timeout 65;

    include /etc/nginx/conf.d/*.conf;
}
EOF

가상호스트 설정

sudo tee /etc/nginx/conf.d/default.conf <<'EOF'
server {
    listen 80;
    server_name _;

    access_log /var/log/nginx/default-access.log main;
    error_log /var/log/nginx/default-error.log;

    root /usr/share/nginx/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        root /usr/share/nginx/html;
        fastcgi_pass 192.168.0.111:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
        include fastcgi_params;
    }

    location = /basic_status {
        stub_status;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }

    location ~ ^/(ping|status)$ {
        fastcgi_pass 192.168.0.111:9000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }

    location ~ /\.ht {
        deny all;
    }
}
EOF

설정 문법 검사

nginx -t

테스트용 html 파일 생성

echo "Nginx Server" | sudo tee /usr/share/nginx/html/web.html
sudo touch /usr/share/nginx/html/index.php

웹서버 소유자 변경

sudo chown -R www-data:www-data /usr/share/nginx/html

NGINX 재시작

sudo systemctl restart nginx

테스트

curl http://192.168.0.101/web.html

Application Server - PHP-FPM

PHP 공식 PPA 저장소 추가(ondrej/php)

sudo add-apt-repository -y ppa:ondrej/php
sudo apt update

PHP 및 관련 확장 모듈 설치

sudo apt install -y php8.3 php8.3-cli php8.3-common php8.3-curl php8.3-dev php8.3-fpm \
  php8.3-gd php8.3-igbinary php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-readline \
  php8.3-redis php8.3-xml php8.3-zip php8.3-pgsql
sudo systemctl enable --now php8.3-fpm
$ php-fpm8.3 --version
PHP 8.3.24 (fpm-fcgi) (built: Aug  3 2025 08:58:02)
Copyright (c) The PHP Group
Zend Engine v4.3.24, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.24, Copyright (c), by Zend Technologies

PHP-FPM 로그 디렉토리 생성

sudo mkdir -p /var/log/php-fpm

PHP-FPM 전역 설정 파일 생성

sudo tee /etc/php/8.3/fpm/php-fpm.conf <<EOF
[global]
pid = /run/php/php8.3-fpm.pid
error_log = /var/log/php-fpm/error.log
include=/etc/php/8.3/fpm/pool.d/*.conf
EOF

PHP-FPM 워커 풀 설정 파일 생성

sudo tee /etc/php/8.3/fpm/pool.d/www.conf <<'EOF'
[www]
user = www-data
group = www-data

; NGINX에서 접근 가능하도록 바인딩
listen = 0.0.0.0:9000
; NGINX 서버 IP만 허용
listen.allowed_clients = 192.168.0.101

listen.owner = www-data
listen.group = www-data
listen.mode = 0666

;CPU 8개, 메모리 16GB, PHP 프로세스당 메모리 사용량이 50MB인 경우
pm = dynamic
pm.max_children = 250
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30

request_terminate_timeout = 30
request_slowlog_timeout = 10
slowlog = /var/log/php-fpm/slow-$pool.log

pm.status_path = /status
ping.path = /ping

access.log = /var/log/php-fpm/access-$pool.log
access.format = "[%t] %m %{REQUEST_SCHEME}e://%{HTTP_HOST}e%{REQUEST_URI}e %f pid:%p TIME:%ds MEM:%{mega}Mmb CPU:%C%% status:%s {%{REMOTE_ADDR}e|%{HTTP_USER_AGENT}e}"

php_admin_value[error_log] = /var/log/php-fpm/error-$pool.log
php_admin_flag[log_errors] = on

php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/sessions
EOF

설정 문법 검사

php-fpm8.3 -t

PHP-FPM 재시작

sudo systemctl restart php8.3-fpm

NGINX 기본 웹문서 루트 생성

sudo mkdir -p /usr/share/nginx/html

PHP 정보 출력 테스트 파일 생성

echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/html/phpinfo.php

웹서버 소유자로 권한 변경 (NGINX가 읽고 실행 가능하도록)

sudo chown -R www-data:www-data /usr/share/nginx/html

PHP 테스트 페이지 호출

curl http://192.168.0.101/phpinfo.php
728x90

Cache Server - Redis Server

Redis 공식 APT 저장소 추가

curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt update

Redis 서버 설치

sudo apt install -y redis-server
systemctl enable --now redis-server
$ redis-server --version
Redis server v=8.2.0 sha=00000000:1 malloc=jemalloc-5.3.0 bits=64 build=dcbeaec24fa29d4

Redis 외부 접속 허용 설정

vim /etc/redis/redis.conf
bind 0.0.0.0
protected-mode yes
requirepass redis_password

Redis 서버 재시작

sudo systemctl restart redis-server

Database Server - PostgreSQL

PostgreSQL 공식 저장소 추가

sudo sh -c "echo 'deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main' > /etc/apt/sources.list.d/pgdg.list"
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo apt update

PostgreSQL 서버 및 클라이언트 설치

sudo apt install -y postgresql-17 postgresql-client-17
$ psql --version
psql (PostgreSQL) 17.5 (Ubuntu 17.5-1.pgdg24.04+1)
sudo systemctl enable --now postgresql

PostgreSQL 외부 접속 허용 설정

sudo vim /etc/postgresql/17/main/postgresql.conf
listen_addresses = '0.0.0.0'

클라이언트 인증 설정 파일 수정

sudo vim /etc/postgresql/17/main/pg_hba.conf
host    all             all             192.168.0.0/24          scram-sha-256

PostgreSQL 재시작

sudo systemctl restart postgresql

데이터베이스 및 사용자 생성

  • postgres 사용자로 psql 접속
sudo -u postgres psql
# 데이터베이스 생성
CREATE DATABASE simpledb;

# 사용자 생성 및 비밀번호 설정
CREATE USER webuser WITH PASSWORD 'securepass';

# 데이터베이스에 대한 권한 부여
GRANT ALL PRIVILEGES ON DATABASE simpledb TO webuser;

# simpledb 데이터베이스로 연결 전환
\c simpledb

# 테이블 생성
CREATE TABLE info (
    id SERIAL PRIMARY KEY,
    message TEXT
);

# 샘플 데이터 입력
INSERT INTO info (message) VALUES ('Hello from PostgreSQL!');

# 특정 테이블에 대한 SELECT 권한 부여
GRANT SELECT ON TABLE info TO webuser;

# psql 종료
\q

서비스 연동 테스트

NGINX 기본 페이지 확인

curl http://192.168.0.101/web.html

NGINX → PHP-FPM 연동 테스트

curl http://192.168.0.101/phpinfo.php

NGINX → PHP → Redis 연결 테스트

sudo tee /usr/share/nginx/html/cache.php <<'EOF'
<?php
$redis = new Redis();
$redis->connect('192.168.0.121', 6379);
echo "Redis 연결 성공";
?>
EOF

NGINX → PHP → PostgreSQL 연결 테스트

sudo tee /usr/share/nginx/html/db.php <<'EOF'
<?php
$conn = pg_connect("host=192.168.0.131 dbname=simpledb user=webuser password=securepass");
if ($conn) { echo "PostgreSQL 연결 성공"; }
?>
EOF

최종 통합 테스트 - 캐시 적용된 index.php

sudo tee /usr/share/nginx/html/index.php <<'EOF'
<?php
// Redis 연결 설정
$redis = new Redis();
$redis->connect('192.168.0.121', 6379);  // Redis 서버 IP와 포트
$redis->auth('redis_password');

// PostgreSQL 연결 설정
$conn = pg_connect("host=192.168.0.131 dbname=simpledb user=webuser password=securepass");
if (!$conn) {
    die("PostgreSQL 연결 실패: " . pg_last_error());
}

// 캐시 키 정의
$cacheKey = 'info_message';
// Redis에서 캐시된 값 가져오기
$cachedValue = $redis->get($cacheKey);

if ($cachedValue !== false) {
    // 캐시가 존재할 경우
    echo "캐시에서 데이터 가져옴: " . htmlspecialchars($cachedValue);
} else {
    // 캐시가 없으면 DB에서 조회
    $result = pg_query($conn, "SELECT message FROM info WHERE id = 1");
    if (!$result) {
        die("쿼리 실패: " . pg_last_error($conn));
    }
    $row = pg_fetch_assoc($result);
    if ($row) {
        $message = $row['message'];

        // Redis에 캐시 저장 (유효기간 300초 = 5분)
        $redis->setex($cacheKey, 300, $message);

        echo "DB에서 데이터 가져옴: " . htmlspecialchars($message);
    } else {
        echo "데이터가 없습니다.";
    }
}

// 연결 종료
pg_close($conn);
?>
EOF
curl http://192.168.0.101/index.php

 

728x90
반응형