User data
User data — user configuration parameters of the server operating system. They are described as scripts in cloud-config format (text files with YAML syntax) or as a bash script. The scripts are automatically Base64 encoded, transferred to the server, and executed by the cloud-init agent when the operating system is first started. The use of user data helps automate server configuration.
Specify user data can be done at the operating system installation stage.
Read more about cloud-config and bash script formats in the instructions User data formats cloud-init documentation.
In scripts, you can pass both individual operating system configuration parameters and entire sequences of parameters. For example:
- time zone;
- create a directory and upload files to it;
- update repositories and install packages;
- place an SSH key on the server;
- configure the domain name resolver configuration file resolv.conf.
Check out the other examples in the manual Cloud config examples cloud-init documentation.
Specify user data
You can only specify user data when installing the Linux operating system by auto-installation. The script text is added to the field User data.
After the automatic installation is complete, the text in the field User data can't be changed.
The maximum size of a script with data that is not Base64 encoded is 16 KB.
Examples of user data
Set time zone
Cloud-config
Bash script
An example script for setting the Europe/Moscow time zone:
#cloud-config
timezone: Europe/Moscow
An example script for setting the Europe/Moscow time zone:
#!/bin/bash
timedatectl set-timezone Europe/Moscow
Create a directory and upload files to it
Cloud-config
Bash script
An example script to create a directory and upload a file to it over the network:
#cloud-config
runcmd:
- mkdir /run/newdir
- [ wget, "http://example.com", -O, /run/newdir/index.html ]
An example script to create a directory and upload a file to it over the network:
#!/bin/bash
mkdir /run/newdir
wget http://example.com -O /run/newdir/index.html
Update repositories and install packages
Cloud-config
Bash script
Sample script to install pwgen and pastebinit:
#cloud-config
package_update: true
packages:
- pwgen
- pastebinit
Sample script to install pwgen and pastebinit:
#!/bin/bash
apt update
apt install pwgen pastebinit
Place the SSH key on the server
Cloud-config
Bash script
Sample script:
#cloud-config
ssh_authorized_keys:
- ssh-rsa AAAAB3N…V7NZ user1@host
- ssh-rsa AAAAB3N…NtHw== user2@server
Sample script:
#!/bin/bash
echo "ssh-rsa AAAAB3N…V7NZ user1@host" >> /root/.ssh/authorized_keys
echo "ssh-rsa AAAAB3N…NtHw== user2@server" >> /root/.ssh/authorized_keys
Customize the configuration file
Cloud-config
Bash script
Sample script for the resolv.conf domain name resolver:
#cloud-config
manage_resolv_conf: true
resolv_conf:
nameservers: ['4.4.4.4', '8.8.8.8']
searchdomains:
- foo.example.com
- bar.example.com
domain: example.com
options:
rotate: true
timeout: 1
Sample script for the resolv.conf domain name resolver:
#!/bin/bash
cat <<EOF > /etc/resolv.conf
domain example.com
nameserver 4.4.4.4
nameserver 8.8.8.8
search foo.example.com bar.example.com
options rotate
options timeout:1
EOF
Disable internet access
Bash script
Python script
Sample script:
#!/bin/bash
ip addr show
public_interface=$(ip -4 addr show | awk '/inet/ && !/127.0.0.1/ && !/192\.0\.2\.0/ && !/10\./ && !/198\.(1[6-9]|2[0-9]|3[0-1])\./ && !/192\.168\./ {print $NF}')
if [ -n "$public_interface" ]; then
ip link set down dev "$public_interface"
else
echo "Public interface not found."
fi
Sample script:
#!/usr/bin/env python3
import subprocess
import re
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def disable_public_interface():
logging.info('Starting disable_public_interface function.')
output = subprocess.check_output('ip -4 addr show', shell=True).decode('utf-8')
interfaces = re.findall(r'^\d+: (\S+):.*?\n(?:.*\n)*?\s+inet (\d+\.\d+\.\d+\.\d+)/\d+', output, re.MULTILINE)
public_interfaces = []
for iface, ip in interfaces:
if iface == 'lo':
continue
if re.match(r'^(127\.|10\.|198\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)', ip):
continue
public_interfaces.append(iface)
for interface in public_interfaces:
command = ['ip', 'link', 'set', 'dev', interface, 'down']
try:
subprocess.run(command, check=True)
logging.info(f'Successfully disabled interface: {interface}')
except subprocess.CalledProcessError as e:
logging.error(f'Failed to disable interface: {interface}, error: {e}')
if __name__ == "__main__":
logging.info('Script started.')
disable_public_interface()
lo gging.info('Script finished.')