Connector · Docker
Connector をコンテナーで実行——受信ポートなし。
公式イメージ ghcr.io/termalinapp/termalin-connector は、Termalin Connector をネットワーク上の任意のマシンで 1 つのコンテナーとして実行します——NAS、ホームラボ、ルーター、Kubernetes クラスター、ECS サービスなど。Termalin へ外向きに接続し、そのネットワーク上のサーバー、内部サイト、デスクトップに到達します。受信ポートを一切開きません。約 4 MB、amd64/arm64、uid 10001 で動作します。
amd64 / arm64 · 受信ポート不要 · Pro(または 14 日間のトライアル)
01 / コンテナーを使う理由
ネットワーク上に 1 つのコンテナー。開放するポートなし。
Connector を使うと、受信ポートも、サーバー上に残り続ける鍵もなしで、Termalin からプライベートなマシンに到達できます。マシンによっては、バイナリとサービスをインストールするより、コンテナーとして追加するほうが簡単です。コンテナーしか動かせないマシンもあります。このイメージはそうしたマシンに適しています。
- ▸NAS やホームラボ。LAN 上の Synology、Unraid、Docker ホストなど。そのマシン自身の SSH にも、ネットワーク上の他のサーバー・サイト・デスクトップにも到達できます。
- ▸ルーター。MikroTik RouterOS 7 はコンテナーを動かせます。その 1 つに Connector を入れれば、ルーター自身とその背後のすべてに到達できます。
- ▸Kubernetes。レプリカ 1 の Deployment で、クラスター内のサービスに内部アドレスで到達できます。
- ▸AWS ECS / VPC。アウトバウンドの HTTPS だけを許可した Fargate または EC2 のタスクが——ロードバランサーも受信ルールもなしで——プライベートなインスタンス、内部サイト、デスクトップに到達します。
02 / イメージ
4 メガバイト、シェルなし、SSH サーバーなし。
イメージは ghcr.io/termalinapp/termalin-connector:<version>(および :latest)で、linux/amd64 と linux/arm64 に対応します。
- ▸約 4 MB。静的ビルドの Connector と CA 証明書だけで、ほかには何も入っていません——シェルも、パッケージマネージャーも、SSH サーバーもありません。uid 10001 で動作し、設定は
/dataボリュームに保存します。 - ▸公開の場でビルド。公開リポジトリ
termalinapp/termalinで、termal.in に公開された署名付きのリリースバイナリだけからビルドされます。各バイナリはイメージに入る前に、リリースマニフェストとその署名に照らして検証されます。 - ▸armv7 はまだビルドしていません(32 ビット ARM)。今のところ amd64 と arm64 のみです。
03 / クイックスタート
1 回の docker run でコンテナーを登録。
キャビネットで登録トークンを取得し(「Connector を追加」)、次を実行します。
docker run -d --name termalin --restart unless-stopped \ -v termalin:/data \ -e TERMALIN_TOKEN=<token> \ -e TERMALIN_TARGET=192.168.1.10:22 \ -e TERMALIN_USER=deploy \ ghcr.io/termalinapp/termalin-connector
変数は次のとおりです。
| 変数 | 説明 |
|---|---|
TERMALIN_TOKEN | 登録トークン。ボリュームにまだ設定がない初回起動時のみ使われます。 |
TERMALIN_TARGET | ターミナル・コマンド・ファイルの接続先となる SSH サーバーの host:port(Docker ホスト、または別のマシン)。コンテナー内の 127.0.0.1 はコンテナー自身を指し、そこには SSH サーバーがありません。 |
TERMALIN_USER | その SSH サーバーのログインユーザー(既定:アカウントの既定値)。 |
TERMALIN_NAME | キャビネットでの名前(既定:コンテナーのホスト名。--hostname かこの変数で設定します)。 |
TERMALIN_SERVER | 既定は https://termal.in。 |
初回起動:/data に設定がなくトークンが設定されていれば、コンテナーは登録を行い、下記のサインイン行を出力して接続します。以降の起動は接続するだけです——トークンは環境変数に残しておいて構いません。再送はされません。設定もトークンもない場合は、その旨を表示して終了コード 1 で終了します。docker stop ですぐに停止します。もう一度登録するには、ボリュームを削除して新しいトークンで起動します。
04 / サインイン行
ターゲット側で証明書を信頼する。
コンテナー内の Connector がターゲットに触れることはありません。登録時に、このアカウント専用の Termalin の短期証明書がサインインできるようにする行を出力します。docker exec termalin termalin-agent check でも同じ行を再表示できます。
cert-authority,principals="termalin-<account id>" ssh-ed25519 AAAA… termalin-connector
これをターゲットのログインユーザーの ~/.ssh/authorized_keys に追加します(1 行、ファイルのモードは 600、~/.ssh は 700)。root で管理しているサーバーなら、代わりにその sshd_config に TrustedUserCAKeys と AuthorizedPrincipalsFile を追加することもできます——check は両方を出力します。これがないと、この Connector 経由のターミナルとコマンドはターゲットに拒否されます。ウェブリンクとデスクトップには不要です。check はターゲットの SSH サーバーが応答するか(sshd=up)も報告します。サインインの状態は ca=unknown になります。コンテナー内からはターゲットのファイルを読めないためです。
05 / SSH サーバー不要
内部サイトとデスクトップは、どこにも sshd なしで。
内部サイトとリモートデスクトップ(RDP、VNC)は SSH を経由しません。バックエンドが Connector に対して、サイトやデスクトップ自身の host:port への接続を開くよう要求し、Connector がそこへ直接つなぎます。そのため、VPC や ECS サービス、自宅ネットワークの中のコンテナーは、SSH サーバーが一切なくても内部サイトやデスクトップを公開できます。データベースパスワードを使うデータベースページも、データベースのポートに対して同じように動きます。
- ▸プライベートアドレスのみ。接続先はプライベートネットワーク上になければなりません——RFC 1918、ループバック、リンクローカル、CGNAT の
100.64/10(Tailscale など)、IPv6 ULA。Connector はインターネットへのリレーではなく、クラウドのメタデータアドレス(169.254.169.254など)は常に拒否されます。 - ▸ターゲットに SSH サーバーが必要なもの:ターミナル、
ssh_execなどのコマンド系ツール、SFTP 経由のファイル、パスワード不要のデータベースツール、メトリクス、バックアップ。TERMALIN_TARGETを設定し、そこにサインイン行を追加してください。
06 / docker compose
同じ内容を compose ファイルで。
services:
termalin:
image: ghcr.io/termalinapp/termalin-connector:latest
restart: unless-stopped
hostname: office-nas
environment:
TERMALIN_TOKEN: ${TERMALIN_TOKEN}
TERMALIN_TARGET: 192.168.1.10:22
TERMALIN_USER: deploy
volumes:
- termalin:/data
volumes:
termalin: Docker ホスト自身に到達するには、その LAN アドレスを使うか、Docker Desktop では host.docker.internal:22 を使います(Linux では extra_hosts: ["host.docker.internal:host-gateway"] を追加します)。
07 / NAS
Synology と Unraid。
- ▸Synology(Container Manager):Registry で
ghcr.io/termalinapp/termalin-connectorを追加し、上記の変数と/data用のボリュームを指定してコンテナーを作成し、「自動再起動」をオンにします。ターミナルを使うには Control Panel → Terminal & SNMP で SSH を有効にし、TERMALIN_TARGET=<NAS address>:22を設定します。 - ▸Unraid:Docker → Add Container で、リポジトリに
ghcr.io/termalinapp/termalin-connector、パス/data→/mnt/user/appdata/termalin、変数をコンテナー変数として設定します。 - ▸バインドマウントしたフォルダーは uid 10001 が書き込めるようにする必要があります(
chown 10001:10001 /mnt/…/termalin)。名前付きボリュームなら Docker が用意してくれます。
08 / MikroTik RouterOS 7
ルーター自身の上で。
今のところ arm64 と x86 のルーターに対応します(armv7 ビルドはまだありません)。container パッケージとデバイスモードを有効にし、次を実行します。
/interface/veth add name=veth-termalin address=172.17.0.2/24 gateway=172.17.0.1
/interface/bridge/port add bridge=containers interface=veth-termalin
/container/envs add name=termalin key=TERMALIN_TOKEN value=<token>
/container/envs add name=termalin key=TERMALIN_TARGET value=192.168.88.1:22
/container/mounts add name=termalin-data src=/usb1/termalin dst=/data
/container add remote-image=ghcr.io/termalinapp/termalin-connector:latest \
interface=veth-termalin envlist=termalin mounts=termalin-data \
root-dir=/usb1/termalin-root start-on-boot=yes logging=yes これは、MikroTik 公式のコンテナーガイドと同じく、172.17.0.1/24 を持つブリッジ containers と外向きの NAT があることを前提としています。ルーター自身の SSH(/ip/service enable ssh)か、その背後の任意のホストを対象にできます。
09 / Kubernetes
レプリカ 1 つ、Secret 1 つ、小さな PVC。
apiVersion: v1
kind: Secret
metadata: { name: termalin }
stringData: { token: "<token>" }
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: termalin-data }
spec:
accessModes: [ReadWriteOnce]
resources: { requests: { storage: 16Mi } }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: termalin-connector }
spec:
replicas: 1
strategy: { type: Recreate }
selector: { matchLabels: { app: termalin-connector } }
template:
metadata: { labels: { app: termalin-connector } }
spec:
securityContext: { runAsUser: 10001, runAsGroup: 10001, fsGroup: 10001, runAsNonRoot: true }
containers:
- name: connector
image: ghcr.io/termalinapp/termalin-connector:0.2.3
env:
- { name: TERMALIN_TOKEN, valueFrom: { secretKeyRef: { name: termalin, key: token } } }
- { name: TERMALIN_TARGET, value: "10.0.12.7:22" }
- { name: TERMALIN_NAME, value: "k8s-prod" }
securityContext: { readOnlyRootFilesystem: true, allowPrivilegeEscalation: false, capabilities: { drop: [ALL] } }
resources: { requests: { cpu: 10m, memory: 16Mi }, limits: { memory: 64Mi } }
volumeMounts: [{ name: data, mountPath: /data }]
volumes:
- { name: data, persistentVolumeClaim: { claimName: termalin-data } } 内部サービスには、ウェブリンクでクラスターアドレスを使って到達します——http://grafana.monitoring.svc:3000 はクラスター DNS を通じてプライベートアドレスに解決されます。登録 1 つにつきレプリカは 1 つにしてください。同じボリュームを使う 2 つの Pod は、同じ Connector が二重に動くことになります。
10 / AWS ECS
Fargate または EC2 のタスク、アウトバウンドのみ。
desired count を 1 にしたサービスに、上記のイメージ、Secrets Manager のトークンを TERMALIN_TOKEN として、そして /data に EFS ボリューム(所有者は 10001——uid/gid 10001 の EFS アクセスポイント)を設定します。必要なのは termal.in への外向きの HTTPS だけです——ロードバランサーも受信ルールも不要です。ターゲット側のセキュリティグループは、使用するポート(22、3389、各サイトのポート)でタスクからの接続を許可する必要があります。ECS のタスクメタデータアドレスは、ほかのすべてのメタデータアドレスと同様に拒否されます。
11 / アップデートと制限
新しいタグを pull する。コンテナーにできないこと。
- ▸アップデート。コンテナーが自分でアップデートすることはありません——新しいタグを pull してコンテナーを作り直します(
docker compose pull && docker compose up -d、または Deployment の新しいイメージタグ)。ボリュームが登録情報を保持します。キャビネットにこのコンテナー用の「今すぐ更新」は表示されません。 - ▸SSH 系の機能にはターゲットが必要。ターミナル、コマンド、ファイル、パスワード不要のデータベース、メトリクス、バックアップには、ターゲット上の SSH サーバーとそこに追加するサインイン行が必要です。イメージ自体は SSH サーバーを持ちません。
- ▸Connector 1 つにつきターゲットの SSH サーバーは 1 つ(
TERMALIN_TARGET)。ウェブリンクとデスクトップは任意のプライベートアドレスを指定できます。 - ▸armv7(32 ビット ARM)はまだビルドしていません。
よくある質問
対応アーキテクチャとイメージのサイズは?
linux/amd64 と linux/arm64 に対応するマルチアーキテクチャのイメージで、サイズは約 4 MB です。静的ビルドの Connector と CA 証明書だけで、ほかには何も入っていません——シェルも、パッケージマネージャーも、SSH サーバーもありません。uid 10001 で動作し、設定は /data ボリュームに保存します。armv7(32 ビット ARM)はまだビルドしていません。
イメージはどこで作られていますか?
公開の場でビルドされています。公開リポジトリ termalinapp/termalin で、termal.in に公開された署名付きのリリースバイナリだけからビルドされます。各バイナリはイメージに入る前に、リリースマニフェストとその署名に照らして検証されます。
コンテナーの中や隣に SSH サーバーは必要ですか?
内部サイト、リモートデスクトップ(RDP/VNC)、データベースページには不要です——これらは Connector を通じてターゲット自身の host:port に直接つながるので、VPC や自宅ネットワークの中のコンテナーは どこにも sshd なしで公開できます。一方、ターミナル、コマンド、SFTP のファイル、パスワード不要のデータベースツール、メトリクス、バックアップには、ターゲット(TERMALIN_TARGET)上の SSH サーバーと、そこに追加するサインイン行が必要です。イメージ自体には SSH サーバーがありません。
コンテナーはどうやってアップデートしますか?
コンテナーが自分でアップデートすることはありません。新しいタグを pull して作り直します——docker compose pull && docker compose up -d、または Deployment の新しいイメージタグです。/data ボリュームが登録情報を保持するので、登録をやり直す必要はありません。キャビネットにコンテナー用の「今すぐ更新」は表示されません。
費用はいくらで、どのプランが必要ですか?
Connector はホスト型の機能なので、Pro または 14 日間のトライアルの Termalin アカウントが必要です。イメージの pull は無料で、追加できる Connector の数に上限はありません。
1 つのコンテナーからネットワーク全体へ。
トークン 1 つ、docker run 1 回、受信ポートなし。NAS、ルーター、Kubernetes、ECS の上で。
Pro(または 14 日間のトライアル) · 内部サイト · リモートデスクトップ