前提条件
- GitHubのアカウントを所有している
- GitHub CLIを導入している
- Tailscaleのアカウントを所有している
- VPS: Ubuntu 26.04
Tailscaleのアカウントは、GitHubアカウントやGoogleアカウントがあればそれを使用して作成できます。
Tailscale公式サイト
GitHub CLIの導入方法
Tailscaleを導入する
VPSにデプロイするだけならLinuxの導入手順だけをこなしてくれれば大丈夫ですが、今後クライアント側の接続もTailscale SSHに切り替えることで以下のメリットがあります。
- VPS側のPublic SSHを閉じることができ、ポートスキャンやSSH接続試行の対象そのものから外せる
- VPSを提供するサービス側でパケットフィルター設定を都度変更する必要がない
Windows / macOSの場合
以下のリンクから対象のOSを選択してダウンロードできます。
ダウンロード後はファイルを実行して、先ほど作成したアカウントを使用してログインしてください。
Linuxの場合
この方法は以下のディストリビューションに対応しています。
- Debian-based distributions
- Ubuntu-based distributions
- Red Hat Enterprise Linux (RHEL), CentOS, Fedora, and derivatives
- Raspberry Pi OS
- Amazon Linux
- openSUSE and SUSE Linux Enterprise
- Oracle Linux
- VMware Photon OS
その他のディストリビューションを使用している場合は以下のリンクから確認してみてください。
以下のコマンドでインストールします。
curl -fsSL https://tailscale.com/install.sh | sh
インストールが完了したらTailscaleのクライアントを起動します。
sudo tailscale up
接続状態を確認する
ここはWindows, macOS, Linux全て共通です。
デバイスに割り当てられたTailscale IPv4/IPv6アドレスを表示する
tailscale ip
デバイスの接続状況を表示する
tailscale status
なお、ブラウザでも接続状態は確認可能です。以下のリンクから確認してみてください。
Tailscale SSHを使用する
ざっくりいうと、Tailscale SSHを使用することでTailscale側がマシンへのSSHアクセスを管理してくれます。既存のSSHポートをパブリックネットワークに公開することなく、SSHアクセスを安全に保護することができます。
デプロイ先のVPSで以下のコマンドを実行します。
tailscale set --ssh
何も表示されないと思います。管理者用のマシン一覧ページ(https://console.tailscale.com/admin/machines) を確認して、サーバーのマシン名に「SSH」のラベルが追加されていれば成功です。
キーの有効期限切れを無効にする場合
Tailnet内のデバイスは、一定期間後にキーの有効期限が切れるようになっています。これは定期的に再認証を行うことで、セキュリティを維持することを目的としています。しかし、サーバやDockerホスト、NASのデバイスといった常時接続が必要なデバイスではキーの有効期限を無効にすることができます。
管理者用のマシン一覧ページ(https://console.tailscale.com/admin/machines) から、各マシンの右側にある横の三点リーダー(…)をクリックしてDisable Key Expiryをクリックします。
しかし、キーの有効期限を無効にするとセキュリティが低下し、デバイスまたはキーが侵害された場合にネットワークが危険にさらされる可能性もあります。信頼できるデバイスに対してのみこの設定を行い、デバイスを紛失したり交換したりした場合は直ちにキーを失効するなどの対応を取りましょう。
タグを設定する
ブラウザの管理画面からAccess controls -> JSON editorを探して開きます。Edit fileのセクションには以下のような記述があると思います。
// Example/default ACLs for unrestricted connections.
{
// Declare static groups of users. Use autogroups for all users or users with a specific role.
// "groups": {
// "group:example": ["alice@example.com", "bob@example.com"],
// },
// 以下略
}
まずはtagOwnersを探して、以下のように編集します。
tag:ciはGitHub Actions用のタグで、tag:vpsはサーバ用のタグです。タグの名前は分かれば何でも良いです。
"tagOwners": {
"tag:ci": ["autogroup:admin"],
"tag:vps": ["autogroup:admin"],
},
次にgrantsを探して、以下のように編集します。
grantsは指定したタグ/グループが、どのタグが付いているマシンに、どのポートで接続可能かを記述しています。
ここで指定するポートはTailnetにおけるものなので、SSH接続を行う場合は22のままで基本は大丈夫です。
"grants": [
// Allow all connections.
// Comment this section out if you want to define specific restrictions.
{"src": ["tag:ci"], "dst": ["tag:vps"], "ip": ["tcp:22"]},
],
つまり、上記の記述ならciタグがついたマシンはvpsタグが付くマシンに向かってTailnet内ポート22番で接続できることを意味するのです。
最後に、sshを探して以下のように編集します。デプロイ先サーバーのユーザー名だけ変えてください。
actionのタイプにはcheckとacceptがありますが、GitHub ActionsでSSHする際はacceptを記述する必要があります。
"ssh": [
// Allow all users to SSH into their own devices in check mode.
// Comment this section out if you want to define specific restrictions.
{
"action": "accept",
"src": ["tag:ci"],
"dst": ["tag:vps"],
"users": ["デプロイ先サーバーのユーザー名"],
},
],
変更が問題なければ、画面下のSaveで変更を保存しましょう。
VPSにタグを付与する
Tailscaleの管理者用のマシン一覧ページから対象のVPSを探し、右側にある横の三点リーダー(…)→Edit ACL Tagsをクリックします。
Edit ACL tags for <マシン名> の部分では、プルダウンでタグを設定できます。先ほど作成したtag:vpsを選択してSaveしておきましょう。
tag:ciはGitHub Actionsでのみ使用します。
TailscaleのOIDC(OpenID Connect) Clientを作成する
この手順を踏む前に、GitHub Actionsを動かす対象のGitHubリポジトリが作成されている必要があります。ご注意ください。
GitHubのリポジトリの作成日によって、以下の説明で紹介する「Subjectの値を組み立てる」方法が若干異なります。2026年7月15日以降にGitHubリポジトリを作成した場合はそのまま読み進めてください。
それ以前に作成したリポジトリで作業を進める場合は、別記事「GitHubリポジトリのOIDC設定でImmutable subject claimを有効化する」にて手順を解説していますので、そちらを参考にしてください。
最初のステップ
Tailscaleの管理画面から、Settings -> Trust credentialsを開きます。画面右上の + Credentialを押して進みます。
OAuthとOpenID Connectがありますが、今回はOpenID Connectを使用します。
Descriptionは任意なので、今回は記述せずに進みます。
Issuerはプルダウンで選択できます。今回はGitHub Actions Runnerを使用するので、GitHubを選択してください。選択すると、自動的にIssuer URLは埋まるはずです。
Subjectの値は、GitHubのリポジトリごとに異なります。以下の手順で取得しましょう。
GitHub CLIでリポジトリの情報を取得する
まずはリポジトリの情報を取得します。user-or-org-nameは自分のGitHubのアカウント名(またはOrganization名)、repo-nameはリポジトリの名前に変えて実行してください。
gh api repos/user-or-org-name/repo-name \
--jq '{
owner: .owner.login,
owner_id: .owner.id,
repository: .name,
repository_id: .id
}'
実行結果の例は以下の通りです。
{
"owner": "TouchKot723",
"owner_id": 111111111,
"repository": "Tailscale-ssh-deploy-sample",
"repository_id": 2222222222
}
owner_idとrepository_idの値がSubjectの組み立てに必要となります。
Subjectの値を組み立てる
2026年7月15日以降に作成されたGitHubリポジトリでは、Subjectの値は以下のように入力する必要があります。
repo:octocat@123456/my-repo@456789:ref:refs/heads/main
引用元
実行結果の例をもとに反映すると以下のようになります。
repo:TouchKot723@111111111/Tailscale-ssh-deploy-sample@2222222222:ref:refs/heads/main
上記の例を参考にしてSubjectの値を組み立てたら、Subjectの部分に入力してください。
なお、Custom claimsの部分は空欄のままで大丈夫です。Continue → を押して進みます。
Scopeの設定
Keys -> Auth Keysを探して、Writeにチェックを入れます。
するとその下に Tags (required for write scope) と書かれたセクションが出現するので、タグを選択してください。今回は、先ほど作成したGitHub Actions用のtag:ciを選択しておきます。
それ以外の設定は特に変更しません。Generate credentialを押しましょう。
Credential createdと書かれたカードが出現すれば成功です。Client IDとAudienceの値が表示されるので、控えておきましょう(Trust Credentialsの一覧でも確認は可能です)。
GitHub Secretsを登録する
対象のGitHubリポジトリのSecretsに、4つの値を記録します。
| Secret名 | 用途 |
|---|---|
| TS_AUDIENCE | 先ほど控えたAudienceの値 |
| TS_OAUTH_CLIENT_ID | 先ほど控えたClient IDの値 |
| VPS_SSH_USER | VPSのユーザー名 |
| VPS_TAILSCALE_HOST | デプロイ先サーバーのIPv4アドレス |
Secretsの登録方法は省略します。
GitHub Actions用のymlファイルを作る
対象のリポジトリ内の.github/workflows/にdeploy.ymlファイルを作成しましょう。
ファイルの中身は以下を参考にしてください。
name: SSH to VPS over Tailscale
on:
workflow_dispatch:
permissions:
id-token: write
jobs:
ssh:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Connect to Tailscale
uses: tailscale/github-action@v4
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
audience: ${{ secrets.TS_AUDIENCE }}
tags: tag:ci
ping: ${{ secrets.VPS_TAILSCALE_HOST }}
- name: Run a command on the VPS
env:
VPS_TAILSCALE_HOST: ${{ secrets.VPS_TAILSCALE_HOST }}
VPS_SSH_USER: ${{ secrets.VPS_SSH_USER }}
run: |
tailscale ssh "$VPS_SSH_USER@$VPS_TAILSCALE_HOST" \
"hostname && uptime"
これを作成したら、変更をコミットしてGitHubにプッシュしてください。
GitHub Actionsを実行する
GitHubのリポジトリのページにアクセスして、Actionsタブを開きます。
左側のメニューから、先ほど作成したワークフロー(SSH to VPS over Tailscale)を選択して、Run workflowボタンを押します。
問題なくワークフローが終了していればOKです。
ワークフロー内のRun a command on the VPSを確認してみましょう。下に実行結果の例を表示しておきます。
Run tailscale ssh "$VPS_SSH_USER@$VPS_TAILSCALE_HOST"
<ここにVPSのマシン名が表示されます>
16:24:16 up 2 days, 17:07, 3 users, load average: 0.05, 0.11, 0.07
これでTailscale + GitHub Actionsを使用してVPSにSSH接続してコマンドを実行することができました。
スクリプトをしっかり組めばデプロイを行うこともできます。また、今回はチュートリアルでmainブランチだけを想定しましたが、複数のブランチに対しても同じように設定してCI / CDを実現することができます。ではよきDevOpsライフを!




