Profile picture

[Ubuntu] 리눅스 환경에서 웹 서비스 배포하기

JaehyoJJAng2023년 03월 19일

▶︎ 개요

‣ 목표

리눅스 환경에서의 웹 서비스 구축을 통해 인프라 구축에 대한 경험과 리눅스 이해도 향상


‣ 주제

리눅스의 기초 핵심이라 생각되는 서비스 관리, 소프트웨어 관리, 네트워크 설정, 방화벽, DNS, 가상 호스트와 Apache 등을 모두 사용하여 인프라를 구축해보는 실습을 진행해보고자 함.

하나의 서버에서 Wordpress, DB를 같이 운영하는 것이 아닌 서비스별로 서버를 나눠서 구축하여 실제 서비스와 비슷한 환경을 구성해보고자 노력하였음.


‣ 구축 환경

  • Ubuntu 22.04 LTS
  • Wordpress
  • Apache
  • PHP
  • MariaDB
  • bind9(DNS)

▶︎ 서버 구성도

image


▶︎ 1. 웹 서버 구축

1. 웹 서버 설치

httpd를 설치하고 방화벽 정책을 추가.

# apache 설치
sudo apt-get install -y apache2

# 방화벽 설정
firewall-cmd --add-service=http --permanent

2. PHP 설치

sudo apt-get install -y php php-mysql

3. 웹 데몬 재시작

PHP를 설치했다면 웹 데몬 재시작

sudo systemctl restart apache2.service

4. 워드프레스 다운로드

sudo apt-get install -y wget
wget -O wordpress.tar.gz https://wordpress.org/latest.tar.gz

# 압축해제
sudo tar -zxvf wordpress.tar.gz -C /var/www/html

# 그림파일 업로드 폴더 생성
sudo mkdir /var/www/html/wordpress/uploads

▶︎ 2. DB 서버 구축

1. MariaDB 설치

워드프레스 설치를 위해서 MariaDB 10.2 버전 이상이 필요함.(mariadb 사이트)

본인의 경우 ubuntu 22.04이기에 해당 OS 설치법대로 작성하겠음.

# mariadb keyring 등록
sudo apt-get install apt-transport-https curl
sudo mkdir -p /etc/apt/keyrings
sudo curl -o /etc/apt/keyrings/mariadb-keyring.pgp 'https://mariadb.org/mariadb_release_signing_key.pgp'

# Mariadb 설치
sudo apt-get update
sudo apt-get install mariadb-server

2. mariadb 초기 설정

/mysql_secure_installation을 통해 보안 설정과 Mariadb의 초기 설정을 만져주자.

/usr/bin/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   #root 암호 설정
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y  
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] no  #원격 접속을 막을 것인가? DB 서버가 따로이기 때문에 no를 해준다
 ... skipping.

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] yes  #테스트 데이터베이스 삭제
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] yes  #저장
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

3. 포트 설정

웹 서버와 DB 서버를 구분했기 때문에 방화벽에서 포트를 허용해줘야 한다.

firewall-cmd --permanent --zone=public --add-port=3306/tcp
firewall-cmd --reload

4. wordpress에서 사용할 DB 생성

만들어진 mariadb에 wordpress에서 사용할 DB 생성 후, 사용자를 만들고 사용자에게 게시판 사용 권한을 부여한다.

sudo mysql -u root -p

MariaDB [(none)]> CREATE DATABASE wordpress;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> CREATE USER adminuser@'%' IDENTIFIED BY 'admin';
Query OK, 0 rows affected (0.002 sec)

MariaDB [(none)]> GRANT ALL PRIVILEGES ON wordpress.* TO adminuser@'%' IDENTIFIED BY 'admin';
Query OK, 0 rows affected (0.002 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> exit

▶︎ 3. 워드프레스 설정

위에서 설치한 웹 서버의 워드프레스에 DB 서버를 연결할 수 있도록 설정해주자.


1. wordpress 경로로 이동

cd /var/www/html/wordpress

2. 샘플 파일 복사하여 새로운 파일로 생성

cp -R wp-config/sample.php wp-config.php

3. wp-config.php를 아래와 같이 수정

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' ); 데이터 베이스이름 설정
/** Database username */
define( 'DB_USER', 'adminuser' ); 데이터베이스 사용자 이름 설정
/** Database password */
define( 'DB_PASSWORD', 'admin' ); 위 사용자의 암호 설정
/** Database hostname */
define( 'DB_HOST', '192.168.219.158' ); DB 서버를 별도로 운영하기위해 DB 서버의 IP주소 설정

4. 워드프레스 실행

설정을 완료하고 내부망에 속해있는 클라이언트(win11)의 브라우저에서 http://ip주소/wordpress로 접근하면 아래와 같이 환경 설정 마법사가 시작될 것이다.
image
언어, 사이트 이름, 관리자, email, 사용자 계정을 추가하고 로그인하면 게시판 사용이 가능하다.


이후 DB 서버에서 접속하여 wordpress의 DB를 살펴보면 방금 내가 만든 유져 정보가 등록된 것도 볼 수 있다.

use wordpress;

show tables;
+-----------------------+
| Tables_in_wordpress   |
+-----------------------+
| wp_commentmeta        |
| wp_comments           |
| wp_links              |
| wp_options            |
| wp_postmeta           |
| wp_posts              |
| wp_term_relationships |
| wp_term_taxonomy      |
| wp_termmeta           |
| wp_terms              |
| wp_usermeta           |
| wp_users              |
+-----------------------+
12 rows in set (0.000 sec)

DESCRIBE wp_users;
+---------------------+---------------------+------+-----+---------------------+----------------+
| Field               | Type                | Null | Key | Default             | Extra          |
+---------------------+---------------------+------+-----+---------------------+----------------+
| ID                  | bigint(20) unsigned | NO   | PRI | NULL                | auto_increment |
| user_login          | varchar(60)         | NO   | MUL |                     |                |
| user_pass           | varchar(255)        | NO   |     |                     |                |
| user_nicename       | varchar(50)         | NO   | MUL |                     |                |
| user_email          | varchar(100)        | NO   | MUL |                     |                |
| user_url            | varchar(100)        | NO   |     |                     |                |
| user_registered     | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| user_activation_key | varchar(255)        | NO   |     |                     |                |
| user_status         | int(11)             | NO   |     | 0                   |                |
| display_name        | varchar(250)        | NO   |     |                     |                |
+---------------------+---------------------+------+-----+---------------------+----------------+
10 rows in set (0.001 sec)

SELECT * FROM wp_users;
+----+------------+------------------------------------+---------------+--------------------+----------------------------------+---------------------+---------------------+-------------+--------------+
| ID | user_login | user_pass                          | user_nicename | user_email         | user_url                         | user_registered     | user_activation_key | user_status | display_name |
+----+------------+------------------------------------+---------------+--------------------+----------------------------------+---------------------+---------------------+-------------+--------------+
|  1 | admin      | $P$BIAusBYSm7YytQGc84rHXiLV5n.r/71 | admin         | yshrim12@naver.com | http://192.168.219.158/wordpress | 2024-06-05 06:01:47 |                     |           0 | admin        |
+----+------------+------------------------------------+---------------+--------------------+----------------------------------+---------------------+---------------------+-------------+--------------+
1 row in set (0.000 sec)

▶︎ 4. DNS 서버 구축

1. DNS 설치

다음 포스팅 참고, 우분투에서 DNS 서버 구축해보기


2. /etc/bind/named.conf.default-zones 설정

# 맨 마지막에 아래 내용 추가
zone "dnsserver.miniproject.com" {
  type master;
  file "/etc/bind/dnsserver.miniproject.com.zone";
};

3. /etc/bind/dnsserver.miniproject.com.zone 파일 설정

$TTL  604800
@ IN SOA dnsserver.miniproject.com. root.dnsserver.miniproject.com. (
            2   ; Serial
       604800   ; Refresh
        86400   ; Retry
      2419200   ; Expire
       604800 ) ; Negative Cache TTL
;
@ IN  NS dns.dnsserver.miniproject.com.
@ IN  A  192.168.219.144
dns   A  192.168.219.144
db    A  192.168.219.145
web   A  192.168.219.158

설정내용 설명

  • $TTL 3H
    • 모든 레코드의 기본 TTL 값은 3시간으로 지정
  • SOA(Start Of Authority) 레코드
    • @는 miniproject.com 도메인을 나타냅니다.
    • dnsserver.miniproject.com.은 권한이 있는 네임 서버입니다.
    • root.dnsserver.miniproject.com.은 관리자 이메일 주소입니다.
    • 시리얼 번호, 갱신 주기, 재시도 주기, 만료 시간, 최소 TTL 값이 설정되어 있습니다.
  • NS(Name Server) 레코드
    • NS 레코드는 네임 서버를 지정합니다. 여기서는 dns.dnsserver.miniproject.com.이 네임 서버로 설정되어 있습니다.
  • A(Address) 레코드
    • @ (즉, miniproject.com)의 IP 주소는 192.168.219.160입니다.
    • dns.miniproject.com의 IP 주소는 192.168.219.160입니다.
    • db.miniproject.com의 IP 주소는 192.168.219.158입니다.
    • client.miniproject.com의 IP 주소는 192.168.56.101입니다.
    • web.miniproject.com의 IP 주소는 192.168.219.159입니다.

4. bind9 서비스 재시작 및 방화벽 설정

# 서비스 재시작
sudo systemctl restart bind9

# 방화벽 설정
sudo firewall-cmd --add-service=dns --permannet
sudo firewall-cmd --reload

5. DNS 테스트

# dns 주소 점검
host dns.dnsserver.miniproject.com
dns.dnsserver.miniproject.com has address 192.168.219.144

# web 주소 점검
host web.dnsserver.miniproject.com
web.dnsserver.miniproject.com has address 192.168.219.158

# db 주소 점검
host db.dnsserver.miniproject.com
db.dnsserver.miniproject.com has address 192.168.219.145

‣ forwarders 지정해주기

해당 DNS 서버의 경우 내부에서만 사용되는 서버이기 때문에,

다른 내부망 서버에서 위 DNS 서버 주소를 인터페이스 설정에 등록할 경우 외부와 통신이 불가능해지는 문제가 발생한다.

이를 방지하기 위해 해당 DNS 서버의 /etc/bind/named.conf.option 파일에 아래와 같이 forwarders를 지정해주자.

options {
  # .... 생략 ....

	forwarders {
	  8.8.8.8;
	};

	allow-query-cache {
	  192.168.219.0/24;
	};

  # .... 생략 ....
};

‣ 웹 서버 및 DB 서버의 DNS 주소 설정

새로 구축한 DNS 서버를 웹 서버와 DB 서버에 등록해주도록 하자.

1. Netplan 구성 파일 수정

sudo vim /etc/netplan/00-installer-config.yaml

2. DNS 서버 추가
nameservers 섹션에 새로운 DNS 서버 IP 주소를 추가하자.

# This is the network config written by 'subiquity'
network:
  ethernets:
    ens18:
      addresses:
      - 192.168.219.158/24
      nameservers:
        addresses:
        - 8.8.8.8
        - 192.168.219.144
        search: []
      routes:
      - to: default
        via: 192.168.219.1
  version: 2

3. Netplan 적용

sudo netplan apply

‣ 브라우저로 접속

이제 IP 주소가 아닌 도메인으로 접속이 가능하다.
image


▶︎ 5. SSL 적용

  • 웹 서버에서 진행함.

1. openssl 설치

sudo apt-get install -y openssl

2. mod_ssl 모듈 활성화

sudo a2enmod ssl

3. 키 생성

cd /etc/ssl/certs/
sudo openssl genrsa -out minipj.key 2048
  • 버전 = genrsa
  • 키 생성 = out
  • 키 이름 = minipj.key
  • 키 비트수 = 2048

4. 인증서(CSR) 생성

sudo openssl req -new -key minipj.key -out minipj.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:kr  #국가 코드
State or Province Name (full name) []:seoul  #시 이름
Locality Name (eg, city) [Default City]:hwaseong  #시/군/구
Organization Name (eg, company) [Default Company Ltd]:minipj  #회사명
Organizational Unit Name (eg, section) []:cloud  #부서명
Common Name (eg, your name or your server's hostname) []:web.dnsserver.miniproject.com  #서비스 도메인명
Email Address []:test@test.com #이메일 주소

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

5. 키와 인증서 합치기

sudo openssl x509 -req -signkey minipj.key -in minipj.csr -out minipj.crt

Signature ok
subject=/C=kr/ST=seoul/L=hwaseong/O=minipj/OU=cloud/CN=web.dnsserver.miniproject.com/emailAddress=test@test.com
Getting Private key

6. 키와 crt의 권한을 제한하고 키를 지정된 경롤로 이동시키기

sudo chmod 600 minipj.key minipj.crt
sudo mv minipj.key /etc/ssl/private/

7. SSL 파일 설정

/etc/apache2/sites-available/default-ssl.conf 파일을 설정해주자.

...
    100 SSLCertificateFile /etc/ssl/certs/minipj.crt
    101 SSLCertificateKeyFile /etc/ssl/private/minipj.key
...

8. apache2 재시작

sudo systemctl restart apache2.service

Loading script...