apache에서 nginx로 갈아타기

요즘 AWS 덕분에 리눅스라는 녀석을 조금 더 딥하게 보고 있는데 리눅스 이녀석 자체만으로 공부할게 너무 많다. 각설하고 오늘은 그동안 공부한 것들 복습도 할겸 미뤄뒀던 동구밭 블로그를 nginx로 갈아탔다. 갈아타는 과정을 좀 정리해보면 다음과 같다.

  1. 리눅스 계정 및 웹서버 루트 폴더 이동
  2. CentOS 5.x 버전에서 yum으로 설치가능한 패키지 버전 문제 확인
  3. CentOS 5.x 버전의 공식 릴리즈 사이트에는 php 버전이 매우 낮음을 확인
  4. CentOS를 6.x 버전으로 업그레이드 가능한지 확인. yum으로는 불가. 백업해서 재설치해야 함을 확인
  5. OS 업그레이드를 포기하고 yum으로 php5.4 버전 설치 (많은 삽질)
  6. yum으로 nginx 설치했는데.. 이것도 버전이 낮아서 yum 레파지토리 변경후 1.6으로 업그레이드

과정이 참 긴데,.. 오늘 느낀점은 yum 명령과 레파지토리에 관련된 내용을 좀더 공부해야겠다는 생각을 했다.

웹서버 루트 폴더 정리

여튼 그간의 과정을 되짚어보자. 일단 웹서버 루트가 어디에 있는지 확인했더니 /home/www 였다. 아~~ 홈폴더 하위에 웹폴더를 뒀었꾸나… 얼마나 개념이 없었는지 실감하면서,.. /var/www/nginx_root로 이동 감행! 이제 나에게 리눅스 계정과 권한문제는 껌이지ㅋㅋㅋ 폴더를 생성하고 소유자를 nginx로 변경, 그리고 wordpress 폴더도 통째로 이동후 소유자(nginx)와 권한을 변경! wp-content 폴더는 간편설치를 위해 655 권한으로 변경. 소유자를 nginx로 했기 때문에 사실 600으로 해도 된다.

nginx와 php 설치

다음으로 아파치 서버와 mysql를 내리고 기존에 설치되어 있는 php 버전을 확인해봤다.

$> php --version

옴마~ 5.1 버전??? 왜이렇게 버전이 낮지? 이거 작년에 설치했을텐데,.. 이유를 알아보기 전에 일단 지우자.

$> yum remove php*

지우고 나서 yum 으로 설치 가능한 패키지를 알아보니 CentOS 5.x 버전에 있는 공식 릴리즈 모듈에는 5.1까지 밖에 없는게 아닌가? “아~ 난감한데… 어떻하지?.. 그냥 최신 버전을 홈페이지에서 직접 받아서 컴파일 할까?” 하다가 예전에 php 버전에 따른 의존성 모듈들 때문에 고생한 한 기억이 떠올라서(파이썬을 직접 업그레이드하다가 꼬여서 파이썬에 의존성이 매우 심한 yum 명령어를 날려버렸던 씁슬한 기억) 이번에는 온전히 yum 으로만 해결하려고 맘먹었다.

이 문제를 어떻게 해결할까? 한참 찾다 결국엔 yum 레파지토리를 업데이트해야한다는 사실까지 알아냈다. ㅎㅎㅎ 아무튼 현재 내가 쓰고 있는 CentOS 버전은 5.11(final) -_-;; yum을 이용해 상위 버전으로 업그레이드는 못한단다. 그리고 5.11의 공식 라이브러리 레파지토리에는 php 버전도 5.1 이고 심지어 nignx도 0.6 버전이었다. 자세한 설치는 검색하면 나온다.

nginx는 php 모듈을 지원하지 않기 때문에 php-fpm 이라는 FastCGI 모듈을 이용해야한다. 여튼 php와 관련된 모든 연동 모듈은 remi 라는 레파지토리를 이용했다. 배가 너무 고픈 관계로 일단 여기까지 정리하고 다음에 이어서 정리하자.

오늘 새롭게 알게된 내용

  1. ningx는 php 대신에 php-fpm 모듈을 이용한다.
  2. 워드프레스에서 이미지 크롭하려면 그래픽 처리와 관련된 php-gd 라이브러리가 설치되어 있어야한다.
  3. CentOS 5는 후졌다. 하지만 어쩔수 없다.
  4. yum 레파지토리를 변경하거나 업데이트 할 수 있다.
  5. 확실히 하드웨어가 저사양일 경우 아파치보다 nginx가 훨씬 좋터라!

리눅스 파일 권한과 워드프레스 설치시 유의점

AWS 서버로 이전하기 위해 필요한 지식들 2탄

지난글에 이어서 2탄으로 정리해본다. 지난글을 되짚어보려니 또 기억이 가물가물… 역시 글은 생각날 때 바로 써야… 흐흑… 각설하고,.. 지난 글을 되짚어보자.

지난글에서 아마존 EC2 인스턴스를 하나 만들고 사용자 계정과 파일 및 폴더 소유자에 대한 이야기를 잠깐 언급했었다. 특히 엔진엑스에서 서버의 실행권한이 nginx 라는 것이 매우 중요하다고 이야기했었다. 이 이야기를 하기 앞서 먼저 리눅스 파일 권한 부터 알아보자.

리눅스 파일 권한에 대한 기본 개념

리눅스를 설치하고 가장 최상위 루트(/)에서 ls -al명령어를 실행해보자.

$> cd /
$> ls
$> ls -al
합계 100
dr-xr-xr-x 23 root root  4096 11월 21 15:10 .           <--- 현재 폴더
dr-xr-xr-x 23 root root  4096 11월 21 15:10 ..          <--- 상위 폴더
-rw-r--r--  1 root root     0 11월 21 15:10 .autofsck
dr-xr-xr-x  2 root root  4096 11월 21 12:12 bin
dr-xr-xr-x  4 root root  4096 11월 21 13:29 boot
... 중략 ...
dr-xr-xr-x 89 root root     0 11월 21 15:10 proc
dr-xr-x---  4 root root  4096 11월  5 06:09 root
dr-xr-xr-x  2 root root  4096 11월 21 12:54 sbin
dr-xr-xr-x 13 root root     0 11월 24 09:54 sys
drwxrwxrwt  3 root root  4096 11월 24 09:54 tmp
... 중략 ..

조회를 해보면 대충 위와 같은 결과를 얻을수있다. 여기서 첫번째 열(drwxrwxrwt)은 계정의 권한을 의미한다. 폴더일 경우 d로 시작되고 심볼릭 링크인 경우엔 l, 그리고 파일은 미지정(-)상태가 된다. 그리고 그 다음 각각 3자리는 아래와 같다.

[1자리:파일타입][3자리:소유자권한][3자리:그룹의권한][3자리:others권한]

위에서 소유자와 그룹은 두번째와 세번째 열에 각각 그 소유자와 그룹 이름을 표시한다. 여기까지는 상식이니까 넘어가고 자세한 내용은 검색하면 많으니까 검색해보자.

루트 폴더(/)의 대부분은 소유자인 루트(root)에게 대부분의 읽기(r),쓰기(w),실행(x)권한이 열려있다. 하지만 몇몇 폴더들은 쓰기 권한이 빠져있는 것을 확인할 수 있다. 대표적으로 리눅스 시스템 폴더(/sys)와 부팅에 필요한 폴더(/boot) 그리고 실행중이 프로세스 정보가 담겨있는 /proc 폴더들은 루트 마저도 쓰기권한이 없는 경우가 많다. 생각해보면 너무나 당연한 권한이다. 이런 권한 때문에 루트(/)폴더에서 일반 유저가 mkdir 명령으로 폴더를 생성하면 퍼미션이 없다며 생성이 되지 않는다.

[ec2-user@/]$> cd /
[ec2-user@/]$> mkdir test
mkdir: `test' 디렉토리를 만들 수 없습니다: 허가 거부

하지만 권한이 있는 폴더에서는 당연히 폴더든 파일이든 생성할수 있다. 그럼 폴더를 하나 생성해보자.

[ec2-user@/]$> cd ~
[ec2-user@~]$ mkdir test
[ec2-user@~]$ ls -al | grep test
drwxrwxr-x   2 ec2-user ec2-user  4096 11월 24 10:41 test

ec2-user 계정으로 폴더를 생성하면 당연히 첫번째 비트는 폴더이므로 [d]가 된다. 그리고 본인이 생성했으므로 당연히 소유자권한은 rwx가 되고, 그룹의 권한은 ec2-user가 속해있는 그룹에게는 모든 권한이 열려있다. 하지만 그외 유저들에게는 쓰기 권한이 없다. 그럼 루트로 폴더를 생성하면 어떤 권한이 생성될까?

[ec2-user@~]$ sudo mkdir test2
[ec2-user@~]$ ls -al | grep test
drwxrwxr-x   2 ec2-user ec2-user  4096 11월 24 10:41 test
drwxr-xr-x   2 root     root      4096 11월 24 10:41 test2

루트 권한으로 폴더를 만들면 일반 유저와는 다르게 그룹 권한도 쓰기권한이 없다. 그만큼 root계정은 보안에 신경쓰고 있음을 보여준다.

아파치나 nginx에서 403 forbidden 에러가 나는 이유

자 이제 이 얘기가 왜 중요한지 알아보자. 보통 웹서버를 설치하고 브라우저로 설정한 파일을 URL로 통해 접근하려고 할때 403 forbidden 에러를 종종 보게 되는데, 바로 이 에러가 파일 권한 문제와 관련이 있다. 이전에도 이와 관련된 글을 쓴적이 있다.

apache나 nginx와 같은 웹서버는 URL을 통해 서버에 있는 특정 파일에 접근(access)하게 되는데 이때 접근 계정은 해당 서버를 실행시킨 계정이 된다. 즉, nginx의 경우 nginx라는 계정으로 해당 파일에 접근하게 되는 것이다. 물론 아파치서버의 경우 apache 계정으로 접근하게 된다. 따라서 웹서버의 최상위경로(doc_root)는 접근하려는 계정에게 최소한 읽기 권한이 있어야 한다.

따라서 nginx의 루트 폴더(document_root)를 누구 소유로 지정하느냐에 따라 최소 권한이 바뀐다.

  • 가령, 루트폴더를 nginx 계정이 소유하고 있다면 최소 400(r–,—,—) 권한이 있어야하고
  • nginx가 아닌 다른 계정(ec2-user)이라면 최소 004(—,—,r–) 권한이 있어야한다.

그런데 nginx 웹서버의 도규먼트 루트 폴더를 계정의 홈폴더(/home/ec2-user) 하위로 지정하고 싶은 경우가 있다.

/home/ec2-user/www

예를 들면, 위와 같은 위치에 www 폴더를 만들고 싶은 경우를 말하는데, 안타깝게도 이렇게 하려면 현재 ec2-user 폴더의 권한도 수정해줘야한다. 왜냐면 ec2-user 폴더는 홈폴더 특성상 700권한으로 지정되어 있기 때문에 소유자 본인 말고는 다른 계정이 접근조차 할수없다.

[ec2-user@/]$> cd /home
[ec2-user@home]$> ls -al
합계 16
dr-xr-xr-x  4 root     root     4096 11월  3 09:27 .
dr-xr-xr-x 23 root     root     4096 11월 24 10:39 ..
drwx------ 15 ec2-user ec2-user 4096 11월 24 11:11 ec2-user

그래서 자신의 홈폴더 하위에 웹폴더를 만들고 싶다면, 웹서버 계정이 접근 가능하도록 /home/ec2-user 폴더에 최소한 읽기 권한은 있어야한다.

drwx—r–

하지만 나는 리눅스가 지정해둔 홈폴더 고유의 권한을 바꾸고 싶진 않기 때문에 www 라는 이름이 /var/www/nginx-root 폴더를 가르키도록 심폴릭 링크를 만들어 사용한다. ln 명령은 일반 유저에겐 권한이 없으므로 sudo를 붙인다.

$> sudo ln -s /home/ec2-user/www/nginx-root www
lrwxrwxrwx   1 root     root        20 11월  4 08:53 www -> /var/www/nginx-root/

워드프레스와 nginx의 소유자 권한

이제 nginx 서버에 워드프레스를 설치해보자. nginx 서버는 지난 1탄에서 살펴봤듯이 master 프로세스는 root가 실행시키고 실제 동작을 담당하는 worker 프로세스는 nginx 라는 계정으로 실행된다. 따라서 워드프레스 설치경로의 소유자를 같은 nginx로 바꿔준다. 만약 다른 계정으로 지정한다면 반드시 nginx 계정이 접근가능하도록 other에 읽기 권한이상을 열어줘야한다.

설치형 워드프레스의 장점, 웹에서 설치하기

워드프레스는 간편하게 클릭만으로 플러그인이나 테마를 설치할 수 있는데 이때 설치되는 과정을 살짝 들여다보자. 1. 먼저, 웹 관리 메뉴에서 테마나 플러그인을 다운로드 받으면,
2. 워드프레스를 실행시키는 프로세스(nginx)가 필요한 파일을 웹에서 다운로드 받는다. 3. 그리고 이것을 wp-contents 폴더에 복사한다. 4. 이때 다운받은 파일의 소유자와 권한은 당연히 nignx가 된다. 5. 하지만 그룹과 other에게 쓰기 권한은 주어지지 않는다.

정리하면 아래와 같이 764(rwx,r-x,–x) 권한으로 지정된다.

drwxr-x–x 11 nginx nginx 4096 11월 24 12:59 penny

여기서의 핵심은 워드프레스를 실행시킨 프로세스가 누구냐는 것이다. 즉, nignx 계정으로 파일을 다운받아 워드프레스가 인식하는 특정폴더(wp-contents)에 파일을 복사하기 때문에 워드프레스 폴더의 소유자가 nignx가 아니라면 other 계정의 쓰기 권한도 지정해야함을 의미한다. 따라서 소유자와 other에 권한이 제대로 매치되지 않으면 그 쉽다는 원클릭 설치도 제대로 안될것이다.

정리하면,

이번 글도 양은 얼마되지 않으나 글로 정리하려니 시간을 엄청 썼다. 이번글은 거의 리눅스 계정과 워드프레스 얘기만 했는데, 다음 편에는 AWS에서 라우터 설정과 nginx에서 멀티 호스팅을 어떻게 전략적으로 응용할수있는지 알아보겠다.

덧,

이 글이 도움이 되셨다면 아시죠? 광고한번 클릭해주세용~ 🙂

angularjs, ui-router를 이용한 사용자 인증 처리

angularjs로 개발을 좀 하다보니 ng-router를 확장한 ui-router가 기능이 너무 막강해서 ng-router가 필요 없을 지경에 이르렀다. 이제는 필수 모듈이 된 ui-router가 앵귤러 2.0에 포함될지는 지켜보겠지만 아무튼 오늘은 각설하고 ui-router를 이용한 사용자 인증 처리에 대해 알아보자.

시작하기 앞서, 전체 소스코드는 요기에 있다.

angularjs 라우터 설정하기

일단 라우터를 아래와 같이 설정한다. 밑에 설정에서 눈여겨 볼 것은 admin 페이지에 authenticate라는 값을 추가했다는 점이다. authenticate는 ui-router에서 제공하는 키워드는 아니고 그냥 인증된 사용자만 접근 가능하다라는 의미를 주기 위한 변수에 불과하다. 이제 이 변수의 의미대로 진짜 인증된 사용자만 접근 가능하도록 구현해보자.

  • signin 페이지: 누구나 접근 가능하다.
  • admin 페이지: 인증된 사용자만 접근 가능다.
// routes.js
(function(){
  'use strict';

  angular
    .module('app')
    .config(function ($stateProvider) {
      $stateProvider
        .state('signin', {
          url: '/signin',
          templateUrl: 'signin/signin.html',
          controller: 'SigninCtrl'
        })
        .state('admin', {
          url: '/admin',
          templateUrl: 'app/admin/admin.html',
          controller: 'AdminCtrl',
          authenticate: true
        });
    });

)();

authenticate 값에 따른 라우터 처리

먼저 앵귤러는 .run() 함수에 인자로 넘긴 콜백함수로부터 시작된다. 이 콜백함수는 페이지가 로드되고 필요한 모듈도 모두 로드되면 호출된다. 초기화 과정에 대한 자세한 내용은 다음 기회에…

라우팅은 URL을 변경해 페이지를 이동시키는 것을 이야기하는데 2가지 방법이 있다.

  1. 하나는 서버에서 URL을 해석해 이동(redirect)시키는 방법이고
  2. 또 다른 하나는 ui-router처럼 클라이언트 딴에서 해쉬URL로 이동시키는 방법이다.

여기서 잠깐, HashUrl이란?

hashUrl은 아래와 같이 url에 샵(#)을 붙여 만든 URL을 의미한다.

https://miconblog.com/#somehash

해쉬URL은 문서 안에 있는 ID로 지정된 엘리먼트를 찾아갈때 쓰인다. 보통 최상위 엘리먼트에 <div id='top'> 같은 값을 주고 Top 버튼을 누르면 스르륵~ 맨위로 올라가게 만든 것도 이런 해쉬를 응용한 방법이다. 해쉬의 장점은 문서 안에서 이동하기 때문에 URL이 변경되도 서버를 거치지 않고, 페이지를 변경할수있다는 장점이 있다. 물론 페이지를 변경하려면 hashChanged라는 이벤트를 잘 모니터링하고 있어야한다.

여하튼 다시 돌아와서 ui-router는 URL 상태가 변경되면 $stateChangeStart 라는 이벤트를 발생시켜준다. 이 이벤트는 현재 페이지에서 다른 페이지로 이동하겠다 혹은 이동했다라는 의미이기 때문에 당연히 이벤트의 함께 넘어오는 정보는 이동할 페이지 정보가 되겠다.

// app.js
(function(){
  'use strict';

  angular.module('app', [
    'ui.router'
  ])
  .run(function ($rootScope, $state) {

    $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
      // 이동할 페이지에 authenticate 값이 있는지 확인해서 라우팅한다.
      if( toState.authenticate ){
        $state.transitionTo('signin');
        event.preventDefault();
      }

    });
  });

})();

위 코드처럼 URL의 상태가 변경되면 페이지를 이동하기 전에 authenticate 값을 미리 확인하고 원하는 처리를 할수있다. 위 코드에서는 현재 내가 인증된 상태인지 아닌지 판단하는 코드는 없지만, 만약 넣는다면 아래와 같이 처리할 수 있겠다.

.run(function ($rootScope, $state, User) {

    $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
      // User 서비스를 추가해서 현재 사용자가 인증된 사용자임을 확인한다.
      if( toState.authenticate && !User.isAuthenticated() ){
        $state.transitionTo('signin');
        event.preventDefault();
      }

    });
  });

정리,

ui-router를 이용한 인증처리를 알아봤는데 다음에는 위 코드에서 사용자 인증에 사용한 User 서비스를 만들어 볼 예정이다.

참고 링크

  • https://medium.com/@mattlanham/authentication-with-angularjs-4e927af3a15f