メインコンテンツへスキップ
  1. Linux 関連記事一覧/
  2. Ubuntu 26.04 LTS Server/

Ubuntu 26.04 LTS Server の初期設定を自動化する(cloud-init)

目次

cloud-init による初期設定の自動化

cloud-init は、サーバーの初回起動時にホスト名・ユーザー・SSH 鍵・ネットワーク・パッケージの導入といった初期設定を自動で行う仕組みです。Ubuntu のクラウドイメージには標準で組み込まれており、クラウドや仮想環境でサーバーを用意するときの初期設定はこれで行います。

手作業で行う初期設定については、ホスト名の変更ユーザー作成と sudo 権限の設定などの各記事で解説しています。本記事では、同じ設定を起動時に済ませる方法を扱います。

本記事の実行例は、cloud-init 26.1 を搭載した Ubuntu 26.04 LTS Server で採取したものです。

与える設定(user-data)

cloud-init に渡す設定は user-data と呼ばれ、#cloud-config で始まる YAML で記述します。本記事では次の設定でサーバーを起動しています。

本記事で使用した user-data
#cloud-config
hostname: sv2
manage_etc_hosts: true
timezone: Asia/Tokyo
users:
  - name: kazulog
    groups: [sudo]
    shell: /bin/bash
    sudo: "ALL=(ALL) NOPASSWD:ALL"
    lock_passwd: false
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... kazulog@client
chpasswd:
  expire: false
  users:
    - name: kazulog
      password: kazulog
      type: text
package_update: true
packages:
  - git
  - nginx
write_files:
  - path: /etc/motd
    content: |
      このサーバーは cloud-init で構成されています。
  - path: /var/www/html/index.html
    content: "<h1>provisioned by cloud-init</h1>\n"
runcmd:
  - [systemctl, restart, nginx]
  - [sh, -c, "echo provisioned at $(date -Is) >> /var/log/provision.log"]

主な項目は次のとおりです。

項目内容
hostnameホスト名。manage_etc_hosts: true を併記すると /etc/hosts も更新される
timezoneタイムゾーン
users作成するユーザー。groupssudo を指定すると管理コマンドを実行できる。sudo は sudoers に書く内容、ssh_authorized_keys は公開鍵
chpasswdパスワードの設定。expire: false を付けないと初回ログイン時に変更を求められる
package_updatetrueapt update 相当を実行する
packages導入するパッケージの一覧
write_files作成するファイル。pathcontent を指定する
runcmd最後に実行するコマンド。リスト形式で書くとシェルを介さず実行される
users を指定すると、イメージの既定ユーザー(Ubuntu のクラウドイメージでは ubuntu)は作成されません。SSH の公開鍵かパスワードのどちらかを必ず設定してください。 どちらも無いとログインできないサーバーができあがります。

user-data をサーバーに渡す方法

cloud-init は、起動時に決まった場所を探して user-data を読み込みます。この置き場所をデータソースと呼び、渡し方は環境によって次の3通りに分かれます。

環境渡し方データソース
クラウド(AWS / GCP / Azure など)インスタンス作成時の「ユーザーデータ」欄に #cloud-config を貼り付ける各クラウドのメタデータサービス
仮想基盤(Proxmox / VMware / CML など)管理画面の cloud-init 設定欄に貼り付ける。基盤側が ISO イメージを作って仮想 CD-ROM として接続するNoCloud
手元の仮想環境cloud-localds コマンドで ISO イメージ(seed ISO)を自分で作り、クラウドイメージと一緒に起動するNoCloud

本記事の実行例は3番目と同じ仕組みで、後述の cloud-init query subplatformconfig-disk (/dev/sr0) を返しているのは、この ISO イメージから読み込んだことを示しています。

手元の仮想環境で試す

クラウドや仮想基盤を使わずに試す場合は、次の3つを用意します。

  1. Ubuntu のクラウドイメージ(通常のインストーラ用 ISO ではなく、インストール済みのディスクイメージ)
  2. seed ISO(user-data を収めた ISO イメージ)
  3. それらを起動する仮想化ソフト(qemu / KVM、libvirt など)

seed ISO の作成には cloud-image-utils パッケージの cloud-localds コマンドを使います。

cloud-localds の導入コマンド
sudo apt install -y cloud-image-utils
cloud-localds の導入 実行例
kazulog@sv1:~$ which cloud-localds qemu-system-x86_64
/usr/bin/cloud-localds
/usr/bin/qemu-system-x86_64

user-data を書いたファイルを用意し、cloud-localds に渡します。

seed ISO の作成コマンド
cloud-localds [ISO] [USER-DATA]
入力箇所入力内容
[ISO]作成する ISO イメージのファイル名
[USER-DATA]#cloud-config で始まる user-data のファイル
seed ISO の作成 実行例
kazulog@sv1:~$ cat user-data.yaml | head -6
#cloud-config
hostname: web01
manage_etc_hosts: true
timezone: Asia/Tokyo
users:
  - name: kazulog
kazulog@sv1:~$ cloud-localds seed.iso user-data.yaml
kazulog@sv1:~$ ls -lh seed.iso
-rw-rw-r-- 1 kazulog kazulog 366K Sep 10 21:19 seed.iso

ネットワーク設定も渡す場合は -N で network-config のファイルを指定します。

ネットワーク設定も含める場合
cloud-localds -N [NETWORK-CONFIG] [ISO] [USER-DATA]
ネットワーク設定も含めた場合の ISO の中身 実行例
kazulog@sv1:~$ cloud-localds -N network-config.yaml seed.iso user-data.yaml
kazulog@sv1:~$ sudo mkdir -p /mnt/seed && sudo mount -o loop,ro seed.iso /mnt/seed
kazulog@sv1:~$ ls -l /mnt/seed
total 0
-rw-rw-r-- 1 kazulog kazulog  33 Sep 10 21:20 meta-data
-rw-r--r-- 1 kazulog kazulog  48 Sep 10 21:20 network-config
-rw-r--r-- 1 kazulog kazulog 478 Sep 10 21:20 user-data
kazulog@sv1:~$ sudo umount /mnt/seed

ISO の中には user-datameta-data-N を指定した場合は network-config が入ります。meta-datacloud-localds が自動で作ります。

あとは、クラウドイメージをディスクとして、seed ISO をもう1台のディスクとして仮想マシンを起動します。Ubuntu 26.04 のクラウドイメージは UEFI で起動するため、OVMF(UEFI ファームウェア)を指定します。

クラウドイメージの入手コマンド
wget https://cloud-images.ubuntu.com/releases/26.04/release/ubuntu-26.04-server-cloudimg-amd64.img
仮想マシンの起動コマンド(qemu の例)
qemu-system-x86_64 -enable-kvm -m 1024 -smp 1 -nographic \
  -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
  -drive if=pflash,format=raw,file=OVMF_VARS.fd \
  -drive file=ubuntu-26.04-server-cloudimg-amd64.img,format=qcow2,if=virtio \
  -drive file=seed.iso,format=raw,if=virtio \
  -net nic -net user

OVMF_VARS.fd/usr/share/OVMF/OVMF_VARS_4M.fd をコピーして使います(UEFI の設定を保存する領域で、仮想マシンごとに1つ必要です)。ovmfqemu-system-x86 パッケージを導入しておきます。

起動すると cloud-init が seed ISO を読み込み、user-data の内容が適用されます。次はコンソールの出力で、user-data に書いた web01 がホスト名になっていること、データソースとして seed ISO(/dev/vdb)が使われたことが確認できます。

起動した仮想マシンのコンソール出力
Ubuntu 26.04 LTS web01 ttyS0

web01 login: [  444.354111] sh[1072]: Completed socket interaction for boot stage config
[  462.016133] cloud-init[943]: Cloud-init v. 26.1-0ubuntu3~26.04.1 running 'modules:final' at Thu, 10 Sep 2026 12:57:00 +0000. Up 461.65 seconds.
コンソール出力(cloud-init の完了とデータソース)
[  465.718178] cloud-init[943]: Cloud-init v. 26.1-0ubuntu3~26.04.1 finished at Thu, 10 Sep 2026 12:57:04 +0000. Datasource DataSourceNoCloud [seed=/dev/vdb].  Up 465.66 seconds
クラウドイメージを qemu-img resize で拡張したものをそのまま起動すると、起動に失敗します。 ディスクの末尾にある GPT の予備ヘッダーが元の位置に残るため、/boot のパーティションが認識されず緊急モードになります(実際に確認しました)。容量を増やす場合は virt-resize などパーティションテーブルまで面倒を見るツールを使うか、拡張せずにそのまま起動してください。

設定が反映されたかの確認

起動後、cloud-init status で実行結果を確認します。--long を付けると詳細が表示されます。

実行結果の確認コマンド
cloud-init status --long
実行結果の確認 実行例
kazulog@sv2:~$ cloud-init --version
/usr/bin/cloud-init 26.1-0ubuntu3~26.04.1
kazulog@sv2:~$ cloud-init status --long
status: done
extended_status: done
boot_status_code: enabled-by-generator
last_update: Thu, 01 Jan 1970 00:00:27 +0000
detail: DataSourceNoCloud [seed=/dev/sr0]
errors: []
recoverable_errors: {}
kazulog@sv2:~$
項目内容
statusdone(完了)/running(実行中)/errordisabled
boot_status_codecloud-init が有効かどうか
detail使用したデータソース(後述)
recoverable_errors処理は続行できたが問題があった項目
処理は完了したものの一部に問題があった場合、statusdone のままで extended_statusdegraded done になり、内容が recoverable_errors に入ります。cloud-init status だけでは気づけないため、--long で確認してください。

パスワードを設定した場合は、passwd -S の2列目が P になっていることで確認できます。

パスワードが設定されていることの確認 実行例
kazulog@sv2:~$ sudo passwd -S kazulog
kazulog P 2026-09-10 0 99999 7 -1

設定した内容が反映されているかは、それぞれのコマンドで確認します。

設定内容の確認 実行例
kazulog@sv2:~$ hostname
sv2
kazulog@sv2:~$ id kazulog
uid=1000(kazulog) gid=1000(kazulog) groups=1000(kazulog),27(sudo)
kazulog@sv2:~$ cat /etc/motd
このサーバーは cloud-init で構成されています。
kazulog@sv2:~$ curl -s localhost | head -2
<h1>provisioned by cloud-init</h1>
kazulog@sv2:~$ cat /var/log/provision.log
provisioned at 2026-09-10T19:37:39+09:00
provisioned at 2026-09-10T19:42:01+09:00
kazulog@sv2:~$ dpkg -l git nginx | grep '^ii'
ii  git            1:2.53.0-1ubuntu1  amd64        fast, scalable, distributed revision control system
ii  nginx          1.28.3-2ubuntu1.10 amd64        small, powerful, scalable web/proxy server
kazulog@sv2:~$ timedatectl | head -3
               Local time: Thu 2026-09-10 19:42:26 JST
           Universal time: Thu 2026-09-10 10:42:26 UTC
                 RTC time: Thu 2026-09-10 10:42:26
kazulog@sv2:~$ ls -l ~/.ssh/authorized_keys
-rw------- 1 kazulog kazulog 110 Sep 10 19:41 /home/kazulog/.ssh/authorized_keys

ホスト名、ユーザーと所属グループ、write_files で置いたファイル、packages で導入したパッケージ、runcmd の実行結果、タイムゾーン、公開鍵のすべてが反映されています。

データソースの確認

cloud-init が どこから user-data を読んだか をデータソースと呼びます。クラウドではメタデータサービス、仮想環境では ISO イメージ(NoCloud)が使われます。

データソースの確認コマンド
cloud-init query platform
cloud-init query subplatform
データソースの確認 実行例
kazulog@sv2:~$ cloud-init query platform
nocloud
kazulog@sv2:~$ cloud-init query subplatform
config-disk (/dev/sr0)
kazulog@sv2:~$

上の例では、nocloud というデータソースが /dev/sr0(仮想的な CD-ROM)から設定を読み込んでいます。

実際に読み込まれた user-data は /var/lib/cloud/instance/user-data.txt に保存されています。サーバーがどの設定で作られたかを後から確認できます。

読み込まれた user-data の確認 実行例
kazulog@sv2:~$ sudo head -11 /var/lib/cloud/instance/user-data.txt
#cloud-config
hostname: sv2
manage_etc_hosts: true
timezone: Asia/Tokyo
users:
  - name: kazulog
    groups: [sudo]
    shell: /bin/bash
    sudo: "ALL=(ALL) NOPASSWD:ALL"
    lock_passwd: false
    ssh_authorized_keys:
kazulog@sv2:~$

実行時間とログの確認

どの処理にどれだけ時間がかかったかは cloud-init analyze blame で確認できます。起動が遅い場合の調査に使います。

実行時間の確認コマンド
sudo cloud-init analyze blame
実行時間の確認 実行例
kazulog@sv2:~$ sudo cloud-init analyze blame | head -10
-- Boot Record 01 --
     07.24200s (modules-final/config-package_update_upgrade_install)
     00.75900s (modules-config/config-apt_configure)
     00.23800s (init-local/search-NoCloud)
     00.15500s (modules-final/config-keys_to_console)
     00.13400s (init-network/config-set_passwords)
     00.11000s (modules-final/config-scripts_user)
     00.10500s (init-network/config-growpart)
     00.10200s (init-network/config-ssh)
     00.07300s (modules-final/config-ssh_authkey_fingerprints)
kazulog@sv2:~$

パッケージの導入(config-package_update_upgrade_install)が大部分を占めていることが分かります。

ログは2種類あります。

ファイル内容
/var/log/cloud-init.logcloud-init 自身の詳細なログ
/var/log/cloud-init-output.log実行したコマンドの出力(apt の出力など)
ログの確認 実行例
kazulog@sv2:~$ sudo ls -l /var/log/cloud-init.log /var/log/cloud-init-output.log
-rw-r----- 1 root   adm   4059 Sep 10 19:42 /var/log/cloud-init-output.log
-rw-r----- 1 syslog adm 109119 Sep 10 19:42 /var/log/cloud-init.log
kazulog@sv2:~$

書式の検証

user-data に誤りがあると、設定の一部が反映されないままサーバーが起動します。投入前に cloud-init schema で検証してください。

書式の検証コマンド
sudo cloud-init schema --config-file [FILE]
入力箇所入力内容
[FILE]検証する cloud-config ファイル
書式の検証 実行例
kazulog@sv2:~$ sudo cloud-init schema --config-file /tmp/good.yaml
Valid schema /tmp/good.yaml
kazulog@sv2:~$ sudo cloud-init schema --config-file /tmp/bad.yaml
Invalid user-data /tmp/bad.yaml
Error: Cloud config schema errors: packages: 'git' is not of type 'array', runcmds: Additional properties are not allowed ('runcmds' was unexpected)

Error: Invalid schema: user-data
kazulog@sv2:~$

誤りがある場合は、項目名と理由が表示されます。上の例では packages に文字列を書いている点(リストである必要がある)と、runcmdruncmds と誤記している点が報告されています。

適用済みの設定を検証する場合は --system を使います。

適用済みの設定の検証 実行例
kazulog@sv2:~$ sudo cloud-init schema --system | tail -3
2. network-config at /var/lib/cloud/instances/ubuntu/network-config.json:
  Valid schema network-config

設定をやり直す

cloud-init は初回起動時にのみ実行され、2回目以降の起動では設定を適用しません。検証環境で設定を作り込む場合は、状態を消してから再起動すると初回起動としてやり直せます。

状態を消して初回起動からやり直すコマンド
sudo cloud-init clean --logs
sudo reboot
状態の消去 実行例
kazulog@sv2:~$ sudo cloud-init clean --logs
kazulog@sv2:~$ ls /var/lib/cloud/
seed
kazulog@sv2:~$

再起動後は user-data が再度読み込まれ、runcmd も実行し直されます。

再起動後の確認 実行例
kazulog@sv2:~$ uptime -p
up 0 minutes
kazulog@sv2:~$ cloud-init status
status: done
kazulog@sv2:~$ cat /var/log/provision.log
provisioned at 2026-09-10T19:37:39+09:00
provisioned at 2026-09-10T19:42:01+09:00
provisioned at 2026-09-10T19:43:35+09:00
kazulog@sv2:~$ cat /etc/motd
このサーバーは cloud-init で構成されています。

runcmd が再度実行され、provision.log に新しい行が追加されています。

cloud-init clean は稼働中のサーバーで実行しないでください。ユーザーやネットワークの設定が再適用され、意図しない状態になることがあります。

cloud-init を無効にする

構築が終わったサーバーで cloud-init を動かしたくない場合は、無効化用のファイルを作成します。

cloud-init を無効にするコマンド
sudo touch /etc/cloud/cloud-init.disabled
無効化の設定 実行例
kazulog@sv2:~$ sudo touch /etc/cloud/cloud-init.disabled
kazulog@sv2:~$ ls -l /etc/cloud/cloud-init.disabled
-rw-r--r-- 1 root root 0 Sep 10 19:44 /etc/cloud/cloud-init.disabled
kazulog@sv2:~$

再起動後は statusdisabled になり、user-data は読み込まれません。

無効化の確認 実行例
kazulog@sv2:~$ cloud-init status --long
status: disabled
extended_status: disabled
boot_status_code: disabled-by-marker-file
detail: Cloud-init disabled by /etc/cloud/cloud-init.disabled
errors: []
recoverable_errors: {}
kazulog@sv2:~$

detail に無効化の理由が表示されます。元に戻す場合はこのファイルを削除します。

ネットワークの設定について

ネットワークの設定は user-data とは別に network-config として渡します。書式は Netplan と同じで、/etc/netplan/50-cloud-init.yaml として書き出されます。詳細はUbuntu 26.04 LTS Server のネットワーク設定で解説しています。

検証環境と実行ログ

本記事の実行例は、CML 上の Ubuntu 26.04 LTS Server(cloud-init 26.1)で採取したものです。各手順の実行ログを以下からダウンロードできます。

手順実行ログ
seed ISO の作成(cloud-localds)log
ネットワーク設定を含めた ISO の確認log
cloud-localds と qemu の導入log
seed ISO から起動した仮想マシンのコンソールlog
実行結果とデータソースの確認log
実行時間とパスワードの確認log
設定内容の反映確認log
ログの確認log
書式の検証log
状態の消去と再起動log
再起動後の確認log
無効化の設定log
無効化の確認log

参考リンク

cloud-init documentation

関連記事

Ubuntu 公式ページ