Fly.io でスマホから SSH 接続でき、アイドル時には自動停止するターミナル環境を立てる
linuxFly.io は Lambda MicroVMs と同じくアプリケーションを動かしたりシェルに入ることができる VM を Firecracker で高速に立ち上げられる PaaS。最近 CEO が Docker の元 CEO に変わった。
Fly Proxy がリクエストを受け、停止している VM を立ち上げ WireGuard トンネルを通してくれるので suspend 状態から純粋な SSH コマンドで接続することができる。これにより最小限の維持コストで Termius などのスマホアプリから接続することが可能になっている。
Lambda MicroVMs で capabilities 付きのサンドボックス環境を立ち上げシェルに入り docker run する - sambaiz-net
flyctl をインストールしてログインする。
$ brew install flyctl
$ fly auth login
アプリとボリュームを作成し、公開鍵を Secrets に保存する。
$ fly apps create fly-ssh-box
$ fly volumes create ssh_data --region nrt --size 1 -a fly-ssh-box
$ fly secrets set "AUTHORIZED_KEYS=ssh-ed25519 *****" -a fly-ssh-box
sshd をインストールし Secrets から authorized_keys を読んで配置するスクリプトを実行する Dockerfile と 停止時の挙動やマウントするボリュームなどの設定を書いた fly.toml を用意する。
$ tree .
.
├── Dockerfile
├── entrypoint.sh
└── fly.toml
$ cat Dockerfile
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssh-server \
&& rm -rf /var/lib/apt/lists/* \
&& sed -i 's/^#\?Port.*/Port 2222/' /etc/ssh/sshd_config \
&& sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config \
&& sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config \
&& mkdir -p /root/.ssh /var/run/sshd \
&& chmod 700 /root/.ssh \
&& chmod 755 /var/run/sshd
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 2222
ENTRYPOINT ["/entrypoint.sh"]
CMD ["sleep", "infinity"]
$ cat entrypoint.sh
#!/bin/bash -e
# Persist host keys across deploys
mkdir -p /data/ssh_host_keys /root/.ssh
if [ -z "$(ls -A /data/ssh_host_keys 2>/dev/null)" ]; then
cp /etc/ssh/ssh_host_*_key* /data/ssh_host_keys/
else
cp /data/ssh_host_keys/ssh_host_*_key* /etc/ssh/
fi
if [ -n "$AUTHORIZED_KEYS" ]; then
echo "$AUTHORIZED_KEYS" > /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
fi
/usr/sbin/sshd
exec "$@"
$ cat fly.toml
app = "fly-ssh-box"
primary_region = "nrt"
[build]
[mounts]
source = "ssh_data"
destination = "/data"
[[services]]
internal_port = 2222
protocol = "tcp"
auto_stop_machines = "suspend"
auto_start_machines = true
min_machines_running = 0
[[services.ports]]
port = 22
デプロイし IP アドレスを割り当てて SSH 接続できることを確認する。スマホからも接続できた。なお IPv4 の割り当ては Trial では行えず $2/月 かかる。
$ fly deploy
==> Verifying app config
Validating /home/sambaiz/fly-ssh-box/fly.toml
✓ Configuration is valid
--> Verified app config
==> Building image
==> Building image with Depot
--> build:
[+] Building 18.1s (9/9) FINISHED
=> [internal] load build definition from Dockerfile
...
$ fly ips allocate-v4 -a fly-ssh-box
$ ssh [email protected]
# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.4 LTS"
...