cfg, a
ctx from context.Background(), and imports for log, basaltic
(github.com/basaltic-sh/sdk-go) and compute
(github.com/basaltic-sh/sdk-go/compute).
- Console
- API
- CLI
- Go
Go to Compute → Instances and choose Create instance. The form is
one card per decision — Details, Flavor, Image, Boot
volume, Data volumes, Networking, SSH keys, IAM role,
User data — with a running summary alongside them.Networking is the card to slow down on. Every interface carries its own
VPC, Subnet, Security groups and Public floating IPs;
Add network interface adds another, and the first in the list is the
primary NIC.
202 with the instance in pending. Building the boot
disk, the interfaces and the seed happens after the response, so poll
GET /v1/instances/{instance_id} and watch current_state.
Sizing: flavors
A flavor is CPU and memory, and nothing else. It carries no disk size — the boot disk is a volume sized at launch — soGET /v1/flavors is a catalog
of compute shapes, not of machine types.
shared | dedicated
shared oversubscribes CPU for higher density. dedicated pins each vCPU
1:1 to a physical core. Both classes run on the same hosts; the class decides
how the instance draws on a host’s threads.general | loadbalancer | database
Only
general flavors can run instances and instance pools. The other two
are reserved for the managed products, whose nodes are operated and priced
by the platform, and are refused here. Pass ?family=general when listing.percent of one vCPU
The guaranteed floor and the ceiling. The instance is entitled to
vcpus × cpu_baseline_pct / 100 cores however busy its neighbours get, and
may not exceed the burst ceiling even on an idle host. Absent means the
flavor guarantees no floor, or imposes no ceiling beyond the vCPU count.aggregate throughput
The instance’s network ceiling, in megabits/s, across all its interfaces.
Absent means uncapped. A resize moves this with the flavor.
GET /v1/flavors is not
paginated.
Choosing an image
image takes four forms, and the difference matters for reproducibility:
- A bare name
- name:version
- A CRN
- An image id
"image": "debian-13" follows the tag. You get whichever build is
current at the moment the instance is created, so two launches a month
apart can boot different bits.amd64). A complete image CRN pins its architecture. See Images and keypairs
for how a tag moves and what the listing does and does not show you.
Disks
volumes is one list, and the boot disk is the entry that says so:
boolean
Marks the disk cloned from
image. At most one entry may set it, and
a boot entry takes no mount_path or fstype — both come from the image,
so sending either is refused rather than ignored.Omit the boot entry entirely and you get the image’s min_disk_gb on the
region’s default tier.integer, 1–16384
required
On the boot entry this may not go below the image’s
min_disk_gb. Anything
smaller is a 400 before the instance row exists, not a failed build.string
With a mount path set, the in-guest agent formats the disk — only if it is
blank — and mounts it there, using
fstype: ext4 by default, or xfs.boolean, default true
Every launch-time volume defaults to true, which is the opposite of a volume
you attach later.
SSH keys and cloud-init
keypairs authorizes existing keypairs on the instance. The public keys are
baked into the seed at launch, so deleting the keypair afterwards does not
remove access from an instance already running.
user_data is base64-encoded cloud-init, and the platform merges it over a
base configuration that creates the login user:
A
user_data document that is not valid YAML fails the build, and the
instance lands in error rather than booting without it.
Giving the instance an identity
At launch,iam_role accepts a role name, UUID or CRN and attaches that IAM role. Software inside the guest then fetches
short-lived credentials from the metadata service at 169.254.169.254 — no
access key is written to the instance, and nothing has to be rotated.
Two conditions, and both are easy to miss. The role’s trust policy must
accept
crn:compute:*:*:instance/* (or the specific instance CRN), and the
principal making the launch call needs iam:PassRole on the role,
separately from compute:CreateInstance. Without the trust policy the
instance launches and the credentials never mint; without iam:PassRole the
launch itself is denied. Roles and instance identity walks
through both.iam_role as an optional summary instead of a string
reference or iam_role_id:
iam:GetRole. It contains only id, crn and name, excluding sensitive role
fields such as policies. The field is omitted when no role is attached, the
role has been deleted or it belongs to another account. Opening the role’s
IAM details still requires iam:GetRole.
Names, tags and metadata
unique per account
1–128 characters, DNS-safe: letters, digits, dot, dash, underscore, starting
and ending alphanumeric. A name that collides with another instance in the
account is a
409.not supported
PATCH /v1/instances/{instance_id} edits description, metadata and
tags. A name is fixed for the life of the instance.In the console those three are the Details, Tags and Metadata
cards on the instance’s Settings tab, and there is no name field among
them.IAM and cost
Read by IAM policy conditions as
basalt:RequestTag/<key> on the create and
basalt:ResourceTag/<key> afterwards, and used for cost attribution. See
policies.replaced, not merged
The map you
PATCH becomes the whole set of your keys.Metadata keys under the
basalt: namespace are control-plane state — how an
instance proves which pool or managed resource it belongs to. You cannot set
them, and you cannot remove them: they are preserved through a PATCH
whether or not you echo them back, and proposing a different value for one
is a 400 rather than a silent drop. Read-modify-write against the whole
metadata map is therefore safe.Reading instance addresses
The instances table shows Private IPv4, Public IPv4, and IPv6 from the primary NIC. Instance details show those same values individually. The Networking tab lists each NIC with its primary addresses. An attached IPv6 floating IP is shown instead of the NIC’s directly attached IPv6 address. The overview shows one address per instance, preferring public IPv4, then public IPv6, then private IPv4.Resource references
See Resource references for classification, image versions and fetching an instance by name or CRN.flavor, keypairs, iam_role, and per-NIC security_groups accept a UUID,
a CRN, or an exact name. Flavors are regional; keypairs and security groups
belong to your account, and IAM roles belong to your account.
subnet accepts a UUID or a complete VPC/subnet CRN. A bare subnet name cannot
be resolved without its VPC parent. Interface attachment likewise requires
a UUID or complete VPC/subnet/interface CRN.
Every compute list accepts exact name and crn filters. They intersect with
other filters and pagination. A foreign or mismatched CRN matches no rows;
a malformed or empty CRN returns 400. Empty names do not broaden the list.
Instance lists also accept flavor and image references. NIC-list names
match interface names within the instance bindings; duplicate names can return
multiple interfaces. Floating IPs have no
name identity.