Repository navigation
GitHub through the proxy: git and gh - #37
Merged
Merged
Conversation
czpython
force-pushed
the
dru-454-github-through-the-proxy
branch
2 times, most recently
from
September 6, 2026 15:02
cbf531c to
6597add
Compare
czpython
force-pushed
the
dru-459-trust-delivery
branch
4 times, most recently
from
September 7, 2026 05:19
3df0ceb to
e8c3b62
Compare
A box must clone, push, and run gh with a Druks App installation token that never enters the box. The proxy carries it. github is one service with three hosts in the catalog. api.github.com and uploads.github.com, where gh puts release assets, take a bearer. github.com takes Basic with x-access-token as the user, since git's smart HTTP refuses a bearer. A service is now the variable a client reads and the upstreams it reaches, each an Upstream that knows its host, its header, and how the credential goes on the wire. The exchange picks the upstream by the host the proxy names, and /upstreams lists every host. gh gets the placeholder in GH_TOKEN and sends it with the token scheme, which the proxy reads like a bearer. git gets it through gh: the box writes the lines gh auth setup-git writes, system wide, so git sends the placeholder as a Basic password and the proxy swaps it. An SSH remote would go around the proxy, so git@github.com: and ssh://git@github.com/ are rewritten to HTTPS. One writer, environment.github, gives the lines beside trust. The lines replace and then add, so they can run again on the same box, as a container restart does. cloud-init runs them as root, the exe setup script with sudo -n, and the docker sandbox image in its entrypoint. That image now carries git and gh, from GitHub's own apt repository. On docker-sbx a custom secret names every host of its service, with --host repeated. The github service there is sbx's own.
czpython
force-pushed
the
dru-454-github-through-the-proxy
branch
from
September 7, 2026 05:23
6597add to
4a1a0a7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes
A box clones, pushes, and runs gh with a Druks App installation token that never enters the box.
githubis one service with three hosts in the catalog.api.github.comanduploads.github.com, where gh puts release assets, take a bearer.github.comtakes Basic withx-access-tokenas the user and the token as the password, since git's smart HTTP refuses a bearer. AServiceis now the variable a client reads plus theUpstreams it reaches, each of which knows its host, its header, and how the credential goes on the wire. The exchange picks the upstream by the host the proxy names, and/upstreamslists every host.GH_TOKEN. git gets it through gh: the box writes the linesgh auth setup-gitwrites, system wide, so git sends the placeholder as a Basic password and the proxy swaps it. An SSH remote would go around the proxy, sogit@github.com:andssh://git@github.com/are rewritten to HTTPS.environment.github, gives those lines besidetrust. They replace and then add, so they can run again on the same box, as a container restart does. A test runs them twice against a real git. cloud-init runs them as root, the exe setup script withsudo -n, and the docker sandbox image in its entrypoint. That image now carriesgitandgh, from GitHub's own apt repository as its install guide gives it.--hostrepeated. Thegithubservice there stays sbx's own.Where this differs from the ticket
git config --system, not by runninggh auth setup-git. gh writes to the user's own config, and cloud-init runs as root while the caller logs in as another user. The lines are the ones gh writes, for every user of the box.git@github.com:andssh://git@github.com/, since a pasted URL can take either.uploads.github.comis a third host, sincegh release uploadputs assets there with the same bearer.gist.github.comis not in the catalog. A gist clone over HTTPS would reach it with the placeholder and fail with401, which is safe and can be added when a box needs it.githubsecret needsgitandgh. The docker sandbox image gets both. The exe image has both. A cloud image without git fails its setup script on the firstgit configline, so the host fails with the reason instead of coming up without the swap.Names
New names, open to change:
Upstream,environment.github.Gates
uv run ruff check,uv run ruff format --check,uv run pyright, anduv run pytestare green.Acceptance
Run on the acceptance stack with this branch built into the API and exchange image, the proxy on the host's tailnet address, the docker sandbox image built from this branch's
images/local, and a Druks App installation token for the private repositoryclawhaven/clawhaven-localdevas a staticgithubsecret. 13 of 13 on docker and 12 of 12 on exe, repeated after the review fixes:GH_TOKEN, git pointed at gh, and both SSH forms rewritten.gh apiread the private repository andgh pr listworked.git cloneover HTTPS, a push of a throwaway branch, and its delete all worked.git@github.com:went over HTTPS through the rewrite.The first docker run found one defect: gh sends
Authorization: token <value>, a scheme the addon did not read, so the placeholder reached GitHub and got401. The addon now reads thetokenscheme like a bearer, with a test. Both halves passed after the fix. The stack was restored afterwards, and the branch images, the token file, and the CA directory were removed from the host.Review
One adversarial review, two findings, both applied.
gh release upload --clobberdeletes the old asset throughapi.github.com, then uploads throughuploads.github.com, which the catalog did not name, so the upload would have failed after the delete. The host is now the service's third upstream, with the bearer.git configrefuses to replace a key that already has two values, which would have stopped sshd after a restart. The lines now replace and then add, in the entrypoint and in the writer, with a test that runs them twice against a real git. The docker half of the acceptance now restarts the box and checks that sshd and gh come back.