Initialization Scripts
Newly deployed Cloud Servers usually require some steps to set up. Everyone has their own list of things to go through from adding new user accounts to running updates and installing common applications. With Initialization scripts , you can automate the tasks you would otherwise perform again and again when booting up a new server.

Adding scripts
You can manage your scripts with the Initialization Scripts feature in your UpCloud Control Panel under your Account section. Click the Add new button at the top of the page to open the editor window.

Copy any pre-existing script you might have into the script text field, or write a new script straight in the browser. Name your scripts so that you can easily distinguish between them. Once you are done, click the Save script button at the bottom to save the changes.
Deploying with a script
The Initialization scripts are supported by all of our public Linux templates. After adding any SSH keys you may wish to use, you can find the option to load your previously saved initialization scripts.
Selecting one of your stored scripts will bring it to the edit field below. You can make any last-minute changes to the script still before deployment, or you can write a completely new script right on the spot. Once you are done making changes, click the Deploy button as usual to deploy the new server. The server will perform the actions dictated by the script during the first boot up saving you considerable time and effort.

If your script didn’t do what you expected, delete the server and deploy a new one to try again.
Writing scripts
Initialization scripts support anything a regular Linux shell script would. Depending on your choice of distribution, the default shell might use different implementations, but the principles remain the same. Below is an example of how to have the server automatically run the update and upgrade routines. The commands depend on the operating system's package manager. The examples cover the following operating systems, installed from the UpCloud templates:
- Ubuntu 22.04, 24.04, and 26.04
- Debian 12 and 13
- AlmaLinux 9 and 10
- Rocky Linux 9 and 10
- Fedora 42 and 43
#!/bin/bash
# Stop at the first command that fails
set -e
# Run the commands in a noninteractive mode
export DEBIAN_FRONTEND=noninteractive
# Update source list and log the output to file
apt-get update > /tmp/init-script.log
# Upgrade available software packages with default options when available
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y upgrade >> /tmp/init-script.logYou can also write the script as a cloud-config file, which starts with #cloud-config. The same file works on all the operating systems listed above. This example installs nginx, adds a user with sudo rights and your SSH key, and starts nginx:
#cloud-config
package_update: true
packages:
- nginx
users:
- default
- name: <username>
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- <ssh-public-key>
runcmd:
- systemctl enable --now nginxIt is also possible to enter a URL in an initialization script. If the script begins with a URL, the deployment process will attempt to fetch the script from that URL and use it instead. This allows greater flexibility including dynamically updating the initialization script between deployments.
Deploying with the API
When you create a server with the API, put the script in the user_data field as a string, with each line break written as \n, and turn on the Metadata service with "metadata": "yes". The API requires it for templates that use cloud-init. The example below deploys Ubuntu Server 24.04 LTS with the shell script above. To use another operating system, list the templates and use the template's UUID as the storage of the storage device.
GET /1.3/storage/templatePOST /1.3/server{
"server": {
"zone": "de-fra1",
"title": "<title>",
"hostname": "<hostname>",
"plan": "PREMIUM-1xCPU-1GB",
"metadata": "yes",
"user_data": "#!/bin/bash\n# Stop at the first command that fails\nset -e\n# Run the commands in a noninteractive mode\nexport DEBIAN_FRONTEND=noninteractive\n# Update source list and log the output to file\napt-get update > /tmp/init-script.log\n# Upgrade available software packages with default options when available\napt-get -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" -y upgrade >> /tmp/init-script.log",
"storage_devices": {
"storage_device": [
{
"action": "clone",
"storage": "01000000-0000-4000-8000-000030240200",
"title": "<title>-disk",
"size": 25,
"tier": "maxiops"
}
]
},
"networking": {
"interfaces": {
"interface": [
{
"type": "public",
"ip_addresses": {
"ip_address": [
{
"family": "IPv4"
}
]
}
},
{
"type": "utility",
"ip_addresses": {
"ip_address": [
{
"family": "IPv4"
}
]
}
}
]
}
},
"login_user": {
"username": "root",
"ssh_keys": {
"ssh_key": [
"<ssh-public-key>"
]
}
}
}
}Checking that the script finished
The script runs during the server's first boot. To check that it finished, connect to the server and run the following commands. The first command waits until cloud-init, which runs the script, has finished.
cloud-init status --wait --long
echo "exit code: $?"For a script that ran without errors, the output looks like this:
status: done
extended_status: done
boot_status_code: enabled-by-generator
last_update: Thu, 01 Jan 1970 00:00:54 +0000
detail: DataSourceUpCloudLocal
errors: []
recoverable_errors: {}
exit code: 0The exit code tells you how the script went:
0: the script finished without an error.1: something failed, for example a command in your script. Theerrorslist shows where.2: cloud-init finished with recoverable errors. These can come from the operating system image rather than your script, so check the script's own output.
Start your scripts with set -e, as in the examples above. Without it, a script carries on after a command fails, and the exit code shows only whether its last command succeeded.
The script's output is in /var/log/cloud-init-output.log.
Debian 11, CentOS Stream 9, AlmaLinux 8 and Rocky Linux 8 don't use cloud-init. On these templates, shell scripts run at the first boot, but cloud-config files don't, and the cloud-init command isn't available. Check the script's results on the server instead, for example its log file.