Wiki: Architecture/06-Data-and-Cryptography
Data and cryptography
Data inventory
Schema: internal/store/migrations/, 66 migrations. Classification:
C credential or secret, P personal data, R private repository
content (as confidential as the repository), O operational.
| Domain | Tables | Class | Notes |
|---|---|---|---|
| Identity | users, emails, ssh_keys, pgp_keys, orgs, org_members, teams, team_members |
P | email addresses in clear; keys are public |
| Credentials | api_tokens, web_sessions, login_tokens, email_tokens, invites |
C | SHA-256 hashes only |
| Repositories | repos, repo_access, team_repos, repo_topics, repo_watchers, repo_pins, repo_bookmarks, page_domains |
O | |
| Collaboration | issues, issue_*, merge_requests, mr_*, labels, milestones, mentions |
R | bodies of issues, comments and reviews |
| Releases, snippets | releases, release_assets, snippets, snippet_files |
R | |
| CI | builds (includes logs), build_schedules, runner_repos, runner_seen |
R | build logs can echo anything a step prints |
| CI secrets | build_secrets |
C | sealed (AES-256-GCM) |
| Integrations | webhooks (secret), webhook_deliveries, mirrors (username, token) |
C | webhook secret and mirror token sealed |
| Notifications | notifications (mail queue), inbox, push_devices (APNs token), push_queue, mail_replies (Message-IDs of posted replies) |
P | device tokens sealed; looked up by SHA-256 |
| Signatures | commit_signatures, settings.key_epoch |
O | verification cache |
| Audit and feed | audit_log, events |
O, P | actor ids, pruned argv, fingerprints and IPs in some audit rows, a hash chain (prev_hash, hash) |
| Dependencies | dep_checks, dep_reports |
O |
Outside the database:
| Data | Location | Class |
|---|---|---|
| Repository contents | <root>/repos |
R |
| LFS objects | <root>/lfs |
R |
| SSH host key | <root>/ssh/host_ed25519 |
C |
| TLS keys (ACME) | <root>/acme |
C |
| SMTP password | /etc/gitbay/config.toml |
C |
| APNs signing key (.p8) | path in push.key_file |
C |
| IMAP password | path in mail.inbound.password_file |
C |
| Secret key file | server.secret_key_file (/etc/gitbay/secret.key) |
C |
| Backups | /var/backups/gitbay, offsite |
all of the above |
No table stores client IP addresses as a column. The daemon writes a
client IP into an audit row only for authentication failures and
throttling (internal/sshd/sshd.go).
At rest
| Item | Protection |
|---|---|
| API tokens, sessions, login links, email codes, invites | SHA-256 of a 256-bit random value; the value is shown once and never stored (internal/store/sessions.go) |
| CI secrets, webhook secrets, mirror tokens, APNs device tokens | AES-256-GCM under a key file outside the database and outside server.root; additional data binds table, column and row (internal/seal, internal/store/secrets.go) |
| SQLite file | mode 0640, directory 0750 |
| Backups | local archives age-encrypted when [backup] age_recipients is set; restic encrypts the offsite copy; neither carries the secret key file, which is copied off the host by hand until a separate keys repository is set up |
| Disk | no application-level encryption; any disk encryption is the host's |
The database file or a backup read by anyone other than the gitbay
user discloses no CI secret, webhook secret, mirror token or device
token without the key file, which neither carries. Rotation:
gitbayd admin secrets rotate (Admin wiki).
In transit
| Channel | Protection |
|---|---|
| SSH | Go x/crypto/ssh; ed25519 host key generated on first start |
| HTTPS | TLS 1.2 minimum (cmd/gitbayd/tls.go), ACME or operator certificates; HSTS one year |
| HTTP port 80 | ACME challenges and redirect only |
| git:// | none (public data only; off by default) |
| Runner ↔ server | SSH |
| SMTP | STARTTLS required unless the relay is local (mail.require_tls), or implicit TLS (mail.tls) |
| APNs | TLS, HTTP/2 |
| IMAP | implicit TLS or STARTTLS, TLS 1.2 minimum, certificate verified (internal/imapc) |
| Webhooks | TLS when the URL is https; HMAC-SHA256 body signature in X-Gitbay-Signature-256 (internal/webhook/webhook.go) |
| Mirrors | per URL; token passed through GIT_ASKPASS, never argv (internal/mirror/mirror.go) |
TLS 1.2 is the minimum, set in code (serverTLS in
cmd/gitbayd/tls.go); cipher suites are Go's defaults.
Cryptographic primitives
| Use | Primitive | Code |
|---|---|---|
| Token generation | crypto/rand, 32 bytes |
internal/store/sessions.go |
| Token storage | SHA-256 | sessions.go |
| LFS transfer tokens | HMAC-SHA256, secret in settings |
internal/lfs/lfs.go |
| Webhook signatures | HMAC-SHA256 | internal/webhook/webhook.go |
| APNs provider token | ES256 JWT (ECDSA P-256) | internal/push/token.go |
| SSH host key | ed25519 | internal/sshd/sshd.go |
| Commit and tag signatures | verify OpenPGP (ProtonMail go-crypto) and SSHSIG | internal/sig |
| LFS object ids | SHA-256 | internal/lfs/lfs.go |
Signature verification results are cached in commit_signatures with
the global key_epoch at the time of verification. Any change to a
trust input (a key added or removed, an email verified) bumps the
epoch, which invalidates every cached result (internal/store/users.go,
internal/control/sig.go).
The server holds no signing key and signs nothing. A "verified" badge means a user's own key signed the commit.
Secret handling rules
- Secrets enter only on stdin. A command must set
ReadsStdinto receive stdin at all;TestStdinCommandsReadStdinenforces it. Examples:repo secret set,repo deploy-key add,repo import --token-stdin(internal/control/build.go,import.go). - Secrets are listed by name, never echoed back.
- The audit log stores argv with flag values stripped
(
internal/control/control.go). - Mail errors are logged with addresses redacted
(
internal/notify/notify.go). - CI secrets travel in the runner's claim only for trusted builds and
reach the container as environment variables through a 0600 env file
or podman's
--env NAMEpass-through, never argv (cmd/gitbay-runner/isolate.go).
Retention
Configured under [retention] for audit, events,
webhook_deliveries, mail and push; unset means keep forever.
Expired sessions and tokens are swept hourly regardless
(internal/config/config.go, cmd/gitbayd/main.go).
Accounts that never verify are removed after
registration.pending_expiry. account export gives a user their data.