앞의 글에서, Nginx Proxy Manager(이하 npm)의 설치 및 초기 설정에 대해서 다루었다. 여기서는 뒷단 서버로 연결하는 설정을 다룬다.

 

Proxy Host 설정

상단의 Dashboard 탭 > Proxy Hosts를 누르거나, 상단의 Hosts 탭 > Proxy Hosts를 누르면, 도메인별 proxy 설정을 할 수 있다. Add Proxy 버튼을 눌러 다음과 같이 채워준다.

static.example.com를 minio 9000/tcp에 연결하는 예제

  • Domain Names: 사용하고자 하는 domain 이름을 적는다. 도메인 이름을 입력하고 엔터(혹은 탭키)를 입력하여 그림과 같이 전체 이름이 회색 블럭으로 입력되도록 한다.
  • Scheme: SSL termination은 npm이 담당하고, npm과 upstream 간에는 HTTP 통신으로 단순화하려고 하니, http로 유지한다.
  • Forward Hostname / IP: 연결시키고자 하는 호스트이름 혹은 IP주소를 입력한다. 다른 docker container 호스트명(hostname 설정을 별도로 하지 않은 경우, container_name)을 직접 입력해도 된다.
    • 공유기(라우터)의 DHCP가 고정으로 할당하는 IP가 있거나 docker network 내의 IP를 입력해도 좋으나, 공유기 설정이 바뀌거나 docker network가 바뀌는 경우 IP도 같이 바뀔 수 있다. 가급적이면 호스트명을 입력하고, 호스트명으로 해당 container 혹은 서버에 접속할 수 있도록 유지하는 것이 좋다.
  • Forward Port: 연결시키고자 하는 호스트에 접속할 수 있는 포트를 입력한다. 같은 docker network에 있는 다른 container에 접속시키는 경우, 굳이 expose로 container의 포트를 docker host에 노출시키지 않아도 된다. 다만, Forward Hostname / IP 부분에 docker host의 IP를 적었을 경우: docker container의 포트를 expose로 host에 노출시키고, 해당 포트를 적어주어야 한다.
  • Block Common Exploits: 활성화하게 되면, SQL injection, file injection, spam block, 몇몇 crawler를 차단, 그리고 몇가지 공격으로부터 차단하는 기능을 제공한다.
  • 위의 세가지 예제(nginx/apache, minio, notebook)에 맞게 적어보면
    • nginx/apache
      • Domain Names: example.com
      • Scheme: http
      • Forward Hostname / IP: nginx (혹은 apache)
      • Forward Port: 80
    • minio
      • Domain Names: static.example.com
      • Scheme: http
      • Forward Hostname / IP: minio
      • Forward Port: 9000
    • notebook
      • Domain Names: nb.example.com
      • Scheme: http
      • Forward Hostname / IP: notebook
      • Forward Port: 8080

다른 패키지 없이, 공인 IP를 알아낼 필요가 생겼다. 요구사항은 다음과 같다.

  • 다른 패키지를 사용하지 말고 python3의 기본 built-in 패키지만 사용할 것 (python3.11)
  • crontab에 등록하여 사용할 것
  • 여러 네트워크 인터페이스(랜카드)가 사용 가능한 상황에서 특정 네트워크 인터페이스를 사용하도록 할 것
    • 두 개의 랜카드가 eth0, eth1로 인터넷에 접속 가능한 시스템에서, 특정 네트워크 인터페이스를 지정하여 public IP를 받아오는 것

 

 

하나의 서버에서 여러개의 도메인에 대한 요청을 처리하기 위해서는 nginx나 apache등의 도메인별 설정을 이용해서 구현이 가능하다. 최근 보안 이슈로 HTTP만으로 웹서비스를 제공하는 경우는 거의 없기에 HTTPS를 위한 인증서를 같이 제공해야하는데, 이는 Let's encrypt 등의 인증기관을 이용하면 무료로 쉽고 빠르게 설정할 수 있다.

다만, 도메인별 설정과 인증서 설정을 웹UI를 통해 쉽게 설정할 수 있는 패키지가 있으니, Nginx Proxy Manager(이하 npm)가 그것이다.

 

Npm은 Nginx의 Reverse Proxy 기능을 이용해서 뒷단(upstream)에서 제공할 다양한 웹 기반의 서비스들의 첫 출입구를 담당해준다. 특징을 몇가지 적어보면:

  • 여러 도메인들에 대한 설정을 UI를 기반으로 쉽게 설정할 수 있다.
  • SSL termination을 제공하여 뒷단 서버와의 소통을 HTTP만 하게 함으로 뒷단 서버의 설정을 간단하게 할 수 있다.
  • HTTP/2, HSTS를 지원하지 않는 웹서버라도, proxy 단에서 지원한다. 또한, websocket를 지원하는 뒷단 서버에게 websocket을 연결한다.
  • nginx의 server, location 등에 추가해야하는 설정들(proxy_pass, proxy_set_header 등)을 추가로 설정할 수 있다.
  • 설정을 저장할 때마다 nginx reload를 실행하고 online/offline 등 상태를 보여주어 설정을 즉시 적용하고 상태를 확인할 수 있다.
    • 다만, 이것은 단점이 되기도 하는데, 잘못된 설정이 저장되었을 때 그 설정이 바로 적용되어 서비스에 문제가 될 수 있다.
  • Docker로 쉽게 사용할 수 있도록 Dockerfiledocker-compose 예제파일을 제공하며, dockerhub에서도 이미지를 제공(2024/04 기준 167M docker pulls)하고 있다.
    • Docker 이미지는 64비트 아키텍쳐(arm64) 뿐 아니라 M1, M2, M3등 Apple silicon(arm64)을 위한 아키텍쳐도 지원한다.
  • 2024년에 들어서는 버젼 release가 빠른 편은 아니지만, 코드는 자주 업데이트 되는 편이다.

여기서는 집에서 소규모로 작게 운영하는 웹사이트들을 가정하고 설명하기로 한다. 실제 production 환경에서 사용하기 위해서는 더 나은 솔루션(AWS의 경우, WAF + ALB SSL termination 등)이 있기 때문에, 높은 트래픽과 높은 가용성이 필요로 하는 환경보다는 낮은 트래픽에 조금 더 쉽게 사용할 수 있는 운영환경에 초점을 맞추고 있다. 또한, 개인적으로 사용하는 homelab에는 서비스들을 docker container로 운영하고 있지 때문에, 여기서도 docker-compose를 이용하여 docker container로 운영하는 방식을 기준으로 설명한다. Docker container들끼리는 docker network로 통신하면 되므로, 개별 서비스에 직접 접근해야하지 않는 이상 각 서비스의 포트를 호스트에 직접 노출시키지 않아도 된다.

 

네트워크 설정

가정집에서 사용 중인 인터넷 환경을 고려해보면, 대개 다음과 같다.

 

공유기에서 서버로 TCP 80/443 포트가 모두 서버로 향하게 설정하는 것이 필요하다. 또한, 서버에서도 npm이 직접 80과 443번 포트를 점유할 수 있도록 설정해야한다. (사용하는 OS환경에 따라 80/443 포트를 이용하기 위해서는 root 권한이 필요할 수 있다.)

 

서버에서는 HTTP로 통신하는 여러 서비스들이 docker container 위에서 운영 중인 것으로 가정한다.

  • npm과 별개로 웹서비스를 제공하기 위한 nginx 혹은 apache (example.com 80 포트)
  • S3와 호환되는 고성능 스토리지 서비스인 MinIO (static.example.com, 9000 포트)
  • jupyter notebook (nb.example.com, 8080 포트)

 

Docker compose

# docker-compose.yml
version: '3.8'

services:
  npm:
    container_name: npm
    image: jc21/nginx-proxy-manager:2.11.1
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    # MySQL/Maria DB가 준비되어 있지 않다면, 아래 environment항목을 삭제 혹은 comment out
    environment:
      DB_MYSQL_HOST: ${NPM_DB_MYSQL_HOST}
      DB_MYSQL_PORT: ${NPM_DB_MYSQL_PORT}
      DB_MYSQL_USER: ${NPM_DB_MYSQL_USER}
      DB_MYSQL_PASSWORD: ${NPM_DB_MYSQL_PASSWORD}
      DB_MYSQL_NAME: ${NPM_DB_MYSQL_NAME}
    volumes:
      - ./nginx-proxy-manager/data:/data
      - ./nginx-proxy-manager/letsencrypt:/etc/letsencrypt
    healthcheck:
      test: ["CMD", "/bin/check-health"]
      interval: 10s
      timeout: 3s
    networks:
      - default
      # 마찬가지로, MySQL 혹은 Maria DB가 준비되어 있지 않다면, 아래 db-network 부분을 삭제
      - db-network

networks:
  default:
    name: ${NETWORK_NAME}
  # 마찬가지로, MySQL/Maria DB가 준비되어 있지 않다면, 아래 db-network 부분을 삭제
  # MySQL/Maria DB를 사용하고, 해당 서비스가 docker container에서 특성 network를 사용 중인 것을 가정
  db-network:
    name: ${NETWORK_NAME_STORAGE}
    external: true
# .env 파일 - docker-compose.yml에서 사용될 변수들을 정의한다.
NPM_DB_MYSQL_HOST=
NPM_DB_MYSQL_PORT=
NPM_DB_MYSQL_USER=
NPM_DB_MYSQL_PASSWORD=
NPM_DB_MYSQL_NAME=

NETWORK_NAME=
NETWORK_NAME_STORAGE=
  • jc21/nginx-proxy-manager 이미지를 사용한다. (2024년 4월 기준으로 2.11.1이 최신)
  • 80/443 포트는 reverse proxy 자체를 위해서, 81번 포트는 reverse proxy 설정을 위한 관리페이지의 접근을 위해서 열어둔다.
    • 80번 포트를 열기 위해서 root 권한이 필요할 수 있다.
  • volumes 항목에서 nginx-proxy-manager가 사용할 data 디렉토리와 인증서 디렉토리(letsencrypt)를 호스트의 특정 디렉토리를 사용하도록 하고 있다.
  • environment 항목에서는 npm이 여러 도메인에 대한 설정을 MySQL에 저장하도록 하고 있다. 만약 MySQL 등이 준비되어 있지 않다면 아래 항목들을 삭제한다. MySQL를 따로 준비하지 않았다면, 이 docker compose 안에 추가해도 되지만, 없어도 sqlite를 사용해서 잘 동작한다
    • environment 항목 전체를 삭제
    • services > npm > networks > db-network 항목을 삭제
    • networks > db-network 항목 전체를 삭제

준비가 되면, docker compose 명령을 이용해서 서비스를 실행시킨다.

docker compose up -d
# docker 버젼에 따라서는
# docker-compose up -d

 

관리도구 설정

도메인별 proxy 설정을 추가하기 위해서는 81번 관리포트로 접근한다. 80/443, 그리고 81번 포트를 열어두었기 때문에 웹브라우져로 http://<서버 주소>:81 를 통해 접속한다. Mac이나 리눅스 개발 환경에서 직접 설정했을 경우, http://localhost:81 혹은 http://127.0.0.1:81 로 접속한다.

 

처음 로그인 시에는 이메일주소 admin@example.com / 비밀번호 changeme 로 접속한다. 첫 접속 후, 관리자 계정의 이름과 이메일 주소, 비밀번호를 설정한다.

 

다음 글에서는 실제로 proxy 설정하는 방법에 대해서 다루어본다.

#!/bin/bash

A="abcd dcba"
B=A
C=${!B}
echo $C
For those who wants to access the icon files directly, the full location is:
/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources

If you get into it with Finder, you'll see the icons. But if you're quite familiar with working on terminal and the names of the icon you need, you can easily copy them to the location you want thru terminal.
현재 날짜(2009년 5월 12일) 기준으로 우분투 최신버젼을 깔고, 안정된 버젼의 source.list를 설정한 다음에 깔리는 vsftpd는 2.0.7이다. 여기서 왠만한 설정을 마치고 Internet Explorer로 접속해보면 잘 보인다. 심지어 문자셋을 EUC-KR로 해두어도 IE7 기준으로는 잘 보인다.
하지만 윈도우 탐색기, explorer.exe로 연결해서 보면 EUC-KR로 된 파일들의 파일명 문자셋이 깨지는 것을 볼 수 있는데, 이는 vsftpd에서 지원하는 "OPTS UTF8 ON"라는 기능 때문이다. ( 관련 링크 )

문자셋 문제인건 알았으나, 각종 검색어에도 불구하고 vsftpd 문자셋에 관련된 검색어는 하나도 낚여올라오지 않았는데, pure-ftpd를 깔으라는게 대세였다.. 알아서 서버와 클라이언트 사이의 문자셋 차이를 변환해준다고..
그러던 와중에 2.0.6의 vsftpd 소스 컴파일 블로그 게시물을 발견하였고, 더 나아가 아래 두 링크에서 결정적인 것들을 얻을 수 있었다.


vsftpd의 소스 중 주석처리 해야할 부분
vsftpd의 소스 패치와 패키징

이 두 블로그를 참고했다.
tistory 블로그와 tistory 블로그의 모체가 되는 테터툴즈(버젼업으로 '텍스트큐브'로 이름이 바뀜. 여기서는 편의상 이전의 이름인 '테터툴즈'라고 한다.)를 따로 설치하여 사용하는 것은 거의 같지만 조금의 차이가 있다.

스킨과 플러그인의 자유도가 테터툴즈가 더 높다고 할 수 있다.
이유인 즉슨 직접 스킨을 업로드 할 수 있다. 이는 tistory도 지원하지만 테터툴즈의 경우, 직접 테터툴즈를 설치할 정도의 사용자라면 직접 스킨을 업로드 하는 인터페이스가 더 편하게 느껴질 수 있다.
또한 플러그인을 직접 추가할 수 있고 더 세분화되게 설정할 수 있기 때문에(모든 소스를 직접 고칠 수 있다. 이는 스킨에도 적용됨) 특성 플러그인을 필요로하는 스킨도 사용할 수 있다는 장점이 있다.(예를들면, gd 라이브러리를 필요로 하는 썸네일 생성 사진 스킨 같은것들)


테터툴즈와 tistory 블로그 장점 중 한가지는 접근 주소를 쉽게 바꿀 수 있다는 것이다.

도메인 이름을 사고, 하위 도메인 즉, 2차 도메인에 대한 주소를 tistory나 테터툴즈가 설치된 서버로 향하게 IP를 지정해주고 적절한 설정을 해주기만 하면 ㅁㅁ.tistory.com 이 아닌 자신이 산 도메인의 하위 도메인 주소로 접근할 수 있다.

여기서 하위도메인이란 예를들어, frostwyrm.tistory.com 의 주소를 예로 들었을 때,
frostwyrm 을 하위도메인, tistory.com 을 주 도메인이름이라고 한다.



tistory의 경우 블로그 관리자 페이지의 '환경설정 → 기본설정' 메뉴의 두번째 항목, "블로그 주소를 설정합니다." 항목을 편집하면 된다.
위의 주소는 tistory가 제공하는 하위 도메인을 이용하는 것이고,
아래 주소는 직접 구입한 도메인 주소 중에서 하위 도메인이 tistory의 IP인 211.172.252.15에 연결되어 있는 하위 도메인 주소를 적어주면 된다.

사용자 삽입 이미지

tistory에서 하위 도메인



테터툴즈의 경우 직접 설치하게 되는 경우, Apache2와 PHP, MySQL은 잘 작동하여 테터툴즈에서 기본적인 읽고 쓰기가 가능한 상태가 되었다고 한다.
개인 사용자의 개별 홈 디렉토리에서 돌리는 웹 서버의 경우, http://서버이름/~사용자ID/tc (예를들면, http://laplace.snu.ac.kr/~iitns/tc/ )와 같은 경로로 접근해야 한다. 이 주소를 자신이 구입한 도메인의 하위 도메인으로 연결하려면 Apache2의 Virtual Host 기능을 이용하면 된다.

여기서는 리눅스 중에서 Ubuntu 7.10 이후의 Apache2 설정을 기준으로 virtual host 설정에 대해서 적어본다. Ubuntu 7.10 이후의 Apache2라면 a2ensite와 a2dissite, a2enmod, a2dismod 등의 간단한 아파치 설정(사실은 soft link를 걸어주는 것 뿐인) 명령어를 통해 쉽게 모듈과 sites 제어가 가능하다.(물론 설정하고 나면 /etc/init.d/apache2 reload 등으로 설정을 아파치에 적용시키는 과정은 필요하지만.)


super user로 로그인해서 /etc/apache2 에 보면 sites-available 디렉토리가 있다. apache2 설정 파일과 사용 가능한 모듈(mods-available), 사용중인 모듈(mods-enabled), 사용 가능한 sites(sites-available), 사용 중인 sites(sites-enabled)이 있다.
사용자 삽입 이미지

여기서 sites-available에 들어가서 파일을 하나 만든다. 해당 도메인의 하위 도메인 정도로 대충 이름을 지어주고 에디터로 열어서 다음과 같이 설정해준다.


<VirtualHost *>
        ServerName blog.pictories.net
        ServerAdmin iitns@laplace.snu.ac.kr
        DocumentRoot /home/iitns/public_html/tc/
        <Directory /home/iitns/public_html/tc/>
                Options FollowSymLinks
                AllowOverride fileinfo
                Order allow,deny
                Allow from all
                Deny from none
        </Directory>
        ErrorLog /var/log/apache2/iitns/blog.log
        LogLevel warn
        CustomLog /var/log/apache2/iitns/blog.log combined
</VirtualHost>

ServerName에는 외부에서 접근하는 주소의 이름.
ServerAdmin은 해당 도메인의 주인 e-mail 주소 (선택사항)
DocumentRoot 이곳에 ServerName으로 접속하면 Root로 보여질 디렉토리를 설정한다.
그리고 그 아래 Root로 보여질 디렉토리에 대한 설정인 <Directory /home/iitns/public_html/tc/>를 통해 해당 디렉토리의 속성을 설정해준다.
경로 끝에는 / 을 붙여 주는 것이 좋다. 어차피 /는 중복되도 한개로 인식하니까..
에러 로그 위치도 적절히 붙여주고 저장한다.

설정이 끝나면 저장나고 그 설정파일을 활성화 시켜주어야 한다. a2ensites <파일이름> 명령어를 통해 방금 저장한 파일 이름을 적어주고 아파치가 다시 설정을 읽어오게 시키면(/etc/init.d/apache2 reload) 하위 도메인으로 잘 작동함을 알 수 있다.

테터툴즈의 경우 가급적이면 처음 설치시부터 주소를 바꿔주는 것이 좋다.
우분투 7.10이 깔려있는 라플라스가 SSH로 접속할 때, 아이디를 치면
iitns@laplace.snu.ac.kr's password: 메시지가 상당히 늦게 떴다..

로그인 뿐 아니라 웹페이지도 뜨는데 시간이 좀 걸렸다..

여기서 포인트는 학교 내부에서 하면 잘되는데 외부에서 하면 딜레이가 나타난다는 것..

왜그런고.. 하니

nsswitch.conf에 있는
hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4
라는 mdns 부분을 comment 처리 해줬더니 고쳐졌다..

빠르다.. 라플라스..

아파치의 문자셋 변경
 
아파치의 문자셋 변경은 각 페이지의 메타태그에서 특별히 문자셋을 지정해주지 않은 경우, 아파치의 문자셋 설정을 따라 읽히게 된다.


아파치 서버의 문자셋은 UTF8로 하는데, 이는 앞으로도 계속해서 이용해져야할 utf8을 이용하기 위해서다..

제로보드 등을 사용할때는 사용할때마다 UTF8 버젼을 사용해주어야 한다..


아니면 웹에 올린 뒤 iconv등으로 변환해주고 메타태그에 적힌 부분을 찾아서 charset=utf-8로 바꿔준다.

아파치에 PHP 모듈 얹기

/etc/httpd/conf/httpd.conf 를 수정하여

모듈을 얹어준다.

LoadModule php5_module modules/libphp5.so
 



아파치 mysql을 시작할때 자동 실행하기
 
우선 runlevel을 알아야 한다.. runlevel등으로

그리고나서 runlevel이 5일 경우는

/etc/rc5.d에 있는 파일 이름을 수정해주면 되는데,

K로 시작하는 것은 자동실행이 비활성,
S로 시작하는 것은 자동실행이 활성화된 것이다.


mv 명령어를 통해서 httpd와 mysql을 S로 시작하게 바꾼다.

K36mysqld
K15httpd를 각각

S36mysqld
S15httpd로 바꾼다.
 

+ Recent posts