← All notes

Technical note · 03

リバースプロキシとTailscale Funnel

自宅のサービスを一つの入口から公開する

リバースプロキシの役割から、NginxとTailscale FunnelでHTTPS公開する安全な手順まで。

Published
2026.09.02
Updated
2026.09.02
Reading
16 min
01

リバースプロキシとは何か

リバースプロキシは、利用者からのリクエストを最初に受け取り、内側にある適切なアプリへ転送して、返ってきた応答を利用者へ返す入口です。利用者はNextcloudや開発ツールの実際のIP・ポートを直接知る必要がありません。

Nginxはホスト名やURLのパスを見て転送先を選べます。HTTPSの処理、アクセスログ、WebSocket用ヘッダーなども入口へまとめられるため、サービスごとに外部公開設定を持たせるより管理しやすくなります。

  • ↳外側: https://[Tailscaleが発行した公開URL]
  • ↳入口: Tailscale FunnelまたはNginx
  • ↳内側: http://[転送先アプリのアドレス]:[転送先アプリのポート番号]
  • ↳返答は同じ入口を通ってブラウザへ戻る
02

公開範囲を先に決める

Tailscale Serveは同じtailnetに参加している端末だけへ共有する方法です。Tailscale Funnelはインターネット上の誰でもアクセスできるURLを作ります。個人用の管理画面やNextcloudは、まずServeまたは通常のTailscale接続を検討し、Funnelは本当に公開が必要な場合だけ使います。

ここでは、Nginxをローカルの入口として動かし、そのNginxだけをFunnelで公開する構成を扱います。バックエンドの各ポートを直接インターネットへ開けません。

03

Tailscaleを導入する

Linux用の公式インストールコマンドはcurlから始まります。『sudo -fsSL』はコマンドとして成立しないため使いません。インストール後にtailscale upを実行し、表示されたURLで認証します。

FunnelにはMagicDNSとHTTPS Certificatesが必要です。管理コンソールのDNSでMagicDNSを有効にし、HTTPS Certificatesも有効にします。元メモの『HTTPS Certificatesをdisableにする』は逆なので修正しました。

EXAMPLEcurl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

# 接続を確認
tailscale status
tailscale ip -4
  • ↳Tailscale v1.38.3以降
  • ↳MagicDNSを有効化
  • ↳HTTPS Certificatesを有効化
  • ↳Funnelを許可するtailnetポリシー
  • ↳公開URLはtailnetの.ts.netドメイン
04

Nginxをローカル入口にする

Nginxは、この端末だけから接続できるアドレスと未使用のポートで待ち受け、LAN内のアプリへ転送します。Funnelが受けたHTTPS通信をNginxの待受先へ渡し、Nginxが指定したアプリへ転送する流れです。角括弧の日本語部分を、自分の環境に合う値へ置き換えます。

EXAMPLEsudo apt update
sudo apt install nginx
sudo nano /etc/nginx/sites-available/reverse-proxy

# reverse-proxy の内容
server {
    listen [この端末だけを示すアドレス]:[Nginxの待受ポート番号];
    server_name _;

    location / {
        proxy_pass http://[転送先アプリのアドレス]:[転送先アプリのポート番号];
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
05

設定を有効化してテストする

設定ファイルをsites-enabledから参照できるようにし、必ず構文テストを通してから再読み込みします。すでに同名のリンクがある場合はlnを繰り返さず、現在の参照先を確認します。

EXAMPLEsudo ln -s /etc/nginx/sites-available/reverse-proxy   /etc/nginx/sites-enabled/reverse-proxy

sudo nginx -t
sudo systemctl reload nginx

# Nginx単体をローカル確認
curl -I http://[この端末だけを示すアドレス]:[Nginxの待受ポート番号]
  • ↳nginx -t が successful になる
  • ↳Nginxの待受先が応答する
  • ↳転送先アプリが起動している
  • ↳Nginxのaccess.logとerror.logを確認できる
06

FunnelでHTTPS公開する

現在のTailscale CLIでは、公開したいローカルの転送先を最後に指定します。Funnelが対応するHTTPS公開ポートで通信を受け、同じ端末で動くNginxの待受先へHTTPで渡します。利用できる公開ポートは、実行前にTailscale公式資料で確認します。

--bgを付けると再起動後も設定が復元されます。表示された公開URLをメモし、シークレットウィンドウなどtailnet外の環境から確認します。

EXAMPLEsudo tailscale funnel --bg --https=[Tailscaleが対応するHTTPS公開ポート番号] http://[この端末だけを示すアドレス]:[Nginxの待受ポート番号]

# 現在の公開状態
sudo tailscale funnel status

# すべてのFunnel設定を解除
sudo tailscale funnel reset
07

複数サービスを管理する

一つの端末には基本的に一つのTailscale用ドメイン名があります。同じ端末で複数サービスを扱う場合は、NginxでURLのパスを分ける、待受ポートを分けてFunnelが対応する公開ポートへ割り当てる、またはサービスごとにTailscaleノードを分けます。存在しない別端末名をserver_nameへ書くだけでは新しいURLは作られません。

EXAMPLEserver {
    listen [この端末だけを示すアドレス]:[Nginxの待受ポート番号];
    server_name _;

    location /[一つ目のアプリを示すパス]/ {
        proxy_pass http://[一つ目のアプリのアドレス]:[一つ目のアプリのポート番号]/;
    }

    location /[二つ目のアプリを示すパス]/ {
        proxy_pass http://[二つ目のアプリのアドレス]:[二つ目のアプリのポート番号]/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
08

独自ドメイン+Nginxで直接公開する別案

独自ドメイン、Let's Encrypt証明書、NginxのHTTPS公開ポートを使う構成はTailscale Funnelとは別の公開方法です。DNSを自分の公開アドレスへ向け、ルーターとファイアウォールでWeb通信に必要なポートへ到達できるようにし、証明書を取得する必要があります。賃貸回線やCGNATでは使えない場合があります。

転送先がTailscale内にある場合、Nginxを動かす端末も同じtailnetへ参加させます。証明書パスはCertbotなどが実際に作成した場所を使います。

EXAMPLEserver {
    listen [HTTPSで使う公開ポート番号] ssl;
    server_name [自分の独自ドメイン];

    ssl_certificate [発行された証明書ファイルの場所];
    ssl_certificate_key [発行された秘密鍵ファイルの場所];

    location / {
        proxy_pass http://[転送先アプリのアドレス]:[転送先アプリのポート番号];
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
09

ファイアウォールは必要最小限にする

Funnelから同じ端末のNginxへ渡す構成では、Nginxの待受ポートをUFWで外部へ開ける必要はありません。待受ポートを無条件で許可すると、Nginxの設定によってはLANや公開インターフェースから直接到達でき、Funnelを通す意味が薄れます。

独自ドメインで直接公開する構成だけ、Web通信に必要な公開ポートを開けます。管理用SSHや転送先アプリのポートは送信元を限定します。

EXAMPLEsudo ufw status verbose

# 独自ドメインでNginxを直接公開する場合の例
sudo ufw allow [HTTPSで使う公開ポート番号]/tcp
10

Nginxが起動しないとき

systemdの『ExecStartPre process exited』『status=1』は、起動前の設定確認に失敗したという結果です。原因そのものはnginx -tやjournalctlの少し上に表示されます。設定を増やす前に、最初のエラー一件を修正します。

EXAMPLEsudo nginx -t
sudo systemctl status nginx --no-pager
sudo journalctl -u nginx -n 100 --no-pager
sudo ss -ltnp

# 設定ファイルと有効化リンクを確認
ls -l /etc/nginx/sites-enabled/
sudo nginx -T
  • ↳セミコロン、波括弧、http://の書き忘れ
  • ↳同じポートを別プロセスが使用
  • ↳sites-enabledのリンク切れ
  • ↳同じserver_nameやlisten設定の重複
  • ↳証明書ファイルが存在しない、または権限不足
  • ↳proxy_pass先のアプリが停止
NEXT NOTE

Infrastructure / Homelab

自宅サーバーの構成メモ

→