.gitbay/wiki/Architecture/03-Deployment.org
85 lines · 7630 bytes
1#+title: Deployment and network
2
3[[file:diagrams/03-deployment.svg]]
4
5The reference deployment is one Linux host built from
6=deploy/cloud-init.yaml=, with the daemon installed by =make deploy=
7(=deploy/install.sh=) and the CI runner by =make deploy-runner=. The
8statements in this document about the host rest on those files.
9
10* Listeners
11
12| Port / path | Protocol | Owner | Default | Auth | Code |
13|----------------------+-------------------+------------+-------------+----------------------------------------+---------------------------------------|
14| 22/tcp | SSH | gitbayd | on | public key; unknown keys only reach =register= when registration is open | =cmd/gitbayd/main.go=, =internal/sshd/sshd.go= |
15| 443/tcp | HTTPS | gitbayd | on | none for pages; session cookie; bearer token for the API | =cmd/gitbayd/main.go= |
16| 80/tcp | HTTP | gitbayd | on with ACME| none; ACME HTTP-01 and redirect only | =cmd/gitbayd/main.go= |
17| 9418/tcp | git:// | gitbayd | off | none; public repositories only | =internal/gitd= |
18| 2222/tcp | SSH (operator) | host sshd | on | public key, no passwords, fail2ban | =deploy/cloud-init.yaml= |
19| =<root>/hook.sock= | Unix socket | gitbayd | on | mode 0600; peer uid must be the daemon's (Linux); per-push token | =internal/hookd/hookd.go= |
20
21With =ssh.mode = system= the host's sshd serves port 22 instead and
22invokes =gitbayd authorized-keys= and =gitbayd shell=
23(=cmd/gitbayd/main.go=).
24
25HTTP server limits: =ReadHeaderTimeout= 10 s, =IdleTimeout= 2 min,
26=MaxHeaderBytes= 64 KiB, no =WriteTimeout= so long git transfers and
27live build logs can stream (=cmd/gitbayd/main.go=).
28
29There is no metrics endpoint. =/healthz= reports the deployed commit and
30a database check.
31
32* Processes and accounts
33
34| Unit | User | Hardening (from the unit files) |
35|------------------------+-------------+---------------------------------------------------------------------------------------------------|
36| =gitbayd.service= | =gitbay= | =CAP_NET_BIND_SERVICE= only; =NoNewPrivileges=; =ProtectSystem=strict= with write access to =/var/lib/gitbay= and =/var/backups/gitbay= only; =ProtectHome=; =PrivateTmp=; =PrivateDevices=; kernel, clock and cgroup protections; =RestrictNamespaces=; =MemoryDenyWriteExecute=; =RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX=; =SystemCallFilter=@system-service= (=deploy/cloud-init.yaml=) |
37| =gitbay-runner.service=| =ci-runner= | =MemoryMax=6G=, =CPUQuota=300%=, =Delegate=yes=, =KillMode=mixed=, =RestrictSUIDSGID=yes=. =NoNewPrivileges=, =ProtectKernelTunables= and =ProtectControlGroups= are relaxed because rootless podman needs =newuidmap=, a proc mount and a writable delegated cgroup; the reasons are in =deploy/gitbay-runner.override.conf= |
38| CI containers | subordinate uids of =ci-runner= | rootless podman, =--pull=never=, operator-provisioned image; see [[file:07-CI-and-Supply-Chain.org][7. CI]] |
39| backup, db-backup, gc, monitor timers | =gitbay= | nightly full archive, hourly database snapshot, weekly =git gc=, hourly health heartbeat (=deploy/cloud-init.yaml=) |
40
41* Filesystem
42
43| Path | Contents | Mode set by code / deploy |
44|-----------------------------------+--------------------------------------------+---------------------------|
45| =/var/lib/gitbay= (=server.root=) | everything below | 0750 (cloud-init) |
46| =<root>/gitbay.db= | SQLite database | 0640 (=internal/store/store.go=) |
47| =<root>/repos/<owner>/<name>.git= | bare repositories | process umask |
48| =<root>/lfs= | LFS objects, content-addressed | 0755 directories (=internal/lfs/lfs.go=) |
49| =<root>/ssh/host_ed25519= | SSH host key | 0600 in a 0700 directory (=internal/sshd/sshd.go=) |
50| =<root>/acme= | ACME account key and certificates | autocert defaults |
51| =<root>/hooks= | generated hook scripts | 0755 |
52| =/etc/gitbay/config.toml= | configuration, including SMTP password | 0640 (cloud-init) |
53| =/etc/gitbay/secret.key= | keys sealing secret columns | 0600, owner =gitbay= (=deploy/install.sh=) |
54| =mail.inbound.password_file= | IMAP mailbox password | 0600 required; the daemon refuses to start otherwise |
55| =/var/backups/gitbay= | backup archives | 0750 (cloud-init) |
56
57* Outbound connections from gitbayd
58
59| Destination | Trigger | TLS | Guard |
60|------------------------+-------------------------------+----------------------------------------------+----------------------------------------------------------------|
61| ACME directory | certificate issue and renewal | yes | host policy limits names to the site and claimed pages domains (=main.go=) |
62| SMTP relay | queued mail | STARTTLS required for a non-local relay, or implicit TLS | =mail.require_tls=; Go's =PlainAuth= will not send credentials over plaintext to a non-local host (=internal/mail/mail.go=) |
63| APNs | queued push | yes, HTTP/2 | provider token signed with the operator's .p8 key |
64| IMAP server | =mail.inbound.poll_interval= | implicit TLS or STARTTLS, certificate verified; no plaintext setting | operator-configured host only (=internal/imapc=) |
65| Webhook URLs | recorded events | yes when https; certificate verified | private, shared, loopback, link-local and multicast targets refused at save and again at connect time; no redirects (=internal/webhook/webhook.go=) |
66| Mirror URLs | mirror schedule | per URL | address check at save and before each sync; git pinned to the checked addresses, no redirects (=internal/mirror/mirror.go=) |
67| Package registries | dependency checks | yes | fixed hosts; only the package name varies (=internal/deps/registry.go=) |
68
69* Host firewall
70
71=deploy/cloud-init.yaml= opens 22, 80, 443 and 2222 inbound with ufw.
72Outbound traffic from the host is not restricted. CI builds are, by
73two nftables tables on the runner's host: trusted builds keep the
74internet, untrusted ones get TCP 80 and 443 and DNS, and neither
75reaches private ranges or the host's loopback beyond DNS (the CI wiki page, #260).
76
77* Change path
78
791. A signed commit merged to =main= through a merge request (direct
80 pushes to =main= are refused by =require-mr=).
812. =make deploy= refuses a dirty tree (=Makefile= =preflight=), builds
82 with the commit stamped in, copies the binary over operator SSH,
83 runs =gitbayd check-config=, restarts the unit
84 (=deploy/install.sh=).
853. =/healthz= reports the commit now serving.