Declare it. Kiln reconciles it.

A deployment declares the resources that should exist. Kiln compares that with what it recorded as the deployment's own and with what is running, then plans the difference.

kiln deployment outputs app --generation 4

A shape change never replaces a VM by surprise.

Profile, CPU, memory and disk size are fixed once a VM exists. Changing any of them means a new VM, so each deployment machine sets a shape_change_policy that says what Kiln may do.

Power mode and private-network attachment are different. Kiln changes those in place and keeps the VM.

Kiln says what to do next.

When Kiln refuses an operation, the deployment's Recovery and Conditions fields say whether to recover, reapply, delete or retry.

safe
The default. Kiln replaces a VM only in phases where it can roll the replacement back, and refuses anywhere else.
reject
Kiln never replaces the VM. It reports what differs and leaves the VM as it is.
replace
You ask for a replacement. Kiln still checks that the deployment owns the VM and that it can roll back.

Outputs belong to one generation.

Clients read service URLs and connection details from the outputs, and never rebuild them from raw resources. Ask for a generation that is no longer current and Kiln answers with a conflict.

kiln deployment outputs app --generation 4 --json kiln deployment outputs app --show-secrets --json
deployment
Its id, name, generation, state and readiness.
services
The URLs, access kind and readiness of each service.
resources
Connection fields for each appliance the deployment uses.
redaction
Whether the response is redacted or raw, and which fields count as secret.

Deploy from a GitHub workflow.

The action sends your Docker build context to Kiln, builds the image there and deploys it. It reads the API URL and token from repository secrets.

It sets two outputs, image_id and machine_id. It refuses a remote API over plain HTTP unless you set allow-insecure-http: true.

Or run the same two steps by hand.

kiln images build --name demo --tag latest --dockerfile-path ./Dockerfile --context-dir . kiln deploy --name demo --image-id <image-id>
- uses: kiln-deploy/action@v1
  with:
    api-url: ${{ secrets.KILN_API_URL }}
    token: ${{ secrets.KILN_TOKEN }}
    name: demo
    dockerfile: ./Dockerfile
    context-dir: .