trstctl /docs GitHub ↗

Issue your first certificate

Goal

When you finish this journey you will have a running trstctl control plane and your first real certificate minted by it, owned, and visible in inventory. It is for anyone evaluating trstctl who wants the shortest path from "nothing installed" to "a signed certificate I can list" — using only the built-in CA, no external issuer, no cloud account. In plain terms: you start a control plane, get a credential to talk to it, name the thing that needs a certificate, flip it to issued, and watch the control plane sign it and record it.

Before you start

  • Docker with the Compose plugin, or a Go toolchain if you run from source. The exact prerequisites and the full first-run walkthrough live in Getting started — this journey lifts its concrete steps into one straight line.
  • About 1 GB of free disk for the PostgreSQL and NATS volumes.
  • A few minutes. Issuance itself is sub-second; most of the wall-clock is the one-time stack startup.

Steps

  1. Bring up the control plane. From the repo root, start the one-command evaluation stack (control plane plus its datastores):

    docker compose -f deploy/docker/docker-compose.yml up --build
    

    You should see Compose wait for PostgreSQL and NATS to report healthy, then the control plane start its event log, projections, orchestrator, and API in order.

  2. Confirm it is serving. The control plane serves over TLS by default with a self-signed evaluation certificate, so check health with -k:

    curl -fksS https://localhost:8443/healthz   # {"status":"ok"}
    

    You should get {"status":"ok"}. The web UI is the same binary at https://localhost:8443. How the API, CLI, and UI fit together is described in Platform & API.

  3. Mint your first API token. A fresh control plane fails closed — every route returns 401 until you present a credential. Run the host-local bootstrap verb (pick any UUID as your tenant id; a single-tenant deployment uses one well-known id):

    trstctl token create --tenant 11111111-1111-1111-1111-111111111111 --subject ci-bot
    # -> prints a trst_... token on stdout. Store it now; it is shown only once.
    

    You should see a trst_... token printed once. It carries operator scopes but deliberately excludes certificate issuance, so a bootstrap credential can administer the platform but cannot self-issue — the registration-authority split described in Policy & governance.

  4. Point the CLI at the control plane. Export the server URL and your token:

    export TRSTCTL_SERVER=https://localhost:8443
    export TRSTCTL_TOKEN=trst_...
    

    You should now be able to run trstctl-cli commands without a 401.

  5. Create an owner, then an identity, then transition it to issued. The owner is the service the certificate belongs to; the identity is the certificate itself; the transition to issued is what drives the control plane to sign:

    owner=$(echo '{"kind":"workload","name":"payments"}' | trstctl-cli owners create -f - | jq -r .id)
    ident=$(echo "{\"kind\":\"x509_certificate\",\"name\":\"payments.svc\",\"owner_id\":\"$owner\"}" \
              | trstctl-cli identities create -f - | jq -r .id)
    echo '{"to":"issued"}' | trstctl-cli identities transition "$ident" -f -
    sleep 2
    

    You should see each command return JSON. The transition to issued makes the orchestrator mint a leaf certificate through the built-in signer-backed CA. The single issuance path and the guarantees around it are covered in Issuance & certificate authorities.

  6. See it in inventory. List the certificates the control plane now tracks:

    trstctl-cli certificates list
    

    You should see your freshly minted certificate — discovered, owned, and tracked. That is your first certificate.

Where next

Journey: J1 Steps through: F4, F10, F11, F12, F8, F14

Rendered live from github.com/ctlplne/trstctl — found a mistake? edit this page.