導入:なんでProxmoxじゃなくてUbuntu + Cockpit?
![]() |
![]() |
ずんだもん「おおつむぎ、新しくサーバ自作したのだ? 今回はProxmoxじゃなくてUbuntuにするって聞いたのだ。」
つむぎ「いやそれな〜。Proxmoxマジ便利ではあるんだけど、ホスト画面CLI前提だし、有線LAN必須だったりして、そこまで本格じゃないサーバをサクッと立てたいときにはビミョいんよね〜。」
- Proxmox VE はDebian前提で、GPUドライバや最新Mesa対応はUbuntuより遅れがちになりやすい。
- Ubuntu 24.04ならIntel Arc + Wayland + SunshineでAV1エンコーディングまで公式サポートが入っており、最新GPUを活かしやすい。
ずんだもん「だからホストをUbuntu 24.04 LTSにして、KVM + Cockpit + Tailscale + Sunshine で全部まとめてみたのか。」
つむぎ「要は“Ubuntuで全部盛りやっちゃおうぜ”ってノリね。いいじゃん〜。」
構成
つむぎ「環境こんな感じ〜。わりと盛りだくさんなんだけど、やってることはシンプル寄りだよ。」
-
OS: Ubuntu 24.04 LTS(デスクトップ)
-
仮想化: KVM + libvirt + Cockpit(Web UI)
-
ネットワーク: Wi-Fi 6 接続のみ(有線なし)
-
GPU: Intel Arc(Core Ultra 世代 iGPU、Wayland + AV1 対応)
-
リモートアクセス:
- VM管理系 → Tailscale +
tailscale serveで Cockpit をHTTPS/TLS化 - ストリーム → Sunshine (host) + Moonlight (iPad / Mac) でAV1/HEVC配信
- VM管理系 → Tailscale +
ずんだもん「要するに、Proxmox級にリモートでいじれるUbuntuデスクトップKVMホストを、Wi-Fi環境だけで作ってみたってことなのだな?」
つむぎ「しかもIntel ArcでAV1キメてく、みたいな。ちょっと未来感あってアガる〜。」
全体の手順フロー
![]() |
![]() |
つむぎ「やることは大きく5ステップに分かれるよ〜。これ頭に入れとくと迷子らない。」
1. システム更新
2. Tailscale インストール・接続・`serve` 設定
3. KVM / libvirt / Cockpit / virt-manager のインストールと初期設定
4. ISO・仮想ディスク用ディレクトリの権限調整
5. Sunshine のセットアップ&自動起動(自動ログイン前提)
ずんだもん「そんなに手順は多くないのだな。LinuxだからCLIオンリーで環境できあがるのはメリットなのだ!」
ステップ1:システム更新
ずんだもん「まずはいつものやつなのだ。」
つむぎ「ここサボると後でパッケージ依存関係でバグるから、サクっとやっとこ〜って感じ。」
sudo apt update
sudo apt upgrade -y
ステップ2:Tailscale + serve で Cockpit をHTTPS化
2-1. Tailscale の導入
ずんだもん「公式スクリプトで一気に入れるのだ。」
つむぎ「これ一発でリポジトリ設定までやってくれるから、素直に乗っかるのが吉〜。」
curl -fsSL https://tailscale.com/install.sh | sh
- install.sh はディストリを自動判定し、Ubuntu用の公式リポジトリを設定して
tailscaleをインストールしてくれる。
2-2. 起動&ログイン
つむぎ「ここでテイルネットデビューしちゃうわけ〜。」
sudo tailscaled &
sudo tailscale up
- ブラウザが開くので、TailscaleアカウントでログインしてこのUbuntuホストをテイルネットに参加させる。
2-3. Cockpit(9090) を tailscale serve で公開
つむぎ「ローカルではCockpitを http://localhost:9090 で動かしておいてね〜。それをTailscaleでラップするイメージ!」
sudo tailscale serve --bg --https=443 http://localhost:9090
- これで
https://<ホスト名>.<テイルネット名>.ts.netにアクセスすると、Tailscale側でTLS終端 → Cockpit(9090)にリバースプロキシされる。
Cockpitが自己署名HTTPSのままなら、バックエンド検証を無視する版:
sudo tailscale serve --bg --https=443 https+insecure://localhost:9090
-
https+insecure://は、自己署名などの不正な証明書チェックをスキップしてプロキシするための方法。
つむぎ「表側はTailscaleのちゃんとした証明書で、裏側は自己署名でもヨシ!っていう、おきがる構成ね〜。」
ステップ3:KVM / Cockpit / virt-manager
![]() |
![]() |
3-1. KVM & libvirt & virt-manager
ずんだもん「ここで仮想化ホストをインストールするのだ。」
つむぎ「ここ通れば“普通のUbuntuデスクトップ”が“ちゃんとしたハイパーバイザ”にクラスチェンジするから、ちょいワクワクするやつ〜。」
sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt,kvm $USER
# または
# sudo adduser $(id -un) libvirt
# sudo adduser $(id -un) kvm
- 再ログイン後、
virt-managerからパスワードなしでローカルKVMホストに接続できる。
つむぎ「グループ追加したら、ちゃんと一回ログアウトしないと反映されないから、そこだけ注意ね〜。」
3-2. Cockpit + 仮想マシンプラグイン
ずんだもん「つぎはCockpit入れてWebブラウザから VM いじれるようにするのだ。」
つむぎ「Virt-Managerとかターミナルだけだとテンション上がらん人、ここからが本番だから〜。」
sudo apt update
sudo apt install -y cockpit cockpit-machines
sudo systemctl enable --now cockpit.socket
# UFWを使っている場合のみ
sudo ufw allow 9090/tcp
- Cockpitの「仮想マシン」タブから、Webブラウザ経由でKVMゲストの作成・起動・コンソール接続ができる。
つむぎ「しかも Tailscale 経由で HTTPS だし、httpで警告でないサーバー、なんか“ちゃんとしてる感”マシマシで最高〜。」
ステップ4:ISO・ディスクイメージ用ディレクトリの権限調整
ずんだもん「ISO置き場は libvirt 標準の /var/lib/libvirt/images/ をそのまま使うのだ。」
つむぎ「ここごちゃると“ISO見えませ〜ん”って怒られるから、先にサクっと揃えとこ〜。」
sudo chown -R root:root /var/lib/libvirt/images/
sudo find /var/lib/libvirt/images/ -type d -exec chmod 755 {} \;
sudo find /var/lib/libvirt/images/ -type f -exec chmod 644 {} \;
# 必要なら ISO だけ個別に
# sudo chmod 644 /var/lib/libvirt/images/*.iso
- libvirt/qemu のデフォルト設定では、root 所有・644 のISOや qcow2 を問題なく読み込める。
ステップ5:Sunshine + 自動起動(自動ログイン)
5-1. 自動ログインを有効化
- GNOMEの「設定 → ユーザー → 対象ユーザー → 自動ログイン」を有効化。
- あるいは
gdm3の設定で同等の自動ログインをオンにする。
つむぎ「Sunshine はデスクトップセッション前提だから、ここサボると“あれ起動してなくね?”ってなるから注意〜。」
5-2. systemd ユーザーサービス
ずんだもん「Sunshine をログイン後に自動起動させる設定なのだ。」
つむぎ「一回作っとけば、毎回ポチポチ起動しなくていいから QOL 爆上がり〜。」
#!/usr/bin/env bash
set -euo pipefail
# ==== Ubuntu バージョン自動判定 ====
if command -v lsb_release >/dev/null 2>&1; then
DISTRO_ID=$(lsb_release -is | tr 'A-Z' 'a-z')
DISTRO_VER=$(lsb_release -rs)
else
# /etc/os-release から取得
if [[ -r /etc/os-release ]]; then
# ID と VERSION_ID をそれぞれ取り出す
DISTRO_ID=$(grep -E '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"' | tr 'A-Z' 'a-z')
DISTRO_VER=$(grep -E '^VERSION_ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
else
echo "ERROR: lsb_release も /etc/os-release も利用できないため、Ubuntuバージョンを判定できません。" >&2
exit 1
fi
fi
if [[ "$DISTRO_ID" != "ubuntu" ]]; then
echo "ERROR: このスクリプトは Ubuntu 専用です。検出ID: ${DISTRO_ID}" >&2
exit 1
fi
# Sunshine の .deb が用意されているのは 22.04 / 24.04 系のみ(現時点)[web:139][web:142]
case "$DISTRO_VER" in
22.04*|24.04*)
echo "[*] Detected Ubuntu ${DISTRO_VER}"
;;
*)
echo "ERROR: サポートしていない Ubuntu バージョンです: ${DISTRO_VER}" >&2
echo " (22.04 または 24.04 系のみ対応)" >&2
exit 1
;;
esac
DISTRO=ubuntu
ARCH=amd64
REPO="LizardByte/Sunshine"
workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT
echo "[*] Fetching latest release info..."
api_url="https://api.github.com/repos/${REPO}/releases/latest"
deb_pattern="sunshine-${DISTRO}-${DISTRO_VER}-${ARCH}\.deb"
deb_url="$(
curl -fsSL "$api_url" \
| grep -Eo "https://[^\"']*${deb_pattern}" \
| head -n 1
)"
if [[ -z "${deb_url:-}" ]]; then
echo "ERROR: 最新の ${DISTRO}-${DISTRO_VER}-${ARCH} 向け .deb が見つかりませんでした。" >&2
exit 1
fi
echo "[*] Downloading: $deb_url"
cd "$workdir"
curl -fsSL "$deb_url" -o sunshine-latest.deb
echo "[*] Installing sunshine-latest.deb ..."
sudo apt install -y ./sunshine-latest.deb
echo "[*] Writing user systemd unit..."
unit_dir="$HOME/.config/systemd/user"
mkdir -p "$unit_dir"
cat > "$unit_dir/sunshine.service" <<'EOF'
[Unit]
Description=Sunshine Game Stream Host
After=graphical-session.target
Wants=graphical-session.target
[Service]
Type=simple
ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/sunshine
Restart=on-failure
RestartSec=5s
Environment=DISPLAY=:0
Environment=XDG_RUNTIME_DIR=/run/user/%U
Environment=XDG_SESSION_TYPE=x11
[Install]
WantedBy=default.target
EOF
echo "[*] Enabling user service..."
systemctl --user daemon-reload || true
systemctl --user enable sunshine || true
systemctl --user restart sunshine || true
echo "[*] Done. Current status:"
systemctl --user status sunshine --no-pager || true
-
/usr/bin/sunshineのパスはwhich sunshineで確認して合わせる。
5-3. 有効化
つむぎ「ちゃんと起動するかテストしてから恒常運用に入るの、大事〜。」
systemctl --user daemon-reload
systemctl --user start sunshine
systemctl --user enable sunshine
- 再起動すると「起動 → 自動ログイン → graphical-session.target 到達 → Sunshine 起動」の流れになる。
ずんだもん「これで物理ホスト再起動しても勝手に Sunshine が動くのだ!」
実際に触ってみるのだ(Cockpit編)
![]() |
![]() |
つむぎ「Tailscaleでつないだ先から、Cockpitはこう見えたよ〜。」
- iPad / Mac のブラウザから
https://<ホスト名>.xxx.ts.netで Cockpit ダッシュボードに問題なくアクセス可能。TLS証明書の更新はTailscale側で自動処理。 - UIはレスポンシブ対応でiPadでも使えるが、VNC コンソールをタッチだけで操作するのは厳しく、外部キーボード・マウスがほぼ必須。
- iPad向けのSPICEクライアントは有料のものが多く、WindowsやLinuxクライアントの方が選択肢あり。
つむぎ「“とりまブラウザでVMオンオフして、細かい操作はちゃんとしたクライアントでやる”って割り切りが一番ストレス少ないかも〜。」
Sunshine編
ずんだもん「今度はデスクトップストリームなのだ。」
つむぎ「ここがVMの管理上重要~。うまく動けば便利でテンション上がるとこ〜!」
- iPad mini の Moonlight クライアントでは、Sunshine側でAV1を有効にするとAV1ストリームとして接続され、ビットレートを抑えつつ低遅延で動作。
- macOS版 Moonlight は現状HEVC中心で、セッション開始に数秒待たされるなど、Windowsホスト時と似た挙動。ただし実用上は問題ないレベル。
- Windows配列キーボードでAppleデバイスを操作すると、いくつかキーの挙動に違和感が出る場面がある(ショートカット周りなど)。
つむぎ「Wi-Fiでも“あ、これ普通にいけるやつじゃん”って感じのレイテンシだったよ。LANケーブルひきたくない民にはだいぶ希望ある〜。」
まとめ
つむぎ「で、やってみてぶっちゃけどうだった〜?」
ずんだもん「まとめると、こうなのだ!」
-
Tailscale は Entra ID(Microsoft Entra ID)などIdPとのSSO連携ができ、
tailscale serveでHTTPS終端と証明書更新を自動化できるので、ゼロトラスト + 簡易リバースプロキシとしてかなり扱いやすい。 - Cockpit はKVMの上に薄いWeb UIを載せているだけなので導入が軽く、Proxmoxほどの本格ハイパーバイザは不要だが「ブラウザからVMを起動・停止したい」ケースには最適。
- 2025年時点のUbuntu 24.04 + Intel Arc ドライバはWayland/AV1含めて成熟しており、Sunshineと組み合わせて低遅延ストリーミングが可能。
- ただし、Moonlight側(特にmacOS/iOS版)のコーデック対応や最適化状況にはまだ制限があり、クライアントデバイスによってAV1/HEVCの挙動差が出る点には注意が必要。
つむぎ「総じて、“Proxmoxほどガチじゃないけど、それなりにちゃんとした仮想マシン管理サーバ欲しい”って人には、この構成かなりアリって感じだね〜。」
スタバにて
![]() |
![]() |
ずんだもん「つむぎ、これでUbuntuデスクトップでPC的に使いつつ、TailscaleもCockpitもSunshineも勝手に立ち上がってサーバーとしても使えるようになったのだ!」
つむぎ「え、やば。電源ボタンポチって、カフェラテ作って戻ってきたら、もうiPadからVMもゲームもいじれるってこと?それ、もはやクラウドギャルハウスじゃん。」
ずんだもん「クラウドギャルハウスの意味が分からんのだ....。それはともかく、Wi‑Fiだけで有線LANいらない、証明書もTailscale serveが自動更新してくれるのは良いのだな。」
つむぎ「それな〜。これならスタバからiPhoneでもいけるし。てか外で VM 再起動してるギャル、世界でウチくらいじゃね? 」
ずんだもん「つむぎ、こないだも寺で座禅してたと思ったら、“悟ったから VM のスナップショット消すわ〜”って言ってたのだ!」
つむぎ「煩悩は消すものでしょ?スナップショも同じ♡」
ずんだもん「“家でも座禅したいから、お坊さんにも Tailscale 入れてもらおう♡” とか言い始めて困ったのだ!」
つむぎ「いいじゃん。これからはゼロトラスト坊主の時代だし?」
ずんだもん「お坊さんに IAM ロール付けようとしないでくれなのだ!」
利用キャラクター
- ずんだもん:VOICEVOX:ずんだもん
- つむぎ:PIXIV:りょうごさん
本記事で使用しているキャラクター画像の著作権は、それぞれの権利者に帰属します。
非商用目的での利用に基づき掲載しています。









