> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tinfoil.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Attested SSH

> Verify an enclave's SSH host key, install a local profile, and connect with native SSH and SCP.

Use `tinfoil attest-ssh` to verify a secure enclave and pin its SSH host key. After setup, connect directly with ordinary `ssh`, `scp`, or `sftp` clients.

Attestation establishes which public key belongs to the expected workload. Each SSH connection then authenticates the server using that pinned key. Native SSH does not fetch fresh attestation or enforce its expiry on every connection.

## Prerequisites

* [Tinfoil CLI](https://github.com/tinfoilsh/tinfoil-cli/releases) v0.18.8 or later and a local OpenSSH client.
* A running workload that declares an [attested key](/containers/attested-keys) named `host-ssh`, using `ecdsa-p256` or `ed25519`, and configures its SSH server to use that key pair.
* A reachable SSH endpoint. To expose port 22 on an administrator workspace, see [Direct admin SSH](/containers/config-networking#direct-admin-ssh).
* Your login public key authorized by the SSH server. The attested host key authenticates the server; your login key authorizes your access.

Your container can use the generated key files to set up its SSH server, converting the private-key format if necessary. For an Ubuntu workspace to adapt, see [confidential-ubuntu](https://github.com/tinfoilsh/confidential-ubuntu). Configure the server to use the granted `host-ssh` key pair instead of generating a separate host identity. Publish that server with the inbound `22` settings in [Direct admin SSH](/containers/config-networking#direct-admin-ssh).

## Inspect the verified profile

For a container managed through Tinfoil Containers, [authenticate the CLI](/containers/cli#authenticating), then run:

```bash theme={"dark"}
tinfoil attest-ssh my-container
```

The CLI resolves the container's hostname, repository, and published SSH port, verifies its attestation, and reads the endorsed `host-ssh` public key. It prints the SSH configuration and a `known_hosts` entry only after verification succeeds, without changing any files.

You can run this whenever the enclave is ready.

## Install the profile

Add `--install` to write the verified profile:

```bash theme={"dark"}
tinfoil attest-ssh my-container --install
```

After verification succeeds, the CLI writes two files under `~/.ssh/tinfoil/`: `my-container.conf` and `my-container.known_hosts`. Re-running `--install` with the same container overwrites those two files. You can use `--name` instead to define an alias.

For `ssh my-container` to use the installed profile, `~/.ssh/config` must contain a top-level `Include tinfoil/*.conf` line before any `Host` or `Match` block. If that line is missing, the CLI asks whether to prepend it. Answer `y` to add it; the rest of the file is left unchanged. Answer `n` to leave `~/.ssh/config` unchanged and print the line to add yourself. Non-interactive runs do not modify `~/.ssh/config` unless you pass `--yes`.

Omit `--install` to print the profile and change nothing. The profile enables strict host-key checking against the endorsed key.

The default login user is `root`. To choose another user or login identity:

```bash theme={"dark"}
tinfoil attest-ssh my-container --install \
  --user app \
  --identity ~/.ssh/my-ssh-key
```

`--identity` selects a local private key for SSH login; it does not enroll its public key on the server. Omit it to use your usual SSH identities and agent.

## Connect with native clients

```bash theme={"dark"}
ssh my-container
scp ./file my-container:/tmp/
sftp my-container
```

These connections go directly to the SSH endpoint. They do not require the Tinfoil CLI to keep running.

## Pin the workload release

A container-name lookup supplies its recorded repository. Verification accepts any release from that repository that is currently endorsed by a freshness witness. To require a specific release when installing the host key:

```bash theme={"dark"}
tinfoil attest-ssh my-container \
  --repo owner/workload@v1.2.3 \
  --install
```

You can also pin the deployment artifact digest, or both tag and digest. See [Pinning the expected workload](/verification/verification-in-tinfoil#pinning-the-expected-workload).

## Refresh after an enclave reboot

Native SSH reports `Host key verification failed` when the installed pin no longer matches the enclave. This happens after a full enclave reboot, which generates a new host key. A container-process restart within the same enclave boot keeps the key.

Once the Tinfoil container has rebooted, rerun:

```bash theme={"dark"}
tinfoil attest-ssh my-container --install
```

If attestation verification fails, the existing profile is left unchanged.

The installed SSH profile does not store the repository policy used to verify it. Repeat the same `--repo` reference when refreshing the profile to enforce the same policy.

## Use a hostname or custom alias

For a hostname, pass the expected configuration repository with `--repo`. The host-side SSH port differs from guest port `22`; set `--ssh-port` to the externally published port. A container-name lookup resolves that port for you. See [Direct admin SSH](/containers/config-networking#direct-admin-ssh).

```bash theme={"dark"}
tinfoil attest-ssh enclave.example.com \
  --repo owner/workload \
  --ssh-port 22022 \
  --name my-workspace \
  --install

ssh my-workspace
```

`--name` sets the SSH alias and profile filenames. It defaults to the container name or hostname. Use a stable alias when the endpoint may change.
