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.
- Quando o cloud-init roda e de onde ele tira as instruções.
- Escrever um
user-datacom 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 statuse os logs.
Conceito: configuração no primeiro boot
- Você cria a máquina e entrega um arquivo user-data (no painel da nuvem, no Multipass, no LXD).
- A máquina liga pela primeira vez. O cloud-init descobre de onde vieram os dados (a datasource: nuvem, Multipass, LXD…).
- Ele cria usuários, instala pacotes, grava arquivos e roda comandos, nessa ordem.
- 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
| Chave | O que faz | Equivale a… |
|---|---|---|
hostname | Nome da máquina | hostnamectl set-hostname |
users | Cria usuários, grupos, sudo e chaves SSH | adduser + usermod + authorized_keys |
package_update / package_upgrade | Atualiza o sistema | apt update / apt upgrade |
packages | Instala pacotes | apt install |
write_files | Cria arquivos com conteúdo e permissões | echo … > arquivo + chmod |
runcmd | Comandos livres, como root, no fim | um script |
timezone | Fuso horário | timedatectl set-timezone |
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.
| Forma | Melhor quando… |
|---|---|
| Multipass | Testar o user-data no seu computador antes de usar na nuvem. |
| LXD | Você já usa LXD e quer instâncias leves pré-configuradas. |
| Nuvem | Servidores de produção. |
| Ansible | Configurar 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 / comando | O que mostra |
|---|---|
cloud-init status --wait | Espera terminar e mostra o resultado |
/var/log/cloud-init-output.log | A saída dos comandos (apt, runcmd): o primeiro lugar para olhar |
/var/log/cloud-init.log | O log detalhado do próprio cloud-init |
sudo cloud-init query userdata | O user-data que a máquina recebeu |
cloud-init analyze show | Quanto tempo cada etapa levou |
Rodar de novo (para testes)
$ sudo cloud-init clean --logs --reboot
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
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.
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
| Comando | O que faz |
|---|---|
cloud-init schema -c ARQ | Valida um user-data |
cloud-init status [--long] [--wait] | Estado da execução |
cloud-init query userdata | Mostra o user-data recebido (com sudo) |
cloud-init analyze show | Tempo de cada etapa |
cloud-init collect-logs | Junta 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:
2. Validar
3. Multipass com user-data
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 -cantes de usar. - Teste localmente com
multipass launch --cloud-inite depois use na nuvem. - Confira com
cloud-init status --longe/var/log/cloud-init-output.log.