Run your first instance
In this tutorial you set up tritonctl, the Triton Cloud tenant CLI, on your own
machine. You sign in to a cloud, register an SSH key, find the subnet and image
your instance boots from, and issue the create command. You end with a
configured CLI, a registered SSH key, and the exact command that creates an
instance in your project.
Allow about 15 minutes.
Before you start
You need four things:
- A
tritonctlbinary on yourPATH. It ships as a tarball namedtritonctl-<STAMP>.tar.gz, built by thedist-clitarget in themariana-trenchworkspace, where<STAMP>is the build stamp of the release. - The URL of your cloud's API endpoint, plus a username and password for it.
- Two UUIDs from your operator: the project you build in, and the VPC your instance attaches to.
- One image UUID from your operator, for the operating system you want to boot.
Your operator supplies the UUIDs because tritonctl cannot discover them.
tritonctl vpc list sends only a project= selector, but GET /v1/vpcs
requires both tenant= and project= and answers 400 MissingScope without
them. tritonctl image list asks for scope=tenant, and GET /v1/images
implements scope=public only, so it answers 400 ScopeNotImplemented.
Every identifier in Triton Cloud is a UUID. No tritonctl argument accepts a
name.
Step 1: Check the binary
On your workstation:
tritonctl --version
The command prints the binary name and its version. If your shell reports that
tritonctl is not found, the binary is not on your PATH yet.
Step 2: Sign in
tritonctl configure authenticates you against an endpoint and stores the
result. Run it with no flags and answer the three prompts:
tritonctl configure
The first prompt is Endpoint, which defaults to http://localhost:8080. The
second is Username. The third is Password: , which does not echo what you
type.
Output:
Configured. Logged in as <USERNAME> at <ENDPOINT>.
Config written to <CONFIG_PATH>
<CONFIG_PATH> is triton/tritonctl/config.json inside your user
configuration directory, for example
~/.config/triton/tritonctl/config.json. The file holds the endpoint and the
access and refresh token pair, and is written with mode 0600.
Confirm who you are:
tritonctl whoami
The command prints your endpoint and the claims decoded from your access token:
endpoint: <ENDPOINT>
auth: identityd token
sub: <USER_UUID>
tenant_id: <TENANT_UUID>
...
If the auth: line reports that you are not authenticated, step 2 did not store
a token. Run tritonctl configure again.
tritonctl refreshes the stored access token for you when it is within 60
seconds of expiring, and writes the new pair back to the config file. Once the
refresh token itself has expired, commands fail with a message telling you the
refresh token has expired. Run tritonctl login and enter your password again.
Step 3: Register your SSH key
Register the public half of an SSH key pair so it can be injected into the instance at first boot. This example uses an Ed25519 key:
tritonctl ssh-key create --name laptop --public-key-file ~/.ssh/id_ed25519.pub
The command prints the new key's UUID first, followed by the full record:
Registered ssh key <SSH_KEY_UUID>
...
Copy <SSH_KEY_UUID>. You pass it to the create command in step 7.
The key belongs to you, the calling user. There is no tenant, silo, or project selector on this command; the server resolves the owner from your token.
List your keys to confirm:
tritonctl ssh-key list
The table has four columns: ID, NAME, FINGERPRINT, and SCOPE. The
fingerprint is the SHA-256 fingerprint the server computed when it accepted the
key.
Step 4: Point the CLI at your project
Every tenant resource is narrowed by project. Set the project once for the rest of this tutorial:
export TRITONCTL_PROJECT=<PROJECT_UUID>
TRITONCTL_PROJECT backs the global --project flag, so every command below
picks it up. Pass --project <PROJECT_UUID> instead if you prefer to be
explicit.
Confirm the endpoint accepts the scope:
tritonctl instance list
The table has four columns: ID, NAME, STATE, and IMAGE. On a new
project the list is empty, which means the command worked. A
400 MissingScope error asking you to scope the list means
TRITONCTL_PROJECT is unset.
STATE renders the lifecycle as a JSON object rather than a bare word: a
running instance shows as {"state":"running"}.
Step 5: Find the subnet
Your instance's primary network interface attaches to a subnet inside your VPC. List the subnets in the VPC your operator gave you:
tritonctl subnet list --vpc <VPC_UUID>
The table has three columns: ID, NAME, and VPC. Copy the ID of the
subnet you want. That is <SUBNET_UUID> below.
--vpc is required. Without it the server answers 400 MissingScope and asks
for a ?vpc=<uuid> selector.
Step 6: Confirm the image
Check that the image UUID your operator gave you resolves and boots the operating system you expect:
tritonctl image show <IMAGE_UUID>
Output:
id: <IMAGE_UUID>
name: <IMAGE_NAME>
os: <OS>
version: <VERSION>
size: <BYTES> bytes
sha256: <SHA256>
(use -o json for the full record)
Step 7: Create the instance
tritonctl instance create does not complete against the current server.
POST /v1/instances requires both a ?tenant=<uuid> and a ?project=<uuid>
selector, and the CLI sends only ?project=, so the request comes back as
400 MissingScope. The command below is correct as written; the missing
selector is a server-contract gap, not something you can work around from the
CLI.
On your workstation:
tritonctl instance create \
--name web-1 \
--image-id <IMAGE_UUID> \
--primary-subnet-id <SUBNET_UUID> \
--ssh-key-id <SSH_KEY_UUID> \
--cpu 2 \
--memory-bytes 4294967296
--memory-bytes is in bytes, so 4294967296 is 4 GiB. Both --cpu and
--memory-bytes are required, and the server rejects zero for either. Add
--disk-bytes to size the boot disk explicitly; the server rejects zero and
anything above 16 TiB, and otherwise floors the disk at the image's content
size. Repeat --ssh-key-id once per key to inject more than one.
On success the command prints the new instance's id, name, lifecycle, and
image lines, then (use -o json for the full record). Copy the id. That is
<INSTANCE_UUID> below.
Step 8: Confirm the instance is running
Read the instance back:
tritonctl instance show <INSTANCE_UUID>
The lifecycle: line shows {"state":"running"} once the instance is up. Until
then it shows one of the other states: {"state":"pending"},
{"state":"provisioning"}, {"state":"stopping"}, {"state":"stopped"}, or
{"state":"failed","reason":"<REASON>"}.
You can also filter the list:
tritonctl instance list --state running
--state is matched case-insensitively against pending, provisioning,
running, stopping, stopped, and failed.
For the full record, including the compute node hosting the instance and the subnet its primary interface attaches to, ask for JSON:
tritonctl instance show <INSTANCE_UUID> -o json
JSON is the stable interface. Table layout is not stable, so use -o json in
anything you script. When you pipe tritonctl output somewhere, it emits JSON
by default without being asked.
Once the create call in step 7 succeeds, tritonctl instance start,
tritonctl instance stop, and tritonctl instance reboot drive the instance
from here, each taking the instance UUID. tritonctl instance reboot calls the
server's restart verb.
Next steps
- Create an instance covers the same task as a recipe, for when you already know what you want.
- tritonctl instance lists every flag on every instance subcommand.
- tritonctl networking commands covers VPCs, subnets, floating IPs, firewall rules, and routes.
- Networking explains how VPCs, subnets, and instance interfaces fit together.
- tritonctl reference is the full command index.