そこそこセキュアな自前 HackMD サーバー構築


TL;DL

  • HackMD とは
    • はい。HackMD
    • めっちゃ便利
  • HackMD のココが駄目
    • 画像を貼ると imgur に Upload される
      • いわゆる URL を知っているすべての人が閲覧できます状態
    • ノートは private にできるが設定し忘れると上の状態になる
  • やりたいこと
    • クラウドサーバー上に HackMD サーバーを立てる
    • SSL/TLS に対応させる
    • Basic 認証をいれる

使うもの

手順

サーバーの用意

  • 自分は Azure + Ubuntu 16.04 でやりました
    • Docker を使うのであまり関係ないと思います
  • Port 80, 443 を開けておく
  • FQDN を取得しておく

いろいろなファイルの用意

最終的な dirctory の中身

$ ls -la
-rw-r--r-- 1 suecharo suecharo  432 Jul 30 10:10 config.json
-rw-rw-r-- 1 suecharo suecharo  764 Aug  1 10:48 docker-compose.yml
-r--r--r-- 1 root   root   46 Jul 30 09:27 .htpasswd
-rw-r--r-- 1 suecharo suecharo 1228 Jul 30 09:28 nginx.conf

docker-compose.yml

  • GitHub Docker HackMD においてある docker-compose.yml ではやりたいことができなかったため書き換えた
    • 設定ファイル的に HTTPS 化はできそうだが、Basic 認証が難しそうだった
  • 一応、database と app_data は docker volume を使って永続化しておく
  • HackMD 自体の container は port を開けず、docker network を使ってやりとりをする
  • Let's encrypt を Host 上でやりたくない場合は、Nginx の container の中でやればいいと思う
docker-compose.yml
version: '3'
services:
  app:
    image: hackmdio/hackmd:latest
    restart: always
    environment:
      - HMD_DB_URL=postgres://hackmd:hackmdpass@database:5432/hackmd
    volumes:
      - ${PWD}/config.json:/hackmd/config.json
      - app_data:/hackmd
  database:
    image: postgres:9.6-alpine
    environment:
      - POSTGRES_USER=hackmd
      - POSTGRES_PASSWORD=hackmdpass
      - POSTGRES_DB=hackmd
    volumes:
      - database:/var/lib/postgresql/data
    restart: always
  nginx:
    image: nginx:latest
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - ${PWD}/.htpasswd:/etc/nginx/.htpasswd
      - ${PWD}/nginx.conf:/etc/nginx/nginx.conf

volumes:
  database:
  app_data:

.htpasswd

  • Basic 認証用
$ apt install -y apache2-utils
$ sudo htpasswd -c -b ${HackMD_dir}/.htpasswd ${user_name} ${Password}
$ sudo chmod 444 ${HackMD_dir}/.htpasswd

Let's Encypt

nginx.conf

  • nginx.conf の書き方自体は宗教がありそうなのであくまで一例として
  • ${your_fqdn} を扱いたい server のものに変える
nginx.conf
user nginx;
worker_processes auto;
error_log  /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log /var/log/nginx/access.log;
    sendfile on;
    keepalive_timeout 65;
    server_names_hash_max_size 1024;
    client_max_body_size 10M;

    server_tokens off;

    # include /etc/nginx/conf.d/*.conf;

    server {
        listen 80;
        server_name ${your_fqdn};
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 default ssl;
        server_name ${your_fqdn};
        ssl_certificate /etc/letsencrypt/live/${your_fqdn}/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/${your_fqdn}/privkey.pem;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        charset utf-8;
        auth_basic 'Secret Zone';
        auth_basic_user_file /etc/nginx/.htpasswd;

        location / {
            proxy_pass http://app:3000;
        }
    }
}

conf.json

config.json
{
    "production": {
        "allowAnonymous": false,
        "allowAnonymousEdits": false,
        "defaultPermission": "editable",
        "email": true,
        "db": {
            "username": "hackmd",
            "password": "hackmdpass",
            "database": "hackmd",
            "host": "database",
            "port": "5432",
            "dialect": "postgres"
        },
        "imageUploadType": "filesystem"
    }
}

起動・動作確認

$ docker-compose up -d
  • 初回時,docker-compose の起動順序の問題で network error が発生することが稀によくある
    • 再度、docker-compose up -d をすれば良い
  • ブラウザで https://${your_fqdn}/ にアクセスする