How do I deploy a Linode using custom disk configurations?

Linode Staff

I would like to know a good way to deploy a Linode using the API that allows me to have a Linode that:

  1. Has no swap
  2. Has a disk that contains one of Linode's stock images but has a custom size
  3. Has an extra disk with a custom size

3 Replies

This is certainly possible. I'll propose two options that will basically go over the following workflow:

  1. Add an empty Linode
  2. Create the boot disk with the desired size
  3. Create the secondary disk with the desired size
  4. Create a Configuration Profile that contains both disks and the preferred kernel option

Using our Linode CLI(which is basically a wrapper of our API), I went through the workflow to create a test Linode. Here's how that looked like:

# Add empty Linode
linode-cli linodes create --region "ca-central" --label "API-Custom-Disk-Example" --type "g6-nanode-1" --private_ip true --group "API"

# Create the boot disk with the desired size 
linode-cli linodes disk-create --label "boot" --size 6000 --image "linode/ubuntu18.04" --root_pass "2HKH$^*llsa..." 19869124

# Create the secondary disk with the desired size
linodes disk-create --label "secondary" --size 3000  19869124

# Create a Configuration Profile that contains both disks and the preferred kernel option
linode-cli linodes config-create --label "boot_config" --kernel "linode/grub2" --devices.sda.disk_id 40616257 --devices.sdb.disk_id 40616264 --root_device "/dev/sda" 19869124

Just in case you need a quick reference, here are the API docs for each endpoint you are going to use when following the workflow above:

The second alternative is using Terraform. Terraform is a cool Infrastructure as Code (IaC) tool that allows you to deploy your infrastructure in a wide number of providers, including us. You simply define the specs needed for a Linode in a file and let Terraform handle the rest. We actually have a quick intro to Terraform in our Docs site that can give you a quick start on Terraform + Linode:

Use Terraform to Provision Linode Environments

Terraform also has a very good documentation on their Linode Provider. More specifically, I think the "linode_instance" resource is where you'll find most of the parameters needed to accomplish your use case:

Terraform linode_instance

So you can have a reference, I created the following Terraform file to create a Linode that fulfills the aforementioned requirements:

provider "linode" {
  token = "my_APIv4_token"
}

resource "linode_instance" "terraform-custom-disk" {
        label = "Terraform-Custom-Disk-Example"
        tags = ["Terraform"]
        region = "ca-central"
        type = "g6-nanode-1"
        private_ip = true

    disk {
        label = "boot"
        size = 6000
        image = "linode/ubuntu18.04"
        root_pass = "terr4form-test"
    }

    disk {
        label = "secondary"
        size = 3000
    }

    config {
        label = "boot_config"
        kernel = "linode/grub2"
        devices {
            sda {
                disk_label = "boot"
            }
            sdb {
                disk_label = "secondary"
            }
        }
        root_device = "/dev/sda"
    }

    boot_config_label = "boot_config"
}

I wanted to add an example using the Linode API. Ive used the Linode CLI to obtain the needed Linode and Disk ID numbers, and some sleep statements to wait for each step to complete before moving on. You can replace these parts with API calls and to remove the dependency of the Linode CLI, and to have your code actually check for completion at each stage, instead of just sleeping for 60 seconds, but that's outside the scope of this discussion.

#!/usr/bin/env bash

# This is optional. I find it useful for debugging
set -xo pipefail

# Put your Linode API Token here
TOKEN="YOUR_LINODE_API_TOKEN_GOES_HERE"

# Create a Linode with no image
curl -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${TOKEN}" \
    -X POST -d '{
      "swap_size": 512,
      "label": "API-Custom-Disk-Example",
      "type": "g6-standard-2",
      "region": "ca-central",
      "group": "API"
    }' \
    https://api.linode.com/v4/linode/instances

# Obtain the Linode's ID
LINODE_ID=$(linode-cli linodes list --text | awk '/API-Custom-Disk-Example/{print $1}')

# Wait while the new Linode is provisioned
printf "Waiting for the Linode to finish provisioning..."
sleep 60
printf "\n"

# Create boot disk
curl -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${TOKEN}" \
    -X POST -d '{
      "label": "boot",
      "image": "private/5877828",
      "size": 24000,
      "root_pass": "aComplexP@ssword"
    }' \
    https://api.linode.com/v4/linode/instances/"${LINODE_ID}"/disks

# Obtain the Boot Disk's ID
DISK_ID=$(linode-cli linodes disks-list $LINODE_ID --text | awk '/boot/{print $1}' | tail -1)
echo $DISK_ID

# Wait to give the disk a chance to finish being created
sleep 60

# Create swap disk
curl -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${TOKEN}" \
    -X POST -d '{
      "label": "swap",
      "size": 512,
      "filesystem": "swap"
    }' \
    https://api.linode.com/v4/linode/instances/"${LINODE_ID}"/disks

# Obtain the Swap Disk's ID
SWAP_DISK_ID=$(linode-cli linodes disks-list $LINODE_ID --text | awk '/swap/{print $1}' | tail -1)
echo $SWAP_DISK_ID

# Create the Linode's Configuration Profile
curl -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${TOKEN}" \
    -X POST -d '{
      "kernel": "linode/grub2",
      "comments": "This is my main Config",
      "memory_limit": 2048,
      "run_level": "default",
      "virt_mode": "paravirt",
      "helpers": {
        "updatedb_disabled": true,
        "distro": true,
        "modules_dep": true,
        "network": true,
        "devtmpfs_automount": false
      },
      "label": "boot-config",
      "devices": {
        "sda": {
          "disk_id": $DISK_ID,
          "volume_id": null
        },
        "sdb": {
          "disk_id": $SWAP_DISK_ID,
          "volume_id": null
        }
      }
    }' \
    https://api.linode.com/v4/linode/instances/"${LINODE_ID}"/configs

Is there a way of doing this from the cloud manager? Currently, I can't deploy a linode without using some type of image. For custom configurations, it would be ideal to create a Linode with no disk configurations, no operating systems, and no configuration profiles. This would be a more advanced use case, but it would allow for something such as the copying of a disk image with a custom configuration and partition layout.

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct