vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Store repository secrets encrypted, with a CLI and a settings form
0c40a1d3b48eb0ade37334f62ee526c371ecb61c · Keenan Nemetz · 7d ago · parent 122cbe4f
Store repository secrets encrypted, with a CLI and a settings form A repository has values that cannot live in its code: a deploy key, a registry token, a staging password. They are now stored in data/secrets.db, sealed with AES-256-GCM under data/secrets.key, and read through one store that records every read and every change. The key is a separate file, and secrets_key can move it, so a backup of the data directory can be a backup of ciphertext rather than of plaintext. `vole secret list|set|get|rm` asks the instance over the key the caller already pushes with, since the store is server-side. set reads the value from stdin or a file and never from the argument list; get writes the value and nothing else. The maintainer role is the capability: the accounts that approve work and allow CI own the credentials those jobs will use. The repository's Settings tab gains the same list — names, versions, who changed one, when a value was last read — with set, replace and delete. It never renders a value, and a maintainer who is not an admin now reaches that page for this section alone. Values are limited to what one environment variable can carry: 128 KiB for NAME=value, valid UTF-8 and no NUL. A longer value could never reach a step, and the refusal says so. Slice 1 of #154.
server/ssh/server.go +8
| @@ -430,6 +430,14 @@ func (s *Server) exec(ch xssh.Channel, req *xssh.Request, command, user, fp, rem | |||
| 430 | 430 | exit(ch, s.serveWorkflowDispatch(ch, argv, user)) | |
| 431 | 431 | return | |
| 432 | 432 | } | |
| 433 | // Repository secrets are a server-side store, so the CLI asks the instance for | ||
| 434 | // them over the same key it pushes with: reading, writing and deleting are all | ||
| 435 | // maintainer capabilities, re-checked here rather than trusted from the client. | ||
| 436 | if len(argv) >= 1 && argv[0] == "vole-secret" { | ||
| 437 | req.Reply(true, nil) | ||
| 438 | exit(ch, s.serveSecret(ch, argv, user)) | ||
| 439 | return | ||
| 440 | } | ||
| 433 | 441 | // The admin API is a fixed command set, not a shell. It is available only to | |
| 434 | 442 | // accounts marked as instance admins. | |
| 435 | 443 | if len(argv) >= 1 && argv[0] == "vole-admin" { | |