はじめに
リモート開発環境でWebブラウザからターミナルにアクセスしたいことがありますが、単純な設定では以下の問題が発生します:
-
exitすると画面が真っ暗になり、手動でリロードが必要 - 複数のブラウザタブでセッションが共有されない
- 接続が切れた際の復旧が面倒
この記事では、ttydとtmuxを組み合わせて、セッション共有と自動復帰機能を持つWebターミナルを構築する方法を解説します。
環境
- Ubuntu 22.04 LTS
- ttyd (snap版)
- tmux
- systemd
基本的な ttyd のインストール
# snapでttydをインストール
sudo snap install ttyd --classic
# バージョン確認
ttyd --version
問題:基本設定では自動復帰しない
最初に試した設定:
[Unit]
Description=Web Terminal with Tmux Session Management
After=network.target
[Service]
Type=simple
User=devuser
Group=devuser
WorkingDirectory=/home/devuser
ExecStart=/snap/bin/ttyd --port 17681 --writable --max-clients 5 --terminal-type xterm-256color tmux new-session -A -s main
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
この設定の問題点:
-
exitするとtmuxセッションが終了 - ttydプロセスも終了してWebSocket接続が切断
- ブラウザでは画面が真っ暗になり、手動リロードが必要
解決策:永続シェルスクリプト
自動復帰機能を実現するため、永続的なシェルスクリプトを作成します。
永続シェルスクリプトの作成
sudo nano /usr/local/bin/tmux-persistent.sh
#!/bin/bash
# 環境変数を設定
export HOME=/home/devuser
export USER=devuser
export SHELL=/bin/bash
export TERM=xterm-256color
export TMPDIR=/home/devuser/.tmux-tmp
# tmux用ディレクトリを作成
mkdir -p "$TMPDIR"
cd /home/devuser
SESSION_NAME="main"
# 永続的なtmuxセッション管理
while true; do
# セッションが存在するかチェック
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "Connecting to existing shared session..."
tmux attach-session -t "$SESSION_NAME"
else
echo "Creating new shared session..."
tmux new-session -s "$SESSION_NAME"
fi
# セッションが終了した場合(すべてのユーザーがdetachまたはexit)
echo ""
echo "Session ended. Restarting in 2 seconds..."
sleep 2
clear
done
実行権限を付与
sudo chmod +x /usr/local/bin/tmux-persistent.sh
sudo chown devuser:devuser /usr/local/bin/tmux-persistent.sh
最終的なsystemd設定
sudo nano /etc/systemd/system/web-terminal.service
[Unit]
Description=Web Terminal with Shared Tmux Session
After=network.target
[Service]
Type=simple
User=devuser
Group=devuser
WorkingDirectory=/home/devuser
ExecStart=/snap/bin/ttyd --port 17681 --writable --max-clients 5 --terminal-type xterm-256color /usr/local/bin/tmux-persistent.sh
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
KillMode=mixed
[Install]
WantedBy=multi-user.target
サービスの有効化
sudo systemctl daemon-reload
sudo systemctl enable web-terminal.service
sudo systemctl start web-terminal.service
sudo systemctl status web-terminal.service
動作確認
1. 基本動作
# ブラウザで http://localhost:17681 にアクセス
# ターミナルが正常に表示されることを確認
2. 自動復帰機能
# ターミナルで以下を実行
exit
# 「Session ended. Restarting in 2 seconds...」が表示される
# 2秒後に新しいセッションが自動開始
# ブラウザのリロードは不要
3. セッション共有
- 複数のブラウザタブで同じURLにアクセス
- 一方で入力したコマンドが他方でも表示される
-
Ctrl+B, Dでdetachすると他のクライアントは継続
ttydオプションの解説
使用しているオプションの詳細:
/snap/bin/ttyd \
--port 17681 \ # 接続ポート
--writable \ # 書き込み許可
--max-clients 5 \ # 最大接続数
--terminal-type xterm-256color \ # ターミナルタイプ
/usr/local/bin/tmux-persistent.sh # 実行するスクリプト
--enable-sixelオプションについて
# Sixel(画像表示)機能を有効にする場合
--enable-sixel
Sixelとは:
- ターミナル内で画像を表示する機能
- データ可視化ツールの出力を直接表示可能
- 帯域幅とCPU使用量が増加
使用例:
# 画像表示
img2sixel picture.jpg
# グラフ表示
gnuplot -e "set terminal sixel; plot sin(x)"
一般的なサーバー管理用途では不要なため、今回の設定では除外しています。
認証機能の追加
Basic認証を追加する場合:
認証ファイルの作成
sudo mkdir -p /etc/ttyd
echo "admin:your_secure_password" | sudo tee /etc/ttyd/auth
sudo chmod 600 /etc/ttyd/auth
sudo chown devuser:devuser /etc/ttyd/auth
サービス設定に認証を追加
ExecStart=/snap/bin/ttyd --port 17681 --writable --max-clients 5 --terminal-type xterm-256color --credential @/etc/ttyd/auth /usr/local/bin/tmux-persistent.sh
注意: Safariでは認証機能が正常に動作しない場合があります。その場合は認証なしで運用し、ファイアウォールやIP制限で代替してください。
セキュリティ対策
IP制限
# 特定のIPからのみアクセス許可
--interface 127.0.0.1 # ローカルからのみ
ファイアウォール設定
# 特定のネットワークからのみアクセス許可
sudo ufw allow from 192.168.1.0/24 to any port 17681
sudo ufw deny 17681
SSH Tunneling(推奨)
# SSH tunnel経由でのアクセス
ssh -L 8080:localhost:17681 user@your-server
# ブラウザで http://localhost:8080 にアクセス
トラブルシューティング
1. セッションが表示されない
# tmuxセッションの状態を確認
sudo -u devuser tmux list-sessions
# ttydのログを確認
sudo journalctl -u web-terminal.service -f
2. 権限エラー
# スクリプトの権限を確認
ls -la /usr/local/bin/tmux-persistent.sh
# 所有者を修正
sudo chown devuser:devuser /usr/local/bin/tmux-persistent.sh
sudo chmod 755 /usr/local/bin/tmux-persistent.sh
3. ポートが使用中
# ポートの使用状況を確認
sudo ss -tlnp | grep 17681
# プロセスを終了
sudo pkill ttyd
カスタマイズ
再起動時間の調整
# スクリプト内の待機時間を変更
sleep 2 # デフォルト
sleep 1 # 高速化
sleep 5 # 余裕を持たせる
カスタムメッセージ
echo "=== Your Company Web Terminal ==="
echo "Welcome back! Session ID: $$"
echo "Server: $(hostname)"
echo ""
複数セッションの管理
# 複数の固定セッションを作成
SESSION_NAMES=("dev" "prod" "debug")
for session in "${SESSION_NAMES[@]}"; do
if ! tmux has-session -t "$session" 2>/dev/null; then
tmux new-session -d -s "$session"
fi
done
まとめ
この構成により、以下が実現できました:
✅ 自動復帰機能: exitしても2秒後に新しいセッション開始
✅ セッション共有: 複数のブラウザタブで同じセッションを共有
✅ 永続性: サーバー再起動後も自動的にサービスが開始
✅ 安定性: 接続が切れても手動リロード不要
Webベースのターミナル環境を構築する際の参考にしていただければと思います。