Install gitlab on docker with systemd

1. Install docker

$ sudo apt-get install docker.io
$ sudo service docker start
# Add user into docker group to use docker command without sudo.
$ sudo adduser <username> docker

2. Pull gitlab community edition image

$ docker pull gitlab/gitlab-ce

3. Configure systemd service

[Unit]
Description=Gitlab in docker.
After=docker.service
Requires=docker.service

[Service]
Restart=always
ExecStartPre=-/usr/bin/docker rm gitlab-ce
ExecStart=/usr/bin/docker run --rm \
          --name gitlab-ce \
          --volume /srv/gitlab/config:/etc/gitlab \
          --volume /srv/gitlab/logs:/var/log/gitlab \
          --volume /srv/gitlab/data:/var/opt/gitlab \
          --publish 80:80 --publish 2222:22 \
          gitlab/gitlab-ce
ExecStop=/usr/bin/docker stop gitlab-ce

[Install]
WantedBy=local.target
$ sudo systemctl enable gitlab-docker

When dokku asking for password

I installed Docker and dokku for fun.
It is correctly works on my sub-laptop when I copy ~/.ssh/id_rsa.pub and run sudo sshcommand acl-add dokku <nickname> but not on my server.
I did same progress on my server, but git, ssh says require password.

So I thoght a few hours. then I relized I changed my ssh daemon’s configuration. I block all users who is not in the ssh group. so I add dokku account to ssh group and tried again. and FAILED.

Finnaly I set password to dokku account. and tried again. ssh and git works WITHOUT PASSWORD.
Maybe the ssh client has failed to login with ssh-key so ask me a password. so I opened /etc/shadow file to find out what happened.
Only the root and dokku has ! on password field. and other non-password account have * on it.

I don’t know what it is for. but it works when I changed ! to *.


심심해서 Docker를 설치하고 dokku까지 설치해봤다.
그런데 실험삼아 서브노트북에 설치한 dokku는 ~/.ssh/id_rsa.pub을 복사해서 sudo sshcommand acl-add dokku <nickname> 해주면 git push 명령도 잘 먹고 ssh [email protected]<hostname> 해주면 정상적으로 접속이 끊기지만 서버컴에 설치한 dokku는 아무리 id_rsa.pub 파일을 집어넣어도 자꾸 패스워드를 물었다.

무슨 차이일까 가만히 생각하다가 내가 서버에는 SSH 데몬의 설정을 건드린 것이 생각났다. 특정 그룹에 있지 않으면 SSH 접속조차 막아뒀다. 그래서 dokku 계정을 ssh 그룹에 추가해줬는데도 결과는 마찬가지였다.

결국 포기하는 마음으로 dokku 계정에 패스워드를 설정하고 접속해봤다. 그런데 마법같이 패스워드를 묻지도 않고 접속이 되었다. 아마 패스워드가 없는 계정은 접속을 막았는데 클라이언트에서 ssh-key로 접속이 안되니 패스워드를 물어본 것 같다. 그래서 /etc/shadow 파일을 잠깐 열어보니 패스워드가 없는 계정은 패스워드 부분에 적힌 값이 두 가지로 나뉘어 있었다. 하나는 *이고 하나는 !인데 다른 계정들은 대부분 *을 사용했는데 root와 dokku만 !를 사용했다. 그래서 혹시나 하고 *로 바꿔보았는데 잘 작동이 되었다.

*!의 차이를 찾아봤는데 다들 기능적으로 똑같다고만 말하고 !는 보통 패스워드가 있던 계정을 사용 못하게 할 때, *는 패스워드가 지정된 적이 없는 계정에 그렇게 적는다고 말한다. 하지만 dokku를 사용해보니 실제로 차이가 있었다.

Apache2에서 Nginx로 갈아탔다.

여태 개인 서버에 Apache2로 워드프레스 블로그도 돌리고 HTML 호스팅도 하고 mod_wsgi를 이용해서 Flask 앱도 올려놓고 했었다. Nginx가 뜬지는 한참 됐는데 계속 갈아타려다가 실패했었다. 그러다가 오늘 완전히 옮겼는데 삽질한 과정을 써놔야 다음에 또 삽질하지 않을 것 같다.

PHP가 실행되지 않고 그냥 원문이 보일 때

index.php에서 /wordpress/로 리다이렉트를 시켜놨는데 얘가 작동을 안하고 HTML이 출력되서 보니 PHP 소스가 그대로 나타나있었다. 그런데 이상하게도 워드프레스 블로그는 PHP인데도 잘 돌아가는 걸 보고 눈치를 챘다. PHP는 태그를 열 때 <?만 쓸 수도 있고 <?php로 쓸 수도 있는데 앞의 것은 short open, 뒤의 것을 full open이라고 한다.

원래 Apache2에서는 PHP를 그냥 사용했지만 Nginx로 갈아타면서 php-fpm을 사용하게 됐는데 이게 설정파일이 다른 위치에 있다. /etc/php5/fpm/php.ini를 열고 short_open_tag = On으로 바꿔주면 된다.

Rewrite engine

글을 쓴지 좀 지난 지금 wordpress의 RSS 피드가 작동하지 않는 걸 깨달았다. Apache2는 .htaccess 파일을 이용해 URL을 멋대로 꼬을 수 있지만 nginx는 그게 안되기 때문에 수동으로 적어줘야 한다.

location /wordpress {
    try_files $uri $uri/ /wordpress/index.php?q=$uri&$args;
}

위와 같이 적어주면 feed도 작동하고 permalink도 잘 작동 한다.

uWSGI 사용

uwsgi를 pip로 깔았다가 아주 고생했다. 참고로 pip로 설치하면 얘가 컴파일을 하기 때문에 uninstall을 해도 uwsgi 실행파일은 남는다. 수동으로 지워주자. 난 이걸로 2시간 삽질 한 것 같다.

그냥 우분투니까 편하게 sudo apt-get install uwsgi 해주면 설치는 끝난다. 설정파일은 대충 아래와 같이 써놓으면 sudo service uwsgi start 명령으로 간단하게 컨트롤 할 수도 있어서 굉장히 편하다.

[uwsgi]
chdir = /var/wsgi
uid = www-data
gid = www-data
chmod-socket = 666
socket = /tmp/ertest.sock
virtualenv = /var/wsgi/venv
plugin = python
wsgi-file = /var/wsgi/ertest.wsgi

여러 개의 가상호스트를 만들 시 duplicated listen options라는 에러가 뜰 때

ertest.kjwon15.net을 earthreader의 데모 인스턴스로 띄워놓아야 하기 때문에 아파치의 vhost처럼 설정을 했는데 얘가 자꾸 같은 포트에 바인딩하지 말라고 찡찡댄다. 왜 그런가 찾아보니 옵션 중 ipv6only=on 부분을 지워버리면 된다. 아직 고쳐지지 않은 버그인가본데 난 그냥 ipv6 부분의 한 줄을 아예 지워버렸다.

Sub-directory에 WSGI 앱 장착하기

그냥 루트 디렉터리에 WSGI 앱을 달면 문제가 없지만 서브디렉터리에 달면 아파치의 mod_wsgi와는 다르게 full-path를 넘겨줘서 문제가 생긴다. 아래와 같이 설정을 추가하면 된다. (가장 아래의 두 줄)

location /earthreader {
    include uwsgi_params;
    uwsgi_pass unix:/tmp/earthreader.sock;
    uwsgi_param SCRIPT_NAME /earthreader;
    uwsgi_modifier1 30; 
}

basic auth 걸기

엄청 간단하다. 아래와 같이 적으면 끝난다. (가장 위의 두 줄)

location /earthreader {
    auth_basic "Personal RSS reader";
    auth_basic_user_file /var/wsgi/earthreader.htpasswd;
    include uwsgi_params;
    uwsgi_pass unix:/tmp/earthreader.sock;
    uwsgi_param SCRIPT_NAME /earthreader;
    uwsgi_modifier1 30; 
}

WSGI 앱의 sub-directory에 basic auth 걸기

난 kjwon15.net/autotweet/에는 암호를 걸지 않고 kjwon15.net/autotweet/teach/에만 암호를 걸어놓고 사용했다. nginx는 nested directory를 지원한다. 아래와 같이 쓰면 된다.

P.s: nested directory 안에서도 설정을 일일히 적어줘야 한다. nginx의 구조상 그렇다는데 왜 그렇게 만들었는지는 의문이다.

location /autotweet {
    location /autotweet/teach {
        auth_basic "Restricted area";
        auth_basic_user_file /var/wsgi/earthreader.htpasswd;

        include uwsgi_params;
        uwsgi_pass unix:/tmp/autotweet.sock;
        uwsgi_param SCRIPT_NAME /autotweet;
        uwsgi_modifier1 30;
    }
    include uwsgi_params;
    uwsgi_pass unix:/tmp/autotweet.sock;
    uwsgi_param SCRIPT_NAME /autotweet;
    uwsgi_modifier1 30;
}