Connecting a repository
kyvlt.sh reaches GitHub through a GitHub App your organisation creates and installs. Nobody types a credential anywhere: repository access is granted in GitHub, by whoever owns those repositories, and every token kyvlt.sh uses is minted from the app and lives an hour.
All of it lives on one page: Integrations → GitHub Actions.
Connect GitHub
Under Repository, press Connect GitHub. GitHub lists every account and organisation you can install on — pick yours, then pick the repositories. Only select repositories is the right answer almost always.
The same link — Add from GitHub, once repositories exist — adds more later, or installs on a second account.
GitHub shows you what the app asks for before you agree:
Secrets: Read and write Variables: Read and write Metadata: Read-onlyThose three and nothing else.
That is all of it. The app cannot read code, issues, pull requests or anything else in a repository — and because you are looking at GitHub’s own page, that is GitHub telling you so rather than us.
Nothing is typed and nothing is created. The app belongs to kyvlt.sh; installing it is what grants it repositories, and removing it in GitHub is what takes them away.
Install it more than once if your repositories live under more than one account.
Connect an environment
Choose a project, then one of its environments, then the repository — the list is what the installation was actually granted, so there is no way to name one kyvlt.sh cannot reach.
Last, the GitHub deployment environment the keys should land in. When GitHub will list a repository’s environments, this is a list too; otherwise it is a field, and the environment must already exist there. Left empty, the keys become repository secrets, which every workflow in the repository can read.
A project is a codebase and a repository is where it lives, so the repository is remembered for the project — the next environment you push arrives with it already chosen.
Check what GitHub has
Press What is in GitHub. It asks GitHub for the secret names that exist now and writes nothing, on either side. It is the fastest way to see that everything is lined up, because the answer arrives while you are still looking.
Running kyvlt.sh yourself
A self-hosted deployment cannot be given this deployment’s private key, so it creates its own app instead — one press, one confirmation on GitHub, and the key is sealed under your organisation’s key and never shown again. The integrations page offers that automatically when the deployment provides no app of its own, and everything after it is identical.
Configure one with Kyvlt:GitHubApp — AppId, Slug, Name and
PrivateKey — and the creation step disappears for everybody using that
deployment. make github-app does the whole flow and writes that
configuration out; make github-app-deploy puts it into a cluster.
In a cluster the key is mounted, not environed, from a Secret called
api-github-app that Helm never sees — the same custody as the root key, and
for the same reason. An environment variable is readable from
/proc/1/environ, is inherited by every child process, and is captured by a
crash dump; and a value passed through Helm is printed back in the clear by
helm get values and kept in every revision of the release history. This key
signs the tokens that write into customers’ repositories, so it gets the
narrower route.
Why an app rather than a token
A personal access token is a credential one person holds, scoped to whatever they happened to tick, valid until it expires — and the only way to find out what it can reach is to try.
An app is different in three ways that matter:
- Access is granted by whoever owns the repositories, in GitHub, in an interface both sides can look at afterwards — and the organisation is chosen from GitHub’s own list rather than typed.
- kyvlt.sh knows what it was given. The repository list on this page is GitHub’s answer, which is why aligning a project is a choice rather than a spelling test.
- Tokens are minted per hour, from a key that never leaves the server. An installation stored here holds no credential at all — it is a number and an account name.
The two targets are not interchangeable
A repository secret and an environment secret with the same name are different objects, and a workflow reads one or the other depending on whether its job names an environment. Changing this after the fact writes a second set of secrets rather than moving the first, so nothing is silently converted — the old ones stay where they are until somebody removes them.
What happens next, and when
Nothing has to be pressed again. A connection owes a push from the moment it is saved, and from then on every write to a key it carries makes one owed.
The push is not part of the write. Saving a value succeeds because kyvlt.sh stored it; a GitHub outage never becomes a failure to keep your own secret. What is owed is remembered and retried, with the delay growing between attempts, and the environment’s row on this page says so the whole time.
Changing or removing things
Granting or removing repositories happens in GitHub, under the app’s installation settings. kyvlt.sh does not need to be told.
Re-pointing a project at a different repository is done by pushing one of its environments again and choosing another. Every environment under it starts owing a push, because the new repository holds whatever was there before kyvlt.sh arrived. The old repository keeps its secrets.
Forgetting an installation is refused while projects are aligned through it, and names them. The alternative is one click that silently stops every environment under those projects.
Uninstalling the app in GitHub stops everything immediately, and the next push says so: GitHub no longer has this installation.
Stopping a push is the unlink beside a connection in the list, and it never removes anything from GitHub. The secrets already there stay exactly as they were, and a workflow that depends on one keeps working. Remove them in GitHub if you want them gone.