cd ~/blog/tailscale-remote-access

2026-07-22

ローカルで動いているWebサービスを出先で利用する方法

TailscaleVPNmacOSセキュリティリモートアクセス

はじめに

自作のWebアプリをMac上でローカル起動して使っているのですが、外出中に「あれどうなってたっけ」と確認したくなる場面が増えてきました。このアプリには認証機能がなく、データがそのまま画面に出ます。

真っ先に思いついたのは ngrok のようなトンネリングサービスですが、これは誰でもアクセスできる公開URLを発行する方式です。URLさえ知られればデータが世界中から見える状態になるため、今回の用途には危険すぎます。かといって、ローカル専用の個人アプリにわざわざログイン機能を実装するのも過剰投資に感じました。

そこで採用したのが Tailscale です。この記事では、認証なしのローカルWebアプリを、自分専用の閉じたネットワーク越しにスマホから安全に見られるようにするまでの手順をまとめます。

なぜTailscaleか

Tailscale は各端末間にプライベートなVPNメッシュ網(WireGuardベース)を作るツールです。同じTailscaleアカウントでログインした端末同士でしか繋がらない閉じたネットワーク(Tailnet)なので、アプリ側に認証機能を追加しなくても、自分専用の安全なリモートアクセスを作れます。

ngrok が不特定多数に公開URLを発行する方式なのに対し、Tailscaleは特定の端末同士だけを直接繋ぐ方式です。公開URLという第三者の入り口を作らない分、個人利用のローカルアプリとは相性が良いと感じました。

セットアップ手順

  1. Mac側にインストール: brew install --cask tailscale(Homebrewが使える場合)。App Store版でもよい
  2. Tailscaleアプリを開いてログイン(Google/GitHub/Microsoft等のSSOアカウントでよい)
  3. システム設定でVPN構成の許可を求められたら許可する
  4. スマホ側にもTailscaleアプリをインストールし、同じアカウントでログイン
  5. これでMacとスマホが同じTailnet(プライベートネットワーク)に参加した状態になる。MacのTailscale IP(100.x.y.z)またはMagicDNS名(Tailscale管理画面で確認可能)を使えば、スマホからMacへ直接アクセスできる

ここまでで、Mac・スマホ双方がお互いを見つけられる状態になります。

アプリ側の設定変更

Tailscaleでネットワークを繋いだだけでは、まだスマホからアプリに届きません。デフォルトの uvicorn は 127.0.0.1(ローカルホストのみ)にバインドされるため、Tailscale経由でも外から届かないのです。ホストを 0.0.0.0 に変更する必要があります。

uvicornはPython製のASGIサーバーで、FastAPIなどのアプリを実際にHTTPサーバーとして起動する役割を担います。

Bash
# 変更前(README.mdの元の起動コマンド)
uvicorn main:app --reload

# 変更後(LAN/Tailscale経由でも到達可能にする)
uvicorn main:app --reload --host 0.0.0.0 --port 8000

スマホからは http://<MacのTailscale IPまたはMagicDNS名>:8000/ でアクセスします。ここで初めて、出先からローカルアプリの画面が開けるようになりました。

--host 0.0.0.0 はTailnet内の端末だけでなく、同じLAN上の全端末からも到達可能になる設定です。Tailscaleの閉域網に閉じたい場合は、ファイアウォールやアプリ側のバインド設定でLAN側からのアクセスを絞る必要があります。

サーバーが動いている間だけスリープを止める

ここまでで出先からアクセスできるようになりましたが、Macがスリープしてしまうとサーバーごと止まってしまいます。かといって常時スリープさせない設定にすると、バッテリー消費や普段使いへの影響が気になります。そこで、サーバープロセスが動いている間だけスリープを防止する方法を使いました。

caffeinate コマンドに実行したいコマンドをそのまま渡すと、そのコマンド(子プロセス)が生きている間だけスリープを防止し、コマンドが終了する(Ctrl+Cでサーバーを止める等)と同時にスリープ防止も解除されます。

Bash
caffeinate -s uvicorn main:app --reload --host 0.0.0.0 --port 8000
  • -s: システムスリープを防止するフラグ(ディスプレイスリープは防止しない)
  • これにより、普段は通常通りスリープするMacも、サーバーを起動している間だけは起きたままになり、外出先からいつでもアクセスできる
  • サーバーを止めれば通常のスリープ挙動に戻るので、常時スリープ無効化するより電力面で扱いやすい

Tailscale IPは固定か

Tailscaleの私設IP(100.64.0.0/10の範囲)は、端末がTailnetに参加した時点で割り当てられ、再起動・スリープ復帰・Wi-Fi切り替えをしても変わりません。デバイスをTailnetから削除して再参加させない限り固定なので、スマホのホーム画面にショートカット(ブックマーク)を作って毎回同じURLでアクセスできます。

数字を覚えたくない場合は、Tailscale管理画面(login.tailscale.com/admin/machines)で確認できるMagicDNS名(http://<デバイス名>.<tailnet名>.ts.net:8000/)を使う方法もあります。こちらもIPと同様に固定です。

セキュリティ上の注意点

Tailscaleの閉域網内であっても、アプリ自体に認証がない点は変わりません。同じTailnetに参加する端末が増える場合は注意が必要です。必要であれば、Tailscaleの「Tailnet lock」や、アプリ側にBasic認証を追加することも検討できます。

参照