Skip to main content

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 tritonctl binary on your PATH. It ships as a tarball named tritonctl-<STAMP>.tar.gz, built by the dist-cli target in the mariana-trench workspace, 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

warning

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