この記事で実現すること
仮想環境のProxmox VE9.2でCloud-Initを活用する方法をまとめています。私はこれまでは単にUbuntu Desktop VMのクローンだけで済ませており、Cloud-Initの最初の手間を考えると大して時短にもならないと考えてましたが、最近はDesktopではなくほぼUbuntu Serverに変わってきていることや小さいノードを複数持たせる傾向にあるため、改めてCloud-Initのメリットを考えてみたいと思います。
Cloud-Initとは ご想像通り、テンプレートを作成し、それを元にVMを構築していくためのものです。複数のLinux VMがあるとしたら共通設定される部分(ユーザー、パスワードやSSH鍵など)は、できるだけ共通化して省力化を図ろうというものです。
Cloud-Initが向いているのは、特にLinuxは親和性が高いのですが、似たような環境をいくつも作成するケースです。 Ubuntuだと開発、監視基盤、自動実行など目的に合わせてLinuxサーバーを構築したり、一時的なテスト端末を用意したりする場合に大きな効果を発揮します。
なぜ使おうと思ったか 元々、Cloud-Initは特別新しいものでもなく、私自身はこれまでもVMのクローンで十分という認識があり、そもそもUbuntuのインストールも簡単にはなっているのでさほど気にしてはいませんでした。 ESXiを使っていた時代にも、そもそもUbuntuも数台あったものの、気が向いたら何かのサーバーを立てるのに使う程度のものであって、本格稼働していたとは言い難い状況でした。
何よりもESXiはVMware Remote Consoleが便利だったおかげで、WindowsやmacOSからのコピペがとても簡単でした。クライアントで必要な情報を集めて、ダウンロードしたものをアップしたり、ダウンロードリンクを纏めてubuntuに取り込み、Ubuntu側で纏めて作業するという流れで運用してました。
ESXiからProxmoxに移行してきて思ったことは、かなりLinuxライクな運用が求められることであり、またCLI中心に戻ってきたと感じたことです。もちろん、ESXiのパッチもコマンドベースでしたが、Proxmoxではかなりパッチの頻度も多く、詳細な情報を見られるようになった反面、運用面ではかなりやることが増えたなと感じます。もっとも、ESXiではブラックボックスでしたのであまり気にしなくてもよかった(色々知らない方が幸せ)と言えます。
ちょうど時代も変わってきたと感じます。世の中にはサイバー攻撃が溢れ、今やパスワード管理というのは時代遅れになってきており、二要素認証だけではなく、フィッシング耐性が求められるパスキーが一般的になりつつあります。ホームラボは今のままで無影響ということにはなりません。これまでよりもセキュリティ対策に注力する必要があります。弱いパスワードのVPN、ホームラボならではの証明書エラー、強度の低いWi-Fiパスワードなど、見直すべき箇所はたくさんあります。世の中のパブリッククラウドのセキュリティ強化の流れからは取り残されたホームユーザーのオンプレミス環境は、今まさに見直しが必要な状況になってきていると思います。そして、そのためには個々のサーバーを場当たり的に構築するのではなく、共通のルールで構築・運用できる基盤が必要になります。
ホームラボの運用について 私個人としてはホームユーザーという立場で、データ保管やネットワークなどが中心の運用になっています。NASはSynologyを使い、ネットワークはUniFiを使い、できれば既にあるものはわざわざ自分では作らないという考えであり、過去、自身で構築している主だったものとしてはESXiに乗ったFirewall(Sophos)でした。
Proxmoxになって、クラスター対応ができるようになり、運用の品質が一段上げられると感じました。前述したようにGUIである程度簡単にやれるのはとても便利でしたが、Ubuntuを活用しているとは言い難く、なぜUbuntu Desktopなの?と聞かれればせいぜいネットワークの設定がGUIで簡単、Firewallの設定が簡単だったということくらいでしょうか。
ProxmoxはGUIを備えているとはいえ、やはり細かな作業単位はコマンドライン中心です。UniFiも見た目の良いコンソールはありますが、実際に細かく見ていくとしたらスイッチにSSHして見ていくしかありません。結局は、なんか不調だなと思ったところで、こういった漠然と手作業でやっていたことについて、品質を上げるためにはある程度の監視基盤や自動実行する基盤が必要と感じるようになりました。こうなってくると複数のVMが必要となり、ハードウェアのリソースにも限りがあります。Ubuntu Serverで最低限度のリソースで稼働できることを目指すようになりました。
AIの活用 これをお読みの皆さんも、お忙しい中、そんなに自宅の基盤の運用に時間を掛けていられないのが実情だとは思います。しかしそれを少し変えられるのは、台頭してきたAIの活用です。監視のための細かなShellを作るなんて仕事以外ではとてもやりきれないものですが、かなりの負荷軽減が可能となってきています。AIでブラウザを操作するということもできますが、コマンドを使えば圧倒的な速度で物事が進みます。しかも再現性が高くなります。
大事なことはこれまで人がわかりやすいGUIや簡易な設定(教育コストが低いもの)に重きが置かれていたものが、AIを使って生産性を高める、運用品質を高められるようになったという事です。
人の作業は曖昧で、VM1つづつ見ても、設定内容がバラバラなものが多いのではないでしょうか。ある程度のルールが決まっていた上で共通の運用基盤を作ることが何よりも品質向上に資するのではないかと思います。
ホームラボの品質向上で目指すもの
GUI+手順ということではなく、コマンドベースで一定の手順で運用し、再現性が高く、確実性を求める
監視を強化する
セキュリティ向上
ダウンタイムの減少
これらを実現するために、それぞれの専門分野のVMを立てて、それ専用のプロダクトを導入することにしました。VMは目的毎に分け、余計なモジュールを入れない事を基本にします。モジュールのアップデートの頻度を少なく、脆弱性のリスクを抑制、OSのリブート頻度を減らし、安定したサービス提供を目指します。 自動実行基盤 パッチ適用、ヘルスチェック→Ansible。きちんとやるにはDev、Productionそれぞれの環境が必要にもなってきます。 監視基盤 定番のGrafana、Loki、Prometheusで監視 運行計画 Semaphore-UI GUIでAnsibleの状況や運行管理(バッチ時刻管理) 証明書管理
運用スタイルの変遷 上記のようなプロダクトの構築を行なっていく上では共通化された認証基盤、それこそ基本の名前解決から全て統一的に対応していくことになります。気が付けば、ターミナル(macOSのiTerm2)、定型処理を行うAnsibleの開発はVSCodeにCodex拡張機能、ClaudeCode拡張機能を用いるのがスタイルになってきました。 Ansible端末を踏み台にProxmoxに接続しコマンドを叩いて結果を収集するなど、気が付けば作業はSSHばかりです。もちろんこれは構築(開発)作業がそうなのであって、実際の運用はGUIが中心になります。
Semaphore-UI運行管理(定期的なAnsibleジョブ実行)
Grafana(Loki,Prometheus)(主にUniFiのネットワーク統計、Syslog管理)
VSCode(ClaudeCode(実装)とCodex(レビュー))
VSCodeはリモート上のAnsibleコードをaiで生成、レビューを実施します。
Cloud-Initに必要なもの 必要なものは簡単にいえば、クラウドイメージのUbuntu本体とユーザー設定です。
実際のCloud-Initの構築 <前提>ファイルシステムはzfsを前提に構築しています。ext4の方は別途ストレージについてはProxmoxサイトなどを参照し、適宜変更ください。
Cloud Image
Proxmox(KVM)用Ubuntu26.04 Cloud image
https://cloud-images.ubuntu.com/resolute/current/ から、resolute-server-cloudimg-amd64.imgをダウンロードします(QCow2 UEFI/GPT Bootable disk image)。
Proxmoxのshellから/var/lib/vz/template/isoに移動し、wget https://cloud-images.ubuntu.com/resolute/current/resolute-server-cloudimg-amd64.imgで取得します。
本記事では2026年6月時点のUbuntu 26.04 LTS cloud imageを利用しています。環境によってはdaily/currentの内容が更新されるため、実際に利用する際はファイル名と日付を確認してください。
1 2 3 4 5 6 7 8 9 10 11 12 root@pve1:~1 cd /var/lib/vz/template/iso root@pve1:/var/lib/vz/template/iso wget https://cloud-images.ubuntu.com/resolute/current/resolute-server-cloudimg-amd64.img --2026-06-06 16:03:50-- https://cloud-images.ubuntu.com/resolute/current/resolute-server-cloudimg-amd64.img Resolving cloud-images.ubuntu.com (cloud-images.ubuntu.com)... 185.125.190.40, 185.125.190.37, 2620:2d:4000:1::1a, ... Connecting to cloud-images.ubuntu.com (cloud-images.ubuntu.com)|185.125.190.40|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 858720256 (819M) [application/octet-stream] Saving to: ‘resolute-server-cloudimg-amd64.img’ resolute-server-cloudimg-amd6 100%[==============================================>] 818.94M 36.5MB/s in 14s 2026-06-06 16:04:04 (59.4 MB/s) - ‘resolute-server-cloudimg-amd64.img’ saved [858720256/858720256]
user-data さて、この内容は人それぞれですので重要な部分は一応抑えつつ、カスタマイズをしていただくことになります。サーバー運用を前提の構築です。
初めに断っておきたいことは、この設定はパスワードレスでサーバー用途として構築するものです。 Ubuntu Desktopではないですし、しかもProxmoxコンソールからパスワードでログインすらできません。その代わり、起動直後からお使いのクライアントから公開鍵認証でSSHできます。
ユーザーの作成(sudo NOPASSWD付き)
SSH公開鍵複数の登録
パスワード認証の無効化(ssh_pwauth: false)
rootログインの無効化(disable_root: true)
SSH hardening(/etc/ssh/sshd_config.d/99-hardening.conf)
タイムゾーン(Asia/Tokyo)・ロケール(ja_JP.UTF-8)
初期パッケージのインストール
unattended-upgradesの設定
まずuser-dataを配置するにあたり、Proxmoxのデータセンターからストレージ”local”に対してスニペットの配置を有効にします。編集ボタンから「スニペット」を加えます。
user-data(Snippets)の配置場所は、/var/lib/vz/snippetsです。
ここでは、user-data-ubuntu-2604.yamlという名前でuser-dataを作成します。viまたはnanoで作成してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 locale: ja_JP.UTF-8 timezone: Asia/Tokyo users : - name: yourname gecos: Yourname groups : - adm - sudo shell: /bin/bash lock_passwd: true sudo : "ALL=(ALL) NOPASSWD:ALL" ssh_authorized_keys: - ssh-rsa AAAA...== cardno:14 700 491 - ssh-rsa AAAA...== yoshi@yoshi-pc - ssh-ed25519 AAAA... ssh_pwauth: false disable_root: true package_update: true package_upgrade: true packages: - openssh-server - qemu-guest-agent - curl - wget - git - vim - unattended-upgrades write_files: - path: /etc/ssh/sshd_config.d/99-hardening.conf owner: root:root permissions: '0644' content: | PasswordAuthentication no KbdInteractiveAuthentication no ChallengeResponseAuthentication no PermitRootLogin no PubkeyAuthentication yes - path: /etc/apt/apt.conf.d/20auto-upgrades owner: root:root permissions: '0644' content: | APT::Periodic::Update-Package-Lists "1" ; APT::Periodic::Unattended-Upgrade "1" ; - path: /etc/apt/apt.conf.d/52unattended-upgrades-local owner: root:root permissions: '0644' content: | Unattended-Upgrade::Automatic-Reboot "false" ; runcmd: - systemctl enable ssh - systemctl enable qemu-guest-agent - systemctl start qemu-guest-agent - systemctl enable unattended-upgrades - dpkg-reconfigure -f noninteractive unattended-upgrades
yournameとなっている箇所は変更してください
公開鍵認証は、ssh_authorized_keys:の場所で3つの鍵が定義されていますので、ご自身の鍵に変更してください(最低1つ必要です)。1つの鍵ごとに先頭に”-“が必要です。空白やインデントは忠実に再現してください。
各セクションの解説 locale / timezone
インストール直後から日本語ロケール・JSTタイムゾーンで起動します。指定しない場合はUTC/英語になります。
users
users: - default と書くとcloud imageのデフォルトユーザー(ubuntu)が作られます。今回はyournameユーザーだけを明示的に定義しています。ここは変更してください。
lock_passwd: true → パスワードログインを無効化
sudo: "ALL=(ALL) NOPASSWD:ALL" → パスワードなしでsudoを許可
ssh_authorized_keys → 3つの公開鍵を登録(これはあくまで鍵を複数登録可能という意図です)
⚠️ GUI の Cloud-Init タブの「ユーザー名」設定(ciuser)は cicustom を使う場合は無効になります。users セクションがすべてを管理します。
ssh_pwauth / disable_root
ssh_pwauth: false → パスワード認証を無効化
disable_root: true → rootログインを無効化
sshd_config.dのhardeningファイルと組み合わせることで確実に無効化されます。
packages
初回起動時に自動インストールするパッケージ。qemu-guest-agent を入れることでProxmoxのGUIにIPアドレスが表示されるようになります。これがないとIPが不明になりSSH接続先を探す手間が生じます。
write_files
ファイルをそのままVM内に書き込みます。
99-hardening.conf → sshdの設定を強化。ssh_pwauth: false と合わせて二重に無効化
20auto-upgrades → unattended-upgradesの自動更新を有効化
52unattended-upgrades-local → 自動rebootを false に設定(デフォルト)。開発用VMなど任意のタイミングでの再起動が許可される場合は後でtrueに変更する
runcmd
初回起動時にコマンドを実行します。サービスの有効化と起動を確実に行います。qemu-guest-agent をstartしないとProxmox GUIにIPが表示されない場合があります。
GUI の Cloud-Init タブとの関係 cicustomでuser-dataを指定した場合、GUIのCloud-Initタブで設定できる項目は以下に絞られます。
項目
有効/無効
IP アドレス (ipconfig0)
✅ 有効
DNS サーバー
✅ 有効
ユーザー名 (ciuser)
❌ 無効(user-data が優先)
SSH 公開鍵 (sshkeys)
❌ 無効(user-data が優先)
IPとDNSはGUIで管理し、ユーザー・SSH鍵・セキュリティ設定はuser-dataで一元管理することになります。
テンプレートVMの作成手順 以下の手順はProxmox上で実施します。ここから大事なところなので慎重に。。。
Secure Boot
2コアCPU
2048MBメモリ
Step 1: VM作成
1 2 3 4 5 6 7 8 9 qm create 9001 \ --name ubuntu-2604-template \ --machine q35 \ --bios ovmf \ --cpu x86-64-v2-AES \ --cores 2 \ --memory 2048 \ --net0 virtio,bridge=vmbr0 \ --agent enabled=1
ポイント:
--bios ovmf でUEFI(Secure Boot対応)
--machine q35 はOVMFに必須
CPUタイプは無難にx86-64-v2-AESとしていますが、Proxmox9.2から導入されたカスタムCPUフラグを参考にカスタムCPUを作成する場合は custom- プレフィックスが必要
ネットワークはvmbr0(デフォルトVLAN)。VM作成後に用途に合わせて変更する
カスタムCPUについては、以下の記事をご覧ください。
Proxmox 9.2 のカスタムCPU設定を試す:AES-NI-V2 からどれだけ速くなるか検証
Step 2: EFI disk追加
1 qm set 9001 --efidisk0 local-zfs:0,efitype=4m,pre-enrolled-keys=1
これによりdisk-0が作成される。
Step 3: TPM追加
Proxmox 9.xでは tpmstate0 が正しいオプション名(tpm0 ではない)。
1 qm set 9001 --tpmstate0 local-zfs:0,version=v2.0
これによりdisk-1が作成される。
Step 4: cloud imageをインポート
1 qm importdisk 9001 /var/lib/vz/template/iso/resolute-server-cloudimg-amd64.img local-zfs
インポートされたdiskは unused0(disk-2) として認識される。
⚠️ disk-0はEFI disk、disk-1はTPM用。cloud imageはdisk-2になる。Step 5で正しく指定すること。
Step 5: SCSIコントローラーとdisk設定
1 2 qm set 9001 --scsihw virtio-scsi-single qm set 9001 --scsi0 local-zfs:vm-9001-disk-2,discard=on,iothread=1,ssd=1
オプション説明:
discard=on: TRIM有効
iothread=1: パフォーマンス向上
ssd=1: SSD emulation
Step 6: Cloud-Init・boot・ネットワーク設定 まずは汎用性を考え、DHCPでIP割り当てにしましょう。Diskの割り当ては念の為、数秒間隔あけて少しゆったり目で実行しましょう。
1 qm set 9001 --ide2 local-zfs:cloudinit
1 qm set 9001 --boot order=scsi0
1 qm set 9001 --ipconfig0 ip=dhcp
Step 7: cicustomの設定
1 qm set 9001 --cicustom "user=local:snippets/user-data-ubuntu-2604.yaml"
これでuser-dataをVMの初回起動時に適用するよう設定される。
Step 8: テンプレート化
テンプレートの設定確認
以下が含まれていることを確認する。
1 2 3 4 5 6 7 8 9 bios: ovmf machine: q35 cpu: x86-64-v2-AES efidisk0: ... tpmstate0: ... cicustom: local:snippets/user-data-ubuntu-2604.yaml scsihw: virtio-scsi-single scsi0: ...,discard=on,iothread=1,ssd=1 agent: enabled=1
実行ログ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 root@pve1:/var/lib/vz/snippets23 qm create 9001 \ --name ubuntu-2604-template \ --machine q35 \ --bios ovmf \ --cpu x86-64-v2-AES \ --cores 2 \ --memory 2048 \ --net0 virtio,bridge=vmbr0 \ --agent enabled=1 root@pve1:/var/lib/vz/snippets24 qm set 9001 --efidisk0 local-zfs:0,efitype=4m,pre-enrolled-keys=1 update VM 9001: -efidisk0 local-zfs:0,efitype=4m,pre-enrolled-keys=1 transferred 0.0 B of 528.0 KiB (0.00%) transferred 528.0 KiB of 528.0 KiB (100.00%) transferred 528.0 KiB of 528.0 KiB (100.00%) INFO: reading raw edk2 varstore from /usr/share/pve-edk2-firmware//OVMF_VARS_4M.ms.fd INFO: var store range: 0x64 -> 0x40000 efidisk0: successfully created disk 'local-zfs:vm-9001-disk-0,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=1M' root@pve1:/var/lib/vz/snippets25 qm set 9001 --tpmstate0 local-zfs:0,version=v2.0 update VM 9001: -tpmstate0 local-zfs:0,version=v2.0 tpmstate0: successfully created disk 'local-zfs:vm-9001-disk-1,size=4M,version=v2.0' root@pve1:/var/lib/vz/snippets26 qm importdisk 9001 /var/lib/vz/template/iso/resolute-server-cloudimg-amd64.img local-zfs importing disk '/var/lib/vz/template/iso/resolute-server-cloudimg-amd64.img' to VM 9001 ... transferred 0.0 B of 3.5 GiB (0.00%) transferred 35.8 MiB of 3.5 GiB (1.00%) transferred 71.7 MiB of 3.5 GiB (2.00%) transferred 107.5 MiB of 3.5 GiB (3.00%) transferred 143.7 MiB of 3.5 GiB (4.01%) transferred 179.6 MiB of 3.5 GiB (5.01%) transferred 215.4 MiB of 3.5 GiB (6.01%) transferred 251.6 MiB of 3.5 GiB (7.02%) transferred 287.4 MiB of 3.5 GiB (8.02%) transferred 323.3 MiB of 3.5 GiB (9.02%) transferred 359.1 MiB of 3.5 GiB (10.02%) transferred 395.0 MiB of 3.5 GiB (11.02%) transferred 430.8 MiB of 3.5 GiB (12.02%) transferred 466.6 MiB of 3.5 GiB (13.02%) transferred 502.5 MiB of 3.5 GiB (14.02%) transferred 538.3 MiB of 3.5 GiB (15.02%) transferred 574.2 MiB of 3.5 GiB (16.02%) transferred 610.0 MiB of 3.5 GiB (17.02%) transferred 645.8 MiB of 3.5 GiB (18.02%) transferred 681.7 MiB of 3.5 GiB (19.02%) transferred 717.5 MiB of 3.5 GiB (20.02%) transferred 753.4 MiB of 3.5 GiB (21.02%) transferred 789.2 MiB of 3.5 GiB (22.02%) transferred 825.0 MiB of 3.5 GiB (23.02%) transferred 860.9 MiB of 3.5 GiB (24.02%) transferred 896.7 MiB of 3.5 GiB (25.02%) transferred 932.9 MiB of 3.5 GiB (26.03%) transferred 968.8 MiB of 3.5 GiB (27.03%) transferred 1004.6 MiB of 3.5 GiB (28.03%) transferred 1.0 GiB of 3.5 GiB (29.03%) transferred 1.1 GiB of 3.5 GiB (30.03%) transferred 1.1 GiB of 3.5 GiB (31.03%) transferred 1.1 GiB of 3.5 GiB (32.03%) transferred 1.2 GiB of 3.5 GiB (33.03%) transferred 1.2 GiB of 3.5 GiB (34.03%) transferred 1.2 GiB of 3.5 GiB (35.03%) transferred 1.3 GiB of 3.5 GiB (36.03%) transferred 1.3 GiB of 3.5 GiB (37.03%) transferred 1.3 GiB of 3.5 GiB (38.03%) transferred 1.4 GiB of 3.5 GiB (39.03%) transferred 1.4 GiB of 3.5 GiB (40.03%) transferred 1.4 GiB of 3.5 GiB (41.03%) transferred 1.5 GiB of 3.5 GiB (42.03%) transferred 1.5 GiB of 3.5 GiB (43.03%) transferred 1.5 GiB of 3.5 GiB (44.03%) transferred 1.6 GiB of 3.5 GiB (45.04%) transferred 1.6 GiB of 3.5 GiB (46.04%) transferred 1.6 GiB of 3.5 GiB (47.04%) transferred 1.7 GiB of 3.5 GiB (48.04%) transferred 1.7 GiB of 3.5 GiB (49.04%) transferred 1.8 GiB of 3.5 GiB (50.04%) transferred 1.8 GiB of 3.5 GiB (51.04%) transferred 1.8 GiB of 3.5 GiB (52.04%) transferred 1.9 GiB of 3.5 GiB (53.04%) transferred 1.9 GiB of 3.5 GiB (54.04%) transferred 1.9 GiB of 3.5 GiB (55.04%) transferred 2.0 GiB of 3.5 GiB (56.04%) transferred 2.0 GiB of 3.5 GiB (57.04%) transferred 2.0 GiB of 3.5 GiB (58.04%) transferred 2.1 GiB of 3.5 GiB (59.04%) transferred 2.1 GiB of 3.5 GiB (60.04%) transferred 2.1 GiB of 3.5 GiB (61.04%) transferred 2.2 GiB of 3.5 GiB (62.04%) transferred 2.2 GiB of 3.5 GiB (63.04%) transferred 2.2 GiB of 3.5 GiB (64.05%) transferred 2.3 GiB of 3.5 GiB (65.05%) transferred 2.3 GiB of 3.5 GiB (66.05%) transferred 2.3 GiB of 3.5 GiB (67.05%) transferred 2.4 GiB of 3.5 GiB (68.05%) transferred 2.4 GiB of 3.5 GiB (69.05%) transferred 2.5 GiB of 3.5 GiB (70.05%) transferred 2.5 GiB of 3.5 GiB (71.05%) transferred 2.5 GiB of 3.5 GiB (72.05%) transferred 2.6 GiB of 3.5 GiB (73.05%) transferred 2.6 GiB of 3.5 GiB (74.05%) transferred 2.6 GiB of 3.5 GiB (75.05%) transferred 2.7 GiB of 3.5 GiB (76.05%) transferred 2.7 GiB of 3.5 GiB (77.05%) transferred 2.7 GiB of 3.5 GiB (78.06%) transferred 2.8 GiB of 3.5 GiB (79.06%) transferred 2.8 GiB of 3.5 GiB (80.06%) transferred 2.8 GiB of 3.5 GiB (81.06%) transferred 2.9 GiB of 3.5 GiB (82.06%) transferred 2.9 GiB of 3.5 GiB (83.06%) transferred 2.9 GiB of 3.5 GiB (84.06%) transferred 3.0 GiB of 3.5 GiB (85.07%) transferred 3.0 GiB of 3.5 GiB (86.07%) transferred 3.0 GiB of 3.5 GiB (87.07%) transferred 3.1 GiB of 3.5 GiB (88.07%) transferred 3.1 GiB of 3.5 GiB (89.07%) transferred 3.2 GiB of 3.5 GiB (90.07%) transferred 3.2 GiB of 3.5 GiB (91.07%) transferred 3.2 GiB of 3.5 GiB (92.07%) transferred 3.3 GiB of 3.5 GiB (93.07%) transferred 3.3 GiB of 3.5 GiB (94.07%) transferred 3.3 GiB of 3.5 GiB (95.07%) transferred 3.4 GiB of 3.5 GiB (96.07%) transferred 3.4 GiB of 3.5 GiB (97.07%) transferred 3.4 GiB of 3.5 GiB (98.07%) transferred 3.5 GiB of 3.5 GiB (99.07%) transferred 3.5 GiB of 3.5 GiB (100.00%) transferred 3.5 GiB of 3.5 GiB (100.00%) unused0: successfully imported disk 'local-zfs:vm-9001-disk-2' root@pve1:/var/lib/vz/snippets27 qm set 9001 --scsihw virtio-scsi-single update VM 9001: -scsihw virtio-scsi-single root@pve1:/var/lib/vz/snippets28 qm set 9001 --scsi0 local-zfs:vm-9001-disk-2,discard=on,iothread=1,ssd=1 update VM 9001: -scsi0 local-zfs:vm-9001-disk-2,discard=on,iothread=1,ssd=1 root@pve1:/var/lib/vz/snippets29 qm set 9001 --ide2 local-zfs:cloudinit update VM 9001: -ide2 local-zfs:cloudinit ide2: successfully created disk 'local-zfs:vm-9001-cloudinit,media=cdrom' generating cloud-init ISO root@pve1:/var/lib/vz/snippets30 qm set 9001 --boot order=scsi0 update VM 9001: -boot order=scsi0 root@pve1:/var/lib/vz/snippets31 qm set 9001 --ipconfig0 ip=dhcp update VM 9001: -ipconfig0 ip=dhcp root@pve1:/var/lib/vz/snippets32 qm set 9001 --cicustom "user=local:snippets/user-data-ubuntu-2604.yaml" update VM 9001: -cicustom user=local :snippets/user-data-ubuntu-2604.yaml root@pve1:/var/lib/vz/snippets33 qm template 9001 root@pve1:/var/lib/vz/snippets34 qm config 9001 agent: enabled=1 bios: ovmf boot: order=scsi0 cicustom: user=local :snippets/user-data-ubuntu-2604.yaml cores: 2 cpu: x86-64-v2-AES efidisk0: local-zfs:base-9001-disk-0,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=1M ide2: local-zfs:vm-9001-cloudinit,media=cdrom ipconfig0: ip=dhcp machine: q35 memory: 2048 meta: creation-qemu=11.0.0,ctime=1780733774 name: ubuntu-2604-template net0: virtio=BC:24:11:C2:29:00,bridge=vmbr0 scsi0: local-zfs:base-9001-disk-2,discard=on,iothread=1,size=3584M,ssd=1 scsihw: virtio-scsi-single smbios1: uuid=0983fbde-74b1-452b-b64e-4c4d38704b02 template: 1 tpmstate0: local-zfs:base-9001-disk-1,size=4M,version=v2.0 vmgenid: 19c0d2da-4008-4e5a-8ee3-5b9adf2a5fdc
これでテンプレートが完成しています。GUIからも確認できますよ!
一旦はここで区切りです。もちろん、次の稼働確認を終えるまで安心できませんが。
VMのclone手順 ここから先はVMを作成する度にカスタマイズしながら構成します。ここからが日々の運用フェーズです。
Full Cloneで作成 Proxmox GUIでテンプレート(VMID 9001)を右クリック →「クローン」。
必ずFull Cloneを選択する。 Linked Cloneはテンプレートのdiskに依存した状態になるため不可。
設定例:
項目
値
Mode
Full Clone
VM ID
103(暫定)
Name
your-vm
ストレージ
local-zfs
⚠️ ストレージをうっかりNFSにしてしまったりしないように。
ディスクリサイズ cloud imageのデフォルトは3.5GBと小さいため、cloneした後に必ず拡張する。
GUIのハードウェアタブでscsi0を選択 →「ディスクアクション」→「リサイズ」で追加サイズを指定。
⚠️ ディスクは拡張のみ可能です。縮小はできません。拡張の対象は作成したVMです。テンプレートではないですよ!
IPの設定(起動前に必ず実施) Cloud-Initは基本的に初回起動時に適用されます。後から再適用する場合は、VM内で cloud-init clean を実行して再起動する必要があります。
GUIのCloud-Initタブで設定するか、コマンドで:
1 2 qm set 103 --ipconfig0 ip=192.168.x.16/24,gw=192.168.x.1 qm set 103 --nameserver 192.168.x.100
ここはGUIの方が簡単かもしれませんね。ただし、同じVMを量産する場合はコマンドが良いでしょうね。
⚠️ 設定変更後は、必ず「イメージ再作成」ボタンをクリックします。これ忘れがちです。
VM起動 これまでの設定の他、必要に応じてCPUやメモリも変更してください(後からでも変更できます)。
DHCPのままでよければそのまま起動してください。VM起動後、1分程度でIPアドレスがサマリーに表示されます。表示されない場合は、、、なんとかDHCPサーバーなどで確認いただき、まずはssh username@IPアドレスで公開鍵認証で接続して確認してください。スニペットが正しくないとうまくIPアドレスも取得できておらずログインできない可能性があります。
うまくいけば、公開鍵認証であっさりと接続できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 $ ssh yoshi@192.168.x.x The authenticity of host '192.168.x.x (192.168.x.xxx)' can't be established. ED25519 key fingerprint is: SHA256:3IIWwGbmYYERfk3bUl3e+YNXKtfkM+uWwBNgzRx4GFc This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added ' 192.168.x.xxx' (ED25519) to the list of known hosts. Welcome to Ubuntu 26.04 LTS (GNU/Linux 7.0.0-15-generic x86_64) * Documentation: https://docs.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of 2026年 6月 6日 土曜日 18:44:34 JST System load: 0.09 Processes: 134 Usage of /: 7.1% of 38.13GB Users logged in: 0 Memory usage: 20% IPv4 address for eth0: 192.168.x.xxx Swap usage: 0% Expanded Security Maintenance for Applications is not enabled. 0 updates can be applied immediately. Enable ESM Apps to receive additional future security updates. See https://ubuntu.com/esm or run: sudo pro status *** System restart required *** The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law.
内部でupdateが進んでいるので、最初はrestart requiredが表示されるでしょう。一旦作成してしまえばDiskやCPUを変えながらさまざまなホストを作成できます。
その後の初期設定など ホスト名変更 cloud-imageのデフォルトhostnameはubuntuになります。vmにログインしたらホスト名を変更します。
1 sudo hostnamectl set-hostname myhost
一旦SSHを抜けて入り直して確認します。
1 2 yoshi@myhost:~$ hostname myhost
Cloud-Initでホスト名も管理できますが、本記事ではuser-dataを共通化するため、ホスト名のみ初回ログイン後に設定しています。
後は/etc/hostsなど、個人的には、他によく見直すものとしては、アップグレード時の自動リブートを有効にする設定くらいでしょうか。以下は自動リブートを有効にする設定です。
1 sudo sed -i 's/Automatic-Reboot "false"/Automatic-Reboot "true"/' /etc/apt/apt.conf.d/52unattended-upgrades-local
Cloud-Init適用の順番(重要) IPアドレスは今回、DHCPから始めましたが、本番サーバーに仕立てるにあたり、固定IPアドレスに変更する場合は、以下の手順となります。VM稼働中に実施します。この後、rebootで再起動します。
1 2 3 4 5 1. GUIのCloud-InitタブでIPやユーザー名を変更する IPv4アドレスは`xxx.xxx.xxx.xxx/24`とサブネットマスクビットの指定が必要です。 2. 「再生成」ボタンを押す(Cloud-InitのISOが更新される) 3. VM内で: sudo cloud-init clean 4. VM内で: sudo reboot
⚠️ 「再生成」を忘れると古い設定のままcloud-initが再実行される。GUIで変更してもVM内の設定は変わらない。
このようなIP変更は従来viやnanoでubuntuのnetplanを手修正していたことを鑑みればとても簡単です。
テンプレートの更新 Ubuntu OSは定期的にバージョンアップしていきますが、そんなに頻繁にテンプレートの更新はせずとも、Cloud Init直後に自動更新が入りますから1年に1回程度の見直しなどで良いでしょう。
まとめ ここまで設定ができるようになれば、Ubuntuのサーバー運用はとても気軽に試すことができるようになります。使ってみれば分かりますが、Cloud-Init、とても便利です。そしてuser-dataに共通部分を加えていくことによって、VMによっての違いが少なくなり、パッチを当てたりする際などの作業が一律で行えるようになります。最終的にはVMのセキュリティを高め、品質向上に一役買うはずです。
補足 user-dataの配置場所は今回はローカルDiskにしましたが、クラスター化されている場合などは、NFSに配置しておくと両ノードから参照できて便利です。
1 qm set 9001 --cicustom "user=local:snippets/user-data-ubuntu-2604.yaml"
という場所は、NFSのパス名に合わせて以下のように変更します。
1 qm set 9001 --cicustom "user=Synology-nfs:snippets/user-data-ubuntu-2604.yaml"