Ubuntu cloud-init

Quando você cria um servidor Ubuntu na nuvem (AWS, Azure, DigitalOcean…) ou numa VM do Multipass, ele já nasce com seu usuário, sua chave SSH e seus pacotes. Quem faz isso é o cloud-init: um programa que roda no primeiro boot e segue as instruções de um arquivo chamado user-data.

Você vai aprender
  • Quando o cloud-init roda e de onde ele tira as instruções.
  • Escrever um user-data com usuário, chave SSH, pacotes e comandos.
  • Validar o arquivo antes de usar, com cloud-init schema.
  • Criar uma VM já configurada com Multipass ou LXD.
  • Conferir se deu certo com cloud-init status e os logs.

Conceito: configuração no primeiro boot

  1. Você cria a máquina e entrega um arquivo user-data (no painel da nuvem, no Multipass, no LXD).
  2. A máquina liga pela primeira vez. O cloud-init descobre de onde vieram os dados (a datasource: nuvem, Multipass, LXD…).
  3. Ele cria usuários, instala pacotes, grava arquivos e roda comandos, nessa ordem.
  4. Nos próximos boots, ele não repete a configuração inicial: ela é só da primeira vez.

O cloud-init já vem instalado no Ubuntu Server e nas imagens de nuvem. No Ubuntu Desktop ele existe, mas fica desligado depois da instalação. Veja nesta máquina real:

$ cloud-init --version
/usr/bin/cloud-init 26.1-0ubuntu3~26.04.1
$ 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     « desligado de propósito no desktop
errors: []
recoverable_errors: {}

Sem sudo, o comando também pode mostrar avisos WARNING … insufficient permissions sobre arquivos que ele não conseguiu ler. Eles não atrapalham o resultado.


O arquivo user-data

O formato mais comum é o cloud-config: um YAML cuja primeira linha é obrigatoriamente #cloud-config.

#cloud-config
# ↑ esta primeira linha é obrigatória

hostname: web1
timezone: America/Sao_Paulo

# Usuários (substitui o usuário padrão "ubuntu", a não ser que você liste "default")
users:
  - default
  - name: ana
    gecos: Ana Souza
    groups: [sudo]
    shell: /bin/bash
    sudo: "ALL=(ALL) NOPASSWD:ALL"        # sudo sem senha (comum em nuvem)
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK3p… ana@notebook

# Pacotes
package_update: true                     # apt update
package_upgrade: true                    # apt upgrade
packages:
  - nginx
  - htop

# Arquivos a criar
write_files:
  - path: /var/www/html/index.html
    content: |
      <h1>Criado pelo cloud-init</h1>
    permissions: "0644"

# Comandos rodados no fim, uma vez, como root
runcmd:
  - ufw allow OpenSSH
  - ufw allow "Nginx Full"
  - ufw --force enable
ChaveO que fazEquivale a…
hostnameNome da máquinahostnamectl set-hostname
usersCria usuários, grupos, sudo e chaves SSHadduser + usermod + authorized_keys
package_update / package_upgradeAtualiza o sistemaapt update / apt upgrade
packagesInstala pacotesapt install
write_filesCria arquivos com conteúdo e permissõesecho … > arquivo + chmod
runcmdComandos livres, como root, no fimum script
timezoneFuso horáriotimedatectl set-timezone
Por que listar default em users?

Sem ele, o usuário padrão da imagem (ubuntu) não é criado. Ferramentas como multipass shell entram com esse usuário: se ele não existir, você só entra pelo seu usuário via SSH.


Validar antes de usar: cloud-init schema

Um erro no user-data só aparece quando a máquina já subiu errada. Valide antes, no seu próprio computador:

cloud-init schema
Confere se o arquivo segue as regras do cloud-config.
-c user-data.yaml
config-file: o arquivo a validar.
$ cloud-init schema -c user-data.yaml
Valid schema user-data.yaml
$ echo $?
0

Exemplos reais de erro, gerados nesta máquina:

$ cloud-init schema -c ruim.yaml
Error: Cloud config schema errors: format-l2.c1: File ruim.yaml is not valid YAML. while parsing a block mapping
  in "<unicode string>", line 2, column 1:
    packages:
    ^
expected <block end>, but found '<block mapping start>'
  in "<unicode string>", line 4, column 2:          « linha 4: indentação errada
     runcmd:
     ^

Error: Invalid schema: user-data

Invalid user-data ruim.yaml
$ cloud-init schema -c semcabecalho.yaml
Error: Cloud config schema errors: format-l1.c1: Unrecognized user-data header in semcabecalho.yaml: "hostname: lab".
Expected first line to be one of: #!, ## template: jinja, #cloud-boothook, #cloud-config, #cloud-config-archive, #cloud-config-jsonp, #include, #include-once, #part-handler
…                                                  « esqueceu o "#cloud-config"

Usar: três formas

Forma 1: Multipass

multipass launch 26.04
Cria uma VM Ubuntu 26.04 (veja KVM).
--name web1
Nome da VM.
--cloud-init user-data.yaml
Entrega o arquivo ao cloud-init da VM.
$ multipass launch 26.04 --name web1 --cloud-init user-data.yaml
Launched: web1
$ multipass exec web1 -- cloud-init status --wait
.....................
status: done                                 « terminou sem erros
$ multipass list
Name                    State             IPv4             Image
web1                    Running           10.73.164.25     Ubuntu 26.04 LTS
$ curl -s 10.73.164.25
<h1>Criado pelo cloud-init</h1>
$ ssh ana@10.73.164.25                       « sua chave já funciona

Forma 2: LXD

$ lxc launch ubuntu:26.04 web2 --config=user.user-data="$(cat user-data.yaml)"
$ lxc exec web2 -- cloud-init status --wait
status: done

O $(cat user-data.yaml) coloca o conteúdo do arquivo dentro do comando (veja LXD).

Forma 3: provedor de nuvem

No painel de criação da máquina, procure o campo User data (às vezes em "Opções avançadas") e cole o conteúdo do arquivo. Pela linha de comando dos provedores, costuma haver uma opção como --user-data file://user-data.yaml.

FormaMelhor quando…
MultipassTestar o user-data no seu computador antes de usar na nuvem.
LXDVocê já usa LXD e quer instâncias leves pré-configuradas.
NuvemServidores de produção.
AnsibleConfigurar máquinas que já existem, de novo e de novo.

Conferir o que aconteceu

$ cloud-init status --long
status: done
extended_status: done
boot_status_code: enabled-by-generator
last_update: Thu, 15 Oct 2026 13:58:02 +0000
detail: DataSourceNoCloud [seed=/dev/sr0]
errors: []
recoverable_errors: {}
$ sudo tail -n 3 /var/log/cloud-init-output.log
Setting up nginx (1.28.0-3ubuntu1) ...
Rule added
Cloud-init v. 26.1-0ubuntu3~26.04.1 finished at Thu, 15 Oct 2026 13:58:02 +0000. Datasource DataSourceNoCloud [seed=/dev/sr0].  Up 61.42 seconds
Arquivo / comandoO que mostra
cloud-init status --waitEspera terminar e mostra o resultado
/var/log/cloud-init-output.logA saída dos comandos (apt, runcmd): o primeiro lugar para olhar
/var/log/cloud-init.logO log detalhado do próprio cloud-init
sudo cloud-init query userdataO user-data que a máquina recebeu
cloud-init analyze showQuanto tempo cada etapa levou

Rodar de novo (para testes)

$ sudo cloud-init clean --logs --reboot
Atenção

cloud-init clean faz a máquina agir como se fosse o primeiro boot: o user-data é aplicado de novo, o que pode recriar chaves SSH do servidor e sobrescrever arquivos. Use só em máquinas de teste.


Quando não funciona

Nada do user-data foi aplicado

O que aconteceu: quase sempre falta a primeira linha #cloud-config; sem ela, o arquivo é ignorado. Como confirmar: cloud-init schema -c user-data.yaml mostra "Unrecognized user-data header".

status: error
$ cloud-init status
status: error

Como resolver: rode cloud-init status --long para ver a lista de erros e procure "Error" ou "Traceback" em /var/log/cloud-init.log. Um runcmd que falhou aparece em /var/log/cloud-init-output.log.

Não consigo entrar por SSH

O que aconteceu: a chave em ssh_authorized_keys está incompleta (copiada cortada) ou é a chave privada. Cole a linha inteira do arquivo ~/.ssh/id_ed25519.pub, que começa com ssh-ed25519.

multipass shell falha depois do cloud-init

O que aconteceu: o users: não incluiu - default, então o usuário ubuntu não existe. Inclua - default ou entre com ssh ana@IP.


Referência

ComandoO que faz
cloud-init schema -c ARQValida um user-data
cloud-init status [--long] [--wait]Estado da execução
cloud-init query userdataMostra o user-data recebido (com sudo)
cloud-init analyze showTempo de cada etapa
cloud-init collect-logsJunta todos os logs num arquivo .tar.gz
cloud-init clean [--logs] [--reboot]Prepara para rodar de novo

Exercícios

1. Primeira linha

Complete a primeira linha obrigatória de um user-data no formato cloud-config:

packages: - nginx

2. Validar

cloud-init user-data.yaml

3. Multipass com user-data

multipass launch 26.04 --name lab user-data.yaml

4. Em que momento o cloud-init aplica o user-data?

5. Onde ver a saída dos comandos de runcmd e dos pacotes instalados?


Resumo

  • O cloud-init configura a máquina no primeiro boot a partir do user-data.
  • A primeira linha precisa ser #cloud-config; o resto é YAML (usuários, pacotes, arquivos, comandos).
  • Valide sempre com cloud-init schema -c antes de usar.
  • Teste localmente com multipass launch --cloud-init e depois use na nuvem.
  • Confira com cloud-init status --long e /var/log/cloud-init-output.log.