Overview
Tinfoil’s own stack is fully open source, which is how anyone can audit what runs inside our enclaves. But your application doesn’t need to be. When an enclave boots, the hardware fingerprints everything inside it and signs that fingerprint with the chip manufacturer’s key. On every connection, the client can verify that the code actually running is exactly the code that was committed to. If you’re open source, anyone can inspect that code themselves. If you’re not, you can choose to have a third-party auditor review it and certify that a given image hash meets their requirements. The fingerprint is public and permanently committed to, even if the source code is not available. Attestation is performed against the pinned SHA256 digest in your configuration, so verification works the same way whether your image is public or private. If your image isn’t public, you can have a third-party auditor review it and certify that a given hash meets their requirements; the fingerprint stays public and permanently committed to either way. A Tinfoil Container has two artifacts, and they follow different visibility rules:- The config repo must be public. Tinfoil measures
tinfoil-config.ymlat the tag you deploy and publishes the measurement to the Sigstore transparency log. Clients verify against that log, so the repo’s contents need to be inspectable. - The Docker image can be private. Your config pins the image by SHA256 digest, and the enclave’s attestation commits to that exact digest. Whether the image bytes are publicly pullable doesn’t affect verifiability; the digest already pins them.
Registry authentication
Private registry support is included with every container subscription. If your Docker images are stored in a private registry, you need to add registry credentials so Tinfoil can pull them during deployment. Supported registries are GitHub Container Registry (ghcr.io), Google Artifact Registry (*-docker.pkg.dev) / Container Registry (gcr.io), Docker Hub (docker.io), Amazon Elastic Container Registry (private ECR), and any other registry that speaks the Docker Registry V2 API over public HTTPS, such as Harbor.
Adding credentials
- Go to the Registry Credentials tab in the Containers section of the dashboard
- Click Configure for your registry type
- Enter your authentication credentials
- Click Save
Debug instances
A production instance receives credentials only for the registries its images come from. A debug instance receives credentials for every registry configured in your org, so you can switch images withtindbg boot. Anyone with SSH access to a debug instance can read those
credentials, so use read-only tokens. A registry added after the debug instance
was created is not available inside it until you update the instance.
GitHub Container Registry (ghcr.io)
Tinfoil needs a personal access token with read access to your packages.Creating a classic PAT
Classic PATs are the most reliable option for ghcr.io because they work with all packages, including those not linked to a specific repository. See GitHub’s guide to creating a classic PAT for full details.- Go to github.com/settings/tokens
- Click Generate new token > Generate new token (classic)
- Give it a descriptive name (e.g. “Tinfoil registry read-only”)
- Set an expiration (90 days is a reasonable default)
- Under scopes, check only
read:packages - Click Generate token and copy it immediately
If your GitHub organization uses SAML SSO, you must authorize the token for your org after creating it. Go to github.com/settings/tokens, find the token, click Configure SSO, then click Authorize next to your organization name. Without this step, pulls from your org’s packages will fail with a 403. See GitHub’s SSO authorization guide.
What to enter in the dashboard
- Username: Your GitHub username
- Token: The personal access token you just created
GitHub’s fine-grained personal access tokens do not support GitHub Packages (including ghcr.io). You must use a classic PAT for pulling container images.
Google Artifact Registry / Container Registry
Tinfoil supports Google Artifact Registry images at*-docker.pkg.dev URLs and gcr.io URLs backed by Artifact Registry.
Tinfoil needs a service account JSON key with read access to your container images. See Google’s service account creation guide and Artifact Registry authentication docs for full details.
Creating a service account
- Open the Google Cloud Console
- Select your project
- Go to IAM & Admin > Service Accounts
- Click Create Service Account
- Name it (e.g. “tinfoil-registry-reader”) and click Create and Continue
- Grant Artifact Registry Reader (
roles/artifactregistry.reader):- At the project level for project-wide access.
- On a specific Artifact Registry repository to limit access to that repository.
- Click Done
Creating and downloading the JSON key
See Google’s guide to creating service account keys for full details.- In the Service Accounts list, click on the service account you just created
- Go to the Keys tab
- Click Add Key > Create new key
- Select JSON and click Create
- A
.jsonfile will download. Store it securely; it can only be downloaded once, and if you lose it you must create a new key.
What to enter in the dashboard
- Service Account Key: Paste the entire contents of the downloaded JSON key file
Service account JSON keys do not expire by default. However, your organization may enforce key expiration via the
constraints/iam.serviceAccountKeyExpiryHours organization policy. If this policy is set, keys will stop working after the configured duration and you’ll need to create a new one.Docker Hub
Tinfoil needs a personal access token with read permissions. See Docker’s access token documentation for full details.Creating an access token
- Log in to Docker Home
- Click your profile avatar > Account settings
- Go to Personal access tokens in the left sidebar
- Click Generate new token
- Enter a description (e.g. “Tinfoil registry read”)
- Set the permission to Read
- Set an expiration date
- Click Generate and copy the token immediately
What to enter in the dashboard
- Username: Your Docker Hub username
- Token: The access token you just created
Docker Hub access tokens support an expiration date set at creation time. The expiration cannot be changed after creation. If you need a different expiration, create a new token. If your account has two-factor authentication enabled, PATs are required for CLI access (passwords will not work).
Amazon Elastic Container Registry
Tinfoil supports one private ECR registry per organization, identified by its hostname (<account-id>.dkr.ecr.<region>.amazonaws.com). The region is derived from the hostname. Commercial, GovCloud, and China (amazonaws.com.cn) partitions are supported; Public ECR (public.ecr.aws) is a public registry and needs no credentials.
ECR issues short-lived registry passwords rather than long-lived tokens. Tinfoil stores an IAM access key pair and exchanges it for a fresh password whenever an enclave needs to pull, including after reboots. The access key pair never leaves Tinfoil; enclaves only ever receive the short-lived password.
Creating an IAM user and access key
See the ECR authentication docs and IAM policy examples for ECR for full details.- In the AWS console, go to IAM > Users and create a dedicated user (e.g.
tinfoil-ecr-pull). Do not use root credentials or an administrator user. - Attach a policy that grants
ecr:GetAuthorizationTokenon*, plusecr:BatchGetImage,ecr:GetDownloadUrlForLayer, andecr:BatchCheckLayerAvailabilityon the repository ARNs Tinfoil should be able to pull. Scope the repository permissions as narrowly as you can; an ECR password inherits all of the IAM user’s ECR permissions, not just the configured hostname. - Under Security credentials, create an access key for programmatic use and copy both the access key ID and the secret access key.
What to enter in the dashboard
- Registry hostname:
<account-id>.dkr.ecr.<region>.amazonaws.com, with no scheme, port, or repository path - Access key ID: The IAM user’s access key ID
- Secret access key: The corresponding secret
ecr:GetAuthorizationToken is rejected immediately. Repository pull permissions are checked separately when you deploy an image.
Temporary credentials (access key IDs starting with
ASIA), SSO sessions, and assume-role chains are not supported. Use a long-lived access key for a dedicated IAM user.Referencing the image
Reference the image by its full ECR path intinfoil-config.yml. The hostname must match the one you saved exactly.
Harbor and other registries
For a registry that is not one of the providers above, configure a custom registry connection with the registry’s hostname, a username, and a secret. This uses standard Docker Registry V2 authentication and works with Harbor, Quay, and any other compatible registry that meets these requirements:- Reachable over public HTTPS on port 443, with a certificate trusted by public CAs
- Hostname only: no scheme, explicit port, path, or IP literal
- If the registry uses bearer-token authentication, its token service must be on the same hostname
registry.gitlab.com authenticates via gitlab.com), are also not supported. One custom registry hostname is supported per organization.
Harbor robot accounts
Harbor’s recommended way to grant pull-only access is a project robot account. See Harbor’s robot account docs for full details.- In Harbor, open the project that contains your images
- Go to Robot Accounts and click New Robot Account
- Give it a name and set an expiration
- Under permissions, grant Pull Repository only
- Click Add and copy the full robot name (e.g.
robot$myproject+tinfoil) and the generated secret
What to enter in the dashboard
- Registry hostname: e.g.
harbor.example.com - Username: The full robot account name, or the username for another registry
- Robot secret / access token: The secret Harbor generated, or a pull-only token for another registry
Referencing the image
Reference the image by its full registry path intinfoil-config.yml. The hostname must match the one you saved exactly; harbor.example.com and registry.example.com are different connections, and a port suffix does not match a hostname saved without one.
Troubleshooting
”Requires authentication” error during deployment
This means the container image is in a private registry but no credentials are configured for that registry type. Fix: Go to the Registry Credentials tab and configure credentials for the registry shown in the error message. The dashboard includes a direct link to the tab in the error.”Expired or been revoked” error during deployment
This means credentials are configured but the registry rejected them. The token may have expired, been revoked, or lost access. Fix: Go to the Registry Credentials tab and update your credentials with a fresh token. After updating, the expired credentials banner will clear automatically. Common causes:- GitHub PAT expired. Classic PATs can be set with an expiration date. Create a new one and update it in the dashboard.
- GitHub PAT not authorized for SSO. If your org enabled SAML SSO after you created the token, you need to re-authorize it.
- Google service account key disabled or deleted. Check the service account in Google Cloud Console. Create a new key if needed.
- Google IAM permissions changed. Verify the service account still has
roles/artifactregistry.reader. - Docker Hub token expired or revoked. Docker Hub tokens have mandatory expiration dates. Create a new access token in Docker Hub settings.
- ECR access key deactivated or deleted. Check the IAM user’s access keys in the AWS console and save a new key pair for the same hostname.
- ECR IAM policy missing repository permissions. Saving credentials only proves
ecr:GetAuthorizationTokenworks. A pull failure on a specific image usually means the policy lacksecr:BatchGetImageorecr:GetDownloadUrlForLayeron that repository, or a cross-account repository policy is missing. - Harbor robot account expired or lacks project access. Robot accounts have an expiration you set at creation. A robot that authenticates but cannot pull a specific image is missing Pull Repository permission on that project.
”Credentials were rejected for this image” on a custom registry
This means your custom registry credentials are valid but the registry refused to let them pull the specific image. The robot account or token lacks pull permission on that repository or project. Grant it in the registry; no change is needed on the Tinfoil side.Custom registry validation fails on save
Saving a custom registry connection fails when Tinfoil cannot reach the registry over public HTTPS on port 443, when the certificate is not trusted by public CAs, or when the registry’s bearer-token service lives on a different hostname than the registry itself. Private-network registries and registries behind a corporate CA cannot be used.Expired credentials banner
When Tinfoil detects that your registry credentials have been rejected during a deployment attempt, an amber banner appears on the Active tab. This banner persists until you update the credentials in the Registry Credentials tab.Using the CLI
The Tinfoil CLI sets the same per-registry credentials, which is convenient when rotating tokens from a script:--key-file - to read the GCR key from stdin instead of disk. Once credentials are stored, any container in the org can pull images from that registry.
ECR and custom registry connections are configured in the dashboard or through the Admin API.