はじめに
このシリーズの開発は、すべて自宅サーバーの上で行っています。手元の Windows PC で VS Code を開き、Remote-SSH という拡張機能でサーバーに接続して、サーバー上のファイルを直接編集し、サーバー上のターミナルでコマンドを実行しています。
これまでの回では当たり前のように「VS Code のターミナルで」と書いてきましたが、その前提になっている接続の方法は紹介していませんでした。この番外編では、Remote-SSH の仕組みと設定の手順、そして実際につまずいたことをまとめます。
ほかの方法との違い
手元の PC で Linux の環境を使う方法には、Windows の WSL もあります。私の使い方では、次のような違いで Remote-SSH を選んでいます。
| WSL | Remote-SSH(自宅サーバー) | |
|---|---|---|
| Linux が動く場所 | 手元の PC の中 | 別のマシン(自宅サーバー) |
| 作ったものの公開 | PC を閉じると止まるので、公開には向かない | サーバーは常時動いているので、そのまま公開できる |
| 開発と本番の環境 | 別々(開発後にサーバーへ持っていく必要がある) | 同じマシン。開発したその場で、本番と同じ構成で確かめられる |
| 必要なもの | PC だけ | 常時動いている Linux サーバー |
組み込みでいえば、Remote-SSH は、手元の PC のエディタとデバッガから、ケーブル越しにターゲットボードを直接触っている状態です。ソースもビルドも実行もターゲット側にあり、手元にあるのは画面と操作だけ、という形になります。
仕組み:画面は手元、それ以外はサーバー
Remote-SSH で接続すると、VS Code は2つに分かれて動きます。

| 場所 | 動いているもの | 役割 |
|---|---|---|
| 手元の PC | VS Code 本体 | 画面の表示と、キーボード・マウスの操作だけ |
| 自宅サーバー | VS Code Server | ファイルの読み書き、ターミナル、拡張機能の多く、ポート転送の受け口 |
VS Code Server は、初めて接続したときに、VS Code が自動でサーバーの ~/.vscode-server に入れてくれます。自分でインストールする必要はありません。
ファイルはサーバー上にしかないので、編集した内容は、保存した瞬間にサーバーのディスクに書き込まれます。ターミナルもサーバー上で動いているので、npm run build や git push は、そのままサーバーの上で実行されます。
手元とサーバーの間は、SSH(暗号化された遠隔ログインの仕組み)の1本の接続だけでつながっています。画面の操作も、ファイルの中身も、ターミナルの入出力も、ポート転送も、すべてこの1本の中を通ります。サーバーの側で開けておく必要があるのは、SSH の 22 番ポートだけです。
準備:鍵を作り、サーバーに登録し、接続先を設定する
ここからは、手元の Windows PC から自宅サーバーへ、パスワードではなく鍵でログインできるようにする手順です。自宅の LAN の中から接続するので、ルーターでポートを開ける必要はありません。
この記事では、サーバーの IP アドレスを 192.168.0.10、サーバーのユーザー名を devuser、接続先に付ける呼び名を myserver としています。ご自分の環境に合わせて読み替えてください。
① SSH のクライアントがあるか確かめる
Windows 10 / 11 には、SSH のクライアントが標準で入っています。PowerShell で確かめます。
PS> ssh -VOpenSSH_for_Windows_… のようにバージョンが表示されれば使えます。
② 鍵を作る
PS> ssh-keygen -t ed25519保存場所を聞かれたら、そのまま Enter で既定の場所(C:\Users\<ユーザー名>\.ssh\id_ed25519)に保存します。パスフレーズ(鍵そのものにかける合言葉)は、設定しておくのがおすすめです。
2つのファイルができます。
| ファイル | 中身 | 扱い |
|---|---|---|
id_ed25519 | 秘密鍵 | 手元の PC から外に出さない |
id_ed25519.pub | 公開鍵 | ログインしたいサーバーに登録する |
組み込みでいえば、秘密鍵はセキュアエレメントの中に閉じ込めた鍵、公開鍵は相手に渡して照合してもらう情報です。
③ 公開鍵をサーバーに登録する
公開鍵の中身を、サーバーの ~/.ssh/authorized_keys に書き足します。Windows には Linux の ssh-copy-id がないので、次の1行で行います。このときだけ、サーバーのパスワードを聞かれます。
PS> Get-Content $HOME\.ssh\id_ed25519.pub | ssh devuser@192.168.0.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"| 部分 | 意味 |
|---|---|
Get-Content … | | 公開鍵の中身を読み出して、次のコマンドに渡す |
ssh devuser@192.168.0.10 "…" | サーバーにログインして、"…" の中のコマンドを実行する |
cat >> ~/.ssh/authorized_keys | 受け取った公開鍵を、登録済みの鍵の一覧の末尾に書き足す |
chmod 700 / chmod 600 | 自分以外は読めないようにする。権限が緩いと、SSH は安全のため鍵を使ってくれない |
④ 接続先に呼び名を付ける
毎回 devuser@192.168.0.10 と打たなくて済むように、設定ファイル C:\Users\<ユーザー名>\.ssh\config に呼び名を登録します。ファイルがなければ新しく作ります。
Host myserver
HostName 192.168.0.10
User devuser
IdentityFile ~/.ssh/id_ed25519⑤ 鍵でログインできるか確かめる
PS> ssh myserverサーバーのパスワードを聞かれずに(パスフレーズを付けた場合は、パスフレーズだけを聞かれて)ログインできれば、準備は完了です。exit で抜けます。
初めて接続したときは、「この相手の指紋はこれですが、接続しますか?」と聞かれます。yes と文字で入力して Enter を押してください。Enter だけを押すと「拒否」として扱われます。
VS Code で接続する
鍵でログインできるようになれば、VS Code 側の作業は少しだけです。
- VS Code の拡張機能で「Remote – SSH」(Microsoft 製)を検索して、インストールします。
- F1 キーを押し、「Remote-SSH: Connect to Host…」を選びます。
- 一覧に、④ で設定した
myserverが出てくるので選びます。 - 新しいウィンドウが開き、初回はサーバーに VS Code Server が自動で入ります(少し時間がかかります)。
- 「フォルダーを開く」で、サーバー上の作業フォルダ(たとえば
/home/devuser/apps/unitconv)を選びます。

接続できると、VS Code の左下に、SSH: myserver のような緑色の表示が出ます。これが出ている間は、エディタで開いたファイルもターミナルも、すべてサーバー上のものです。

接続を終えるときは、この左下の表示をクリックして「リモート接続を閉じる」を選びます。
日々の使い方
ターミナル
Ctrl + Shift + `(バッククォート。日本語キーボードでは @ のキー)で、ターミナルが開きます。このターミナルはサーバーの上で動いているので、行頭はサーバーのプロンプト([devuser@myserver unitconv]$ など)になります。シリーズの記事で「VS Code のターミナルで」と書いているのは、すべてこのターミナルのことです。
ポート転送:サーバーで動かした画面を、手元のブラウザで見る
サーバーで動かした開発用のサーバー(たとえば 第4回の Vite の開発サーバー)は、外から勝手につながらないよう、サーバー自身(127.0.0.1)からの接続だけを受け付けるようにしています。そのままでは、手元の PC のブラウザから見られません。
そこで使うのが、VS Code のポート転送です。
- VS Code の下部パネルの「ポート」タブを開きます。
- 一覧に、サーバーで待ち受けているポート(たとえば 5173)があれば、そのまま使います。サーバーでプログラムを起動すると、自動で追加されることもあります。
- なければ「ポートの転送」を押して、ポート番号を入力します。
- 手元の PC のブラウザで、
http://localhost:5173/…を開きます。

SSH の接続の中を通して、サーバーの 5173 番を、手元の PC の 5173 番につないでいる状態です。インターネットには一切公開されません。組み込みでいえば、デバッガのケーブルの中に、もう1本の信号線を通してもらうようなものです。
シリーズでは、開発中の画面の確認(第4回)や、ビルドしたサーバーの単体確認(第7回)で、この方法を使っています。
GitHub への push は VS Code に任せる
サーバー上で書いたソースは、GitHub の非公開リポジトリに送って保管しています。ここで、「サーバーから GitHub に、どうやって認証するか」という問題が出てきます。
最初に考えた方法:SSH 鍵
最初は、GitHub にも SSH 鍵で接続しようとしました。ただ、サーバーに秘密鍵を置くと、サーバーが乗っ取られたときに、その鍵で入れる GitHub のリポジトリまで危険になります。そこで、手元の PC の鍵をサーバーから借りて使うエージェント転送という方法も試しました。秘密鍵は PC から出さず、サーバーからの署名の依頼だけを、SSH の接続の中で PC に中継してもらう仕組みです。
ところが、PowerShell から ssh -A で入ったときは転送が効いたのに、VS Code のターミナルでは、転送の目印になる SSH_AUTH_SOCK が空のままで、うまくいきませんでした。
落ち着いた方法:HTTPS + VS Code のサインイン
実は、VS Code には、手元でサインインしている GitHub のアカウントを使って、サーバー上の git の認証に答える仕組みがあります。普段から VS Code の「ソース管理」の画面で push していたのは、この仕組みのおかげでした。

この仕組みが使えるのは、送り先が HTTPS 形式(https://github.com/…)のときだけです。SSH 形式(git@github.com:…)で登録していると、SSH 鍵で接続しようとして失敗します。送り先の形式は、次のコマンドで確かめて、必要なら書き換えます。
$ git remote -v
$ git remote set-url origin https://github.com/example-user/apps-hello.git
$ git push -u origin main行頭の $ は、一般ユーザーで実行するコマンドであることを示す記号(プロンプト)です。実際に入力するのは $ の後ろからです。
この方法なら、サーバーには SSH 鍵もパスワードも置きません。手元の VS Code でサインインしている間だけ push できる、という形になります。組み込みでいえば、鍵はセキュアエレメント(手元の PC)から一切出さず、必要なときだけ署名を代行してもらう形です。
| 方法 | 秘密鍵・認証情報の場所 | 結果 |
|---|---|---|
| サーバーに SSH 鍵を置く | サーバー | 採用しない(サーバーが乗っ取られると鍵も漏れる) |
| エージェント転送 | 手元の PC | VS Code のターミナルでは転送されず、うまくいかなかった |
| HTTPS + VS Code のサインイン | 手元の PC(VS Code) | 採用。VS Code のターミナルやソース管理から push できる |
注意点は、VS Code を通さずに(たとえば PowerShell の ssh で)サーバーに入ったときは、この仕組みが使えないことです。push は、VS Code のターミナルかソース管理の画面から行います。
つまずいたこと
PowerShell では、外部のコマンドに ~ が通じない
エージェント転送を試したとき、PC の鍵を ssh-agent(鍵を預かって署名を代行する常駐プログラム)に読み込ませようとして、次のエラーになりました。
PS> ssh-add ~\.ssh\id_ed25519
~\.ssh\id_ed25519: No such file or directory直前の ls ~\.ssh では、ファイルがちゃんと見えていたのにです。PowerShell では、~(ホームフォルダ)が展開されるのは、ls のような PowerShell 自身のコマンドのときだけで、ssh-add のような外部のプログラムには、~ という文字がそのまま渡されてしまいます。
PowerShell の変数 $HOME を使えば解決します。
PS> ssh-add $HOME\.ssh\id_ed25519C でいえば、プリプロセッサが展開してくれると思っていたマクロが、展開されずに文字列のまま関数に渡ったような状態です。この記事の手順③で $HOME を使っているのも、このためです。
初めての接続先で、Enter だけを押すと拒否になる
初めて接続する相手には、SSH が「この相手の指紋はこれですが、本物と信じて接続しますか?」と聞いてきます。なりすましのサーバーにつながっていないかを確かめるための仕組みで、組み込みでいえば、初回のペアリングで相手のデバイス ID を確かめるのと同じです。
ここで Enter だけを押すと「拒否」として扱われ、Host key verification failed. で止まります。y だけでも受け付けられず、yes と文字で入力する必要がありました。
push が突然、認証エラーになる
それまで送れていた push が、ECONNREFUSED /run/user/…/vscode-git-….sock というエラーで失敗したことがあります。上の図の「認証の窓口」に、ターミナルがつながらなくなっていたのが原因で、ターミナルを開き直すと直りました。詳しくは、Git のつまずきをまとめた番外編で紹介しています。
VS Code の PATH が、サーバーの設定に紛れ込む
VS Code のターミナルには、VS Code 自身が使うフォルダ(~/.vscode-server/…)が、コマンドを探す場所の一覧(PATH)に追加されています。そのため、ターミナルの PATH をそのまま書き込むようなコマンドを実行すると、サーバーの設定に VS Code の都合が紛れ込みます。私の場合は、PM2 の自動起動の設定でこれが起きました。詳しくは、第2回で紹介しています。
設定を変えても、接続し直すだけでは反映されないことがある
SSH の設定ファイル(config)を書き換えた後、左下の表示から「リモート接続を閉じる」で接続し直しても、新しい設定が効かないことがあります。VS Code が、裏で前の接続を使い回すことがあるためです。
そのときは、F1 →「Remote-SSH: Kill VS Code Server on Host…」で接続先を選び、サーバー側の VS Code Server をいったん止めてから接続し直します。
まとめ
Remote-SSH を組み込みの言葉に置き換えると、次のようになります。
| Remote-SSH の要素 | 組み込みでいうと |
|---|---|
| 手元の VS Code と、サーバーの VS Code Server | 手元のエディタ・デバッガと、ターゲット上のデバッグモニタ |
| SSH の1本の接続 | デバッガのケーブル(すべての信号がこの中を通る) |
| ポート転送 | ケーブルの中に通してもらう、もう1本の信号線 |
| 秘密鍵と公開鍵 | セキュアエレメントの中の鍵と、相手に渡して照合してもらう情報 |
| 初回接続の指紋の確認 | 初回のペアリングで相手のデバイス ID を確かめる |
| VS Code による GitHub の認証 | 鍵は手元から出さず、署名だけを代行してもらう |
一度設定してしまえば、普段は VS Code を開いて接続先を選ぶだけで、サーバー上のファイルとターミナルを、手元のパソコンと同じ感覚で使えます。開発した場所がそのまま本番のサーバーなので、「手元では動いたのに、サーバーでは動かない」という問題が起きにくいのも、自宅サーバーで学ぶうえでの大きな利点だと感じています。
この記事は、シリーズ「組み込みエンジニアの Web 開発入門」の1本です。ほかの回は、シリーズの目次からどうぞ。



コメント