์›Œํฌ์ƒต RHEL 8 ๋ฒ ํƒ€: ์ž‘๋™ํ•˜๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ•

RHEL 8 ๋ฒ ํƒ€๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋งŽ์€ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ ๋ชฉ๋ก์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐ๋Š” ๋ช‡ ํŽ˜์ด์ง€๊ฐ€ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ๋กœ๋Š” ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜์—์„œ๋Š” Red Hat Enterprise Linux 8 ๋ฒ ํƒ€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธํ”„๋ผ๋ฅผ ์‹ค์ œ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์›Œํฌ์ˆ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์›Œํฌ์ƒต RHEL 8 ๋ฒ ํƒ€: ์ž‘๋™ํ•˜๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ•

๊ฐœ๋ฐœ์ž๋“ค ์‚ฌ์ด์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ธ Python์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ์„ ์œ„ํ•œ ์ƒ๋‹นํžˆ ์ผ๋ฐ˜์ ์ธ ์กฐํ•ฉ์ธ Django์™€ PostgreSQL์˜ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ด๋“ค๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก RHEL 8 Beta๋ฅผ ๊ตฌ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ (๋ถ„๋ฅ˜๋˜์ง€ ์•Š์€) ์žฌ๋ฃŒ๋ฅผ ๋ช‡ ๊ฐ€์ง€ ๋” ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž๋™ํ™”์˜ ๊ฐ€๋Šฅ์„ฑ์„ ํƒ๊ตฌํ•˜๊ณ , ์ปจํ…Œ์ด๋„ˆ๋กœ ์ž‘์—…ํ•˜๊ณ , ์—ฌ๋Ÿฌ ์„œ๋ฒ„๋กœ ํ™˜๊ฒฝ์„ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ด ํฅ๋ฏธ๋กญ๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์ด ๋ฐ”๋€” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋จผ์ € ์ž‘๊ณ  ๊ฐ„๋‹จํ•œ ํ”„๋กœํ† ํƒ€์ž…์„ ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜์•ผ ํ•˜๋Š”์ง€, ์–ด๋–ป๊ฒŒ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š”์ง€ ์ •ํ™•ํžˆ ํ™•์ธํ•œ ๋‹ค์Œ ์ž๋™ํ™”ํ•˜์—ฌ ๋” ๋ณต์žกํ•œ ๊ตฌ์„ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜ ์šฐ๋ฆฌ๋Š” ๊ทธ๋Ÿฌํ•œ ํ”„๋กœํ† ํƒ€์ž…์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

RHEL 8 ๋ฒ ํƒ€ VM ์ด๋ฏธ์ง€ ๋ฐฐํฌ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ€์ƒ ๋จธ์‹ ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์„ค์น˜ํ•˜๊ฑฐ๋‚˜ ๋ฒ ํƒ€ ๊ตฌ๋…์—์„œ ์ œ๊ณต๋˜๋Š” KVM ๊ฒŒ์ŠคํŠธ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ์ŠคํŠธ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํด๋ผ์šฐ๋“œ ์ดˆ๊ธฐํ™”(cloud-init)๋ฅผ ์œ„ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ฐ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•  ๊ฐ€์ƒ CD๋ฅผ โ€‹โ€‹๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋””์Šคํฌ ๊ตฌ์กฐ๋‚˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํŒจํ‚ค์ง€์— ๋Œ€ํ•ด ํŠน๋ณ„ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ํ•„์š”๋Š” ์—†์œผ๋ฉฐ ์–ด๋–ค ๊ตฌ์„ฑ์ด๋“  ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

์ „์ฒด ๊ณผ์ •์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์žฅ๊ณ  ์„ค์น˜

์ตœ์‹  ๋ฒ„์ „์˜ Django๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Python 3.5 ์ด์ƒ์ด ์„ค์น˜๋œ ๊ฐ€์ƒ ํ™˜๊ฒฝ(virtualenv)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ฒ ํƒ€ ๋…ธํŠธ์—์„œ Python 3.6์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ํ•ด๋‹น๋˜๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

[cloud-user@8beta1 ~]$ python
-bash: python: command not found
[cloud-user@8beta1 ~]$ python3
-bash: python3: command not found

Red Hat์€ RHEL์—์„œ Python์„ ์‹œ์Šคํ…œ ํˆดํ‚ท์œผ๋กœ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋Ÿฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์‚ฌ์‹ค ๋งŽ์€ Python ๊ฐœ๋ฐœ์ž๋Š” ์—ฌ์ „ํžˆ Python 2์—์„œ Python 2๋กœ์˜ ์ „ํ™˜์„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ๋Š” ๋ฐ˜๋ฉด Python 3 ์ž์ฒด๋Š” ํ™œ๋ฐœํžˆ ๊ฐœ๋ฐœ ์ค‘์ด๋ฉฐ ์ ์  ๋” ๋งŽ์€ ์ƒˆ ๋ฒ„์ „์ด ์ง€์†์ ์œผ๋กœ ๋“ฑ์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‹ค์–‘ํ•œ ์ƒˆ Python ๋ฒ„์ „์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋™์‹œ์— ์•ˆ์ •์ ์ธ ์‹œ์Šคํ…œ ๋„๊ตฌ์— ๋Œ€ํ•œ ์š”๊ตฌ๋ฅผ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด ์‹œ์Šคํ…œ Python์ด ์ƒˆ ํŒจํ‚ค์ง€๋กœ ์ด๋™๋˜์—ˆ์œผ๋ฉฐ Python 2.7 ๋ฐ 3.6์„ ๋ชจ๋‘ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ์‚ฌํ•ญ๊ณผ ๋ณ€๊ฒฝ ์ด์œ ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ ์ถœํŒ๋ฌผ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋žญ๋˜ ํ™”์ดํŠธ์˜ ๋ธ”๋กœ๊ทธ (๋žญ๋˜ ํ™”์ดํŠธ).

๋”ฐ๋ผ์„œ Python์„ ์ž‘๋™ํ•˜๋ ค๋ฉด ์ข…์†์„ฑ์œผ๋กœ python3-pip๊ฐ€ ํฌํ•จ๋œ ๋‘ ๊ฐœ์˜ ํŒจํ‚ค์ง€๋งŒ ์„ค์น˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

sudo yum install python36 python3-virtualenv

Langdon์ด ์ œ์•ˆํ•œ ๋Œ€๋กœ ์ง์ ‘ ๋ชจ๋“ˆ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜๊ณ  pip3์„ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–จ๊นŒ์š”? ๋‹ค๊ฐ€์˜ค๋Š” ์ž๋™ํ™”๋ฅผ ์—ผ๋‘์— ๋‘๊ณ , pip ๋ชจ๋“ˆ์€ ์‚ฌ์šฉ์ž ์ •์˜ pip ์‹คํ–‰ ํŒŒ์ผ์ด ์žˆ๋Š” virtualenv๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Ansible์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด pip๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘๋™ ์ค‘์ธ Python3 ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Django ์„ค์น˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ณ„์† ์ง„ํ–‰ํ•˜๊ณ  ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ์‹œ์Šคํ…œ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐ๋„ท์—๋Š” ๋‹ค์–‘ํ•œ ๊ตฌํ˜„ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ํ•˜๋‚˜์˜ ๋ฒ„์ „์ด ์ œ์‹œ๋˜์–ด ์žˆ์ง€๋งŒ ์‚ฌ์šฉ์ž๋Š” ์ž์‹ ์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ Yum์„ ์‚ฌ์šฉํ•˜์—ฌ RHEL 8์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ PostgreSQL ๋ฐ Nginx ๋ฒ„์ „์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

sudo yum install nginx postgresql-server

PostgreSQL์—๋Š” psycopg2๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ virtualenv ํ™˜๊ฒฝ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ Django ๋ฐ Gunicorn๊ณผ ํ•จ๊ป˜ pip3์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋จผ์ € virtualenv๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Django ํ”„๋กœ์ ํŠธ๋ฅผ ์„ค์น˜ํ•  ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜๋ฅผ ์„ ํƒํ•˜๋Š” ์ฃผ์ œ์— ๋Œ€ํ•ด์„œ๋Š” ํ•ญ์ƒ ๋งŽ์€ ๋…ผ์Ÿ์ด ์žˆ์ง€๋งŒ, ์˜์‹ฌ์Šค๋Ÿฌ์šธ ๊ฒฝ์šฐ ์–ธ์ œ๋“ ์ง€ Linux Filesystem Hierarchy Standard๋ฅผ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ FHS๋Š” /srv๊ฐ€ "ํ˜ธ์ŠคํŠธ๋ณ„ ๋ฐ์ดํ„ฐ(์›น ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ๋ฐ ์Šคํฌ๋ฆฝํŠธ, FTP ์„œ๋ฒ„์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ, ์ œ์–ด ์‹œ์Šคํ…œ ์ €์žฅ์†Œ ๋“ฑ ์‹œ์Šคํ…œ์ด ์ƒ์„ฑํ•˜๋Š” ๋ฐ์ดํ„ฐ)๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค." ๋ฒ„์ „(FHS์— ํ‘œ์‹œ๋จ)์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. 2.3๋…„์—๋Š” -2004)."

์ด๊ฒƒ์ด ๋ฐ”๋กœ ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ์ด๋ฏ€๋กœ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ฌ์šฉ์ž(ํด๋ผ์šฐ๋“œ ์‚ฌ์šฉ์ž)๊ฐ€ ์†Œ์œ ํ•œ /srv์— ๋„ฃ์Šต๋‹ˆ๋‹ค.

sudo mkdir /srv/djangoapp
sudo chown cloud-user:cloud-user /srv/djangoapp
cd /srv/djangoapp
virtualenv django
source django/bin/activate
pip3 install django gunicorn psycopg2
./django-admin startproject djangoapp /srv/djangoapp

PostgreSQL ๋ฐ Django ์„ค์ •์€ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑ, ์‚ฌ์šฉ์ž ์ƒ์„ฑ, ๊ถŒํ•œ ๊ตฌ์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. PostgreSQL์„ ์ฒ˜์Œ ์„ค์น˜ํ•  ๋•Œ ๋ช…์‹ฌํ•ด์•ผ ํ•  ํ•œ ๊ฐ€์ง€๋Š” postgresql-server ํŒจํ‚ค์ง€์™€ ํ•จ๊ป˜ ์„ค์น˜๋˜๋Š” postgresql-setup ์Šคํฌ๋ฆฝํŠธ์ž…๋‹ˆ๋‹ค. ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ํด๋Ÿฌ์Šคํ„ฐ ์ดˆ๊ธฐํ™” ๋˜๋Š” ์—…๊ทธ๋ ˆ์ด๋“œ ํ”„๋กœ์„ธ์Šค์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํด๋Ÿฌ์Šคํ„ฐ ๊ด€๋ฆฌ์™€ ๊ด€๋ จ๋œ ๊ธฐ๋ณธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. RHEL ์‹œ์Šคํ…œ์—์„œ ์ƒˆ PostgreSQL ์ธ์Šคํ„ด์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

sudo /usr/bin/postgresql-setup -initdb

๊ทธ๋Ÿฐ ๋‹ค์Œ systemd๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ PostgreSQL์„ ์‹œ์ž‘ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Django์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ €์žฅ์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ ๊ตฌ์„ฑ ํŒŒ์ผ(์ผ๋ฐ˜์ ์œผ๋กœ pg_hba.conf)์„ ๋ณ€๊ฒฝํ•œ ํ›„ PostgreSQL์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด pg_hba.conf ํŒŒ์ผ์—์„œ IPv4 ๋ฐ IPv6 ์„ค์ •์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

systemctl enable -now postgresql

sudo -u postgres psql
postgres=# create database djangoapp;
postgres=# create user djangouser with password 'qwer4321';
postgres=# alter role djangouser set client_encoding to 'utf8';
postgres=# alter role djangouser set default_transaction_isolation to 'read committed';
postgres=# alter role djangouser set timezone to 'utc';
postgres=# grant all on DATABASE djangoapp to djangouser;
postgres=# q

/var/lib/pgsql/data/pg_hba.conf ํŒŒ์ผ์—์„œ:

# IPv4 local connections:
host    all        all 0.0.0.0/0                md5
# IPv6 local connections:
host    all        all ::1/128                 md5

/srv/djangoapp/settings.py ํŒŒ์ผ์—์„œ:

# Database
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.postgresql_psycopg2',
       'NAME': '{{ db_name }}',
       'USER': '{{ db_user }}',
       'PASSWORD': '{{ db_password }}',
       'HOST': '{{ db_host }}',
   }
}

ํ”„๋กœ์ ํŠธ์—์„œ settings.py ํŒŒ์ผ์„ ๊ตฌ์„ฑํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์„ฑ์„ ์„ค์ •ํ•œ ํ›„ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•œ ํ›„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๊ด€๋ฆฌ์ž๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

./manage.py runserver 0.0.0.0:8000
./manage.py createsuperuser

WSGI? ์™€?

๊ฐœ๋ฐœ ์„œ๋ฒ„๋Š” ํ…Œ์ŠคํŠธ์— ์œ ์šฉํ•˜์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด WSGI(์›น ์„œ๋ฒ„ ๊ฒŒ์ดํŠธ์›จ์ด ์ธํ„ฐํŽ˜์ด์Šค)์— ์ ํ•ฉํ•œ ์„œ๋ฒ„์™€ ํ”„๋ก์‹œ๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด uWSGI๊ฐ€ ํฌํ•จ๋œ Apache HTTPD ๋˜๋Š” Gunicorn์ด ํฌํ•จ๋œ Nginx์™€ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ์กฐํ•ฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์›น ์„œ๋ฒ„ ๊ฒŒ์ดํŠธ์›จ์ด ์ธํ„ฐํŽ˜์ด์Šค์˜ ์—ญํ• ์€ ์›น ์„œ๋ฒ„์˜ ์š”์ฒญ์„ Python ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. WSGI๋Š” CGI ์—”์ง„์ด ์กด์žฌํ–ˆ๋˜ ๋”์ฐํ•œ ๊ณผ๊ฑฐ์˜ ์œ ๋ฌผ์ด๋ฉฐ, ์˜ค๋Š˜๋‚  WSGI๋Š” ์‚ฌ์šฉ๋˜๋Š” ์›น ์„œ๋ฒ„๋‚˜ Python ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ด€๊ณ„์—†์ด ์‚ฌ์‹ค์ƒ์˜ ํ‘œ์ค€์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋„๋ฆฌ ์‚ฌ์šฉ๋จ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ด๋Ÿฌํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ž‘์—…ํ•  ๋•Œ ์—ฌ์ „ํžˆ ๋ฏธ๋ฌ˜ํ•œ ์ฐจ์ด๊ฐ€ ๋งŽ๊ณ  ์„ ํƒ ์‚ฌํ•ญ๋„ ๋งŽ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์†Œ์ผ“์„ ํ†ตํ•ด Gunicorn๊ณผ Nginx ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ์„ค์ •ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋‘ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋ชจ๋‘ ๋™์ผํ•œ ์„œ๋ฒ„์— ์„ค์น˜๋˜๋ฏ€๋กœ ๋„คํŠธ์›Œํฌ ์†Œ์ผ“ ๋Œ€์‹  UNIX ์†Œ์ผ“์„ ์‚ฌ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ๊ฒฝ์šฐ๋“  ํ†ต์‹ ์—๋Š” ์†Œ์ผ“์ด ํ•„์š”ํ•˜๋ฏ€๋กœ ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€ systemd๋ฅผ ํ†ตํ•ด Gunicorn์— ๋Œ€ํ•œ ์†Œ์ผ“ ํ™œ์„ฑํ™”๋ฅผ ๊ตฌ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์†Œ์ผ“ ํ™œ์„ฑํ™” ์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ €, UNIX ์†Œ์ผ“์ด ์ƒ์„ฑ๋  ์ง€์ ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ListenStream ์ง€์‹œ์–ด๊ฐ€ ํฌํ•จ๋œ ์œ ๋‹› ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜๊ณ , ๊ทธ๋Ÿฐ ๋‹ค์Œ Requires ์ง€์‹œ์–ด๊ฐ€ ์†Œ์ผ“ ์œ ๋‹› ํŒŒ์ผ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์œ ๋‹› ํŒŒ์ผ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์„œ๋น„์Šค ๋‹จ์œ„ ํŒŒ์ผ์— ๋‚จ์€ ๊ฒƒ์€ ๊ฐ€์ƒ ํ™˜๊ฒฝ์—์„œ Gunicorn์„ ํ˜ธ์ถœํ•˜๊ณ  UNIX ์†Œ์ผ“ ๋ฐ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ WSGI ๋ฐ”์ธ๋”ฉ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๊ธฐ์ดˆ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ์œ„ ํŒŒ์ผ์˜ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ์ž…๋‹ˆ๋‹ค. ๋จผ์ € ์†Œ์ผ“์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

์ด์ œ Gunicorn ๋ฐ๋ชฌ์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

[Unit]
Description=Gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=cloud-user
Group=cloud-user
WorkingDirectory=/srv/djangoapp

ExecStart=/srv/djangoapp/django/bin/gunicorn 
         โ€”access-logfile - 
         โ€”workers 3 
         โ€”bind unix:gunicorn.sock djangoapp.wsgi

[Install]
WantedBy=multi-user.target

Nginx์˜ ๊ฒฝ์šฐ ํ”„๋ก์‹œ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์ •์  ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ(์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ)๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. RHEL์—์„œ Nginx ๊ตฌ์„ฑ ํŒŒ์ผ์€ /etc/nginx/conf.d์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋ฅผ /etc/nginx/conf.d/default.conf ํŒŒ์ผ์— ๋ณต์‚ฌํ•˜๊ณ  ์„œ๋น„์Šค๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธ์ŠคํŠธ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋„๋ก server_name์„ ์„ค์ •ํ•˜์‹ญ์‹œ์˜ค.

server {
   listen 80;
   server_name 8beta1.example.com;

   location = /favicon.ico { access_log off; log_not_found off; }
   location /static/ {
       root /srv/djangoapp;
   }

   location / {
       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_pass http://unix:/run/gunicorn.sock;
   }
}

systemd๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Gunicorn ์†Œ์ผ“๊ณผ Nginx๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•  ์ค€๋น„๊ฐ€ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ž˜๋ชป๋œ ๊ฒŒ์ดํŠธ์›จ์ด ์˜ค๋ฅ˜์ธ๊ฐ€์š”?

๋ธŒ๋ผ์šฐ์ €์— ์ฃผ์†Œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด 502 ์ž˜๋ชป๋œ ๊ฒŒ์ดํŠธ์›จ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ์ด๋Š” UNIX ์†Œ์ผ“ ๊ถŒํ•œ์ด ์ž˜๋ชป ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ฑฐ๋‚˜ SELinux์˜ ์•ก์„ธ์Šค ์ œ์–ด์™€ ๊ด€๋ จ๋œ ๋ณด๋‹ค ๋ณต์žกํ•œ ๋ฌธ์ œ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

nginx ์˜ค๋ฅ˜ ๋กœ๊ทธ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ค„์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2018/12/18 15:38:03 [crit] 12734#0: *3 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.122.1, server: 8beta1.example.com, request: "GET / HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/", host: "8beta1.example.com"

Gunicorn์„ ์ง์ ‘ ํ…Œ์ŠคํŠธํ•˜๋ฉด ๋นˆ ๋‹ต์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

curl โ€”unix-socket /run/gunicorn.sock 8beta1.example.com

์™œ ์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ์•Œ์•„ ๋ด…์‹œ๋‹ค. ๋กœ๊ทธ๋ฅผ ์—ด๋ฉด ๋ฌธ์ œ๊ฐ€ SELinux์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์ฑ…์ด ์ƒ์„ฑ๋˜์ง€ ์•Š์€ ๋ฐ๋ชฌ์„ ์‹คํ–‰ ์ค‘์ด๋ฏ€๋กœ init_t๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด ์ด๋ก ์„ ์‹ค์ œ๋กœ ํ…Œ์ŠคํŠธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

sudo setenforce 0

์ด ๋ชจ๋“  ๊ฒƒ์ด ๋น„ํŒ๊ณผ ํ”ผ๋ˆˆ๋ฌผ์„ ๋‚ณ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ๋””๋ฒ„๊น…ํ•˜๋Š” ๊ฒƒ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฌธ์ œ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๊ฒ€์‚ฌ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ ๋ชจ๋“  ๊ฒƒ์„ ์›๋ž˜ ์œ„์น˜๋กœ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜๊ฑฐ๋‚˜ ์ปฌ ๋ช…๋ น์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด Django ํ…Œ์ŠคํŠธ ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•˜๊ณ  ๋” ์ด์ƒ ๊ถŒํ•œ ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•œ ํ›„ SELinux๋ฅผ ๋‹ค์‹œ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

sudo setenforce 1

ํ˜„์žฌ ์‹ค์ œ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— audit2allow๋‚˜ sepolgen์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฝ๊ณ  ๊ธฐ๋ฐ˜ ์ •์ฑ…์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Gunicorn์ด ์•ก์„ธ์Šคํ•˜๋ ค๋Š” ํ•ญ๋ชฉ๊ณผ ์•ก์„ธ์Šค๋ฅผ ๊ฑฐ๋ถ€ํ•ด์•ผ ํ•˜๋Š” ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์™„์ „ํ•œ ๋งต์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‹œ์Šคํ…œ์„ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด SELinux๋ฅผ ๊ณ„์† ์‹คํ–‰ํ•˜๋Š” ๋™์‹œ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๊ณ  ๊ฐ์‚ฌ ๋กœ๊ทธ์— ๋ฉ”์‹œ์ง€๋ฅผ ๋‚จ๊ฒจ ์‹ค์ œ ์ •์ฑ…์ด ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ—ˆ์šฉ ๋„๋ฉ”์ธ ์ง€์ •

SELinux์—์„œ ํ—ˆ์šฉ๋˜๋Š” ๋„๋ฉ”์ธ์— ๋Œ€ํ•ด ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋“ค์–ด๋ณธ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์‹ฌ์ง€์–ด ๊ทธ๊ฒƒ์„ ๊นจ๋‹ซ์ง€๋„ ๋ชปํ•œ ์ฑ„ ๊ทธ๋“ค๊ณผ ํ•จ๊ป˜ ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •์ฑ…์ด ์ƒ์„ฑ๋˜๋ฉด ์ƒ์„ฑ๋œ ์ •์ฑ…์€ ํ™•์ธ๋œ ๋„๋ฉ”์ธ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ํ—ˆ์šฉ ์ •์ฑ…์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Gunicorn์— ๋Œ€ํ•ด ํŠน์ • ํ—ˆ์šฉ ๋„๋ฉ”์ธ์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ์ผ์ข…์˜ ์ •์ฑ…์ด ํ•„์š”ํ•˜๋ฉฐ ์ ์ ˆํ•œ ํŒŒ์ผ์„ ํ‘œ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ƒˆ๋กœ์šด ์ •์ฑ…์„ ์ˆ˜๋ฆฝํ•˜๋ ค๋ฉด ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

sudo yum install selinux-policy-devel

ํ—ˆ์šฉ๋œ ๋„๋ฉ”์ธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ํŠนํžˆ ์ด๋ฏธ ์ƒ์„ฑ๋œ ์ •์ฑ… ์—†์ด ์ œ๊ณต๋˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฒฝ์šฐ ๋ฌธ์ œ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ Gunicorn์— ํ—ˆ์šฉ๋˜๋Š” ๋„๋ฉ”์ธ ์ •์ฑ…์€ ์ตœ๋Œ€ํ•œ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์œ ํ˜•(gunicorn_t)์„ ์„ ์–ธํ•˜๊ณ  ์—ฌ๋Ÿฌ ์‹คํ–‰ ํŒŒ์ผ์„ ํ‘œ์‹œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์œ ํ˜•(gunicorn_exec_t)์„ ์„ ์–ธํ•œ ๋‹ค์Œ ์‹œ์Šคํ…œ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ‘œ์‹œํ•˜๋„๋ก ์ „ํ™˜์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์‹คํ–‰์ค‘์ธ ํ”„๋กœ์„ธ์Šค. ๋งˆ์ง€๋ง‰ ์ค„์€ ์ •์ฑ…์ด ๋กœ๋“œ๋  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

gunicorn.te:

policy_module(gunicorn, 1.0)

type gunicorn_t;
type gunicorn_exec_t;
init_daemon_domain(gunicorn_t, gunicorn_exec_t)
permissive gunicorn_t;

์ด ์ •์ฑ… ํŒŒ์ผ์„ ์ปดํŒŒ์ผํ•˜์—ฌ ์‹œ์Šคํ…œ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

make -f /usr/share/selinux/devel/Makefile
sudo semodule -i gunicorn.pp

sudo semanage permissive -a gunicorn_t
sudo semodule -l | grep permissive

SELinux๊ฐ€ ์•Œ ์ˆ˜ ์—†๋Š” ๋ฐ๋ชฌ์ด ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ ์ด์™ธ์˜ ๋‹ค๋ฅธ ๊ฒƒ์„ ์ฐจ๋‹จํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

sudo ausearch -m AVC

type=AVC msg=audit(1545315977.237:1273): avc:  denied { write } for pid=19400 comm="nginx" name="gunicorn.sock" dev="tmpfs" ino=52977 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0

SELinux๋Š” Nginx๊ฐ€ Gunicorn์—์„œ ์‚ฌ์šฉํ•˜๋Š” UNIX ์†Œ์ผ“์— ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ ์ •์ฑ…์ด ๋ณ€๊ฒฝ๋˜๊ธฐ ์‹œ์ž‘ํ•˜์ง€๋งŒ ์•ž์—๋Š” ๋‹ค๋ฅธ ๊ณผ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ œํ•œ ๋„๋ฉ”์ธ์—์„œ ๊ถŒํ•œ ๋„๋ฉ”์ธ์œผ๋กœ ๋„๋ฉ”์ธ ์„ค์ •์„ ๋ณ€๊ฒฝํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ httpd_t๋ฅผ ๊ถŒํ•œ ๋„๋ฉ”์ธ์œผ๋กœ ์ด๋™ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Nginx์— ํ•„์š”ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋˜๊ณ  ์ถ”๊ฐ€ ๋””๋ฒ„๊น… ์ž‘์—…์„ ๊ณ„์†ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

sudo semanage permissive -a httpd_t

๋”ฐ๋ผ์„œ SELinux๋ฅผ ๋ณดํ˜ธํ•œ ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๊ณ (SELinux ํ”„๋กœ์ ํŠธ๋ฅผ ์ œํ•œ ๋ชจ๋“œ๋กœ ๋†”๋‘์–ด์„œ๋Š” ์•ˆ ๋จ) ๊ถŒํ•œ ๋„๋ฉ”์ธ์ด ๋กœ๋“œ๋˜๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ์ •ํ™•ํžˆ ๋ฌด์—‡์ด gunicorn_exec_t๋กœ โ€‹โ€‹ํ‘œ์‹œ๋˜์–ด์•ผ ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ. ์•ก์„ธ์Šค ์ œํ•œ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ ค๋ฉด ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•ด ๋ณด์„ธ์š”.

sudo ausearch -m AVC -c gunicorn

/srv/djangoapp์˜ ํŒŒ์ผ์— ๋Œ€ํ•ด ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” 'comm="gunicorn"'์„ ํฌํ•จํ•˜๋Š” ๋งŽ์€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด๋Š” ๋ถ„๋ช…ํžˆ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ๋ช…๋ น ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ถ”๊ฐ€์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

type=AVC msg=audit(1545320700.070:1542): avc:  denied { execute } for pid=20704 comm="(gunicorn)" name="python3.6" dev="vda3" ino=8515706 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0

gunicorn ์„œ๋น„์Šค์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ps ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. gunicorn์ด ์ž‘์—…์ž ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด virtualenv ํ™˜๊ฒฝ์—์„œ Python ์ธํ„ฐํ”„๋ฆฌํ„ฐ์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ด ๋‘ ์‹คํ–‰ ํŒŒ์ผ์„ ํ‘œ์‹œํ•˜๊ณ  Django ํ…Œ์ŠคํŠธ ํŽ˜์ด์ง€๋ฅผ ์—ด ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

chcon -t gunicorn_exec_t /srv/djangoapp/django/bin/gunicorn /srv/djangoapp/django/bin/python3.6

์ƒˆ ํƒœ๊ทธ๋ฅผ ์„ ํƒํ•˜๋ ค๋ฉด ๋จผ์ € gunicorn ์„œ๋น„์Šค๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰์‹œ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ ์„œ๋น„์Šค๋ฅผ ์ค‘์ง€ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์ดํŠธ๋ฅผ ์—ด ๋•Œ ์†Œ์ผ“์ด ์‹œ์ž‘๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ps๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ๋ ˆ์ด๋ธ”์„ ๋ฐ›์•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

ps -efZ | grep gunicorn

๋‚˜์ค‘์— ์ผ๋ฐ˜ SELinux ์ •์ฑ…์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”!

์ง€๊ธˆ AVC ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ฉด ๋งˆ์ง€๋ง‰ ๋ฉ”์‹œ์ง€์—๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด permissive=1์ด ํฌํ•จ๋˜์–ด ์žˆ๊ณ  ๋‚˜๋จธ์ง€ ์‹œ์Šคํ…œ์— ๋Œ€ํ•ด์„œ๋Š” permissive=0์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์–ด๋–ค ์ข…๋ฅ˜์˜ ์•ก์„ธ์Šค๊ฐ€ ํ•„์š”ํ•œ์ง€ ์ดํ•ดํ•˜๋ฉด ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋•Œ๊นŒ์ง€๋Š” ์‹œ์Šคํ…œ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๊ณ  Django ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ๋ช…ํ™•ํ•˜๊ณ  ์œ ์šฉํ•œ ๊ฐ์‚ฌ๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

sudo ausearch -m AVC

๊ทธ๊ฒƒ์€ ๋‚˜์™”๋‹ค!

Nginx์™€ Gunicorn WSGI๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฐ–์ถ˜ ์ž‘๋™ํ•˜๋Š” Django ํ”„๋กœ์ ํŠธ๊ฐ€ ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. RHEL 3 ๋ฒ ํƒ€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ Python 10 ๋ฐ PostgreSQL 8์„ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒ์„ฑ(๋˜๋Š” ๊ฐ„๋‹จํžˆ ๋ฐฐํฌ)ํ•˜๊ฑฐ๋‚˜ RHEL 8 Beta์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹ค๋ฅธ ๋„๊ตฌ๋ฅผ ํƒ์ƒ‰ํ•˜์—ฌ ๊ตฌ์„ฑ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ž๋™ํ™”ํ•˜๊ณ  ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ฑฐ๋‚˜ ์ด ๊ตฌ์„ฑ์„ ์ปจํ…Œ์ด๋„ˆํ™”ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€