Dojoサーバー構築!

さくらインターネットさんのご厚意により、各Dojo毎にインスタンスがひとつ提供されるというニュースが流れたのを見た方も結構おられるとは思いますが、今回はCoderDojo調布のインスタンスセットアップで行った事を備忘録的に書いてみたいと思います。

TL;DR

ログイン設定

割り当てられたインスタンスにログインして、真っ先にした事は各ユーザーの公開鍵の登録でした。Dojoインスタンスでは公開鍵認証のみになっているので(チャレンジパスワードを使えるようには出来ます)、使用する人は公開鍵の登録が必要です。最初はインスタンスの申請者の鍵だけが登録されているので、使用する人から送って貰った公開鍵を登録します。登録された公開鍵に対する秘密鍵が設定されているターミナルからログインすることが出来ます。

次に、共通アカウントの常時共用はよろしくないので、普段使う人のアカウント作成を行いました。その中で管理者となる人のアカウントのsudoの設定を行います。

ここで失敗

インスタンスの設定で必要の無いポートを閉じようと思い、iptablesを叩いてしくじりました。Dojoに提供していただいているインスタンスはコンソールが使えないので、二進も三進も行かなくなり、一旦削除申請→削除の後に再申請しました。副産物として、代理申請のサンプルを作ることが出来ました。

コンソールが使えないのでiptablesはノータッチにしましょう

APT初期設定

次に、インストール直後の状態のAPTとパッケージを更新します。

$ sudo apt-get update
$ sudo apt-get upgrade

これで、APTデータベースと、インストールされているパッケージが最新になります。

PHP7.1インストール

PHPのバージョン番号を指定してインストールする環境を構築します。*1
まずは、APTにリポジトリを追加するためのリポジトリ追加ツールをインストールします。

$ sudo apt-get install -y software-properties-common python-software-properties

ツールがインストールされたらPHPのリポジトリを追加します。

$ sudo add-apt-repository ppa:ondrej/php

リポジトリが追加されたらAPTデータベースを更新し、バージョンを指定してPHPをインストールします。

$ sudo apt-get update
$ sudo apt-get install -y php7.1
$ php -v
PHP 7.1.7-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Jul  7 2017 09:41:45) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache
v7.1.7-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2017, by Zend Technologies

PHPのインストールが終わったら、nginxから使うためにFPMをインストールします。

$ sudo apt-get install php7.1-fpm

node.js環境構築

次にnode.jsを使えるようにします。Ubuntuに標準で入っているnode.jsではなくて、「n」というツールでStableバージョンをインストールします。まず、Ubuntuの標準のnpmと、nodejsをインストールします。しかし、APTでそのまま入れるととんでもなく古いのがインストールされ、その後にnpmが動かなくなるのでもうちょっと新しいものが入るように設定します。

curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -

その後に、nodejsをインストールします。

$ sudo apt-get -y install npm nodejs

インストール後に、npmを更新します。

$ sudo npm i -g npm

次にnode.jsのバージョン管理ツール「n」をインストールします。*2

$ sudo npm i -g n

これで「n」が使えるようになります。この「n」を使ってnode.jsをインストールします。

$ sudo n stable

インスト〜ルが終わったらバージョン確認をします。

$ node -v
v8.2.1

Stableのバージョンであれば成功です。この後はUbuntuのnodejsは必要ないので削除しておきます。

$ sudo apt-get purge nodejs

nginxインストール

Ubuntuの標準でインストールされるnginxはだいぶ古いので、最新版をインストールするための設定を行います。*3
まずはnginxのPGPキーをAPTに登録します。

$ sudo curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -

次にリポジトリを追加します。

「/etc/apt/sources.list」の最後に、下記の2行を追記してください。

deb http://nginx.org/packages/ubuntu/ xenial nginx
deb-src http://nginx.org/packages/ubuntu/ xenial nginx

「xenial」の部分はディストリビューションによって変わります。
具体的には「/etc/lsb-release」の「DISTRIB_CODENAME」の文字列になります。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial

リポジトリの追加が終わったら、APTデータベースを更新しnginxをインストールします。

$ sudo apt-get update
$ sudo apt-get install nginx

まず、「/var/run/php/php7.1-fpm.sock」があることも確認しておきます。 次にPHP7.1が使えるようにnginxを設定します。「/etc/nginx/conf.d/default.conf」に下記を追記します。

location ~ ^/~([^/]+)/(.+\.php)$ {
  alias /home/$1/public_html/$2;
  fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
  fastcgi_index index.php;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  include fastcgi_params;
}

location ~ ^/~(.+?)(/.*)?$ {
  alias /home/$1/public_html$2;
}

location ~ \.php$ {
  alias   /var/www/html;
  fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
  fastcgi_index index.php;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  include fastcgi_params;
}

location / {
  root   /var/www/html;
}

また、Dojo名のサブドメイン(調布の場合は「chofu」)を登録してもらっている場合は、「server_name」も変更しておきます。

server_name  chofu.coderdojo.jp;

Let's Encryptを設定する

nginxでHTTPSを使用するために、Let's Encryptの設定を行います。*4

Let's Encryptで使うツール「certbot」をAPTでインストールするために、certbotのリポジトリをAPTに登録します。

$ sudo add-apt-repository ppa:certbot/certbot  

登録が終わりましたら、APTデータベースを更新し、certbotツールをインストールします。

$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx

正常にインストールが終わりましたら、証明書を取得します。 certbotがポート80を使うのでnginxを止めておきます。

$ sudo service nginx stop

nginxが正常に停止した後、証明書を取得します。

$ sudo letsencrypt certonly --standalone -d [FQDN]

[FQDN]には、HTTPSを設定するFQDNを入れてください。

実行すると、

Saving debug log to /var/log/letsencrypt/letsencrypt.log  
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):

と訊かれるので、有効なメールアドレスを入力してください。メールアドレスを入力すると、

Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org  
    
-------------------------------------------------------------------------------  
Please read the Terms of Service at  
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree  
in order to register with the ACME server at  
https://acme-v01.api.letsencrypt.org/directory  
-------------------------------------------------------------------------------  
(A)gree/(C)ancel:

と訊かれるので、「A」を入力してリターンを押してください。リターンを押すと、

-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o:

と訊かれるので通常は「N」を入力してリターンを押してください。
すると、次のように表示されて、「/etc/letsencrypt」ディレクトリが生成されます。

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for chofu.coderdojo.jp
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/chofu.coderdojo.jp/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/chofu.coderdojo.jp/privkey.pem
   Your cert will expire on 2018-06-03. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

次に、「/etc/nginx/conf.d/default.conf」に設定を追記します。
port443で待ち受ける設定と、証明書の読み込みを追記します。
ドメイン部分は各Dojoで変更してください。

listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/chofu.coderdojo.jp/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chofu.coderdojo.jp/privkey.pem;

これでhttpsでの待ち受けは出来るのですが、port80に来たアクセスを強制的に443に転送する場合は、下記も追記してください。

if ($scheme != "https") {
    return 301 https://$host$request_uri;
}

nginxを再起動すると設定が反映されます。

$ sudo service nginx restart

let's encryptの証明書は有効期限が3ヶ月と短いので、毎月1日に自動更新するようにcronに設定します。

0 4 1 * * /usr/bin/certbot renew && /usr/sbin/service nginx reload

gitbucketの起動

Dojoで使っているコードの管理をするためにgitbucketをインストールしました。
gitbucketのReleaseページから「gitbucket.war」をダウンロードしてきます。

github.com

ダウンロードが終わりましたら実行します。

$ java -jar gitbucket.war --port=8000

「--port」はポート番号の指定です。CoderDojo調布ではメンター連絡用にSlackを使用し、インテグレーションとしてポート8080を使う「hubot」を動かすため、gitbucketのデフォルトポート「8080」から「8000」に変更しています。アクセスする時は、

http://[設定したFQDN]:8000

とします。nginxの管理下に無いのでHTTPSにはなりません。nginxでProxyの設定をするとHTTPSに出来るかもしれません。

マインクラフトマルチサーバーを起動

マインクラフトはデフォルトではポート25565を使うので、iptablesでポートを開放します。

$ sudo iptables -A INPUT -p tcp --dport 25565 -j ACCEPT

マインクラフトマルチサーバーは、マインクラフトのオフィシャルからダウンロードし設置するだけで起動出来ますが、プラグインを簡単に使えるようにするために「Spigot」サーバーをビルドして設置します。

BuildToolsは実行したディレクトリにファイルを大量に生成するため、まず最初に作業用ディレクトリを作成し中に入ります。そして「BuildTools」を取得します。

$ wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar

BuildToolsのダウンロードが終わりましたら、バージョン(リヴィジョン)を指定してサーバーアプリをビルドします(結構時間がかかります)。

java -jar BuildTools.jar --rev latest

上記の例だと現在の最新安定版がビルドされます。 バージョン番号を指定するには下記のようにします。

java -jar BuildTools.jar --rev 1.12.1

終了すると「Spigot-[バージョン番号].jar」というファイルが生成されていれば成功です。 このファイルをマインクラフト用のディレクトリにコピーし実行します。サーバーアプリも実行したディレクトリに大量にファイル/ディレクトリを生成するので、マインクラフト用のディレクトリを切って、その中で実行してください。

java -jar -Xms512M -Xmx1024M ./Spigot-[バージョン番号].jar &

オプションは使用するメモリ量の指定です。Dojoサーバーではこれより多いとメモリが足りなくなり、Spigotが落ちます。マルチサーバーが起動出来ると、マインクラフトのマルチでDojoサーバーのアドレスへ繋ぐことが出来ます。ホスト名を登録してもらっている場合はそのアドレス(CoderDojo調布の場合は「chofu.coderdojo.jp」)で繋ぐことが出来ます。

hubot関連

CoderDojo調布では、メンター連絡用にSlackチームを作成し、hubotを使い各種連携を行なっています。これはまた別で書きたいと思います。

*1:参考:意外とPHPのバージョンを指定してUbuntuにインストールする方法が載ってないのでまとめる

*2:ここで「node」が無いとエラーになる場合があります。その場合は「sudo ln -s /usr/bin/nodejs /usr/local/bin/node」を実行してください。

*3:参考:Ubuntuに最新のnginxをインストールする

*4:参考:How To Secure Nginx with Let's Encrypt on Ubuntu 16.04 | DigitalOcean