Wiki: Architecture/06-Data-and-Cryptography

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 ReadsStdin to receive stdin at all; TestStdinCommandsReadStdin enforces 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 NAME pass-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.