Container registry
Registry (/gravity/registry) is where you find container images to
deploy and where your organization keeps its own private images. Every
container image pushed to your organization’s registry is signed and scanned
for known vulnerabilities automatically - see What happens on every
push - and the signature lets you
prove which image you deployed.
Browsing public images
Section titled “Browsing public images”The registry opens on a curated list of well-known official images -
nginx, postgres, redis, node, python, ubuntu, and similar -
with a search box and a row of quick-search shortcuts above it. Click any
image (or a search result) to open its detail page, which shows:
- Star count, pull count, and when it was last updated.
- A tag table you can filter, each with its size and when it was pushed.
- A ready-to-copy pull command for the selected tag.
- A Deploy button that opens the instance creation wizard with this image and tag chosen. The server the wizard creates then pulls that exact image and starts it.
Star the heart icon on any card to pin it to a Favourites section at the top of the default view - favourites are remembered on your device.
Public images are not scanned or signed by Sencai. Scanning and signing apply to the images in your organization’s own registry, described next. Images in a registry you run yourself can be scanned on request or on a schedule, but are not signed.
Your organization’s registry
Section titled “Your organization’s registry”The Sencai tab is your organization’s own, private registry. Every image
name is git.sencai.space/<organization>/<image>. Do not work out
<organization> from the organization’s display name: it is the organization’s
short name (its slug, for example acme), and the Access panel shows the
exact Image prefix to use.
The tab lists every image in the registry (Image, Processing, Scan, Signature, Attestation and Pushed), and each image has its own page. The image page lists its tags with when each was pushed, who pushed it, its digest (the fingerprint of the exact image content), and the same four status badges, followed by the selected version in detail, a Push history and the Signing keys card. See What the statuses mean. Scanning, signing and the commands below apply to container images. Other OCI artifacts pushed the same way, such as a Helm chart, are signed but not scanned. Packages of other types (npm, PyPI and similar) are listed under Other packages and are neither scanned nor signed.
Select a version and choose Deploy to a new server to start it on a new instance: the wizard opens with the image and its digest chosen, and only a signed version can be deployed. Running on lists the servers Sencai has deployed that version to. See Deploy a container to a new instance.
The private registry itself is part of every paid plan. See sencai.space/pricing for what comes with it.
The Storage card shows approximate registry usage: the compressed layers of every current image, added up. A layer that several images share is counted for each of them, so the figure can overstate. When your environment has a storage limit configured, the card shows the usage next to it and warns when you are close.
At the moment the registry enforces one limit that is the same for every organization: 20 GB in total, and 5 GB for a single image (its manifest and layers). A push that would go over either is rejected by the registry with an error in your Docker client. A larger allowance is not something you can set yourself; ask your account team if you need one.
Access
Section titled “Access”Pushing and pulling images needs a registry token, because your Sencai sign-in is not a registry password. A token belongs to you, works for one organization only, and can be revoked at any time.
- Open Registry and select the Sencai tab.
- In the Access panel, choose Create token.
- Give it a Name, choose under What may it do either Pull (download images) or Push (upload images, which are then scanned and signed), and pick Expires after 30, 90 or 365 days. The default is 90 days.
- Choose Create token. The Copy your token window shows the token,
your username and a ready-made
docker logincommand. The token is shown once and Sencai never stores it - only its name, last eight characters, scope and expiry. When you close the window it is gone; if you lose it, revoke it and create another.
The Access panel also shows the Registry host, the Image prefix your images must be pushed under, your registry login, and Your tokens with each token’s name, scope, last eight characters, expiry and status. To revoke a token choose Revoke, then Confirm revoke.
Then sign in with Docker. Do not put the token in the command itself - that
would leave it in your shell history. Run the command from the window (it uses
--password-stdin, so the token is not part of it) with the username shown
there, paste the token, and press Enter:
docker login git.sencai.space -u <username-from-the-dialog> --password-stdinThen press Ctrl-D to end the input. After that, a normal push works:
docker tag api:1.4 git.sencai.space/acme/api:1.4docker push git.sencai.space/acme/api:1.4A few things to know:
- Push needs permission. The Push option is offered only if your role allows pushing; if it is missing, ask an organization admin. Pulling is available to every member, auditors included. See Who can do what.
- Admins see everyone’s tokens. Admins can switch the token list to Show everyone’s and revoke other members’ tokens.
- Access follows your membership. Change someone’s role and their access follows within about two minutes; remove them from the organization and their tokens stop working. A token cannot do more than its owner can.
- Limits. You can hold up to 10 active tokens in one organization. You are notified in the app seven days before one of your own tokens expires; for the CI and runtime credentials below, the people who can manage them (admins) are notified.
- Push to your organization’s name only. Only
git.sencai.space/<organization>/...is scanned and signed. An image pushed anywhere else on the registry (for example under your personal name) is removed and you are notified. - Names are lower case. The registry lower-cases image names and tags, so
Acme/API:V1is stored asacme/api:v1.
Credentials for CI and runtimes
Section titled “Credentials for CI and runtimes”A personal token is the wrong tool for a build server or a cluster: it belongs to a person, and it stops working when that person leaves. Admins can create two kinds of organization credentials instead, from the CI push credential and Runtime pull credential cards beside the Access panel (they are shown only to people who can manage them). Jobs on Sencai’s own hosted runners need neither: they get a credential of their own for the length of the job, described in Push images from CI.
| Credential | Can do | Use it for |
|---|---|---|
| CI push credential | Push and pull | Build systems outside Sencai (GitHub Actions, GitLab CI, any other CI) and runners you provision yourself |
| Runtime pull credential | Pull only | Servers and clusters that run your images (imagePullSecret) |
Both are created with New credential on their card (a name and an expiry), shown once, and revocable from the same card with Revoke and Confirm revoke. Each card also shows the credential’s login. A push made with the CI credential is attributed to the CI credential in the image history and is signed like any other authorized push.
GitHub Actions
- name: Log in to the Sencai registry env: SENCAI_REGISTRY_USER: ${{ secrets.SENCAI_REGISTRY_USER }} SENCAI_REGISTRY_TOKEN: ${{ secrets.SENCAI_REGISTRY_TOKEN }} run: printf '%s' "$SENCAI_REGISTRY_TOKEN" | docker login git.sencai.space -u "$SENCAI_REGISTRY_USER" --password-stdin- name: Build and push run: | docker build -t git.sencai.space/acme/api:${{ github.sha }} . docker push git.sencai.space/acme/api:${{ github.sha }}GitLab CI
build: image: docker:27 services: [docker:27-dind] script: - printf '%s' "$SENCAI_REGISTRY_TOKEN" | docker login git.sencai.space -u "$SENCAI_REGISTRY_USER" --password-stdin - docker build -t git.sencai.space/acme/api:$CI_COMMIT_SHA . - docker push git.sencai.space/acme/api:$CI_COMMIT_SHAStore the token and username as masked secrets in the CI system, not in the repository.
Kubernetes (pull secret)
Do not pass the token to kubectl as an argument (--docker-password=...):
that puts it in your shell history and in the process list. Let Docker write
the credentials file into a scratch directory instead, using the same
--password-stdin login as above, and create the secret from that file:
mkdir ./sencai-pull-configdocker --config ./sencai-pull-config login git.sencai.space -u <runtime-credential-username> --password-stdinPaste the runtime credential’s token, press Enter, then Ctrl-D. Then create the secret and remove the directory:
kubectl create secret generic sencai-registry \ --type=kubernetes.io/dockerconfigjson \ --from-file=.dockerconfigjson=./sencai-pull-config/config.jsonrm -r ./sencai-pull-configThe scratch directory holds the token in readable form until you remove it, so
delete it straight away as shown. Reference the secret from your pods with
imagePullSecrets: [{ name: sencai-registry }]. Rotate it by creating a new
runtime credential, updating the secret, and revoking the old one before it
expires.
What happens on every push
Section titled “What happens on every push”Within moments of a push, Sencai picks it up and does three things without you asking:
- Records the push. The exact image content (its digest) is captured as soon as the push lands, so a tag that is overwritten later does not make the earlier push disappear from the Push history on the image page. If a tag was overwritten within seconds, before the earlier push could be captured, the history says so. If a push is ever missed, a check that runs every 15 minutes finds it, so the worst case is “processed up to 15 minutes late”, never “never processed”.
- Signs it. The image is signed with your organization’s own signing key
- see Image signing and verification. Only pushes made by someone who is allowed to push are signed.
- Scans it. The image is scanned with Trivy for known vulnerabilities in its operating system and application packages. After the first scan, and after every rescan you start yourself, a signed attestation of the scan result is attached to the image.
Typically a single image is recorded, signed and scanned within a couple of minutes. Large images, many pushes at once, or a refresh of the vulnerability data take longer; every image shows where it is in the process, including its place in the queue. Work is shared between organizations in turn, so another organization’s backlog cannot starve yours, although a busy platform can still make you wait for your turn. A scan you start yourself with Scan again queues behind scans of fresh pushes.
Details that matter:
- Tagged images are rescanned. A scan reflects the vulnerability data of the day it ran, and new vulnerabilities are published every day. Images that a tag currently points to (and the platform images inside a multi-platform image that a tag points to) are rescanned automatically once their latest scan is more than seven days old. Rescans are queued a few at a time, hourly, after the scans of fresh pushes, so the interval is about a week and can be longer when many images are due at once. A rescan that failed is not tried again for six hours. A digest that no tag points to any more is not rescanned automatically, so if you still run it (for example because you pull by digest), rescan it yourself with Scan again. An automatic rescan updates the findings but does not replace the attached scan attestation; the attestation is refreshed on the first scan and on rescans you start yourself.
- Multi-platform images (an image index) are signed as a whole and each platform image inside is signed and scanned separately. The index shows a combined state, for example “Partially scanned (1 of 2 platforms)”.
- Container images only. Other artifacts, such as Helm charts, are signed but show “Not a container image - not scanned”. The signature and attestation objects themselves, and build attestations from your builder, are hidden from the list unless you switch on Show signatures and attestations.
- Nothing blocks a deploy. Scanning and signing report on an image; they
do not stop it from being pulled or run, and Sencai has no policy that
refuses a vulnerable image. If you want a gate, your pipeline can check the
signed scan attestation with
cosign verify-attestation(see Image signing and verification). The registry screens themselves are not an interface for pipelines. Keep in mind that the attestation is refreshed only on the first scan and on rescans you start yourself, not by the automatic weekly rescan. - Not the instance scan. The registry scan is separate from the scanning of images that run on your cloud instances. Both appear under Vulnerabilities, with a switch between them.
What the statuses mean
Section titled “What the statuses mean”Every status is shown as text; none of them is shown as “clean” unless Sencai has evidence that something was actually analyzed. A page that has something in progress refreshes itself every few seconds until everything has settled.
Processing
| Status | Meaning |
|---|---|
| Waiting to be processed | The push was seen or listed but processing has not started yet |
| Queued — N ahead | Waiting its turn |
| Processing… | Being worked on |
| Processed | Done |
Processing failed (<reason>), retrying at <time> |
A step failed for a temporary reason; it is repeated automatically with growing delays (one minute, five, fifteen, an hour, six hours, a day), up to eight times |
Gave up after N attempts — <reason> |
Retries ran out. The reason is shown; Scan again or Sign again (if your role allows) starts again |
| Scanning is not enabled in this environment | The environment you are using has not switched the feature on. This never means the image is clean |
Scan
| Status | Meaning |
|---|---|
| Scan queued / Scanning… | Waiting, or running |
| Waiting for vulnerability data | Scanning is paused because the vulnerability data is missing or more than seven days old. Signing carries on |
Too large to scan (limit <size>) |
The compressed image exceeds the scan size limit (3 GB at the moment). It is signed; it is not scanned |
| Not a container image — not scanned | A Helm chart or another artifact |
| Not scanned | No scan has been recorded for this image |
| Partially scanned (1 of 2 platforms) | A multi-platform image where only some platform images have a finished scan |
Scan failed (<reason>), retrying at <time> / Scan failed — <reason> |
A scan failed; temporary failures are retried |
Scan results
| Result | Meaning |
|---|---|
| Clean | The scan succeeded, found no vulnerabilities, and recognized the operating system (or found application packages) - so there was something to check |
| Counts by severity, for example 3 critical, 5 high | One or more vulnerabilities were found. Severities are Critical, High, Medium, Low and Unknown |
| Scanned — no packages found, cannot confirm the image is clean | The scan succeeded, but the image has no recognizable operating system or packages (for example a scratch image holding one binary). Sencai does not call this clean |
<OS> is end of life — results may be incomplete |
The base operating system no longer receives security updates, so the vulnerability data for it is incomplete. Counts are shown, and they are a minimum |
Based on vulnerability data from <date> |
The scan ran with vulnerability data three to seven days old |
Signature
| Status | Meaning |
|---|---|
| Signing… | In progress |
Signed · key <fingerprint> · checked <time> |
The signature is attached and was found in place at the last check |
| Not signed — pushed by an account that may not push here | The image was refused for signing (see below) |
| Signature removed — re-signing / Signature changed — re-signing | The signature objects next to the image were deleted or replaced; Sencai is attaching the signature again |
Signing failed (<reason>), retrying at <time>, Gave up after N attempts — <reason>, Not signed — signing service unavailable, retrying at <time> |
Signing hit a problem; temporary ones are retried |
| Not signed — signing key check failed | See When an image is not signed |
| Nothing to sign | The item is not an image or artifact that gets signed |
| Signing is not enabled in this environment | The environment you are using has not switched signing on |
Attestation (the signed scan result attached to the image): No attestation, Attestation pending, Attested with the time it was attached, Attestation failed, retrying, Attestation failed, and Attestation: gave up. The attestation badge reports whether the attestation was attached. It does not report whether someone tampered with it; a deleted or replaced signature is reported by the signature status above.
A push that is overwritten by a newer one within seconds, before it could be captured, is listed in the Push history as Overwritten by a newer push before it could be captured; only the newer one is processed.
An image is refused for signing when it was pushed by an account that was not allowed to push to your registry at that moment, for example a credential whose owner lost the permission. A refused image is never signed, the members who have access to security findings (Read security findings, see Who can do what) are notified in the app, and the only way forward is a push by an authorized account.
Sencai also re-checks the signatures it attached every 15 minutes (in batches, oldest check first). If a signature is deleted or replaced behind your back, the image shows Signature removed or Signature changed, Sencai attaches it again, and a changed signature also notifies the members with access to security findings and writes an audit log entry. You usually see this within 15 minutes; deleting or replacing one of the signature tags is looked at sooner.
Severity counts are security data. People who can read the registry but do not have access to security findings see the processing, scan and signature states but not the counts, the findings, or the attestation.
Findings and triage
Section titled “Findings and triage”Open an image, select a tag, and the Findings card lists what its latest
finished scan found, grouped by vulnerability and package (Severity,
CVE, Package, Fix, Installed at, Decision). Installed at
lists the places in the image where the package was found; Fix shows the
fix version when there is one, or No fix yet. Findings in a tag that were
present in the previous tagged version and are gone now are marked Fixed in
<digest>. If a newer scan is queued, running or failed, the card says so and
keeps showing the findings of the last scan that finished. Below the findings,
Scan history lists every scan of the version (what started it, when it
finished, the counts, the scanner version and the date of the vulnerability
data).
Under Security → Vulnerabilities (/gravity/security/vulnerabilities) a
switch chooses between Instances & manual findings and Registry
images, and the summary shows coverage next to the counts: for example “3
critical in 12 of 13 images - 1 not scanned”. An image that has not been
scanned is never counted as zero.
People with response access can record a decision on a finding. On the image page, choose Decide next to the finding, then choose Accept the risk, Mark as false positive, or Reopen, give a Reason (required for the first two) and, for an accepted risk, an optional expiry date, and Save. The finding then shows Risk accepted or False positive. The decision applies to that vulnerability and package in that image across every future push and rescan, an expired decision stops applying, and every decision is recorded in the audit log. The registry table under Vulnerabilities shows the decision but you record it on the image page. See Vulnerabilities.
When a critical or high vulnerability that is new to an image appears in your registry, the members with access to security findings get a notification in the app. It is batched: at most one notification per image per hour, and only for findings the image has not had before.
Scan again and Sign again
Section titled “Scan again and Sign again”On an image page, Scan again queues a new scan of the selected version (a multi-platform image gets one scan per platform image). It runs behind scans of fresh pushes, the earlier result stays in place until the new scan succeeds, and the new scan replaces the attached scan attestation when it finishes. Sign again appears when the signature failed, was given up on, went missing or was changed; it attaches a new signature and does not override a refused image. Both need permission to update the registry and each is limited to ten requests an hour for the organization. Scan again is unavailable while another scan of the same image is queued or running, and for items that are not container images.
Who can do what
Section titled “Who can do what”Registry permissions are part of permissions in depth. Roles get these by default. Per-member denies and custom roles apply to them in the way that page describes: where custom roles are not available yet, the role defaults below are what counts.
| Permission | Lowest default role | What it allows |
|---|---|---|
Read (git.registry:read) |
Viewer | See images, tags and statuses; download the public signing key and the signature material; see your own tokens and access state |
Export (git.registry:export) |
Viewer | Create and revoke your own pull token |
Create (git.registry:create) |
Member | Create and revoke your own push token; decides whether your registry account can push |
Update (git.registry:update) |
Member | Scan again and Sign again |
Revoke (git.registry:revoke) |
Admin | See and revoke other members’ tokens |
Manage (git.registry:manage) |
Admin | Create the CI push and runtime pull credentials |
Manage repository settings (git.repo-settings:manage) |
Admin | Manage a repository’s deploy keys, Actions secrets and variables, and webhooks (see Repositories) |
Read security findings (security:read) |
Viewer | See finding details, severity counts and the scan attestation; also decides who is notified about new findings and refused pushes |
Respond to security findings (security:respond) |
Member | Accept risk or mark a false positive |
Auditors can read the registry, verify signatures offline, and create pull tokens, but cannot push.
Connecting an external registry
Section titled “Connecting an external registry”Custom Registries (/gravity/registry/registries, reached from the
Registry page’s own tab) connects a private Docker Registry v2 endpoint you
already run - Harbor, GitLab’s container registry, or a plain Docker
Registry v2 server - so you can browse it from inside Sencai without
switching tools, and scan its images for known vulnerabilities. Images in an
external registry are not signed by Sencai.
Add registry asks for a URL, an optional username (for basic auth -
for a GitLab personal access token, set the username to oauth2), and an
optional token. Only an organization admin can add or remove a custom
registry. The URL must be https://, on port 443, at a public IPv4 address;
see Scan images in your own registry
for the full rules.
Once added:
- Test connection checks reachability, the certificate, the login and whether the catalog can be read, and shows which of those it proved. The headline is Connected, Authentication failed or Connection error.
- Opening a connected registry lists its repositories and lets you browse tags. If the registry doesn’t expose a browsable catalog, adding an API URL (GitLab-compatible) enables discovery through that API instead; otherwise you can look up a specific repository path directly to see its tags.
- Test on a repository card (or Scan on a tag) scans that image now, and the Scheduled scans card repeats a scan every day, three days or week. Results appear on the scan page and under Security → Vulnerabilities.
- Repositories can be starred as favourites, scoped to that registry.
Editing a registry lets you update its URL, username, or token at any time - leave the token field blank to keep the existing one. Changing the URL, username or token clears the last test result, so a registry you pointed at a wrong address is not shown as connected.
Removing images
Section titled “Removing images”Sencai doesn’t currently offer an in-app retention or bulk-cleanup policy for images in your organization’s own registry - manage lifecycle through your CI pipeline (for example, tagging conventions and pipeline-driven deletion) for now. Deleting an image does not delete its history in Sencai’s audit log.
What’s next
Section titled “What’s next”- Image signing and verification - download your key and prove which image you deployed
- Scan images in your own registry - connect a registry you run and scan its images
- Deploy a container to a new instance - run an image from here on a new server
- Vulnerabilities - findings for registry images and running instances
- CI & pipelines - how workflows run and where pipeline secrets live