AWS EB에서 Let’s Encrypt 수동으로 갱신하기

Let’s encrypt 라는 녀석을 알고 무료로 HTTPS를 적용한지 벌써 석달이 됐다. 다 좋은데 불편한게 하나 있다면 바로 인증서를 3개월 마다 갱신해야한다는 것이다. 그래서 어떤 분은 3개월짜리 크론잡을 돌리시는 분도 있지만 난 설정을 또 해야하는 귀차니즘도 있고 3개월짜리 크론잡에 확신이 없었다.

AWS 빈스톡(beanstalk) 인스턴스가 언제 내려갈지 장담할 수 없기 때문에 주기를 걸면 왠지 틀어질것 같고, 그렇다고 날짜를 고정한 크론잡을 돌리자니 수동이나 다를바가 없었다. 그럴바엔 그냥 귀차니즘도 덜고 수동으로 갱신하는 방법이 맞겠다 싶었다. 그래서 그 때를 기다린지 3개월! 참 오래도 기다렸다.

갱신하기

빈스톡 설정(.ebextension) 에서 certbot-auto를 설치해서 쓰고 있었기 때문에 갱신할때도 EB 설정에 넣어두고 배포를 다시 해볼까 싶었지만 굳이 배포할것도 없는데 인증서 때문에 배포한다는게 또 귀찮아서 그냥 터미널에서 작업을 먼저 해보기로 했다.

$> cd /var/app/current  // EB 앱에 설치되는 위치 
$> ls -al
... 
drwxr-xr-x   2 nodejs nodejs   4096 10월 30 03:51 bin
-rwxr-xr-x   1 nodejs nodejs  57312 10월  5 09:05 certbot-auto
drwxr-xr-x   4 nodejs nodejs   4096 10월 30 03:51 config
...

썰봇(certbot-auto)이 설치 됐는지 확인은 했고, 인증서 갱신(renew)을 하기전 혹시 모르니까 테스트를 해봤다. 참고로 썰봇은 루트 권한을 요구하기 때문에 반드시 sudo 나 루트 권한을 획득한 후에 명령을 실행한다.

$> sudo ./certbot-auto renew --dry-run

... 중략 ...    
Cert not due for renewal, but simulating renewal for dry run Plugins selected: 
Authenticator standalone, 
Installer None Running pre-hook command: service nginx stop 
Output from service: Stopping nginx: 
Hook command "service nginx stop" returned error code 137    
... 중략 ...

1 renew failure(s), 0 parse failure(s)

하하 이게 뭔가요? 싶었는데 자세히 읽어보면 nginx 문제 인것 같다. 그래서 직접 nginx를 죽여봤다.

$> sudo service nginx stop Stopping nginx: /sbin/service: line 66: 25051 죽었음 env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}

$> ps -ef | grep nginx root 25067 1 0 10:10 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf -g daemon off; nginx 25070 25067 0 10:10 ? 00:00:00 nginx: worker process ec2-user 25091 23820 0 10:11 pts/0 00:00:00 grep --color=auto nginx 

어허! 이건 또 뭔가요? 엔진엑스가 죽지 않는다!! 죽여도 죽여도 좀비 처럼 다시 살아난다. 자동 재시작을 멈추기 위해서는 아래와 같은 명령을 이용한다.

$> sudo initctl stop nginx

자 이제 nginx는 멈췄고, 다시 renew –dry-run을 해보니 이제는 문제가 없다. 그럼 –dry-run 옵션을 빼고 갱신을 해보자. 참고로 이 글을 쓰는 시점엔 이미 갱신을 완료해서 로그 캡처를 못했다.

$> sudo ./certbot-auto renew

인증서를 갱신했다면 nginx를 다시 죽지 않는 좀비(?) 모드로 실행해준다.

$> sudo initctl start nginx

제대로 갱신 됐는지 확인하기

인증서 확인을 위해 certificates 명령을 실행해봤다.

$> sudo ./certbot-auto certificates Saving debug log to /var/log/letsencrypt/letsencrypt.log

* * *

Found the following certs: Certificate Name: rlibro.com Domains: rlibro.com Expiry Date: 2018-02-10 02:16:31+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/rlibro.com/fullchain.pem

## Private Key Path: /etc/letsencrypt/live/rlibro.com/privkey.pem

이제 89일 남았다! 유후!!

다시 캘린더에 갱신 날짜를 입력해 둬야겠다.

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

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에서 멀티 호스팅을 어떻게 전략적으로 응용할수있는지 알아보겠다.

덧,

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

외부 도메인을 AWS에 설정하기

드디어 서버 이전을 완료했다. 그동안 임시 도메인을 쓰고 있었는데… 도메인 설정까지 완전 이전완료! 그동안 귀찮고 편리하다는 이유만으로 호스팅에 의존하다보니 진작에 알 수 있었던 것들을 이제서야 알게됐다. 특히 도메인 관련!! 내가 너무 모르고 있었나싶다.

최근 AWS에서 라우터를 하나 설정하고 도메인도 하나 샀다. 도메인을사면 자동으로 Hosted Zones이 만들어지는데 이 상태에서 A레코드만 추가하면 wiki.miconblog.com 같은 서버 도메인을 쉽게 만들수있다. 하지만 기존에 샀던 이 도메인을 AWS와 연결하려고 찾아봤더니 AWS 가이드엔 도메인 운영 자체를 AWS로 옮기는 방법만 있지 다른 얘기는 못찾겠다. ㅎㅎㅎ 그래서 진짜 도메인 이전을 하려고 하니 이게 진짜 좀 귀찮터라.. 그러다 오늘 다른 방법을 찾았다.

Hosted Zones 설정

일단 AWS 라우터에 가서 Hosted Zones을 하나 생성한다. 이때 기존에 샀던 도메인 이름을 넣고 생성하면 2개의 레코드가 자동으로 생성되는데, 하나는 네임서버(NS)고 또 하나는 SOA라는 타입의 레코드가 생성된다. 스크린샷 2014-11-14 오후 12.31.21 그리고 여기에 A타입의 레코드를 하나 추가한다. 참고로 A타입 레코드는 IP와 연결해준다.

기존 도메인의 DNS 변경

이제 다음 할일은 기존 도메인을 구입한 사이트에 들어가서 DNS 서버의 주소를 변경해주는 일이다. 앞에서 NS 타입으로 생성된 레코드 정보를 보면 네임서버 주소가 1차에서 4차까지 나와 있다. 요걸 그대로 넣어주면 끝~!!

설정이 끝났다면 이제 여유를 가지고 기다리기만하면 된다.

알고보면 참 별거아닌건데,.. 너무 오래걸렸다. ㅎㅎ

mac 커맨드 라인에서 AWS로 파일 올리기

앞으로 이사 만료일까지 4일 남았다. 4일안에 모든걸 해치워야한다. 귀차니즘을 이겨내고 잘 할수있을까? 일단 닷네임에서 AWS로도메인 이전하는건 보류.. 그냥 기존에 닷네임에서 카페24로 바라보던 DNS 서버를 다시 닷네임 자체 DNS로 변경후 A레코드만 추가하면 되는거였다. 이렇게 간단한걸 왜 싹다 AWS로 통일하려고 했을까? AWS가 그렇게 싸지도 않은데 말이지… 암튼 사설이 길었다. 각설하고,…

Mac 에서 AWS로 파일 올리기

매우 간단하다. secure copy 라는 명령어를 이용하면 된다. 여기서 중요한건 바로 콜론(:)!! 콜론을 빼먹으면 안된다.

$> scp -i [aws-인증키.pem] [/로컬PC의 경로/파일명.zip] ec2-user@xxx.xxx.xxx.xxx:[올릴 파일명]

서버에서 AWS로 파일 옮기기

이것도 사실 매우 간단하다. 그냥 wget이나 curl을 응용하면 된다.

$> wget '서버URL'

나도 모르게 줄줄이 새고 있었어 ㅜㅜ

AWS로 옮긴지 이제 한달도 안됐다. 그동안은 AWS로 연습한다고 라우터도 만들고 RDS도 만들어보고 물론 EC2 인스턴스도 만들었었지. 그러다 문득, AWS 비용이 만만치 않다라는 얘기를 상기시키며 살짝 불안감에 떨면서 청구 금액을 봤는데,.. 지난달에 내가산 도메인 말고 비용은 0원이다. 당연하지! 1년간 무료라메? 라고 생각하면서 별 생각없었는데….ㅜㅜ

1년간 무료는 EC2 서버 한다였다는 사실을 이제서야 깨달았다. 청구서의 상세 내역을 보니까 어머나~ 내가 테스트로 만들어본 RDS가 엄청 비싼 녀석이었다. 한번도 접속안했고, 그냥 켜놓기만 했는데.. 벌써 40불… 후덜덜…. 바로 RDS 인스턴스 삭제…

젠장,.. 물론 세미나가서 받은 100불짜리 크레딧으로 직접적인 비용을 쓰진 않았으나… 아깝네..ㅎㅎ 또,.. 새는 돈이 없는지 다시 확인했다. 다행히 다른 녀석들은 한달 써봐야 0.1불도 안나가네.. 다행이다.

강의나가면 AWS로 실습하려했는데 전략을 바꿔야겠다.