オフライン環境へVSCodeとRemote Developmentを導入してlinux開発を快適にする

VSCodeを使いたいのに開発環境にインターネットが無いんだけど・・・
VSCode Remote Developmentめちゃ便利だけど職場の環境は無理かな・・・
もうvimやgdbやgitコマンドの使い方をググるのに1日溶かしたくない・・・
という人へ贈る。

# 開発現場の状況を整理
- クライアント(VSCodeを開きたいマシン)
    - オフラインのWindows
    - プロキシの中など実質オフラインも可
    - OpenSSHなぞ入っていない(こともある)
    - 管理者権限もない(こともある)
    - ここにVSCodeを入れて使います！
- ターゲット(対象となる開発マシン)
    - linuxに直接VSCode入れるのも面倒だしVNCやRDPは重い
    - ここにはvscode-serverを入れます！
    - sshd、gccやgdbがここに入っていること！

# 解決のポイント
- 必要なプラグインはあらかじめダウンロード
- vscodeのバージョン(コミット)に対応したvscode-serverを手動で取得しておく
- SSH Extentionの中のコケるポイントwgetをcpに変えて回避

# 手順
## 1.必要なものをダウンロード
オフライン環境に展開するために、必要なものをあらかじめダウンロードします。

### 必須
- [Visual Studio Code](https://code.visualstudio.com/)
    - ページ下部 .zip 64bit または 32bit より合ったものをダウンロードしましょう。
    - 適当な場所に展開しておきます。
- [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)
    - ページ右の Resources より Download Extentions からダウンロードしましょう。
- [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)
    - ページ右の Resources より Download Extentions からダウンロードしましょう。
- vscode-server-linux-x64.tar.gz
    - VSCodeのバージョンを確認してダウンロードします。(後述)

### 必要に応じて入れるもの
- クライアント
　- [OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/releases)
        - OpenSSH が入ってない人へ。
        - 適当な場所に展開しておきます。
    - [Japanese Language Pack for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja)
        - Englishは嫌な人へ。
    - その他欲しいプラグイン
- ターゲットマシン
    - sshd : ssh接続を受け付けるようにしておきます。
    - gcc : C/C++のコンパイルに必要ですね。
    - gdb : デバッガです。開発に必要な方は。

## 2. VSCodeへプラグインを入れる
プラグイン一覧の右肩の… から Install from VSIX... を選んでダウンロードしておいた各プラグインを導入します。
方法はググりましょう。

## 3. sshの公開鍵認証を設定しておく
このステップはググりましょう。要するに以下です。
1. クライアント: ssh-keygenを実行(OpenSSHのフォルダにssh-keygenは入っています。)。パスフレーズ等の入力は不要。
2. クライアントに生成されたid_rsa.pubの内容をサーバーの~/.ssh/authorized_keysに書き込む
3. .sshやauthorized_keysのパーミッションに気をつけましょう。
4. クライアントの~/.ssh/configにconfigを書いておきましょう。
5. 必要に応じてProxyCommandなど設定しましょう。
6. OpenSSH単体(ssh.exe)で公開鍵認証できることを確認しておきましょう。

```~/.ssh/configの例
Host target
    HostName targetのIPアドレス
    User targetのログインユーザー
    IdentityFile クライアントのid_rsaへのパス
```

## 4. VSCodeのバージョンを確認
メニューから Help > About で Commit: を確認します。Copyもできます。

```バージョンの確認結果
Version: 1.43.1
Commit: fe22a9645b44368865c0ba92e2fb881ff1afce94
Date: 2020-03-18T07:01:20.184Z
Electron: 7.1.11
Chrome: 78.0.3904.130
Node.js: 12.8.1
V8: 7.8.279.23-electron.0
OS: Windows_NT x64 10.0.18362
```

## 5. vscode-server-linux-x64.tar.gz のダウンロード
Commitを入れたURLから vscode-server-linux-x64.tar.gz をダウンロードします。

```例
https://update.code.visualstudio.com/commit:fe22a9645b44368865c0ba92e2fb881ff1afce94/server-linux-x64/stable
```

## 6. ダウンロードした vscode-server-linux-x64.tar.gz をターゲットに転送する
後述のコードにwgetが含まれるせいでRemote Developmentの立ち上げに失敗する要因となっています。
まずはwgetの代わりに自分で取ってきたモノをターゲットマシンに転送しておきます。
クライアントからscpでターゲットの/tmpなどへ送りましょう。(OpenSSHのフォルダにscpは入っています。)
ここでも公開鍵認証がうまく設定できているか動作確認ができますね。

```powershell
.\scp \path\to\vscode-server-linux-x64.tar.gz target:/tmp
```

## 7. Remote - SSH の改造
ターゲットで実行されるwgetをcpコマンドに置き換え、オフライン環境でもあたかもwgetが成功したかのように書き換えます。
クライアントの ~\.vscode\extensions\ms-vscode-remote.remote-ssh-0.50.0\out\extention.js を編集します。
ターゲット上でwgetする筈のコードを/tmpからコピーしてくるコードに変更しています。

```extention.ja(オリジナル)
wget ${function(e){return e?"--tries=1":""}(!!m)} --connect-timeout=7 --dns-timeout=7 -nv -O vscode-server.tar.gz $DOWNLOAD_URL
```
```extention.ja(変更後)
cp /tmp/vscode-server-linux-x64.tar.gz vscode-server.tar.gz
```

手順は以上です。VSCodeからターゲットに接続できるか確認しましょう。
プラグインをVSCode上からターゲットへ入れることもできます。
vsixファイルをターゲットへ転送しておき、Install from VSIX...でインストールすることもできます。

# トラブルシューティング
## Connectionができない
- ssh.exeの公開鍵認証が通るか確認しましょう。

## Got Connection 1とか出たのにエラーが出る
- sshd_configを確認しましょう。
    - https://code.visualstudio.com/docs/remote/troubleshooting
    - AllowTcpForwarding yes
    - AllowStreamLocalForwarding yes
- ターゲットのファイアーウォール(OUTPUT)を確認しましょう。

# Refs
- [VSCODE remote development リモートホストがインターネットにつながらない環境での接続](https://qiita.com/waterame/items/9979f1730cccddc8e608)
- [【VS Code】Internet環境のないサーバでRemote Development機能を使用する方法](https://www.mathkuro.com/?p=726)
- [Use VS Code Remote Development w/o marketplace, update connectivity #15](https://github.com/microsoft/vscode-remote-release/issues/15#issuecomment-489969139)