Private Registries
Public images need no credentials. To deploy an image from a private registry, supply registry_username and registry_password in app_config. The registry host is derived from image_ref, so you only provide the username and credential.
Pull from a private registry
curl -u "$USER:$PASS" -X POST https://api.foundrydb.com/app-services \
-H "Content-Type: application/json" \
-d '{
"name": "my-api",
"plan_name": "tier-2",
"zone": "se-sto1",
"app_config": {
"image_ref": "ghcr.io/acme/api:1.0.0",
"container_port": 8080,
"registry_username": "acme-bot",
"registry_password": "ghp_XXXXXXXXXXXXXXXXXX"
}
}'
The platform authenticates the pull using these credentials on the VM. For GitHub Container Registry (ghcr.io) the password is a personal access token or a fine-grained token scoped to the repository. For Docker Hub (docker.io) it is your Docker Hub password or an access token. For other registries, the username and password are whatever the registry expects for its docker login equivalent.
Credential handling
registry_password is write-only: the API never returns it in any response. The credential travels to the VM over the encrypted internal task channel, where the agent writes an OCI auth file before pulling. It is not logged or stored in plaintext.
On a redeploy (via PATCH), you can omit registry_password to keep the existing credential:
curl -u "$USER:$PASS" -X PATCH https://api.foundrydb.com/app-services/{id} \
-H "Content-Type: application/json" \
-d '{
"app_config": {
"image_ref": "ghcr.io/acme/api:1.1.0",
"container_port": 8080,
"registry_username": "acme-bot"
}
}'
The stored password is reused as long as registry_username is unchanged. If you change the username, you must also supply the new password.
On rollback, the same rule applies: the current stored password is reused when the rolled-back revision's registry_username matches the current one.
Common registries
| Registry | image_ref prefix | Notes |
|---|---|---|
| GitHub Container Registry | ghcr.io/org/image:tag | Use a personal access token with read:packages scope. |
| Docker Hub (private) | docker.io/org/image:tag | Use a Docker Hub access token (not your account password). |
| GitLab Container Registry | registry.gitlab.com/group/project:tag | Use a deploy token or personal access token with read_registry scope. |
| AWS ECR | 123456789.dkr.ecr.eu-west-1.amazonaws.com/image:tag | Use an IAM access key ID as username and the temporary ECR password as the password. Note ECR passwords expire every 12 hours; a PATCH is required to refresh. |
| Custom | Any hostname in the image_ref | The registry host is derived from the first segment of image_ref. |