Visual Studio Codeを iPadからも自由に使う 〜 code-server とVPN での構築手順 〜

AI開発を学び始めると、JupyterLab(notebooks)をはじめ、開発環境のクラウド利用率が高いことに気付く。巨大なデータを扱い、すぐ陳腐化する高性能マシン(CPU/GPU/メモリー)を利用する必要がままあり、利用履歴をきちんと管理しようと考えれば、クラウド化はまあ当然の帰結か。

で、どうせクラウド化していくのなら、とことんクラウド化しようと思い至り、普段使うVisual Code Studio もクラウド化しちゃうことにします。どこでもiPadだけで開発できるし、長期休暇とってるときも、iPadだけあれば安心な状況を作れるし。

code-server とは? なんで code-server?

  • Visual Studio Code(以下、VS Code) の開発は、Microsoft がOSS(MITライセンス)として進める“Code – OSS” を中心に行われている。
  • その「Code – OSS」に、Webサーバ機能等を薄くラッパーし、同じくOSS(MITライセンス)で提供しているのが、Coder社のcode-serverだ。
  • VS Code 自体も、Remote Tunnel や Remote SSH といった機能を組み合わせて同様の事を実現できるが、現状だとWebブラウザから利用するには vscode.devを利用する必要がある。このあたりの仕様をMSが数ヶ月単位で変更したりもするのでキャッチアップが大変。GitHub Codespacesを利用する手もあるが、定常的に利用するには利用料金が高い。
    – よって今回は code-server と、SoftEtherを利用してGCP上で独自構築することにした。

システム全体像

SoftEther network on GCP

  • 基本的なアーキテクチャは「code-serverを使ってブラウザ上だけでセキュアで快適に開発してみる」をベースとする。VPN接続を行うための SoftEather、及び code-serverをHTTPS化したりの設定を追加で施す。
  • 当初、SSHの踏台サーバの導入も考えたが、GCPのブラウザやiPadアプリからSSHが普通にできちゃうことや、最悪の場合は作業者のIPアドレスだけを通すSSHを許可して設定するようにして普段はSSH閉じてた方が、自分のまわりで利用するには安全だという結論に至ったので、当面はSSH踏台は想定しないことにします。なので初期立ち上げ作業(今回の作業)の最後にSSH閉じます。

PC / iPad

  • 今回のそもそも、iPadで仕事すればいいじゃんwという発想から始まったです。
  • code-serverの入ったサーバにSSHするためのkeyを持ってます。
  • SoftEatherに VPN 接続するための設定を行います。

AWS || GCP

  • code-server や、SoftEther VPを入れます。
  • 踏台サーバからのSSHと、VPN(UDP)のみ許可します。
  • masuidriveさんがAWSで実装しているので、AWSな人はそっちを参考にすればいいじゃん。あと、自分今後AI学習を進めていく中で、GCP使いたいじゃん。という2つの理由から GCP で構築します。

GCPでのサーバ構築

サーバ構築の要となるVPCまわりは、中の人が書いた「Google CloudのVPCを基礎から始める」を参考にします。

任意の Project を作成(利用)して、そのProject下で VPCネットワーク > 「+VPCネットワークを作成」を選択します。細かい手順は上記の中の人が書いた記事通りに進みます。記事中の「ファイアウォールルール」は、今回の用途に合わせて以下のように設定します

firewall rules for SoftEther on GCP

外からのアクセスは、SoftEther で L2TP/IPsec を利用するので UDP 500 と UDP 4500を許可。作業用SSH(TCP 22)と、GUI 管理ツール(Mac版は存在するけどメンテ終了してるようで動かないけど)の TCP 443 を一時的に許可。SoftEtherとcode-serverが内部で通信するためにサブネット内の通信を許可します

あと、Compute Engine のインスタンス作成時に「IP転送を有効にする」を「ON」にする必要があります。後からでもCLIで変更できるようですが、Webコンソールからは変更できないので注意が必要です

今回もCompute Engineの最安インスタンスを利用するので、いつも通り swap 設定を行います

SoftEtherのインストールと設定

Compute Engine の default OS が Debian 11 で、apt パッケージがあったのでインストールしてみました。が、自分のせいなのかうまく設定できませんでした。よって、コードからビルドしました

必要なパッケージと、好みのパッケージをインストール

sudo su -
apt update && apt upgrade
apt -y install cmake gcc g++ libncurses5-dev libreadline-dev libssl-dev make zlib1g-dev wget emacs git bridge-utils

SoftEtherの最新版をインストール

wget https://www.softether-download.com/files/softether/v4.42-9798-rtm-2023.06.30-tree/Linux/SoftEther_VPN_Server/64bit_-_Intel_x64_or_AMD64/softether-vpnserver-v4.42-9798-rtm-2023.06.30-linux-x64-64bit.tar.gz
tar zxvf softether-vpnserver-v4.42-9798-rtm-2023.06.30-linux-x64-64bit.tar.gz 
mv vpnserver/ /usr/local/vpnserver
cd /usr/local/vpnserver
make

systemctlのservice定義を作成

cat << EOT > /etc/systemd/system/vpnserver.service
[Unit]
Description=SoftEther VPN Server
After=network.target network-online.target

[Service]
ExecStart=/usr/local/vpnserver/vpnserver start
ExecStop=/usr/local/vpnserver/vpnserver stop
Type=forking
RestartSec=3s

[Install]
WantedBy=multi-user.target
EOT

パーミッションを絞る

chmod 600 *
chmod 700 vpncmd
chmod 700 vpnserver 

serviceの有効化と開始

vpnserver systemctl daemon-reload
systemctl enable vpnserver.service
systemctl start vpnserver.service

VPN Server の管理者用パスワード生成

./vpncmd

vpncmd command - SoftEther VPN Command Line Management Utility Developer Edition
SoftEther VPN Command Line Management Utility (vpncmd command)
Developer Edition
Version 5.01 Build 9674   (English)
Compiled 2020/12/03 09:35:09 by Unknown at Unknown
Copyright (c) all contributors on SoftEther VPN project in GitHub.
Copyright (c) Daiyuu Nobori, SoftEther Project at University of Tsukuba, and SoftEther Corporation.
All rights reserved.

By using vpncmd program, the following can be achieved.

1. Management of VPN Server or VPN Bridge
2. Management of VPN Client
3. Use of VPN Tools (certificate creation and Network Traffic Speed Test Tool)

Select 1, 2 or 3: 1

Specify the host name or IP address of the computer that the destination VPN Server or VPN Bridge is operating on.
By specifying according to the format 'host name:port number', you can also specify the port number.
(When the port number is unspecified, 443 is used.)
If nothing is input and the Enter key is pressed, the connection will be made to the port number 443 of localhost (this computer).
Hostname of IP Address of Destination:

If connecting to the server by Virtual Hub Admin Mode, please input the Virtual Hub name.
If connecting by server admin mode, please press Enter without inputting anything.
Specify Virtual Hub Name:
Connection has been established with VPN Server "localhost" (port 443).

You have administrator privileges for the entire VPN Server.

VPN Server>ServerPasswordSet
ServerPasswordSet command - Set VPN Server Administrator Password
Please enter the password. To cancel press the Ctrl+D key.

Password: *************************************************
Confirm input: *************************************************


The command completed successfully.

VPN Server>exit

以上までで、SoftEtherのインストールと起動設定、管理者用パスワードの設定が完了

GUI管理ツールを利用した設定(Windowsのみ)

管理ツールを使った設定方法は、検索すればごろごろ出てくるので、ログインするところまではそちらを参照してください

SoftEther GUI Admin tool  / HOME

「仮想HUBの作成(C)」から、仮想HUBを作成する(図では「VPN」という名前で作成)。その後、仮想ハブのリストに表示された仮想HUB名を選択し「仮想HUBの管理(A)」をクリックすると、VPNの管理画面に遷移します

SoftEther GUI Admin tool  / VPN Management

VPNの管理画面で必須の設定は「ユーザーの管理(U)」と「仮想NATおよび仮想DHCPサーバ機能(V)」です

SoftEther GUI Admin tool  / VPN USER Management

ユーザ管理画面では、「ユーザ名(U)」と認証方法(図ではパスワード認証)を設定します

SoftEther GUI Admin tool  / Secure NAT Management

仮想NATおよび仮想DHCPサーバ機能の設定画面では「SecureNAT機能を有効にする(E)を選択します

SoftEther GUI Admin tool  / Secure NAT Management 2

SecureNATの設定画面では、ネットワークインターフェイスの設定にIPアドレス、サブネットマスクを指定し、仮想NAT機能を使用するをチェック。仮想DHCPサーバもチェックし、配布するIPアドレス帯、及びサブネットマスクを設定します。それからオプションとしてデフォルトフェートウェイのアドレスと、DNSサーバのアドレスを設定します

SoftEther GUI Admin tool  / L2TP over IPsec Settings

最後に、iPad / Mac から L2TP サーバ機能でアクセスしたいので「L2TPサーバー機能を有効にする(L2TP over IPsec)」をチェックし「IPsec事前共有鍵(P)」を適当に指定します

以上で設定完了です

CLI(vpncmd)での設定

上記にてGUIで行った操作をCUIで行う場合は、以下の操作を vpncmd のパスから実行します
(事前に上記説明の通り「./vpnvmd で管理者パスワードは設定済の想定)

まず、必要な変数を決めて(調べて)変数化しておきます(お好みで)

SE_HUBNAME="{{ SoftEtherの仮想HUB名 ※自分で決める(上記GUIの場合「VPN」として作成}}"
SE_USERNAME="{{ VPNアクセス時のユーザ名 ※自分で決める}}"
SE_PASSWORD="{{ VPNアクセス時のパスワード ※自分で決める}}"
SE_PSK="{{ VPNアクセス時の「IPsec事前共有鍵」 ※自分で決める}}"
HOST_IP="10.0.0.0"
DHCP_GW="10.0.30.1"
DHCP_START="10.0.30.10"
DHCP_END="10.0.30.200"
DHCP_MASK="255.255.255.0"
SE_HOST="localhost"
GLOBAL_IP="{{ Compute EngineのグローバルIP }}"

仮想HUBを作成します

./vpncmd "$SE_HOST" /SERVER /CMD HubCreate "$SE_HUBNAME"

実行すると、何度か管理者用パスワードを聞かれる(下記 ******* の部分)ので、先に設定した管理者用パスワードを入力します
(以下、./vpncmd実行時には管理者用パスワードを聞かれるので都度入力します ※面倒な人は ./vpncmd の対話的インターフェイスでCMD以下を実行しても大丈夫だと思いますが、微妙に/HUB の指定が必要だったり必要でなかったりするので注意が必要です)

vpncmd command - SoftEther VPN Command Line Management Utility
SoftEther VPN Command Line Management Utility (vpncmd command)
Version 4.42 Build 9798   (English)
Compiled 2023/06/30 11:06:58 by buildsan at crosswin with OpenSSL 3.0.9
Copyright (c) 2012-2023 SoftEther VPN Project. All Rights Reserved.

Password: *************************************************

Connection has been established with VPN Server "localhost" (port 443).

You have administrator privileges for the entire VPN Server.

VPN Server>HubCreate VPN
HubCreate command - Create New Virtual Hub
Please enter the password. To cancel press the Ctrl+D key.

Password: *************************************************
Confirm input: *************************************************


The command completed successfully.

VPNアクセス時のユーザ/パスワードを設定し、L2TPサーバー機能(L2TP over IPsec)を有効にする

./vpncmd "$SE_HOST" /SERVER /HUB:VPN /CMD UserCreate "$SE_USERNAME" /GROUP:none /REALNAME:none /NOTE:none
./vpncmd "$SE_HOST" /SERVER /HUB:VPN /CMD UserPasswordSet "$SE_USERNAME" /PASSWORD:"$SE_PASSWORD"
./vpncmd "$SE_HOST" /SERVER /CMD IPsecEnable /L2TP:yes /L2TPRAW:no /ETHERIP:no /PSK:"$SE_PSK" /DEFAULTHUB:DEFAULT

仮想NAT、および仮想DHCPサーバ機能を設定する

./vpncmd "$SE_HOST" /SERVER /HUB:VPN /CMD SecureNatEnable
./vpncmd "$SE_HOST" /SERVER /HUB:VPN /CMD SecureNatHostSet /MAC:none /IP:"$DHCP_GW" /MASK:"$DHCP_MASK"
./vpncmd "$SE_HOST" /SERVER /HUB:VPN /CMD DhcpSet /START:"$DHCP_START" /END:"$DHCP_END" /MASK:"$DHCP_MASK" /EXPIRE:7200 /GW:none /DNS:none /DNS2:none /DOMAIN:none /LOG:no /PUSHROUTE:"$HOST_IP/$DHCP_MASK/$DHCP_GW"

以上で、SoftEtherのCLIでの設定は完了です

code-serverのインストールと設定

以下のコマンドでインストールします

WORK_DIR="/home/ubuntu/projects"
USER_ID=1000
GROUP_ID=1000
PORT=8888

cd ~
curl -L https://github.com/coder/code-server/releases/download/v4.14.1/code-server-4.14.1-linux-amd64.tar.gz | tar xfz - -C /usr/local/

mkdir -p $WORK_DIR
chown $USER_ID:$GROUP_ID $WORK_DIR

EXEC_PATH=/usr/local/code-server-4.14.1-linux-amd64/bin/code-server

cat << EOT > /etc/systemd/system/code-server.service
[Unit]
Description=VSCode in a browser
After=network.target

[Service]
Type=simple
ExecStart=$EXEC_PATH --host 0.0.0.0 --port $PORT --locale ja-JP $WORK_DIR
WorkingDirectory=$WORK_DIR
ExecStop=/sbin/start-stop-daemon --stop -x $EXEC_PATH
Restart=on-failure
User=$USER_ID

[Install]
WantedBy=multi-user.target
EOT
systemctl daemon-reload
systemctl enable code-server.service
systemctl start code-server.service

以上で、code-server のインストールと設定は完了です

iPadでVPN設定&WebブラウザからVS Codeの利用

iPadの設定画面>一般>VPNとデバイスの管理>VPN で、VPN構成を追加します

VPN Setting on iPad 1

タイプは「VPN」、説明は任意の名前、サーバはCompute EngineのグローバルIP、アカウントはSoftEtherでユーザ用に作成したユーザ名+「@(仮想HUB名)」、パスワードはSoftEtherでユーザ用に作成したパスワード、シークレットはSoftEtherのL2TPサーバー機能の設定画面で指定した「IPsec事前共有鍵(P)」を設定します

VPN Setting on iPad 2

iPadの設定画面で「VPN」を有効にすると、設定した内容でVPN接続します

VPNに接続した状態で、ブラウザで「Compute EngineのローカルIPアドレス+:8888」でアクセスすると、code-server の起動画面が表示されます

code-server login page on GCP via softether

ここで求められるデフォルトパスワードは、/home/{SSH認証鍵を登録したユーザ名}/.config/code-server/config.yamlに設定されています。変更ももちろん可能です(VPNなのであんまり関係無いですが)

パスワード認証が問題無く終われば、VS Code の初期画面が表示されます

code-server welcome page on GCP via softether

以上で、code-server(Visual Studio Code)がVPN経由でブラウザ上から利用できるようになりました

今後余裕があれば(需要がありそうだったら)、code-serverのバージョンアップについてや、HTTPS化などについても投稿できたらいいなと思います


Special Thanks

SoftEther 関連

今回採用しなかった方法

code-server 関連情報(TODO: HTTPS化)

GCP 関連