• 모두를 위한 모바일 네트워크, dokupe.

    IT 기술이 전 세계에 녹아들기 시작한 후로부터, 우리 일상의 온라인 서비스 의존도는 점점 더 높아지고 있다. 점점 더 많은 전화 통화와 메시지를 주고받으며, 점점 더 복잡한 일을 인터넷으로 처리한다. 하루가 다르게 지구를 뒤엎는 데이터 패킷의 양은 늘어나고 있다. 밀접한 네트워크 엑세스는 어느 순간 우리에게 너무나 당연한 것이 되었고, 한 순간이라도 네트워크 엑세스 없이 일상을 보낸다는 것은 상상하기 어려운 일이 되고 있다. 그런데, 이 ‘만약’ 이라는 상황은 언제나 예기치 못한 때 찾아온다. 단순히 자연재해나 정전 등이 원인이 될 수도 있고, 더 나아가서는 정치적인 목적을 위해 국가 주도로 네트워크 사용을 차단하거나 악의적인 집단에 의해 공격받아 장기간 사용 불능이 될 수도 있다. 비현실적적으로 느껴질 수도 있지만, 이미 세계의 여러 국가에서 경험했고, 일부는 지금도 경험하고 있는 상황이다.

    물론 해외 이야기까지 꺼내지 않더라도, 우리는 충분히 많은 네트워크 단절 사태를 경험했지 않은가. 지난 2011년 대규모 정전사태는 물론이고, 2014년 모 통신사의 가입자 확인 모듈 장애로 발생한 전국적인 통신 장애나, 2016년 발생한 경주 지진으로 해당 지역 일대의 통신망이 과부화된 일 등 기억을 되돌려보면 이미 다양한 원인으로 발생하는 통신 장애는 그리 낯선 것이 아니다.

    그럼 우리가 할 수 있는 일은 뭘까? 끔찍한 일이 터지지 않게 기도하며 정부와 통신사만 응원할 것인가? 하나의 방법이 될 수는 있지만, 필자는 조금 더 능동적인 솔루션을 생각하고 있다. 외부 단체나 자원에 의존하지 않으며, 익숙한 방식으로 기초적인 음성통화, 메시징, 데이터 통신이 가능한 모바일 네트워크를 만들어보려 한다. 이런 모바일 네트워크는 10여년 전에는 통신사의 전유물이였지만, 이제는 힘없는 개인도 충분히 들일 수 있을 정도의 (비교적) 저렴한 하드웨어와, 여러 오픈소스 소프트웨어들이 온라인에 공개되어 있다. 적당히 응용하면 전통적인 고정식 기지국을 넘어 라즈베리 파이 등의 소형 컴퓨터를 활용해 들고 다닐 수 있는 기지국을 만들 수도 있을 것이다.

    위에서는 예기치 못한 상황에서 사용할 수 있는 백업 네트워크의 역할을 강조해서 설명했지만, 더 나아가 개인적으로는 사회에 모종의 메시지를 남길 수 있지 않을까 생각하고 있다. 네트워크는 엄연히 공공재의 성격을 띠어야 한다. 일부 주도권을 가진 사람들이 자신들의 이익을 위해 타인의 정보 접근을 제한해서는 안된다는 말이다. 이미 망 중립성이라는 개념도 존재하지만, 유지/보수와 사업 이익의 문제점 등 현실의 벽 때문에 쉽게 실현되지는 않고 있다. 다만, 통신사들은 더 이상 네트워크가 단순히 자신들의 사업 아이템만은 아니라는 것을 상기할 필요가 있다. 마치 전기와 수도를 사용하는 것처럼, 네트워크는 사회적 계층에 상관없이 누구나 사용하는 필수 자원의 범위에 완전히 들어왔다. 외부적인 요인을 가져와 국민들의 정보 접근을 제한하게 된다면 이는 우리 모두의 교육에 대한 기회를 박탈하는 것과 같고, 보이지 않는 손으로 눈과 귀를 막아버리는 것과 같다. 사업 아이템과 공공재 사이의 균형을 맞추지 않는다면, 일개 개인이라도 직접 나서서 독자적인 통신망을 구축할 수 있다는 것을 보여주고 싶다. 더 나은 미래를 위해, 누군가는 움직여야 한다.

    앞으로의 진행 상황과 관련된 기술적인 내용들은 이 GitHub 페이지와 공식 프로젝트 페이지 에서 확인할 수 있을 것이다.

  • Jenkins로 Docker 이미지 배포 자동화하기

    오늘날 개발되고 상용화된 대부분의 서비스들은 어떤 천재 혼자 뚝딱 만들어 낸 것이 아니다. 다양한 특기를 가진 다양한 사람들이 함께 품어 만들어낸 불교의 사리 같은 것이다. 그리고 자연스럽게 가뜩이나 어려운 일의 중간 과정이 진짜 알맹이를 가로막지 않도록 여러 도구와 개념들이 등장했는데, 그 중 하나가 지속적으로 코드의 품질을 관리할 수 있고, 또 나아가 배포까지 이어질 수 있는 CI와 CD (Continuous Integration / Continuous Delivery)다. 내가 작성한 코드를 그대로 내 컴퓨터에서 테스트하고 사용한다면 아무 상관 없는 이야기겠지만, 여러 팀원이 함께 코드를 작성하는 환경에서는 각종 이슈와 신규 배포의 진행사항을 기록하는 일도 필요하고, 내가 사용하지 않는 개발환경을 요구하는 코드를 빌드할 일도 생긴다. 이런 여러가지 문제를 다 내려놓고. 일단 귀찮다. 하루이틀도 아니고 이 모든 일들을 매일 반복한다고 생각해보자. 말 그대로의 주객전도다.

    위에서 언급한 CI와 CD의 개념은 이런 문제들을 해결하기 위해 탄생했다. 그리고 가장 대중적인 도구로 Jenkins를 뽑을 수 있겠다. 이미 전세계 다양한 팀에서 Jenkins를 사용해 자신들의 코드를 자동 빌드하고, 테스트하고, 변경점을 기록하고 있다. 필자는 어딘가의 팀에서 개발자로 활동하고 있지 않지만, 평소 취미 목적으로 만드는 소프트웨어들을 개인 노트북에서 코딩해 Docker 이미지로 빌드한 후, Docker Hub 저장소를 통해 개인 서버들로 전송해 구동하는 과정을 자주 거치고 있어 귀차니즘을 참지 못하고 Jenkins에 손을 대게 되었다.

    DinD (Docker-in-Docker)


    지금부터 하나 재미있는 시도를 해보자. 바로 Jenkins를 Docker 컨테이너로 구동한 후, 그 컨테이너 안에 또 Docker 데몬을 구동해 도커 안의 도커 환경을 만들어 볼 거다. Jenkins 컨테이너가 자체적으로 Docker 이미지를 생성할 수 있게 만드는 거다. Git에 새로운 코드를 커밋하면 Jenkins가 이를 감지하고 자동으로 Docker 이미지를 생성해, 업로드까지 해주는 구성을 해보자.

    필자는 관련 정보를 검색하던 중 발견한 Seapy님의 Docker 이미지를 사용했다. Docker Hub에 공개된 여러 이미지들을 테스트해봤으나 이 이미지가 가장 깔끔하고 사용하기 편해 그대로 사용하고 있다. 다른 이미지를 사용할 예정이거나, 혹은 직접 이미지를 빌드해 사용하고 싶다고 해도 기본적인 설정 방법은 같으니, 참고하길 바란다.

    호스트 컴퓨터에서, 아래 명령어를 통해 이미지를 다운받고 실행해보자.

    docker run -p 연결할_포트번호:8080 -v 연결할/경로:/var/jenkins_home --privileged seapy/jenkins-dind:1.554.3
    

    위의 연결할_포트번호에는 웹 브라우저에서 접근 시 사용할 포트번호를, 연결할/경로에는 Jenkins 컨테이너의 /var/jenkins_home 폴더와 연결될 호스트 컴퓨터의 폴더 경로를 입력한다. Docker 컨테이너는 일반적으로 컨테이너가 변형될 경우 안의 데이터의 안전을 장담할 수 없는 구조라 이렇게 호스트 컴퓨터의 폴더를 연결해두면 컨테이너에 문제가 생겨도 데이터는 안전하게 지킬 수 있다.

    중간에 다른 문제가 발생하지 않았다면, 정상적으로 컨테이너가 구동되고 웹 브라우저로 Jenkins에 접근도 잘 될 것이다. 사용한 이미지가 조금 연식이 있어 (마지막 업데이트가 년단위 전이다…) Jenkins도 구버전이 구동되어 있을 것인데, 사실 이 상태로도 정상적인 사용은 가능하다. 귀찮은 사람은 이대로 사용하고, 최신 버전을 사용하지 못하면 온몸에 가시가 돋는 얼리어답터 분들은 docker execattach 명령 등을 통해 해당 컨테이너에 Java8를 설치한 후 웹 콘솔에서 업데이트 버튼을 누르면 된다. 최신 버전의 Jenkins는 Java8를 요구하는데, 이 이미지에 설치된 구버전은 Java7만 사용하고 있기 때문이다. 꼭 기억하길 바란다. 컨테이너는 일종의 프로세스 개념이라, Java8이 없어 다운받은 업데이트 파일을 정상적으로 구동하지 못할 경우 컨테이너가 그대로 꺼져버린다. 괜히 삽질하지 마시길.

    자, 그대로 사용하시던 혹은 업데이트를 하셨던, 이제 우리의 알맹이를 공략하자. Jenkins 웹 콘솔에서 새로운 Item 버튼을 타고 프로젝트 생성 페이지로 넘어가보자. 프로젝트 이름을 입력하고, Freestyle project를 누르면 된다.

    혹시 최신 버전의 Jenkins로 업데이트한 후, 새로운 Item 버튼을 누르면 빈 페이지만 보일 경우, Jenkins 관리 -> 플러그인 관리 메뉴에 들어가 External Job Monitor을 최신 버전으로 업데이트하면 된다. 이 버그리포팅을 참조하면 도움이 될 것이다.

    상세 구성을 할 수 있는 페이지가 나올건데, 소스 코드 관리 라는 항목에서 Git을 선택하고 자신의 저장소 URL과 인증 정보 등을 입력한다. 필자는 BitBucket을 연동할 생각이기에 그 아래 항목의 빌드 유발 항목에서 Build when a change is pushed to BitBucket 을 선택했다.

    필자처럼 BitBucket을 사용할 경우 프로젝트 생성 전 Jenkins 관리 -> 플러그인 관리 메뉴에서 BitBucket 플러그인을 미리 설치해둬야 한다. 설치하지 않을 경우 위 항목이 보이지 않는다.

    아래의 빌드 항목에는 직접 실행 가능한 쉘 명령어를 입력할 수 있는데, 아래처럼 이미지 생성 후 업로드하는 명령어를 지정하면 된다.

    docker build -t 저장소명/이미지명 .
    
    docker push 저장소명/이미지명
    


    모두 설정을 마쳤을 경우 아마 위 이미지와 비슷할 것이다. 저장을 눌러 빠져나오자.

    이제 테스트 타임이다! 코드에 변경점을 준 뒤 Git에 업로드한 뒤 두근두근 기다리면 된다. 정상적으로 과정을 따라왔다면, 아마 별 문제 없이 빌드와 배포 과정이 진행될 것이다.

    자동화 별 것 없네

    수고하셨다. 자동화 생각보다 별 것 없다. 여러분은 약간의 시간을 투자하여 매일 반복하는 지루한 작업을 줄인 참된 인간이 된 것이다. 이 글에서는 Docker 이미지의 자동 빌드 & 배포만 예시로 들었지만, 이 환경을 기반으로 어떤 종류의 자동화도 할 수 있으니 이제 본인 편의에 맞게 커스터마이징 해나가면 된다.

    Knock ‘em dead!

  • 라즈베리 파이로 Docker Swarm 클러스터 만들기

    사실 처음부터 이 프로젝트를 하려고 한 건 아니였다. 혼자 시작한 프로젝트라면 자비로 모든 하드웨어를 사들여야 하는데, 필자가 그럴 돈이 어디 있는가. 그런데 우연히 학교에서 지원금 빵빵히 받아 프로젝트를 진행하던 친구가 기술 자문 겸 노가다꾼으로 초대해 주면서 열심히 노동하고 왔다. 사실 라즈베리 파이로 클러스터 만들어 가지고 노는 사람들은 이전부터 유튜브 등지에서 종종 봐 왔었고, 관심이 없는 것은 아니였기에 필자에게도 좋은 기회가 아니였나 싶다.

    프로젝트의 목표는 저비용 + 저전력 + 작은 공간에서 분산 컴퓨팅 환경을 직접 구축하고 체험하는 것이다. 물론 이 작은 ARM 보드가 몇개 더 모인다고 해서 프로덕션 단계의 애플리케이션을 돌리는 건 어렵고, AWS 등의 상용 클라우드 서비스를 사용하는 편이 훨씬 더 간단하고 강력하지만, 직접 그와 비슷한 환경을 구축해본다는 것 자체에 의미를 뒀다.

    piluster

    개발자의 본업은 이름 짓는 것이라고 종종 말해왔지만, 이번에는 도저히 시간을 투자할 수 없었다. 나는 한번의 작업을 위해 고속버스를 타고 슝슝슝 달려와야 하는 입장이라 도착도 하기 전에 피로가 한가득 쌓여있었고, 작업 중에도 역시나 생각하지도 않은 문제들이 펑펑 터져나와서 작명이라는 고도의 문학적이고 감성적인 일은 어려웠다. 결국 그냥 라즈베리 파이 + 클러스터 라고 해서 piluster로 퉁 쳤다. 당장 부를 이름이 없는데 어쩌겠는가 :).


    사용한 장비는 위와 같다. 라즈베리 파이 3 5대, 짱짱하고 싼 마이크로 5핀 5개, 외부 전원 공급이 가능한 USB 허브, 그리고 적당한 공유기, 스위칭 허브 (물론 인터넷에서 USB OTG만을 통한 클러스터 구축 방법도 보긴 했지만, 여기서는 가장 범용적인 방법을 선택했다.)

    각 파이에는 당시 최신 버전의 Raspbian Jessie LITE와 Docker Engine이 설치되었다. 이 곳이 곳에서 설치 정보를 참고할 수 있다.

    중간 과정

    사실 이전에 이미 Docker Swarm에 대해 작성한 글이 있다. 그러기에 자세한 내용은 언급하지 않겠으나, 최소한의 구축 방법만 적으려 한다.

    Leader로 삼을 라즈베리 파이에서 docker swarm init 명령어를 통해 Swarm 클러스터를 시작할 수 있다. 아마 아래와 같은 출력값이 나올 것이다.

    Swarm initialized: current node (gjm2fxwcx29ha4rfzkw3zskvt) is now a manager.
    
    To add a worker to this swarm, run the following command:
    
        docker swarm join \
        --token xxx \
        ip_address:2377
    
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
    

    저 중 docker swarm join으로 시작하는 출력값을 잘 복사해뒀다, worker로 삼을 파이들에 접속 후 입력하자. 그러면 고맙게도 알아서 차곡차곡 Swarm 클러스터에 노동자로 붙게 된다. 모두 끝났다면, Leader 노드에서 docker node ls 명령어를 입력해 제대로 클러스터가 구성되었는지 확인하자.

    ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
    aaa *  rpi-01   Ready   Active        Leader
    bbb    rpi-02   Ready   Active
    ccc    rpi-03   Ready   Active
    ddd    rpi-04   Ready   Active
    eee    rpi-05   Ready   Active
    

    위와 비슷하게 출력된다면 별 문제 없다는 뜻이다.

    이제 클러스터가 묶였으니, 가장 중요한 애플리케이션을 올려볼 차례다. ARM용으로 빌드된 어떤 이미지라도 클러스터에 올릴 수 있지만, 필자는 편의상 직접 만든 divergence 웹 애플리케이션을 사용했다. 별도의 DB를 연결할 필요도 없어 여러모로 간편했기도 하고 말이다.

    원하는 이미지를 worker 노드에 다운로드 받은 후, 아래 명령어를 통해 서비스를 생성해보자.

    아래 명령어에 추가로 집어넣을 수 있는 옵션들은 여기에서 확인할 수 있다.

    docker service create --name 서비스_이름 -p 외부포트:내부포트 만든이/이미지_이름:1(컨테이너 갯수)
    

    생성 후에는 docker service ls 명령어로 전체 서비스 목록을, docker service ps 서비스_이름 으로 원하는 서비스의 자세한 정보를 볼 수 있다.

    ID            NAME      IMAGE              NODE     DESIRED STATE  CURRENT STATE            
    id  서비스_이름.1  만든이/이미지_이름:1  rpi-01  Running        Running 3 seconds ago
    

    위와 같이 정상적으로 서비스가 구동된 것을 확인한 후, curl이나 웹 브라우저 등을 통해 미리 지정한 포트로 접근을 해 보면 정상 가동되고 있는 것을 확인할 수 있다.

    여기서 잠깐, 클러스터에 서비스가 딱 한 컨테이너로 실행되고 있는 상태에서 간단한 퍼포먼스 테스트를 해보았다. 사용한 툴은 apib. 소개 그대로 심플한 http 퍼포먼스 테스팅 툴이다. macOS에서 brew를 통해 간단히 설치할 수 있었다.

    60초간 100명의 가상 접속자를 만들어 라즈베리 파이를 괴롭힌 결과, 아래와 같은 값을 얻었다.

    흠. 인터레스팅 하다. 무선 네트워크 간섭 등 여러가지 장애물이 껴 있어 신뢰도 높은 값이라고는 절대 지칭하지 못하겠지만, 추후 부하분산 상태에서의 값과 비교할 가치는 충분히 있어 보인다. 자 그럼, 바로 다음 값을 측정할 준비를 해보자.

    방금 우리가 측정한 서비스는 컨테이너 1개로 돌아가고 있었다. 다시 말해, 클러스터를 묶지 않은 상태와 다를 것이 없다는 뜻이다. 다행히 Swarm 클러스터는 정말 간편하게 이미 돌아가는 서비스의 부하분산 설정을 할 수 있다. 아래 명령어를 따라와 보자.

    docker swarm scale 서비스_이름=컨테이너_갯수
    

    위에서 입력한 숫자만큼 내 서비스의 컨테이너 갯수가 늘어난다. Leader 포함 5개의 노드로 구성된 (Swarm 모드에서의 Leader 노드도 동시에 worker처럼 컨테이너를 돌릴 수 있다.) 클러스터에서 5를 지정하면 각 노드마다 하나씩의 컨테이너가 자동으로 자리잡게 된다. 그렇다고 한 노드에 하나의 컨테이너만 들어갈 수 있는 것은 아니라, 그 이상의 숫자도 얼마든지 지정 가능하다. 이 글에서는 편의를 위해 1노드 1컨테이너. 즉, 5개까지만 복제시켰다.

    docker service ls 명령어 등을 통해 모든 컨테이너가 정상적으로 구동되고 있는 것을 확인했다면, 다시한번 퍼포먼스 테스트를 해볼 차례다. 위 단일 컨테이너 테스트와 동일한 조건값으로 진행하였다.

    오호라. 확실히 평균 지연시간부터 최소 지연시간까지 모두 줄어든 것을 볼 수 있다. 위와 비교해 엄청나게 늘어난 초당 요청 횟수를 통해 여러 컨테이너로 부하분산이 되었다는 것을 확인할 수 있다. 조그만한 라즈베리 파이라도 클러스터링을 통해 확실한 퍼포먼스 향상을 꾀할 수 있다는 것을 직접 눈으로 봤다.

    마무리

    위에서 언급했던 것처럼, 이제는 대부분의 경우에서 물리적 서버 환경을 직접 구축하는 것보다 상용 클라우드 서비스를 사용하는 것이 훨씬 경재적이고 강력한 시대가 되었다. 더군다나 비 x86 아키텍처에 성능도 떨어지는 라즈베리 파이 놀음은 전혀 쓸모없는 짓처럼 보일지도 모른다.

    하지만, 아무리 훌륭하고 편한 솔루션들이 무수히 존재한다고 하더라도 이런 본질로 돌아가보는 행위가 가끔씩은 꼭 필요하다고 생각한다. 다 떠나서 손바닥 위의 작은 컴퓨터 보드 여러대가 네트워크를 타고 하모니를 이루는 광경을 직접 만들고 느끼는 건 정말로 황홀하지 않는가. 저렴한 가격과 적은 전기, 그리고 정말 적은 공간에서 분산 컴퓨팅을 직접 체험해본다는 취지는 훌륭하게 달성한 것 같다. 표면적인 데이터 측정은 끝났으니, 이제 더욱 Geek처럼 가지고 놀 일만 남았다.

  • 라즈베리 파이를 이용한 OpenVPN 환경 구축하기

    이제 VPN 기술은 일부 IT 종사자들의 전유물이 아니게 되었다. 당장 국내에서 가장 대중적으로 판매되는 대부분의 공유기에도 기본적으로 이 기능이 탑재되고 있고, 인터넷 검열국가 대한민국에서 ‘국민에게 해로운 자료를 거른다’ 라는 말 아래에 뭉텅뭉텅 잘려나가는 콘텐츠들을 보기 위해 선택하는 길이기도 하다. 이렇게 겉으로 보기에는 우리 삶에 깊숙히 다가운 VPN이지만, 과연 그 속은 어떨까?

    VPN 터널을 구성해주는 프로토콜은 여러가지가 있지만, 현재 세계에서 가장 대중적인 것은 PPTP다. VPN에 대해 평소 잘 모르는 분들도 이 이름은 한번쯤 들어봤을 거다. 당장 위에서 언급한 대부분의 공유기에 내장된 VPN 서버 기능이 바로 이 프로토콜만을 지원하기도 하고 말이다. 대중화된 만큼 설정법도 간단하고, 정보도 많다. 더 이상의 장점은… 언급하기 어렵다. 다른 문제는 일단 다 내려놓고, VPN의 생명인 보안 문제가 너무너무 크기 때문이다. 개인적으로 암호보안 쪽의 전문가는 아니지만, PPTP의 키 교환 알고리즘이 지금 시점에서는 너무나 간단해서 슝 뚫려버린다 라고 알고 있다. 심지어 애플의 최신 iOS와 macOS에서는 연결 지원 자체를 끊어버렸을 정도. 그러니 아직까지 PPTP를 사용 중인 분들, 또는 앞으로 개인 VPN 서버를 구성하고 싶으신 분들은 한시빨리 대체제를 찾아야 한다.

    L2TP/IPSEC이라는 좋은 선택지도 있고, 다른 훌륭한 프로토콜도 많이 존재하지만 이번에 필자가 꺼낼 것은 OpenVPN이다. 오픈소스에, 안전하고, 대부분의 현대 운영체제를 지원하며, 보안 인증도 상당히 간편하다. 필요할 때 작동시킬 수 있는 컴퓨터만 있다면 다른 준비물은 필요 없다. 다만 필자는 아무래도 설치되는 컴퓨터는 언제나 접속이 가능해야 하는 서버 역할을 해야 하고, 전력과 공간 부분에서 이득을 볼 수 있는 라즈베리 파이를 선택했다. 아래에 후술할 메뉴얼도 라즈베리 파이를 위해 설계된 자동화 도구를 사용할 것이다. 다른 OS나 장비를 사용하시는 분들은 개념 참고만 해주시면 감사하겠다.

    탈바꿈

    반복적인 단순 작업은 지루하고 재미없다. 중간에 정신 놓고 실수를 벌릴 확률도 커진다. 처음 라즈베리 파이에 VPN 서버를 구성하려 할 때 이런 걱정부터 앞섰는데, 다행히 누군가 PiVPN 이라는 자동화 프로젝트를 완성시켜 두었다. 아래 명령어를 통해 바로 내 라즈베리 파이에 다운로드받아 보자.

    curl -L https://install.pivpn.io | bash
    

    미리 PiVPN 측에서 인스톨 스크립트를 잘 만들어둔 덕에, 손가락 빨며 기다리면 된다.


    설치 과정 중 따로 스크린샷을 찍지 못해 이 문서의 자료를 일부 가져왔습니다.

    아마 조금 기다리면 위와 같은 설정 인터페이스가 출력될 것인데, 시키는데로만 하면 된다. 더 이상의 스크린샷은 첨부하지 않겠다. 사용할 네트워크 인터페이스 (유선의 경우 기본 eth0)을 선택하고, 연결에 사용될 네트워크 프로토콜 (UDP 권장)을 고르고, 연결 포트와 암호화 수준, 기본 DNS 서버 정도만 딸깍딸깍 선택해주면 순식간에 끝난다. 아 정확히 말하면 완전 순식간은 아니고, 라즈베리 파이의 불쌍한 연산처리 능력으로 키 암호화를 하느라 조금 걸릴 수는 있다.

    인스톨러를 따라 모든 설정 후 리부팅까지 마쳤다면, sudo apt-get upgrade를 통해 새로 설치된 패키지들이 제대로 최신 버전으로 설치되었는지 확인해 주자.

    이제 정말로 남은 것은 내 OpenVPN 서버에 연결할 수 있는 계정을 추가해주는 일이다. pivpn add 명령어를 통해 간단히 ID와 비밀번호를 집어넣고 계정이름.ovpn으로 끝나는 접속 암호화 키를 받을 수 있다. 이 과정까지 완료되었다면 생성된 ovpn 파일을 내가 사용하는 기기로 옮겨주자. (scp 파일전송을 가장 권장하고, 전통적인 ftp 등 선호하는 방법으로 옮기면 된다.) 만약 라즈베리 자체의 소프트웨어 방화벽 & 상단에 공유기가 존재한다면, 꼭 포트를 열어주는 작업도 잊지 말기 바란다.

    라즈비안의 기본 소프트웨어 방화벽 (iptables) 기준으로, 아래 명령어를 통해 방화벽 룰 포워딩이 가능하다.

    sudo /sbin/iptables -P FORWARD ACCEPT
    sudo /sbin/iptables --table nat -A POSTROUTING -o eth0 -j MASQUERADE
    

    작업을 마쳤다면, root 계정으로 전환 후 아래 명령어로 영구 저장하자. (저장하지 않으면 재부팅 시 방화벽 룰이 기본값으로 복구된다.)

    iptables-save > /etc/iptables/rules.v4
    

    연결

    OpenVPN이라는 이름답게 정말 다양한 플랫폼의 다양한 연결 클라이언트를 선택할 수 있다. 필자의 경우 iOS에서는 공식 OpenVPN 클라이언트 (앱스토어에서 내려받을 수 있다), macOS에서는 Tunnelblick를 애용하고 있다. 클라이언트는 이것 외에도 정말 다양하게 많이 존재하지만, 모두 공통적으로 준비한 ovpn 파일을 선택하고, 설정한 비밀번호만 입력해주면 된다. 본인 취향에 맞추어 원하는 클라이언트를 사용할 것.

  • SMB를 사용하는 macOS Time Machine 백업 서버 만들기


    애플의 macOS는 Time Machine 이라는 환상적인 백업 솔루션을 지원한다. ‘타임 머신’ 이라는 이름에 걸맞게, 각 백업 시점의 스냅샷을 찍어 나중에 언제라도 원하는 시점으로 슝 돌아갈 수 있는 놀라운 녀석이다. 문제는 또 애플 아니랄까봐, 본격적으로 기능 사용을 위해서는 요런 비싸고 성능 떨어지는 물건을 사야 한다는 거다. 애플의 Airport 라우터 시리즈는 정말 최악이다. 가격은 하늘을 찌르는데 유저 편의는 손톱만큼도 신경 쓰지 않는다. NAT 규칙 하나를 변경하기 위해 풀 리부팅이 필요하다고 하면 믿겠는가.

    저걸 살 돈이면 이름있는 브랜드의 새로운 4K 모니터를 마련할 수도 있다. 그럼 어떻게 할까? 백업을 하지 말아야 할까? 아니다. 모든 시스템에는 예외없이 백업이 필요하다. 지갑을 여는 대신, 공돌이 기질을 아낌없이 뽑아내 DIY 원격 백업 시스템을 만들어 보자.

    준비물

    필자는 RAID 5 디스크가 연결된 Ubuntu 16.04 LTS 로 동작하는 서버를 사용했다. 비슷한 사용 환경을 구축할 수 있는 어떤 Linux 배포판이나 디스크라도 상관 없다. 다만, 어디까지나 백업 데이터가 저장되는 서버인 만큼 안정성을 제 1순위로 생각하여 잘 준비하도록 하자.

    그리고 시작하기 전 “왜 애플 기기의 백업 데이터 전송인데 AFP가 아니라 SMB를 사용하지?” 라고 의문이 들 수도 있을 것인데, 애플은 이미 OS X 매버릭스 시절부터 기본 파일 전송 프로토콜을 AFP에서 SMB2로 변경했다. 프로토콜별 퍼포먼스 차이를 자세히 꿰고 있지는 않지만, 기존 AFP보다 SMB2가 의미 있을 정도로 빠르고 효율적이라는 판단이 나와 변경을 감행한 것 같다. 물론 아직 Time Machine 백업은 AFP를 계속 사용하고 있는 것 같고 SMB를 사용하면 여러모로 귀찮아 지는 건 사실이지만, AFP를 Linux에서 사용할 수 있게 해주는 최신 버전의 netatalk가 자체 이슈가 해가 넘어가도록 픽스되지 않고 있어 일종의 편법을 소개하려 한다. 애플이 직접 공인한 SMB2 프로토콜을 사용해 더 나은 속도로 백업을 진행할 수 있기도 하고 말이다.

    Samba 서버 세팅하기

    이미 유닉스 계열 OS들의 파일 공유 표준은 Samba가 자리를 차지하고 있다. 알고 있을수도 있지만, 윈도우에서 사용되던 SMB (Server Message Block)을 다시 구현해 오픈소스화 시킨 소프트웨어다. 위에서 파일 공유의 표준 자리를 차지하고 있다고 한 만큼 이미 많은 Linux 배포판의 패키지 관리 도구들에서 빠르게 설치할 수 있도록 준비를 마쳐뒀다.

    sudo apt-get install samba samba-common-bin
    

    그럼 바로 Ubuntu 배포판 기준으로, 위 명령어를 통해 필요한 소프트웨어를 먼저 설치하도록 하자.

    다음으로 SMB를 통한 접속에 사용할 계정을 만들 거다. 기존 유닉스 계정과는 별개로 취급해야 하니 나중에라도 햇갈리지 말 것.

    sudo smbpasswd -a 유저명
    

    위 명령어로 진행할 수 있다.

    이제 Samba 서버의 설정을 조금 만져주면 된다. 정말 별로 안 남았다. 설정 파일의 경로는 /etc/samba/smb.conf 다. 선호하는 에디터로 해당 파일을 열었으면, 아래를 참고해 주시길 바란다.

    #======================= Global Settings =======================
    
    [global]
    
    ## Browsing/Identification ###
    
    # Change this to the workgroup/NT-domain name your Samba server will part of
       workgroup = WORKGROUP
    
    # server string is the equivalent of the NT Description field
    	server string = %h server (Samba, Ubuntu)
    
    # Windows Internet Name Serving Support Section:
    # WINS Support - Tells the NMBD component of Samba to enable its WINS Server
    #   wins support = no
    
    # WINS Server - Tells the NMBD components of Samba to be a WINS Client
    # Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
    ;   wins server = w.x.y.z
    
    # This will prevent nmbd to search for NetBIOS names through DNS.
       dns proxy = no
    
    ...
    
    

    아마 위와 같은 설정 스크립트가 쫘르륵 나올 것인데, 분량에 겁먹지 말고 찬찬히 읽어보면 전혀 어려울 건 없다. 나머지는 딱히 안 건들어도 되고, 아래의 내용만 [global] 태그 아래에 추가해주자.

    path = 내가_공유할_저장경로
    valid users = 유저명
    writable = yes
    

    공유 프로토콜을 수동 설정하고 싶을 경우 (SMB의 버전 등), 아래의 내용을 넣으면 된다.

    min protocol = SMB1
    max protocol = SMB3
    

    위는 최소 사용 프로토콜을 SMB1, 최대 프로토콜을 SMB3로 설정한 예시다. 본인의 입맛에 맞게 적당히 수정해서 사용하자.

    쉽다. 사실 이 설정 파일에서 공유 경로의 접근 퍼미션도 설정할 수 있긴 한데, 개인적으로는 chown 등의 명령어를 통해 따로 설정하는 것을 추천한다. 이런 중요한 설정은 특정 소프트웨어에 의존성이 생기면 영 좋지 않다.

    모두 저장하고 나왔으면, 이제 아래 명령어로 Samba 서버를 가동해보자.

    sudo systemctl enable smbd
    sudo systemctl start smbd
    

    방화벽을 사용중일 경우, SMB 프로토콜의 기본 포트인 445를 허용해주자. Ubuntu 기준 sudo ufw allow 445 명령어다. 추가적으로 서버 상단에 공유기 등이 달려있다면 알아서 허용해주도록 하자.

    이제 접속할 클라이언트 장비에서 우리 서버로 접속 테스트를 해보자. macOS 기준 아래 독 바의 Finder 아이콘 오른쪽 클릭 -> 서버에 연결 -> 나오는 주소창에 smb://서버주소 로 접속 가능하다. 아래 이미지를 참고하자.


    계정 정보를 물어볼 때는 처음에 설정했던 SMB 전용 계정을 입력하자. 유닉스 계정과 햇갈리지 말고.

    짠. 제대로 진행했다면 아마 정상적으로 접속이 될 것이다. 이제 SMB를 사용하는 파일 서버는 완성되었다. 그럼 Time Machine 백업은 어떻게 할까?

    Time Machine 백업 이미지 만들기

    사실 OS X 매버릭스 시절부터 기본 파일공유 프로토콜이 SMB2로 변경되었다고 해도, 그대로 SMB 파일 서버를 Time Machine 백업 서버로 지정할 수는 없다.(또는 어렵다. 구글링을 열심히 해 봐도 관련 정보가 정말 드물다.) 그래서 우리는 약간의 꼼수를 쓸 꺼다. 바로 별도의 백업 이미지를 만들어 SMB 서버에 담는 것. 이렇게 하면 비단 SMB뿐만 아니라 어떤 종류의 파일공유 프로토콜을 사용하는 서버에도 Time Machine 백업이 가능하다. 마음껏 응용해주면 좋겠다.

    이미지를 만들기 전, 아래 명령어로 지원하지 않는 네트워크 드라이브로의 Time Machine 백업을 허용해주자. 사실 ‘지원하지 않는 네트워크 드라이브’ 라는 말과 달리 여전히 AFP를 통한 파일 서버가 아니면 아무 설정 없이 Time Machine 유틸리티에 드라이브가 뜨지 않는다. 필자도 처음에 기대했었는데 그게 아니더라. 그래서 우리가 별도의 이미지를 만드는 것이다. 이 명령어를 입력해줘야 이미지를 통한 꼼수 백업이라도 가능해지니 눈물을 흘리며 엔터를 누르자.

    sudo defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1
    

    이제 정말로 이미지를 생성하기 위해 아래의 명령어를 입력하자. 입력하기 전 cd 명령어로 생성을 원하는 경로로 이동 후 진행하면 더 좋다.

    sudo hdiutil create -size 300g -type SPARSEBUNDLE -fs "HFS+J" TimeMachine.sparsebundle
    

    명령어를 읽어보면 알겠지만, 직접 최대 용량과 파일 시스템 등을 지정해줄 수 있다. 적당히 본인에게 맞게 수정하도록 하자. 그리고 혹시라도 300GB의 이미지를 생성하면 바로 300GB를 떡하니 차지하고 있는 것은 아닐지 걱정하지 않아도 된다. macOS의 sparsebundle은 일종의 동적 디스크라, 용량이 들어올수록 점점 늘어난다. 다시 말해, 처음에는 작다는 말이니까 용량 걱정은 하지 말자.

    이제 이미지가 정상적으로 모습을 보일 것인데, 이걸 아까 연결해둔 SMB 서버에 올리기만 하면 끝이다. Finder 창을 연 후 쭉 끌어 놓아주자.

    전부 다 올라갔다면, 이제 서버 위에 있는 이미지를 더블클릭해 마운트해 보자. 약간의 시간이 지나면 둥 하는 소리와 함께 좌측에 내 이미지가 외장 디스크처럼 마운트되어 있는 것을 볼 수 있다.

    이제 백업할 시간이다. 다시 터미널을 열어, 아래 명령어로 Time Machine 백업 경로를 강제 지정해주자. 이렇게 안 해주면 인식을 못하더라. 슬프게.

    sudo tmutil setdestination /Volumes/TimeMachine
    

    이제 Time Machine 유틸리티를 실행하면 정상적으로 우리의 이미지가 안녕 하고 손을 흔들어줄 것이다. 남은 것은 백업 단추를 누르고 커피라도 한잔 마시고 오는 것. 백업이 끝나면 일반적인 외장 디스크를 마운트 해제하는 것처럼 추출 버튼을 누르면 된다. 나중에 백업을 할 때는 위와 마찬가지로 마운트만 해주면 되고.

    처음 Time Machine 백업을 돌릴 때는 저어어어엉말 느리다. 컴퓨터의 말 그대로의 모든 것을 백업해야 하니 이해는 가지만, 그래도 느리다. 이유는 애플이 백업 중에도 다른 작업에 지장이 가지 않게 일종의 리밋을 걸어뒀기 때문.

    느린 속도에 속이 터진다면 아래 명령어로 쓰로틀을 풀어주자. 만약 재부팅할 경우 자동 적용 해제되니 참고하시길.

    sudo sysctl debug.lowpri_throttle_enabled=0
    

    눈에 띄게 속도가 향상됬다면 씩 웃어주자.