Tutorial of automated Letsencrypt certificates with nginx

지난 포스팅에서는 certbot을 사용하여 gitlab의 인증서를 설치하는 법에 대해서 작성하였고, 자동으로 인증서를 재발행하도록 해 보아야겠다고 생각했었는데, 오늘은 엔진엑스에 인증서를 설정하고 자동으로 갱신되도록 하는 부분에 대해 작성해 보려 한다.

지난 포스팅 이후에 인증서 재발행을 간단히 실행해 보고, 문제가 될 수 있는 지점을 하나 발견하였다. –manual 옵션으로 인증서를 발행한 경우에는 certbot renew 명령으로 인증서 재발행이 불가능하다는 것이다.

기본적으로 certbot은 인증서를 생성하는 과정에서 해당 도메인에 접속가능한 것을 확인한 후에 인증서를 발행해 준다. 인증서를 수동으로 발행할 때에도 정해진 경로에 해당 파일을 생성하고 certbot에서 생성한 키를 파일 내용으로 적어서 저장한 후, 이후 과정을 진행했었다.

–manual을 쓰지 않아야 한다면, 명령줄 하나만으로도 가능하지 않을까라는 생각이 들었고, 어렵지 않게 파악한 명령줄은 다음과 같다.

certbot certonly \
  --webroot -w /var/www/blog.osg.kr \
  -d blog.osg.kr \
  --agree-tos

위에 입력한 옵션들에 대한 설명은 다음과 같다.

certonly(부명령어)는 인증서를 발행까지만 하고 자동 설치는 하지 않을 때 사용한다.
–webroot는 위에서 이야기한 인증 파일을 둘 경로를 지정할 때 사용하며, -w 옵션으로 해당 경로를 설정한다. 이 옵션을 사용할 때는 해당 경로를 미리 생성해 놓아야 한다.
-d는 SSL 인증서를 발행할 대상 도메인 이름을 지정할 때 사용한다.
–agree-tos는 이용약관에 동의한다는 것을 옵션으로 설정하는 것이다.

위와 같이 입력하고 실행하면 되는데, 뭔가 빠진 느낌이 들지 않는가. 그렇다. 위의 명령어를 실행하기 전에 먼저 해 주어야 할 것이 있다. 그건 바로 nginx에 .well-known 디렉토리에 대한 경로를 설정해 주어야 하는 것이다.

server {
    listen 80;
    server_name blog.osg.kr;

    ...
    
    location /.well-known/acme-challenge {
        root /var/www/blog.osg.kr/;
    }
}

파랗게 적은 부분은 .well-known/acme-challenge의 경로의 root를 설정해 주는 것이다. root로 설정했기 때문에 실제 파일의 경로는 아래와 같은 경로가 된다. 이제 nginx를 재시작 해 준다.

/var/www/blog.osg.kr/.well-known/acme-challenge/인증파일명

위에서 언급했던 certbot 명령줄을 입력해 주면, certbot이 위의 파일을 엑세스 한 후 해당 파일을 삭제하고, 최종적으로 인증서를 발행해준다. 인증서 발행 경로를 따로 지정하지 않았으므로 /etc/letsencrypt/live/blog.osg.org에 인증서가 발행되게 된다.

인증서 발행 후에는 nginx의 설정 파일에 아래와 같이 추가로 HTTPS 접속에 대한 설정을 해 주어야 한다. 인증서 적용에 필요한 부분만 적었기에 다른 부분들은 생략하였다.

server {
    listen 443 ssl;
    server_name blog.osg.kr;

    ...

    ssl_certificate /etc/letsencrypt/live/blog.osg.kr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.osg.kr/privkey.pem;
}

SSL은 공개키 알고리즘을 사용하므로 ssl_certificate은 full chaining된 인증서의 경로를 적어주면 되고, ssl_certificate_key는 해당 인증서에 대한 개인키 경로를 적어주면 된다.

이제 엔진엑스를 재시작한 후, 자신의 도메인에 접속(필자의 경우 https://blog.osg.kr)하면 다음과 같이 자물쇠 표시가 된다.

이제 이 경로를 통해서 주고 받는 패킷들은 공개키 알고리즘을 사용해서 암/복호화가 이루어진다.

이제 앞서 이야기한 것처럼 인증서를 자동으로 재발행하는 게 가능하다.

certbot renew

라는 명령어 한 줄이면, 발행한 모든 인증서를 갱신해 준다. 하지만 발행한 지 일정 시간이 지나지 않으면 아직 발행할 때가 아니라며 인증서를 갱신해 주지 않는다.

이럴 때 강제로 인증서를 갱신하는 옵션이 있다.

certbot renew --force-renewal

–force-renewal 옵션을 추가로 적어주기만 하면, 인증서가 자동으로 갱신된다.

이제 해당 명령을 쉘스크립트로 생성하고, crontab에 원하는 주기에 한 번씩 실행되도록 등록해 주면 모든 준비가 끝난다. 인증서 갱신 때문에 인증서 설정을 새로한다든가 하지 않아도 된다. 단, 갱신된 인증서를 적용하려면 웹서버를 재시작해 주어야 한다. 웹서버 재시작까지 스크립트로 미리 준비해 둔다면, 별도로 웹서버를 재시작할 필요도 없을 것이다.

아참, 아직 crontab에 등록하는 것까지는 하지 않았다. 조만간 실행해 보고 잘 되면 추가로 포스팅 하도록 하겠다.

이제 인증서 발행과 설정 때문에 리소스를 과도하게 투입하지 않아도 된다. 사람이 손으로 일일이 설정하는 것들은 자동화해야 한다. 이렇게 자동화하면 아무리 많은 인증서도 자동으로 갱신되니 신경쓸 필요가 없다. 모든 설정이 끝났다면 인증서 갱신에 대한 걱정은 내려놓고, 집중해야 할 개발업무로 달려가면 된다.

2017 데이터 그랜드 컨퍼런스에 참석하며…

키노트와 비즈니스 키노트, 일련의 발표들을 들었다. 그리고 점심시간엔 부스에 전시된 제품들이나 연구결과들을 공유하는 자리에 가서 궁금한 것들을 물어보고 답변도 듣는 시간을 가졌다. 부스에서는 나도 모르게 “그러면 이 솔루션은 어디에 활용하는 건가요? 사용대상은 누구인가요?” 등의 질문이 툭 튀어나왔다. 산업 및 조직심리를 공부할 때 지도교수님께 지겹도록 들었던 질문을 내가 하고 있다니 세상에나!

연구결과는 실용성이나 시사점 또는 공익성이 있어야 하는 거다. 데이터 분석결과는 퍼즐조각들과 같아서, 하나의 이야기로 잘 연결하여 유의미한 그림을 제공하게 되면 분석결과의 가치가 빛을 발하게 된다. 그런데, 필자는 피같은 시간을 내서 갔는데, 어떤 명확한 그림에 대한 구경도 못한 채 그냥 분석해서 결과를 리뷰하는 수준으로 끝난 발표시간이 있었다. 빅데이터를 아무리 외치고 머신러닝을 한다고 해도, 산업이 크게 발전할 수 없는 데에는 다 그만한 이유가 있는 거라는 생각이 들었다.

예나 지금이나 변함없는 생각은 데이터 분석결과보다도 분석결과가 어떤 옷을 입느냐가 훨씬 더 중요하다는 것이다. 앞으로도 수많은 데이터들이 의미로 옷입고 세상에 자신을 드러냈으면 좋겠다. 조금 더 그런 자리에 있을 거라고 믿어본다. 나도 일조할 수 있으면 좋겠다고 생각하며 글을 맺는다.

JetBrains Night 서울

JetBrains에서 필자가 관심갖고 있는 영역을 모두 행사에서 다룬다고 한다.

첫째는 IDE Tips & Tricks 파트다. Webstorm에 이어 PhpStorm과 PyCharm까지 사용하다가 Android Studio를 사용해야 하는 상황까지 되어서, IDE를 여러개 쓸 수 없다는 생각에 IntelliJ IDEA까지 구매를 했음에도, 사실 아직도 많은 단축키를 제대로 활용하고 있지 못한 점이 영 마음에 걸린다. 과거에 한글97 워드프로세서의 단축키 80-90%를 암기해서 쓸 때만도 못한 수준이다. 뭐 개인적으로 단축키는 조금씩 암기하고 사용해 가고 있지만, 좀 더 능숙하게 연장을 다루고 싶은 마음은 늘 마음 한 구석에 있었다. 어떤 팁과 트릭이 공개될 지 궁금하다. 이참에 눈감고도 한글97을 썼던 느낌으로 IDE를 써야겠다는 강렬한 열망 같은 게 마음 속에서 꿈틀댄다.

둘째는 작업흐름이다. Trello, Gitlab, Jira, Slack 등을 사용했을 때의 잇점은 기록을 통해서 소통을 개선한다는 점이다. 문제를 빨리 발견할 수 있다는 점, 지식 전파가 빨리 이뤄진다는 점이 협업 도구 사용의 강점이라 할 수 있는데, JetBrains에서 제시하는 팀웨어 도구들이 어떤 지점에서 작업 흐름을 개선하고 생산성을 향상시키도록 고안됐을지 궁금하다.

셋째와 넷째는 최근 인기 상승 중인 Kotlin에 대한 내용이다. 안그래도 안드로이드 개발 및 iOS 개발을 모두 해야 할 때 리액트 네이티브나 자마린 같은 하이브리드 플랫폼을 선택해야 할 지, 안드로이드 앱은 Kotlin으로 iOS 앱은 Swift로 개발하는 게 좋을지 고민하는 중이었다. 이전에 Ionic과 React Native로 하이브리드 앱을 개발해 보았지만, 결국 네이티브 단에서 발생하는 이슈를 해결하려면 네티이브를 잘 알아야만 했다. 그렇지 않다보니 여차하면 삽질하기 일쑤였다. 그러던 와중에 현재는 java로 개발한 안드로이드 앱을 유지보수하고 있는데, 과연 코틀린이 가져올 생산성의 향상은 어느 정도일지, 그리고 코틀린의 특장점을 소개하는 자리가 될 것 같은데, 궁금하다.

행사 링크는 여기를 클릭!

docker –link option is deprecated

도커가 컨테이너를 띄울 때 내부 아이피를 사용하는데, 그 아이피가 고정되어 있지 않기 때문에, 컨테이너 간에 접근할 때 아이피를 사용하면 그 때 당시에는 되겠지만, 추후에 컨테이너를 다시 띄우면 IP 주소가 새로 할당되기 때문에 컨테이너 이름을 호스트 이름으로 사용해야 한다.

과거에는 –link 옵션을 사용해서 컨테이너를 서로 연결해 주었다. 이제는 docker network가 그 기능을 대신하고 있고, –link 옵션은 deprecated 상태이다. 언젠가 완전히 사라질 것이다.

네트워크를 설정하는 방법은 우선 도커 네트워크를 생성한다. 그 후에 컨테이너를 띄울 때 해당 네트워크를 사용하도록 설정해 주면 된다. 해당 네트워크를 사용하는 컨테이너에서 접근하고자 하는 대상 컨테이너 이름을 호스트 이름으로 사용할 수 있게 된다.

우선 도커 네트워크를 생성할 이름과 함께 아래와 같이 입력한다.

docker network create NETWORK-NAME

ls 명령어를 사용하여 도커 네트워크가 추가된 것을 확인한다.

docker network ls

이제는 특정 컨테이너를 실행할 때 사용할 네트워크를 지정해 준다. mysql과 php-fpm을 사용한다고 가정하고 아래와 같이 –network 옵션을 설정해 준다.

docker run ..... --name mysql --network NETWORK-NAME mysql:5.x.x
docker run ..... --name php --network NETWORK-NAME php:5.6-fpm

이제 호스트이름을 그냥 사용하면 된다. 위의 경우와 같이 컨테이너를 띄웠다면, 각 컨테이너의 이름인 mysql, php로 상호간에 접근할 수 있게 되었다.

그리고 이렇게 하면 해당 컨테이너의 해당 포트로 바로 접근 가능하므로 굳이 port를 publish 하면서 사용하지 않아도 된다.

만일 NGINX 컨테이너를 하나 더 띄워서 nginx.conf 에서 fastcgi를 설정하는 경우라면 php-fpm은 보통 9000번 포트를 사용하니 아래와 같이 설정해 주면 된다. 해당 서버 설정 구간에 다음과 같이 호스트명으로 잡아주면 된다.

fastcgi_pass php:9000;

 

참고자료: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/

https://docs.docker.com/engine/userguide/networking/

Vultr 서비스 사용기

국내 호스팅으로 CAFE24를 아주 작게 사용해왔었다. 월 500원의 비용으로 매우 저렴하게 이용했었다. 워드프레스로 블로그를 시작하면서부터 SSL 인증서가 적용되지 않는 점이 마음에 걸렸다. Letsencrypt를 사용하여 발급받은 인증서는 CAFE24에 자동으로 업로드가 되지 않아서 고객센터를 통해서 요청해야 했고, CAFE24의 응대는 깔끔한 느낌이 아니었다. 그리고 결정적으로 SSL을 443 포트로 서비스 받을 수 없었다.

“클라우드 서비스 중에 좀 저렴하고 쓸만한 게 없을까? 혹시 지금쯤이면 좀 쓸만할 게 있을까?” 하는 마음으로 반신반의하며 구글링한 결과 해외 서비스로 VULTR가 있다는 것을 알게 되었다. 여러 서비스들이 있었지만, 가격대비 스펙이 매우 훌륭하여 선택하였다.

현재 VC2 서비스로 5불 짜리를 이용하고 있다. 가장 저렴한 요금제는 2.5불 짜리가 있는데, 1 CPU, SSD 20G, 메모리 512MB, 트래픽 500GB인데, 운영체제까지 입맛에 맞게 골라서 쓸 수 있다는 점에 확 넘어가 버렸다. 카페24의 최저 요금 서비스가 월 500원으로 SSD 200MB에 트래픽 400MB을 제공하는 것에 비하면 가성비는 Vultr의 압승이라는 생각이 들었다.

참고로 Windows OS는 월 16불의 추가비용을 내고 사용할 수 있다. 하지만, ISO 파일을 업로드 하면 추가 비용 없이 사용할 수 있다. 해당 ISO 파일은 VirtIO 세팅이 된 파일이 아니면 설치가 제대로 되지 않는다고 한다.

처음에는 가격부터 따져보았다. 어차피 큰 요금 차이가 아니니 써보고 로케이션이 맘에 안 들면 바꾸자고 생각했다.

월 2.5불의 최저 요금제를 지원하는 Location은 미국 마이애미와 뉴저지였다. ping을 쳐 보니 300~400ms 정도가 나왔다. 그래도 쓸만하지 않을까 하는 마음으로 일단 뉴저지 Location으로 신청해 보았다. 터미널을 사용하는데, 역시 반응속도 300~400ms는 답답한 감이 많았다. 싸게 쓰려 했으나, 지리적으로 우리나라에 사는 한 뉴저지는 불편하겠다고 판단했다.

그래서 고민을 다시 시작했다. 커피 한잔에 5~6천원 한다고 보면 그냥 5불짜리를 사용하는 것도 나쁘지 않겠다는 생각이 들었다.

5불짜리는 1 CPU, SSD 25G, 메모리 1GB, 트래픽 1TB 이었다. 이참에 한 달에 하루는 날을 정해서 음료고 뭐고 먹지 말자고 다짐하고, 그 돈으로 서버를 굴리자고 생각하고 다시 로케이션을 탐색했다.

가장 가까운 곳으로 도쿄와 싱가폴이 있었고, 그 다음으로 미국의 로스엔젤레스와 시애틀이 눈에 들어왔다. VULTR에서는 핑 테스트 할 수 있는 정보를 다음 경로에서 제공하고 있다.

https://www.vultr.com/faq/#downloadspeedtests

집에서는 KT 0.5G 인터넷을 사용중인데, ping을 날려보면 도쿄는 무슨 이유인지 반응속도가 30~100ms 에 이르기까지 널을 뛰는 모습을 보여주었고, 싱가폴은 90~100ms, 시애틀은 140~160 정도를 오가며 안정적인 모습을 보여주었다. 마지막으로 LA를 찍어보았는데, 134~136ms 정도를 꾸준히 안정적으로 유지하는 모습을 보여줬다.

도쿄는 가깝고 빠를 땐 빠르지만 안정적이지 못하다는 느낌을 받았다. 사실 일본은 자연 재해가 발생할 경우 그렇게 안전하지 않을 수도 있다는 생각이 들어서 선택지에서 제외했다. 싱가폴도 가깝기는 하지만, 동남아 쪽이 아닌이상 국제 서비스를 하기에는 반응속도 때문에 이용자들이 너무 느리다고 생각할 수 있겠다는 생각이 들었다.

LA를 선택하면 필자도 크게 불편을 느끼지 않을 것 같았고, 미국 전역에서 접속해도 느리다는 생각을 하지 않을 것 같았다. 뭐 아직 미국을 대상으로 무슨 서비스를 할 생각은 없지만, 마음은 늘 원대하게 품어보는 것이니ㅎㅎ

결국 LA에 VC2 인스턴스를 생성하였으며, 필자는 도커 기반으로 서버를 운영할 것이라 운영체제는 CoreOS를 선택해서 설치하였다.

스냅샷 기능을 사용하면 현재의 상태를 보존할 수 있다. 다른 인스턴스로 이관할 필요가 있을 때 사용하면 된다. 고스트 이미지 떠 놓은 느낌이랄까. 일단 오늘 워드프레스를 이전한 기념으로 VULTR 사용기를 작성해 보았다.

참, VULTR은 회원에게 보상해 주는 제도가 있다. 회원의 소개로 가입해서 결제하면, 회원에게 보상을 해 준다. 보상 비용은 Paypal 계좌로 받을 수도 있고, 서버 운영비 계좌로 받을 수도 있다. 아래와 같은 배너도 제공해 준다. 원하는 배너를 선택해서 활용하면 되겠다.

그럼 VULTR 서비스에 대해 자세히 알아보려면, 클릭↓ 꾹~*

phinx 실행시 timezone 문제 발생하는 경우

사실 phinx의 문제라기보다는 php 환경변수로 timezone이 설정되지 않아서 발생하는 경고 메시지이다.

필자는 phinx를 사용하여 마이그레이션하려할 때 아래와 같은 경고 메시지를 받았다.

Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone.

설명에도 나와있듯 php.ini에 date.timezone 값을 설정해 주거나, 관련 코드 실행시에 date_default_timezone_set()을 사용하면 된다.

우리나라의 경우에는 ‘Asia/Seoul’을 다음과 같이 적어주면 된다.

date.timezone = Asia/Seoul

date_default_timezone_set(‘Asia/Seoul’);

필자는 서버 환경 설정과 관계 없이 코드를 통해 동일한 결과를 만들어 내기 위해 phinx.php에 코드로 작성하여 문제를 해결하였다.

phinx db migration tool setting

phinx.yml 에서

host를 localhost로 할 때엔 unix_socket을 정해줘야 한다.

host가 localhost인데 unix_socket이 설정되어 있지 않으면, 다음과 같은 에러를 보게 된다.

[InvalidArgumentException]
There was a problem connecting to the database: SQLSTATE[HY000] [2002] No such file or directory

unix_socket을 사용하지 않으려면 host를 127.0.0.1로 하면 된다.

참고자료: https://stackoverflow.com/questions/22188026/sqlstatehy000-2002-no-such-file-or-directory/25782795#25782795

Database migration with alembic or phinx

어떤 언어로 개발하든 데이터베이스를 수정할 일이 생기는 경우가 발생한다. 개발자의 개발 머신과 테스트 서버 그리고 상용 서버에 이르기까지 모두 적용해 주어야 한다. 때로는 어떤 상황으로 되돌아가야 하는 경우도 생긴다. 이와 같은 DB 변경 사항 적용을 마이그레이션이라 부르며, CodeIgniter나 Laravel 그리고 Django에서는 마이그레이션 기능을 내장하고 있다. 프레임워크와 별도로 작동하는 패키지가 있는지 찾아보다가 두 가지를 발견하였다.

alembic은 python용 DB 마이그레이션 패키지이고, phinx는 php용 도구이다.

사용법은 프레임워크에서 제공하는 기능과 별 차이가 없다.

한 가지 눈에 띄는 게 있다면 phinx는 change() 메서드에 특정 메서드를 사용하여 마이그레이션 코드를 작성하면, 리버스 코드를 작성하지 않아도 rollback이 자동으로 된다고 하는 점이 특징으로 보인다.

아직 사용해 보지는 않았지만, 자동으로 create & drop이 된다면 편리할 것 같다. 사용해보고 후기를 이어서 작성해 볼까 한다.

Android build setting

Andriod 앱을 빌드하기 위해서는 당연히 android sdk가 있어야 한다.

예전엔 android sdk를 다운받을 수 있었는데, 지금은 sdk tools를 별도로 제공하고 있다. 사용하려면 명령줄에서 실행해야 한다.

필자는 jenkins를 docker로 띄워 놓은 상태였고 git repository로부터 webhook이 걸리면 gradlew명령어를 사용해서 apk를 자동으로 빌드하려는 상황이었다.

jenkins 컨테이너 내에 jenkins 사용자의 홈디렉토리는 기본으로 /var/jenkins_home에 세팅된 것을 기준으로 정리하였다.

이후에 tools/bin에 있는 sdkmanager를 실행하여 sdk들을 설치하게 되면 관련 sdk들이 tools 디렉토리의 상위 디렉토리에 위치하게 되며 해당 디렉토리를 anroid sdk 디렉토리로 사용하게 된다. 따라서 android sdk 디렉토리를 먼저 생성해 주어야 한다.

mkdir /var/jenkins_home/android-sdk

그리고 android sdk tools의 압축을 풀면 tools 디렉토리에 내용이 담겨있다. android sdk 디렉토리로 복사하였다.

cp -R tools /var/jenkins_home/android-sdk/tools

안드로이드 sdk에는 기본적으로는 platform, build tool 정도만 설치하면 앱을 빌드할 수 있다. 하지만 추가로 외부 라이브러리들을 사용한다면 해당 라이브러리들은 리포지터리에서 찾는 과정을 거치게 된다.

필자가 작업하는 프로젝트는 안드로이드 23버전을 사용하여 제작하고 있다. 그리고 외부 라이브러리들을 사용하고 있었다. 이에 필요한 sdk들을 아래의 명령을 사용하여 설치하였다.

sdkmanager \
  "platform-tools" \
  "platforms;android-23" \
  "build-tools;23.0.3" \
  "extras;android;m2repository" \
  "extras;google;m2repository"

앞의 3가지는 앱 빌드에 필요한 안드로이드 sdk들이고, 뒤의 두 개의 extras는 안드로이드와 구글 리포지터리이다. 외부 라이브러리를 사용하면서 리포지터리를 이렇게 추가해주지 않으면 gradle을 실행했을 때 라이브러리들을 찾을 수 없다고 하며 오류가 발생한다.

안드로이드 스튜디오를 사용하지 않고 빌드를 해야 하는 상황이 되다보니 처음엔 막막했지만, gradle이 오류를 친절히 알려주어서 방향을 빨리 잡을 수 있었다.

이제 sdk를 설치했으니 sdk가 어디에 있는지 알려주어야 한다.

안드로이드 프로젝트의 최상위 디렉토리에 local.properties에 다음과 같이 적어주었다.

sdk.dir=/var/jenkins_home/android-sdk
ANDROID_HOME=/var/jenkins_home/android-sdk

이제 gradlew을 실행하면 빌드에 성공한다.

Gitlab with docker and setup ssl using letsencrypt on macOS

Docker image를 생성하고 실행한다.

컨테이너의 443, 80, 22 포트는 각각 Mac의 8443, 8080, 8022로 매핑해준다. 동일한 포트로 사용하기 원하면 443:443과 같이 써주면 된다.

sudo docker run --detach \
 --hostname gitlab.example.com \
 --publish 8443:443 --publish 8080:80 --publish 8022:22 \
 --name gitlab \
 --restart always \
 --volume /Users/[username]/apps/gitlab/config:/etc/gitlab \
 --volume /Users/[username]/apps/gitlab/logs:/var/log/gitlab \
 --volume /Users/[username]/apps/gitlab/data:/var/opt/gitlab \
 gitlab/gitlab-ce:latest

Letsencrypt 인증서 생성을 위해 certbot을 설치한다.

brew install certbot

certbot을 사용하여 인증서를 만들려고 시도하였다.

sudo certbot certonly --manual -d mydomain.org

하지만 augeas 와 관련된 오류를 만났다. 퍼미션 관련 설정을 해 주었다.

sudo chown [username] /usr/local/lib/pkgconfig

다시 certbot을 실행하여 인증서 생성을 시도하였다.

sudo certbot certonly --manual -d mydomain.org

접속할 수 있는 IP인지 물어본다. y로 대답한다.

Are you OK with your IP being logged?
----------------
(Y)es/(N)o:

생성할 파일의 내용과 경로를 알려준다. 준비가 되면 엔터를 치라고 한다.

Create a file containing just this data: 293487987fd9s87s98fa798s7df7sadf987saf79dsa97afsd897dsaf987 And make it available on your web server at this URL: http://mydomain.org/.well-known/acme-challenge/fas89adfs87dasf9asdf78

-----------------------------
Press Enter to Continue

해당 경로에 파일을 만들어주어야 하기 때문에 gitlab.rb를 편집한다.

vi /Users/[username]/apps/gitlab/config/gitlab.rb

다음 줄을 추가해 준다.

nginx['custom_gitlab_server_config'] = "location ^~ /.well-known { alias /etc/gitlab/www; }"

해당 내용을 적용해 준다.

docker exec -it gitlab /bin/bash gitlab-ctl reconfigure

그리고 아래의 경로에 해당 파일을 위에서 알려준 내용으로 만들어 주었다.

vi /Users/[username]/apps/gitlab/config/www/acme-challenge/[instructed filename]

파일내용:
293487987fd9s87s98fa798s7df7sadf987saf79dsa97afsd897dsaf987

다시 certbot을 실행한 shell로 돌아가서 Enter를 누른다.

이제 /etc/letsencrypt/live/[mydomain.org]에 인증서 파일들이 생겼다. ssl 디렉토리를 생성하고 인증서를 복사한다.

cd /Users/[username]/apps/gitlab/config
mkdir ssl
cd ssl
sudo cp /etc/letsencrypt/live/[mydomain.org]/fullchain.pem ./
sudo cp /etc/letsencrypt/live/[mydomain.org]/privkey.pem ./

다시 gitrab.rb를 편집하러 간다.

vi /Users/[username]/apps/gitlab/config/gitlab.rb

다음 3개의 줄을 편집해 준다.

external_url 'https://[mydomain.org]'
nginx['ssl_certificate'] = "/etc/gitlab/ssl/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/privkey.pem"

첫째 줄은 외부 접속 경로를 설정해 주는 것이다. 필자는 외부에서도 접속할 수 있게 하려고 하였기 때문에 개인적으로 사용하는 도메인 이름을 적어 주었다.

둘째, 셋째 줄은 인증서 파일에 대한 경로를 설정해 주는 것이다.

이제 준비가 되었다. 적용해 준다.

docker exec -it gitlab /bin/bash gitlab-ctl reconfigure

웹 브라우저를 띄우고 접속해 본다.

필자는 공유기 – MacOS – docker container(Ubuntu 16.04) 의 구조였고, 포트는 8443:8443:443이었으므로

https://[mydomain.org]:8443

으로 접속하였다. 자물쇠가 나오는 것을 확인하면 SSL이 제대로 설정된 것이다.

두서 없이 썼지만, 기억은 잘 잊혀지므로  기록하였다.

다음엔 letsencrypt 인증서 만료 기간이 3개월이니, 자동으로 갱신되도록 만들어 보아야겠다.