Confluence, Jira, Bitbucket의 systemd unit 설정

In 네트워크와 시스템 관리 by Choi Kyung-sik

2012년 즈음에 Confluence, Jira, Stash(Bitbucket의 이전 이름)를 데비안 시스템에 TAR.GZ Archive 파일을 사용하여 처음 설치하였다. 시작 스크립트는 공식적인 지원 대상이 아니고 그에 대한 문서의 내용도 부실해서 직접 만들어야 했다. Confluence, Jira, Stash가 Tomcat을 사용했기 때문에 데비안 6.0(Squeeze)의 Tomcat 6을 참고하여 init.d 스크립트를 작성했었다. Tomcat과 같이실제 제작자(upstream)의 소프트웨어는 데비안 개발자가 데비안의 정책에 맞게 패키지를 만든다. init.d 스크립트를 작성할 때 그것에 맞게 하려고 했고 아래에 나올 내용인 사용자와 그룹 생성, 설치 디렉토리와 홈 디렉토리가 그를 반영한 것이다.

데비안 8(Jessie)에서 systemd가 디폴트 시작 시스템으로 완전히 들어왔다. 한동안 데비안 7(Wheezy)에서 업그레이드를 해야 할지 주저했던 기억이 난다. 그러나 systemd는 SysV 스크립트 파일을 분석하고 변환하는 방식으로 하위 호환성을 제공하였다. 내가 작성한 구식의 스크립트는 살아남을 수 있었다.

최근에 MySQL에서 PostgreSQL로 옮기는 작업을 진행하면서 init.d 스크립트도 버리기로 하였다. 관리의 측면에서 Confluence, Jira, Bitbucket의 서비스 설정은 init.d 스크립트보다는 systemd unit 설정 파일이 더 낫다. 업그레이드되면서 환경 변수 등이 변한다면 init.d 스크립트도 이를 반영해야 할 경우가 생기기 때문이다.

사용자와 그룹 생성

보안상의 이유로 데몬(서비스)은 root 관리자 계정으로 실행하지 말아야 한다. 보안 취약점을 이용하여 악의적인 사용자가 root 권한이 있는 데몬을 사용한다면 시스템에 재앙을 가져온다. 따라서 서비스는 일반 사용자로 실행하여야 한다.

Confluence 서비스에서 사용할 confluence 그룹과 confluence 사용자를 생성하기 위해 다음과 같이 한다.

# groupadd confluence
# useradd confluence -M -g confluence -d /opt/share/confluence -s /bin/false

위의 useradd 명령어에서 -d 옵션으로 홈 디렉토리는 지정하지만 -M 옵션으로 홈 디렉토리를 생성하지 않는다. confluence 사용자는 서비스 실행만을 위해 존재하기 때문에 홈 디렉토리를 생성할 필요는 없다. 마찬가지로 로그인 시 사용할 쉘을 지정하는 -s 옵션에서 /bin/false로 하여 로그인을 허용하지 않는다. jira와 bitbucket도 위의 confluence가 나온 부분을 대체하여 사용자와 그룹을 만들어 줄 수 있다.

데비안의 tomcat6 패키지와 비교해 보자.

# cat /etc/passwd | grep tomcat6
tomcat6:x:109:115::/usr/share/tomcat6:/bin/false
# cat /etc/passwd | grep confluence
confluence:x:1002:1002::/opt/share/confluence:/bin/false

사용자와 그룹을 한꺼번에 삭제하고 싶다면 ‘deluser’ 명령어를 사용한다. 다음의 명령어는 stash 사용자와 그룹을 한 번에 제거한다.

# deluser stash
설치 디렉토리와 홈 디렉토리

Confluence, Jira, Bitbucket을 어느 디렉토리에 설치하는 것이 좋을까? 데비안 개발자가 패키지를 만들면서 신경 쓰지 않는 /opt, /srv, /usr/local, /home 디렉토리가 적당해 보인다. 나는 위의 사용자 생성에서 보듯이 /opt/share 디렉토리 안에 confluence, jira, bitbucket으로 선택했다. 데비안에서 운영체제에 종속적이지 않은 Tomcat 같은 패키지는 /usr/share 디렉토리에 들어간다. 그래서 /opt/share로 하였다. 이것은 취향의 문제로 여러분은 다른 곳에 설치할 수 있다.

보안 측면을 짚어 보기 위해 좀 더 살펴본다. Download Confluence Server, Download Jira Software Server, Download Bitbucket Server에서 TAR.GZ Archive 파일을 다운로드 할 수 있다. 다운로드한 파일을 /opt/share로 복사한 후 다음의 작업을 한다. 여기서는 Confluence만 예제로 보인다. Jira와 Bitbucket도 confluence가 나온 부분을 jira와 bitbucket으로 변경하여 같은 작업을 할 수 있다.

# cd /opt/share
# tar zxvf atlassian-confluence-<version>.tar.gz
# mv atlassian-confluence-<version> confluence
# chown -R root:root confluence
# chown -R confluence:confluence confluence/logs
# chown -R confluence:confluence confluence/temp
# chown -R confluence:confluence confluence/work

보안을 강화하기 위해 라인 4에서 7까지 파일의 소유자와 그룹을 설정하였다. confluence 사용자로 실행하는 Confluence 데몬은 logs, temp, work 디렉토리에만 쓰기 권한을 가진다. 다른 곳은 사용자와 그룹을 root 소유로 설정하였기 때문에 confluence 사용자로 실행하는 서비스는 파일을 저장할 수 없다.

데비안의 Tomcat 패키지 방식으로 하려면 몇 가지 작업을 더 해야 한다. logs, work 디렉토리는 /var/lib/confluence 안에 들어가야 하고 temp 디렉토리는 /tmp 안에 위치해야 한다. 그러나 이 디렉토리들은 중요도가 떨어지고 업그레이드할 때마다 해주기 번거롭기 때문에 그렇게까지는 하지 않았다.

Confluence, Jira, Bitbucket은 데이터를 사용자가 설정하는 홈 디렉토리에 저장한다. 어디로 설정하는 것이 좋을까? /var 디렉토리는 변하는 데이터를 저장하는 곳이기에 적당하다. 데비안의 패키지는 /var/lib 디렉토리를 사용한다. 나는 /var/local/lib 디렉토리 안의 confluence, jira, bitbucket으로 설정했다. /var/local은 데비안 개발자가 관심을 두지 않는 곳이기 때문에 선택했다. 이 역시 취향 문제다.

Confluence의 홈 디렉토리를 생성하기 위해 다음과 같이 한다. Jira와 Bitbucket도 confluence가 나온 부분을 변경하여 같은 작업을 할 수 있다.

# mkdir -p /var/local/lib/confluence
# cd /var/local/lib
# chown confluence:confluence confluence
# chmod g-s confluence

mkdir 명령어의 -p 옵션은 상위 디렉토리인 lib가 존재하지 않을 때 생성하라는 의미이다. 라인 3에서 confluence 사용자로 실행하는 Confluence 데몬이 쓸 수 있도록 사용자와 그룹의 소유주를 confluence로 설정한다. 라인 4는 /var/local/lib/confluence 디렉토리의 스티키 비트(sticky bit)를 사용하지 않으므로 제거한 것이다. 데비안에서 /var/local 디렉토리는 그룹에 스티키 비트가 설정되어 있어서 디렉토리나 파일을 생성하면 스티키 비트가 붙는다.

추가로 데이터베이스를 만들고 홈 디렉토리 설정 등을 한다면 Confluence, Jira, Bitbucket을 설치할 준비를 마친 것이다. 이제 이 글의 주제인 systemd unit 설정으로 넘어가자.

systemd unit 설정

시스템의 전원을 켜면 복잡한 여러 부트 단계를 거쳐 PID=1을 가지는 init 프로그램이 실행된다. init 프로그램은 모든 프로세스의 최상위 조상이고 시작 시 필요한 프로그램을 실행한다. 데비안 jessie 이후로 init 프로그램인 /sbin/init은 /lib/systemd/systemd에 대한 심볼릭 링크이다. systemd init 프로세스는 다음의 디렉토리에서 unit 설정 파일을 읽어 들여 병렬적(parallel)으로 프로세스들을 생산한다. 병렬적이기 때문에 기존의 순차적인 SysV init보다 빠르다.

  • /lib/systemd/system : 운영체제의 디폴트 설정 파일
  • /etc/systemd/system : 시스템 관리자의 설정 파일
  • /run/systemd/system : 실행 시간에 만들어지는 설정 파일

unit 설정 파일의 접미사에 따라 서비스(.service), 장치(.device), 마운트(.mount), unit 설정 파일의 그룹(.target) 등 다양한 타입이 있다. Confluence, Jira, Bitbucket의 서비스를 위해 /etc/systemd/system 디렉토리 안에 .service로 끝나는 unit 설정 파일을 만들 것이다.

Confluence의 unit 설정 파일인 /etc/systemd/system/confluence.service의 내용은 다음과 같다.

[Unit]
Description=Atlassian Confluence
After=network.target

[Service]
Type=forking
User=confluence
PIDFile=/opt/share/confluence/work/catalina.pid
ExecStart=/opt/share/confluence/bin/start-confluence.sh
ExecStop=/opt/share/confluence/bin/stop-confluence.sh

[Install]
WantedBy=multi-user.target

프로그램의 흐름을 따라가는 절차적인 SysV init 스크립트와 비교하면 unit 설정 파일은 선언적으로 이해하기 쉽다. unit 설정 파일은 윈도우 운영체제의 .ini 확장자를 지닌 설정 파일에서 사용하는 문법을 사용한다. 대괄호의 절(section)로 시작하여 한 줄마다 ‘변수=값’으로 이루어진다. 변수는 지시자(directive)라 부른다. unit 설정 파일은 [Unit], [Install] 절을 기본적으로 가져야 한다. 서비스 unit 설정 파일은 추가로 [Service] 절을 반드시 포함해야 한다.

[Unit] 절은 unit의 일반적인 정보를 지닌다. 라인 2의 Description 지시자에는 unit의 원하는 이름을 넣어준다. 종속성 지시자인 After는 먼저 실행돼야 하는 unit을 지정한다. Confluence는 웹 서버이므로 시스템의 네트워크 설정이 먼저 이루어지는 것이 필요하다. 따라서 라인 3에서 네트워크 관련 unit들은 모아 놓은 network.target을 설정한다.

[Install] 절은 unit을 설치하기 위한 정보로 systemd가 사용하지 않는다. 아래에서 볼 systemctl의 enable과 disable에서 이 절을 사용하여 심볼릭 링크를 만들거나 삭제한다. SysV의 런레벨과 비슷한 것으로 multi-user.target은 런레벨 2에서 4에 해당한다. ‘ls -al /lib/systemd/system/runlevel*‘ 명령어로 확인해 볼 수 있다.

[Service] 절은 서비스 unit을 위한 것이다. 라인 6의 Type=forking은 라인 9의 ExecStart에서 설정한 start-confluence.sh가 fork()를 호출할 것임을 의미한다. 전통적인 UNIX 서비스가 행동하는 방식으로 Tomcat도 이처럼 한다. Type을 forking으로 한다면 PIDFile의 설정을 권고하고 있다. 라인 8에서 Confluence가 사용하는 Tomcat의 PID 파일의 위치를 설정한다. 라인 10의 ExecStop에서 서비스 종료에 사용할 파일을 지정한다. 라인 7에서 서비스를 실행할 사용자로 confluence를 설정한다.

Jira의 unit 설정 파일은 다음과 같다.

[Unit]
Description=Atlassian Jira
After=network.target

[Service]
Type=forking
User=jira
PIDFile=/opt/share/jira/work/catalina.pid
ExecStart=/opt/share/jira/bin/start-jira.sh
ExecStop=/opt/share/jira/bin/stop-jira.sh

[Install]
WantedBy=multi-user.target

Bitbucket의 unit 설정 파일은 다음과 같다.

[Unit]
Description=Atlassian Bitbucket
After=network.target

[Service]
Type=forking
User=bitbucket
PIDFile=/opt/share/bitbucket/work/catalina.pid
ExecStart=/opt/share/bitbucket/bin/start-bitbucket.sh
ExecStop=/opt/share/bitbucket/bin/stop-bitbucket.sh

[Install]
WantedBy=multi-user.target
systemctl 사용한 unit 설정의 활성화, 시작, 종료 등

다음에서 Confluence에 대한 명령문의 실행 예만 든다. Jira와 Bitbucket도 confluence가 나온 부분을 jira와 bitbucket으로 변경하여 실행할 수 있다. 명령문 실행에서 서비스를 나타내는 .service 접미사는 생략할 수 있다. 예를 들면 confluence.service 대신 confluence를 사용하여 타이핑을 줄일 수 있다. bash에서 <TAB> 키로 자동 완성 기능을 사용한다면 큰 의미는 없다.

unit 설정 파일을 새로 만들었거나 변경했다면 systemd가 그것을 알 수 있게 다음의 명령어를 실행한다.

# systemctl daemon-reload

시스템 부팅 시에 서비스를 실행하려면 다음의 명령어를 실행한다. [Install] 절의 WantedBy 지시자 값으로 설정한 multi-user.target의 디렉토리에서 심볼릭 링크로 연결된다.

# systemctl enable confluence.service
Created symlink /etc/systemd/system/multi-user.target.wants/confluence.service → /etc/systemd/system/confluence.service.

다음의 명령어로 서비스를 시작(start), 종료(stop)하고 서비스의 상태(status)를 본다.

# systemctl start confluence.service
# systemctl stop confluence.service
# systemctl status confluence.service

서비스에 문제가 발생하면 다음의 명령어를 실행하여 무엇이 문제인지 확인해 본다.

# journalctl -xe
관련 소스 코드

Confluence, Jira, Bitbucket의 init.d 스크립트

참고 자료