Provision with cloud-init
cloud-init is the industry-standard multi-distribution method for cross-platform cloud instance initialization. Garden Linux uses cloud-init on all major cloud platforms (AWS, Azure, GCP, OpenStack) for first-boot provisioning and configuration.
What is cloud-init?
cloud-init is a widely-adopted provisioning tool that automates the initialization of cloud instances. It runs on every boot (not just first boot) and performs tasks including:
- Creating users and groups
- Adding SSH authorized keys
- Configuring networking (DHCP, static IPs)
- Writing files to disk
- Running custom shell scripts
- Installing packages
- Configuring system services
cloud-init fetches its configuration from the cloud platform's metadata service or via user-data mechanisms specific to each platform.
When to Use cloud-init
Use cloud-init for:
- AWS deployments — EC2 instances
- Azure deployments — Virtual machines
- GCP deployments — Compute Engine instances
- OpenStack deployments — Nova instances
- VMware deployments — vSphere virtual machines
For bare-metal and PXE boot deployments, use Ignition instead, as Ignition is designed for first-boot-only metal provisioning.
Prerequisites
- Garden Linux cloud platform image (aws, azure, gcp, openstack, vmware flavors automatically include cloud-init)
- Access to the cloud platform's user-data mechanism (varies by platform)
Common Provisioning Tasks
Enable SSH
Garden Linux disables SSH by default for security. Enable SSH using cloud-init user-data:
#!/usr/bin/env bash
systemctl enable --now sshThis is the minimal user-data required for all Garden Linux cloud deployments to enable remote SSH access.
Create Users
Add a new user with SSH key authentication:
#cloud-config
users:
- name: myuser
groups: wheel
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExamplePublicKeyHere user@hostThe wheel group provides passwordless sudo access in Garden Linux.
Default Usernames per Platform
Garden Linux cloud images include a platform-specific default user:
| Platform | Default Username |
|---|---|
| AWS | ec2-user |
| Azure | azureuser |
| GCP | gardenlinux |
| OpenStack | admin |
These users are pre-configured with SSH key access via the cloud platform's metadata service. You only need to enable SSH to access them.
Configure Networking
Most cloud platforms handle networking automatically via DHCP and metadata services. For custom network configuration, use cloud-init network configuration:
#cloud-config
network:
version: 2
ethernets:
eth0:
dhcp4: false
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1
nameservers:
addresses:
- 9.9.9.9
- 1.1.1.1Run Custom Scripts
Execute shell commands or scripts during instance initialization:
#!/usr/bin/env bash
# Enable SSH
systemctl enable --now ssh
# Install additional packages
mount -o remount,rw /usr
apt-get update
apt-get install -y htop vim curl
mount -o remount,ro /usr
# Configure application
mkdir -p /opt/myapp
cat > /opt/myapp/config.yaml <<EOF
database:
host: db.example.com
port: 5432
EOFGarden Linux mounts /usr read-only by default. Remount it read-write before installing packages, then remount read-only afterward.
Write Configuration Files
Use cloud-config to write files to disk:
#cloud-config
write_files:
- path: /etc/hostname
content: |
my-server.example.com
owner: root:root
permissions: '0644'
- path: /opt/myapp/config.yaml
content: |
database:
host: db.example.com
port: 5432
owner: root:root
permissions: '0600'Install Packages
Install additional software packages on first boot:
#cloud-config
packages:
- htop
- vim
- curl
- jq
runcmd:
- mount -o remount,rw /usr
- apt-get update
- apt-get install -y htop vim curl jq
- mount -o remount,ro /usrConfigure Systemd Services
Enable and start systemd units:
#cloud-config
runcmd:
- systemctl enable --now ssh
- systemctl enable --now my-custom-serviceDeliver the Configuration
How you deliver cloud-init configuration depends on the cloud platform. Each platform provides its own mechanism for attaching user-data to instances:
| Platform | Delivery Mechanism | Official Documentation | Garden Linux Guide |
|---|---|---|---|
| AWS | EC2 user-data | EC2 User Data | Install on AWS |
| Azure | Custom data | Azure Custom Data | Install on Azure |
| GCP | Metadata | GCP cloud-init | Install on GCP |
| OpenStack | ConfigDrive or metadata service | OpenStack User Data | Install on OpenStack |
For step-by-step deployment walkthroughs including instance creation with user-data, see the platform-specific tutorials:
cloud-config vs Shell Scripts
cloud-init supports two user-data formats:
Shell Scripts (Shebang Format)
Start with a shebang (#!/usr/bin/env bash). cloud-init executes the script directly:
#!/usr/bin/env bash
systemctl enable --now ssh
echo "Hello from Garden Linux" > /etc/motdcloud-config (YAML Format)
Start with #cloud-config. Provides declarative configuration:
#cloud-config
users:
- name: myuser
groups: wheel
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza...
write_files:
- path: /etc/motd
content: |
Hello from Garden LinuxUse shell scripts for simple tasks and procedural logic. Use cloud-config for declarative user and file management.
Troubleshooting
View cloud-init Logs
Check cloud-init execution logs:
# View cloud-init status
cloud-init status --long
# View cloud-init logs
journalctl -u cloud-init
# View detailed logs
cat /var/log/cloud-init.log
cat /var/log/cloud-init-output.logValidate Configuration Syntax
Test cloud-config syntax before deploying:
# Validate cloud-config YAML
cloud-init schema --config-file user_data.yaml
# Dry-run cloud-init
cloud-init devel schema --config-file user_data.yamlCommon Errors
- SSH not enabled — Ensure user-data includes
systemctl enable --now ssh - User not created — Verify cloud-config YAML syntax and check
/var/log/cloud-init.log - Metadata not fetched — Confirm the instance has network connectivity to the metadata service
- Script not executed — Ensure shell scripts start with a valid shebang (
#!/usr/bin/env bash)
Advanced Configuration
Multi-Part MIME User-Data
Combine multiple user-data formats (cloud-config + shell script):
#!/usr/bin/env python3
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
combined = MIMEMultipart()
# Part 1: cloud-config
cloud_config = """#cloud-config
users:
- name: myuser
groups: wheel
"""
combined.attach(MIMEText(cloud_config, 'cloud-config'))
# Part 2: shell script
shell_script = """#!/usr/bin/env bash
systemctl enable --now ssh
"""
combined.attach(MIMEText(shell_script, 'x-shellscript'))
print(combined.as_string())Conditional Execution
Run commands only on specific platforms:
#cloud-config
runcmd:
- [ sh, -c, 'if [ "$(cloud-init query platform)" = "aws" ]; then echo "Running on AWS"; fi' ]Fetch External Configuration
Download and apply configuration from external sources:
#cloud-config
runcmd:
- curl -o /tmp/setup.sh https://example.com/setup.sh
- bash /tmp/setup.shReference
- cloud-init Documentation
- cloud-init Examples
- cloud-init Module Reference
- cloud-init Network Configuration
- AWS EC2 User Data
- Azure Custom Data
- GCP cloud-init
- OpenStack User Data