無料で最強のクラウドノート環境を手に入れる

# 最強の無料クラウドノートとは

自分がクラウドノートに求めていた条件

 - デバイス間同期
 - マークダウンで書ける
 - コードブロックのシンタックスハイライト
 - 高度な検索
 - ブラウザからアクセス可能
 - カラーセットのカスタマイズ
 - プラグインによる拡張
 - Vimキーバインド
 - バージョン管理

とまぁいろいろあったんですが、これを無料で実現するのは今まで無理でした。
というか有料でもあるのか分からん…

が！最近、一見関係のない2つの記事を読んで閃いてしまいました。

 - [ブラウザでVS codeが使えるクラウド IDEの大本命「Coder」](https://qiita.com/MegaBlackLabel/items/bbec97db769667962bce)
   - (上記を自前ホストできるのがこちら→) [code-server](https://github.com/codercom/code-server)
 - [GCPで永久無料枠を利用してサービスを立ち上げたときにしたことの備忘録](https://qiita.com/riku-shiru/items/a870edd9dc0b132e092c)


**(あれ？自分の求めてるクラウドノート、8割がたVSCodeで出来るやん？)**
・
・
・
**(ていうかcode-server使ってクラウドに乗せれば[^1]10割出来るやん？)**
・
・
・
**(ていうかGCPならコンテナ1個動かす程度の環境を無料で手に入るやん？)**
・
・
・

勝ったわ。これは大勝利だわ。


# 最強の作り方

## 結局何するの？
要するにGCPの永久無料インスタンスにcode-serverブチ込んで、
Dockerコンテナとして起動して色々設定して使います。

<img width="1473" alt="Screen Shot 2019-04-21 at 2.46.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128115/e234c583-446d-b8ed-5533-9206ea7f0670.png">



## 作り方

結論から言うと、流石に永久無料枠(microインスタンス)だけだと
メモリ足りずに起動できませんでした＼(^o^)／

というわけで、本題以外にスワップ領域の設定が挟まって以下のような流れになります。

 - GCPの永久無料インスタンスを一個立ち上げる
 - Dockerをインストール
 - HDDスワップ領域を1GB~2GBほど確保
   - SSDじゃないので少しもっさりする、しかしそこは「無料」の魅力で十分カバーできる
 - クラウドノートとして使うための設定をする
 - Gitをインストール(Optional)


あ、お金積める人ならインスタンスタイプmicroじゃなくて
smallを選んでメモリ1.7GB確保すればスワップ要らないよ。

あとGCPは最初の1年結構な額の無料枠があるので、
無料期間が終わるまではマシンパワー増強して賄うのもあり。

というわけで早速GO!

## 永久無料のマシンを1個貰う

もうどんだけ丸投げするんだよって話ですが、
[GCPで永久無料枠を利用してサービスを立ち上げたときにしたことの備忘録](https://qiita.com/riku-shiru/items/a870edd9dc0b132e092c)
の「IPアドレスを固定する」までを参考に、無料枠でインスタンスを一個立ち上げます。
HTTPSはチェック有効にして、ポート443が通信できるようにしておきましょう。

## Dockerをインストール

立ち上げた直後のVMにはDockerが入ってないのでインストールします。

(GCP詳しくない人向け)VM一覧の赤枠のところをポチるとブラウザからSSHできます。
<img width="985" alt="Screen Shot 2019-04-14 at 1.24.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128115/14ba6f60-5f32-603c-d092-ea50f19004df.png">
 
SSH後、以下コマンドを実行

```bash

sudo curl -fsSL get.docker.com -o get-docker.sh && sh get-docker.sh && sudo gpasswd -a $USER docker && sudo docker run hello-world && rm -f get-docker.sh
```

コマンドは[Linux に Docker を一発インストールするワンライナー](https://qiita.com/KEINOS/items/bdc9450c1a88c210aa88)より拝借。

## スワップ領域の確保

```bash
# スワップがないことを確認 (Swap: 0 0 0 となっているはず)
free -m

# スワップファイルを作成。とりあえず2GBあれば十分すぎるほど足りるだろう
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# スワップができたことを確認 (Swap: 2047 0 2047 となっているはず)
free -m

# サーバーが再起動してもスワップを使うようにfstabに追記
sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'
```

## code-serverのインストール

### ディレクトリとHTTPS通信用の証明書の準備

素の状態でcode-serverコンテナを立ち上げると、コンテナ終了時にデータがすべて吹っ飛ぶので
code-serverコンテナマウント用にいくつかディレクトリを作ります。
今回は`/coder` ディレクトリとして話を進めます。

```bash
sudo mkdir /coder
sudo mkdir /coder/home # ユーザーデータ永続用
sudo mkdir /coder/home/certs # オレオレサーバー証明書参照用
sudo mkdir /coder/data # ノートデータ永続用

# dockerコンテナがcoderユーザーで起動するため権限を追加しています
# さすがにホストにcoderユーザーを作って所有者をcoderにしてコンテナ内のuidと合わせて…
# というのはオーバーキルな感じがするのでこれで妥協
sudo chmod 777 /coder/home /coder/data
```

オレオレサーバー証明書の作成

```bash

# 実行後いろいろ聞かれますが、自分以外が見るわけではないので最悪全部ブランクでも問題ありません
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /coder/home/certs/coder.key -out /coder/home/certs/coder.crt

# こちらもコンテナ内部で使用するため権限変更
sudo chmod 644 /coder/home/certs/*

```

### 起動

```bash

# 起動する: passwordはお好みの文字列に変更
sudo docker run -it \
  -p 443:8443 \
  -v /coder/home:/home/coder/ \
  -v /coder/data:/home/coder/project/code-server \
  codercom/code-server code-server \
  --password hogehoge \
  --cert /home/coder/certs/coder.crt \
  --cert-key /home/coder/certs/coder.key 
```

起動コマンドは長いですが、

 - docker runの引数で内部8443ポートをホストのポート443にマッピング、  
 マウントポイント2つ追加
 - code-serverの引数で証明書と鍵の指定、パスワードの指定

を行っています。自動的にコンテナ再起動して欲しい場合は`--restart=always` も追加。

このクッソ長いコマンドがアレだと思う人はdocker-compose.yml作るなりするものありです。

### ログイン

ブラウザで `https://(VMの外部IPアドレス)` にアクセスします。
ブラウザから警告が出ますが、これはオレオレ証明書なのでしょうがないです。進みましょう。
Chromeなら白いボタンを押して詳細表示→ページ下部のIPアドレスをクリック。

![Screen Shot 2019-04-14 at 0.45.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128115/c1239304-c28d-a6d7-44e0-743a712286f3.png)

code-serverの画面が出るので、先程指定したパスワードを入力して
ENTER IDEを押下すると、いつもの見慣れたVSCode画面になります。

![Screen Shot 2019-04-14 at 3.23.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128115/a966ee33-b338-84bb-dcfd-b098cd51c8a4.png)

### 設定

VSCodeの画面になったら、拡張機能タブを選択してVimを入れます。
(え？Vim派じゃないから入れたくない？別にいいけどさ…)
他にも入れたい拡張があれば自由に入れましょう。

あくまでクラウドノート環境を目指すので、開発環境ゴリゴリ作るとかはやめましょう。
リソースも貧弱なので泣く羽目になります

![vim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128115/ffb60127-b507-88a6-1587-3b5f3ce82915.png)


そして、クラウドノートっぽい挙動にするために左ペインのツリーは最終更新日で
ファイルを並び替えるようにします。設定を開き、sortorderで検索すると出ます。

![sort_order.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128115/7c13628d-f3b9-b629-ea09-e6196601a729.png)

設定は完了です。流石にフォルダ直下はきれいにしておきたいので、
Notebooksフォルダを作ってその下にバンバンmdファイルを
作っていくような感じにすればいいかなと思います。

### バージョン管理(やりたい人だけ)

Cmd+Jでターミナルを表示して、初期設定
(Debug ConsoleにフォーカスあたってるのでTerminalタブに切り替える)

#### 鍵の作成

```bash
ssh-keygen -t rsa
```

(守備範囲外なので簡易説明)
その後、
・ `/home/coder/.ssh/id_rsa.pub` をGitHubに登録します。
・ GitHubにノート管理用のプライベートリポジトリを作っておきます。

#### Git初期設定

名前やメールアドレス、リポジトリは適宜読み替えて下さい。

```bash

# GitHubで使ってるやつを入力
git config --global user.name "hoge"
git config --global user.email "xxxx@yyyy.com"

# git管理開始
git init
echo '.Trash*' >> .gitignore # ゴミ箱ディレクトリを除外
git add .
git commit -m "Initialize"

# GitHubのリポジトリと紐付け
git remote add origin git@github.com:username/repository_name.git
git push -u origin master
```

## 設定完了！！

というわけで、一応HTTPS通信で暗号化もして実践的に使えるようになりました。
以下とりあえず一週間ほど運用した所感です。

 - 初回Open後、読み込みまではちょっとかかる
 - その後、エディタ画面は普通に快適
 - 左ペインのツリーの更新が遅いときは、新規作成ボタンの横のリロードボタンを押す
 - プロジェクトではなくノートとして使うなら、更新順に並ぶのはやっぱり良い
 - 複数箇所から開いていて変更箇所が衝突しても、VSCodeの保存時衝突検出が優秀なので安全
 - テキスト中心なら28GBあれば安心。一生大丈夫なレベル
 - Gitバージョン管理は細かくやらず、日次バックアップ的なゆるい位置づけのほうが気楽でいい
 - シークレットウインドウでこのページ専用に一個ウインドウ使った方がアプリみたいに使えて良い

総合的には、たまにもっさりだけど普通にVSCodeそのものが強すぎるので
マシンパワーが貧弱でも他のクラウドノートに勝てるんじゃないかという感じ。


## 夢が広がりんぐ！！！

一応このままでも「無料で最強のクラウドノート」というゴールは達成しましたが
ここからさらにbetterな環境に育てていければと思います。

いろいろ嫌になって環境ぶっ壊して最初から作り直し、ということになっても
ノートの内容をGitHubのプライベートリポジトリに上げておけば
作り直したあとにpullするだけでまるっと復活するので良きですね。

とりあえずIP直打ちで警告画面出るのはダサいのでドメインはなんとかしたい感。


[^1]: デバイス間同期は厳密には一つの場所にいつもアクセスという形になるが