0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ttydでWebターミナル構築:セッション共有と自動復帰を実現する

0
Posted at

はじめに

リモート開発環境でWebブラウザからターミナルにアクセスしたいことがありますが、単純な設定では以下の問題が発生します:

  • exitすると画面が真っ暗になり、手動でリロードが必要
  • 複数のブラウザタブでセッションが共有されない
  • 接続が切れた際の復旧が面倒

この記事では、ttydtmuxを組み合わせて、セッション共有と自動復帰機能を持つ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ベースのターミナル環境を構築する際の参考にしていただければと思います。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?