Compare commits

...

319 commits

Author SHA1 Message Date
raito 8c0c7b517f feat: block automatically crawlers if the blocker is enabled
This help us getting rid of useless traffic by crawlers.

It is enabled for gerrit01 which is suffering the most from this.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-19 19:12:10 +02:00
raito d5500d7c4e fix(buildbot): bring back the old Gerrit reporting
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-18 23:22:51 +00:00
raito eaf48a0cdd fix(buildbot): use builder-9 as builder-10 is down
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-18 23:22:51 +00:00
raito e3129fec51 fix(buildbot): fix CORS properly
wildcards are not allowed in the headers.
We need to include credentials as well.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-18 23:22:51 +00:00
raito 437293bdaa fix(buildbot): remove CORS wildcards for their precise Gerrit hosts
wildcards are not supported in CORS headers, so this design was quite
wrong actually.

We can just use the actual Gerrit hostname for now.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-18 23:22:51 +00:00
mei (ckie) df8a57f91a
users: add ckie 2024-10-18 14:43:25 +03:00
Yureka 97bee26977 new ssh key for yureka 2024-10-10 13:42:29 +00:00
Luke Granger-Brown 84cfbdb050 feat: check formatting and validity of alerts
Fixes #94.
2024-10-07 20:00:54 +00:00
Luke Granger-Brown 6a8f49f180 feat(gerrit): add some basic theming
This is based on some of the preliminary colour work done by @ckie in
the the-distro/floral.systems repo.
2024-10-07 19:27:13 +00:00
Yureka 06dd4d6e85 update hydra 2024-10-07 19:25:51 +02:00
Luke Granger-Brown de085155a6 fix: update paths to floral secrets to secrets/floral/ 2024-10-07 15:48:05 +00:00
Luke Granger-Brown 2001012325 feat(uptime-kuma): status.forkos.org should point at the ForkOS page 2024-10-07 15:47:33 +00:00
raito fbf26302b6 hotfix(lix): use build01 features for build02 remote builder
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-07 15:26:27 +02:00
raito 1701a2b388 hotfix: bump buildbot-nix to restore backward compat with Lix deployments
We oopsie dropped `hydraJobs` support to move to `buildbotJobs`.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-07 15:26:19 +02:00
raito decc9963ee feat: add buildbot.lix.systems
This introduces a new Buildbot instance using all the previous work.

This is a "Raito's VM" hardware type.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:53:25 +02:00
raito daa99e83e8 fix(buildbot): add gerrit.lix.systems as known host
Otherwise, buildbot cannot listen to the stream of events.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:53:04 +02:00
raito 160e7c5ecb fix(secrets): rekey for buildbot.lix.systems and build02.aarch64.lix.systems
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:52:37 +02:00
raito b56b8963a2 feat: introduce Buildbot multi-tenancy
This shares the same expression to deploy the Buildbot.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:28:29 +02:00
raito 192ba49f7c fix(secrets): lists of lists are wrong, prepend the globals
Otherwise, I won't be in the list.

This adds the active infra core members of Lix as well.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:28:29 +02:00
raito 9ad7e7b139 feat(tenancy): tag machines accordingly to their tenancy
@lix for Lix machines.
@floral for Floral machines.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:28:29 +02:00
raito 96f5d45ff3 feat(lix): add buildbot.lix.systems key for extra build capacity
Otherwise, buildbot.lix.systems will not be able to access it anymore.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:28:29 +02:00
raito 3df1697289 fix(secrets): rekey the monitoring password
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:28:29 +02:00
raito 76276a8da3 feat: add build01.aarch64.lix.systems
This is the first Lix machine we are enrolling in our infrastructure
(!).

It's using all the previous commits to make it cozy with our current
infra style.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:10:28 +02:00
raito 7e205b16d0 feat(common/hardware/oracle-vm): enable systemd initrd
Let's minimize the amount of scripted initrd stuff if we can.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:10:28 +02:00
raito 1e421889e4 feat(monitoring): add static label for tenancy
So we can distinguish easily things in the dashboards.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:10:16 +02:00
raito 8838709a95 fix(common/hardware/oracle-vm): forgotten virtio modules
Otherwise, the machine won't reboot because virtio-scsi is not available
in the initrd.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:10:04 +02:00
raito 002db9a78f feat: introduce tenant-specific extra build capacity
At Lix, we have few aarch64-linux and aarch64-darwin systems we use to
boost our CI.

This is a module to handle tenant-specific extra build capacity without
it leaking over the rest of the deployment.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:09:23 +02:00
raito 6978c1271d feat: introduce floral and lix common modules
This way, we can mark tenancy appropriately in a common expression and
add all machines altogether in the same entrypoint.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 11:09:11 +02:00
raito 92560708b8 feat: multi-tenant secrets
Lix may have its own secrets and we want to maintain a certain
generalization level on the NixOS modules, so we can decorrelate which
secret we select dynamically by having a simple tenancy hierarchy
system.

This unfortunately requires to rewrite all call sites with a floral
prefix until we migrate them to the simple internal secret module which
is aware of this.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 08:10:44 +00:00
raito 3b6be269d6 feat: introduce Oracle VMs and Hetzner VMs as hardware types
This includes aarch64-linux variants for these hosters.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 08:10:44 +00:00
raito acaaad68bb feat: introduce resource control over all machines
We were using over all our machines in the Lix infrastructure.
It still makes sense for all our machines.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 08:10:44 +00:00
raito 3c9b077bb2 feat: add more admins tools from lix infra
We had this in our equivalent file.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 08:10:44 +00:00
raito c23d290647 docs(README.md): explain how to deploy things
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 08:09:53 +00:00
raito c0689e6832 feat: add @localboot tags for machine which can be deployed
colmena does not support netboot deployment, this is fine. We can fix it
later.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 08:09:53 +00:00
raito a2eecd1886 feat(buildbot): disable manhole debugging
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 07:59:56 +00:00
raito b5d412a5ba feat: adopt new version of Buildbot with incoming ref data
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-06 07:59:56 +00:00
Yureka 01f8322df9 update hydra/lix 2024-10-05 23:33:17 +02:00
Yureka 3072dfad55 update flake inputs 2024-10-05 23:30:21 +02:00
Maxine Aubrey 86e833f52a
chore(tf): drop all gandi resources 2024-10-05 18:46:45 +02:00
raito 1a862b2b0f hotfix: add the path to the stateless uptime kuma's password file
Forgotten in the previous merge.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-05 16:33:38 +02:00
raito 6d3e14ec27 feat: finer-grained ACLs for server accesses
In the process of adding multi-tenant infrastructure, it seems relevant
to add finer-grained ACLs.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-10-05 16:20:19 +02:00
Ilya K 5582a0a29b Fix Hydra exporter crash loop nonsense 2024-10-01 19:27:13 +03:00
Ilya K 4ddf87fa8e Add new metric to Hydra exporter 2024-10-01 19:27:05 +03:00
Ilya K 98d899fabc Update Hydra 2024-10-01 19:26:58 +03:00
Kiara Grouwstra b291caac46 feat(monitoring): add uptime-kuma for status page, fixes #97
Adds a service for a status page using
[`uptime-kuma`](https://uptime.kuma.pet/).
2024-10-01 16:13:23 +00:00
Ilya K e2c6550796 Hydra metrics
Yoink the nixos org exporter, rewrite most of it, deploy
2024-10-01 19:06:26 +03:00
raito 4749d204bf feat: add stateless-uptime-kuma-password secret
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-29 16:01:23 +02:00
raito c86cefe21f Merge pull request 'feat(gerrit): run git-gc-preserve on a daily timer' (#110) from gerrit-gc into main 2024-09-28 20:13:39 +00:00
raito f321ab6450 users: add winterqt
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-28 21:09:06 +02:00
Maxine Aubrey 8d95d1f850
fix(dns): dnsimple expects FQDNs in CNAMEs
DNSimple doesn't appear to follow the typical behaviour of appending the
domain unless the CNAME is terminated with `.`

To avoid further problems, let's just explicilty use the FQDN for all
CNAMEs.

https://support.dnsimple.com/articles/cname-record/

For comparison:
```
;; ANSWER SECTION:
alerts.forkos.org.	300	IN	CNAME	meta01.infra.p.
```

```
;; ANSWER SECTION:
alerts.forkos.org.	181	IN	CNAME	meta01.infra.p.forkos.org.
meta01.infra.p.forkos.org. 181	IN	A	163.172.69.160
```
2024-09-24 23:11:28 +02:00
Maxine Aubrey 29c1b366c6
feat(dns): migrate forkos.org zone to dnsimple 2024-09-24 21:10:39 +02:00
Maxine Aubrey 16027be2ca
fix(dns): apex cnames are not allowed
change flowery.systems from CNAME to ALIAS pointing to news.forkos.org
2024-09-24 20:50:41 +02:00
Janik Haag d780f18534 Merge pull request 'feat(dns): migrate functions from gandi to dnsimple' (#113) from janik/dnsimple into main
Reviewed-on: the-distro/infra#113
Reviewed-by: Maxine Aubrey <max@ine.dev>
2024-09-24 18:37:55 +00:00
Janik Haag 8acc60e328
feat(dns): migrate functions from gandi to dnsimple 2024-09-24 00:25:58 +02:00
Maxine Aubrey e3b6cb72b4
feat(dns): add dnsimple to terraform configuration 2024-09-23 19:49:21 +02:00
Janik Haag d462e8ca9c
feat(gerrit): run git-gc-preserve on a daily timer 2024-09-18 22:27:57 +02:00
raito 94d1881e10 feat(gerrit): add git-gc-preserve script
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-02 11:05:54 +02:00
raito 132d2866b5 feat(channels): add minimal ISO for x86_64-linux
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 20:14:02 +02:00
raito a14f496db8 fix(channel-scripts): fix RUST_LOG=info
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 20:03:11 +02:00
raito c2ad3d6d26 fix(channel-scripts): push OTLP properly now
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 19:56:46 +02:00
raito 4c7943349b fix(flake): bump channel-scripts to obtain the fixed rename
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 19:50:02 +02:00
raito 9a04ef909b feat(nixpkgs): run oxidized channel scripts
We don't need weird Perl scripts where we are going. Here's a streaming
channel-scripts deployment with plenty of bells, including OTLP.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 19:32:23 +02:00
Ilya K c1712dc1fa Set up tempo 2024-08-31 15:05:30 +03:00
raito 8073ae6942 feat(s3-revproxy): tune the cache-control
Adopt the original values from the Perl script.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 00:52:13 +02:00
raito c38e9b482f feat(web): provide a directory listing via s3-revproxy
Thanks to Jade Lovelace who built all this machinery for Lix initially.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 00:29:18 +02:00
raito 9063138156 feat(secrets): add s3 reverse proxy API keys
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 00:19:49 +02:00
raito 322f10d9ae feat(dns): add raw S3 reverse proxies domains for channel scripts
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-31 00:19:40 +02:00
Ilya K bf7252c210 terraform/hydra: more nixpkgses now 2024-08-30 21:34:30 +03:00
raito c969625b0f fix(sniproxy): outside/inside of infra, the ingress IPs are different
In my infrastructure, the source node is 99::1, outside of my infra,
it's ::1.

All of this machinery was never really meant to be used on this scale,
so oopsie.

We should build our own sniproxy at some point.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-30 19:01:44 +02:00
raito 1b22c1f0ae fix(hydra): proxy it over my sniproxy
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-30 18:34:35 +02:00
Ilya K 30d759edf4 terraform/hydra: switch k900-experiments jobset to less-nixpkgses branch 2024-08-30 19:22:09 +03:00
Pierre Bourdon cd92c9588f
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=f1b552ecbf2d011cd4fdb93d7d117388ab9c0027' (2024-08-12)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=44b9a7b95d23e7a8587cb963f00382046707f2db' (2024-08-25)
• Updated input 'hydra/lix':
    'git+https://git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=5137cea99044d54337e439510a647743110b2d7d' (2024-08-10)
  → 'git+https://git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=278fddc317cf0cf4d3602d0ec0f24d1dd281fadb' (2024-08-17)
• Updated input 'hydra/nix-eval-jobs':
    'git+https://git.lix.systems/lix-project/nix-eval-jobs?ref=refs/heads/main&rev=c057494450f2d1420726ddb0bab145a5ff4ddfdd' (2024-07-17)
  → 'git+https://git.lix.systems/lix-project/nix-eval-jobs?ref=refs/heads/main&rev=42a160bce2fd9ffebc3809746bc80cc7208f9b08' (2024-08-13)
• Updated input 'hydra/nix-eval-jobs/flake-parts':
    'github:hercules-ci/flake-parts/9227223f6d922fee3c7b190b2cc238a99527bbb7' (2024-07-03)
  → 'github:hercules-ci/flake-parts/8471fe90ad337a8074e957b69ca4d0089218391d' (2024-08-01)
• Updated input 'hydra/nix-eval-jobs/treefmt-nix':
    'github:numtide/treefmt-nix/0fb28f237f83295b4dd05e342f333b447c097398' (2024-07-15)
  → 'github:numtide/treefmt-nix/349de7bc435bdff37785c2466f054ed1766173be' (2024-08-12)
2024-08-25 22:07:24 +02:00
raito 024b431cbc feat(grafana): plug jsonnet-based dashboards in provisioning
Add the gerrit dashboards as an example.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-24 16:32:21 +02:00
raito d1ffce9336 feat(grafana): jsonnet-based dashboards
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-24 16:17:52 +02:00
Ilya K aef541829e Fix pyroscope datasource 2024-08-24 11:39:25 +03:00
raito 1fc15526d7 fix(pyroscope): add the gRPC endpoint as proxy as well
This is not documented but necessary for Alloy to operate.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-24 10:33:49 +02:00
raito 2544adba8e fix(gerrit): setup Alloy & Pyroscope more according to the docs
Still not working due to "unimplemented: error 404 not found" at push
time, but it's really unclear now why this occur.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-24 08:45:20 +02:00
raito 4f4a25a5ad feat(gerrit): push pyroscope profiling to Pyroscope
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 22:37:33 +02:00
raito 702867cd62 feat(pyroscope): add push API & reverse proxy
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 21:04:22 +02:00
raito 7cde6e92ae feat(grafana): add Pyroscope datasource
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 21:04:11 +02:00
raito 42cfa695ea dns: add pyroscope.forkos.org → meta01
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 21:03:07 +02:00
raito ac7815321a feat(pyroscope): add secrets and storage
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 20:58:08 +02:00
raito db46b01ae9 feat(monitoring): add pyroscope to the infrastructure
Vendored for the time being.
See https://cl.forkos.org/c/nixpkgs/+/181 for upstreaming properly.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 20:43:00 +02:00
raito c380f29937 fix(grafana): remove the global pgsql module dependency for now
We should re-introduce it once things are a bit scoped out.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 20:43:00 +02:00
raito 5dc6165c2e feat(gerrit): add git in the environment to perform git-native clones
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 20:43:00 +02:00
raito 0eaaf860d1 feat(common): enable system wide diff in the activation output
This helps me to review what changes could be problematic in advance.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-23 20:43:00 +02:00
raito bf1b8d4d19 secrets: rekey for public01 access to metrics
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-21 16:45:12 +02:00
raito 58c0dd3d2e feat(public): add listmonk instance on news.forkos.org
To prepare for public communications and updates.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-21 16:45:12 +02:00
raito 8c35dfa8e0 fix(gerrit): tinker a bit with gerrit defaults for transfer & caching
We had some issues in the past with too many packfiles and timeout
during transfers, let's try to provide a bit of relief in bad scenarios.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-21 16:31:16 +02:00
Yureka cfc24abfe1 adjust hydra-gc numbers
for the new ssds
2024-08-20 12:08:49 +02:00
Yureka a72a991863 add A record for cache.forkos.org 2024-08-19 23:06:46 +02:00
Pierre Bourdon f938fcb24e
hydra: increase git operations timeout 2024-08-16 17:44:45 +02:00
Pierre Bourdon 6881351f23
build-coord: copy the baremetal-builders DNS64 config 2024-08-16 09:33:48 +02:00
Pierre Bourdon d3e053809c
hydra: log_prefix needs to be / terminated 2024-08-16 09:25:46 +02:00
Pierre Bourdon e2a990c982
hydra: listen on 127.0.0.1 instead of localhost
For some cursed reasons, the latter doesn't work on build-coord:

Aug 16 07:06:22 build-coord hydra-server[109560]: Resolved [localhost]:3000 to [::1]:3000, IPv6
Aug 16 07:06:22 build-coord hydra-server[109560]: Resolved [localhost]:3000 to [127.0.0.1]:3000, IPv4
Aug 16 07:06:22 build-coord hydra-server[109560]: Binding to TCP port 3000 on host ::1 with IPv6
Aug 16 07:06:22 build-coord hydra-server[109560]: Binding to TCP port 3000 on host 127.0.0.1 with IPv4
Aug 16 07:06:22 build-coord hydra-server[109560]: 2024/08/16-07:06:22 Can't connect to TCP port 3000 on 127.0.0.1 [Invalid argument]
2024-08-16 09:20:49 +02:00
Pierre Bourdon 5fdce0e2b5
hydra: move from bagel-box to build-coord 2024-08-16 09:03:29 +02:00
Pierre Bourdon ce3a40671c
acme: make ToS and contact config common 2024-08-16 09:03:08 +02:00
Pierre Bourdon 8ffb7e51f1
tf/gandi: reduce all TTLs from 1h to 5m
Serving DNS is absurdly cheap (and we don't even do it ourselves right
now), and this makes it easier to iterate on DNS configs.
2024-08-16 08:51:31 +02:00
Pierre Bourdon b7d913b22f
tf/gandi: move hydra CNAME to build-coord 2024-08-16 08:50:35 +02:00
Pierre Bourdon c33326f836
hydra: switch to using mTLS instead of local peer auth 2024-08-16 08:19:18 +02:00
Pierre Bourdon 0dd333c573
postgres: add mTLS support
New client certs can be minted via the provided script, which is meant
to be run on the postgres server (where the CA private key is
conveniently deployed).
2024-08-16 07:59:12 +02:00
Pierre Bourdon e7f25d6ee2
tf/gandi: add a postgres CNAME to bagel-box 2024-08-16 07:34:55 +02:00
Pierre Bourdon 29babfc5c4
Revert "Partial revert "Add Grapevine Matrix server and matrix-hookshot""
This reverts commit 17c342b33e.

Grapevine's use of IFD was fixed upstream.
2024-08-15 16:22:22 +02:00
Pierre Bourdon 50fadb45e2
common: define TZ in base server configs, remove heretical host-specific configuration 2024-08-13 22:38:40 +02:00
Pierre Bourdon 37bcb261ab
ssh-keys: add build-coord, rekey secrets 2024-08-13 22:36:30 +02:00
Pierre Bourdon 5dd9ad553c
build-coord: add initial config 2024-08-13 22:36:30 +02:00
raito 3f2909dd8a public-keys: add public01 SSH host key
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-13 19:15:05 +02:00
Pierre Bourdon 90325344a3
Reserve builder-11 for build coordination, rename to build-coord 2024-08-13 19:12:36 +02:00
Pierre Bourdon 5ace7a63d8
forgejo: base on forgejo-lts since forgejo got bumped to a new master in nixpkgs 2024-08-13 01:50:19 +02:00
Pierre Bourdon 434def3337
flake.lock: Update
Flake lock file updates:

• Updated input 'agenix':
    'github:ryantm/agenix/de96bd907d5fbc3b14fc33ad37d1b9a3cb15edc6' (2024-07-09)
  → 'github:ryantm/agenix/f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41' (2024-08-10)
• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=4b107e6ff36bd89958fba36e0fe0340903e7cd13' (2024-07-22)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=f1b552ecbf2d011cd4fdb93d7d117388ab9c0027' (2024-08-12)
• Updated input 'hydra/lix':
    'git+https://git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=6b4d46e9e0e1dd80e0977684ab20d14bcd1a6bc3' (2024-07-16)
  → 'git+https://git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=5137cea99044d54337e439510a647743110b2d7d' (2024-08-10)
• Updated input 'hydra/lix/nix2container':
    'github:nlewo/nix2container/20aad300c925639d5d6cbe30013c8357ce9f2a2e' (2024-04-13)
  → 'github:nlewo/nix2container/3853e5caf9ad24103b13aa6e0e8bcebb47649fe4' (2024-07-10)
• Updated input 'hydra/lix/pre-commit-hooks':
    'github:cachix/git-hooks.nix/e35aed5fda3cc79f88ed7f1795021e559582093a' (2024-04-02)
  → 'github:cachix/git-hooks.nix/f451c19376071a90d8c58ab1a953c6e9840527fd' (2024-07-15)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/9355fa86e6f27422963132c2c9aeedb0fb963d93' (2024-07-16)
  → 'github:NixOS/nixpkgs/154bcb95ad51bc257c2ce4043a725de6ca700ef6' (2024-08-09)
2024-08-13 01:11:38 +02:00
Pierre Bourdon 8b1ade5580
Revert "update hydra"
This reverts commit f7907a2915.

We develop straight on lix-project/hydra, as discussed a few times on
the Lix development channel.
2024-08-13 01:11:31 +02:00
Pierre Bourdon 42b3977e8f
flake: remove an extra nixpkgs lying around 2024-08-13 00:38:51 +02:00
Pierre Bourdon 17c342b33e
Partial revert "Add Grapevine Matrix server and matrix-hookshot"
This partially reverts commit d2f3ca5624.

Said commit requires IFD to eval, which is generally unwanted, and is
currently forbidden on Hydra (imo: rightfully so, we should try to
properly separate evals from builds).

The services/ file for grapevine is kept but will not work without the
flake.nix change reapplied.
2024-08-13 00:35:10 +02:00
Pierre Bourdon ca904d7b4e
tf: use tf.ref instead of config.resource.* when dependencies matter
Using config.resource.* gets interpolated by Nix, whereas tf.ref gets
interpolated by Terraform. The latter ends up generating implicit
dependencies between resources.

In practice, the lack of dependencies was only showing up when creating
a new Hydra project + jobset at the same time - the concurrent /
misordered creation sometimes required two different TF applications to
create first the project then the jobset (the first application would
end up with a failure).
2024-08-12 19:36:50 +02:00
raito 84efd0976d feat(alerts): add a sync failed too often alert
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-09 16:25:34 +02:00
raito e2f5a7b0e4 feat(alerts): add basic postgresql alerts
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-09 16:06:34 +02:00
raito 7388de79c4 feat(alerts): add some basic "host & hardware" alerts
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-08-09 16:06:34 +02:00
Ilya K f8cad42b5c Set up alertmanager-hookshot-adapter 2024-08-09 14:03:56 +00:00
Ilya K 9ad279a505 Set up admins + DNS for hookshot 2024-08-09 14:03:56 +00:00
Ilya K d2f3ca5624 Add Grapevine Matrix server and matrix-hookshot
It doesn't want to work.
2024-08-09 14:03:56 +00:00
Yureka d635042e57 adjust timer for staging sync services 2024-08-08 15:22:44 +02:00
Yureka b6375b8294 add staging sync services 2024-08-08 15:16:04 +02:00
Yureka 420e6915df Vous avez des branches divergentes et vous devez spécifier comment les réconcilier 2024-08-08 10:39:00 +02:00
Yureka dbb4e03292 Revert "builders: direct buildbot to /mnt store via ForceCommand"
This reverts commit dfd48f2179.
2024-08-08 10:37:42 +02:00
Yureka cd0621ba55 builders/netboot: add separate firmware_part output 2024-08-06 13:26:51 +02:00
Yureka dfd48f2179 builders: direct buildbot to /mnt store via ForceCommand 2024-08-06 13:26:35 +02:00
Yureka b1c28cfc7c bagel-cache.s3-web.delroth.net -> cache.forkos.org 2024-08-06 13:26:15 +02:00
Yureka a69750b495 update buildbot-nix 2024-08-06 13:26:01 +02:00
Yureka 77ff556583 builders: fix provisioning of ssh hostkeys 2024-08-05 08:18:20 +02:00
Yureka fe3cb577c1 fix eval 2024-08-05 07:20:59 +02:00
Yureka 20fc4c8f96 builders: move provisioning of ssh hostkeys to a systemd service
at first activation it does not yet have a working network setup
2024-08-05 07:17:45 +02:00
Yureka bce44930b1 builders: provision ssh hostkeys on boot 2024-08-04 18:12:02 +02:00
Yureka 27d66d390e update iusb-spoof and start service on boot 2024-08-03 23:38:21 +02:00
Yureka 79dea0686b add 'notipxe' netboot loader based on systemd-initrd + u-root 2024-08-03 20:28:57 +02:00
Yureka aeb8102ae4 builders: do not mount / and /boot on netboot systems 2024-08-03 20:01:39 +02:00
Yureka 830dcbf6bc builders: do not mount / and /boot on netboot systems 2024-08-03 18:41:01 +02:00
Yureka f7907a2915 update hydra 2024-08-03 18:40:25 +02:00
Yureka 93822775a9 baremetal-builders: do not create swapfile on rootfs when netbooting 2024-08-03 18:10:59 +02:00
Yureka dd028656ac builders: fix serial console 2024-08-02 13:21:04 +02:00
Yureka 88317d099c attempt to fix netboot hydra jobs 2024-08-02 01:05:20 +02:00
Yureka 1cbf286f18 build netboot files from hydra 2024-08-01 22:47:25 +02:00
Yureka 6dc424dd43 wob01: serve an ipxe over iusb-spoof 2024-08-01 22:16:48 +02:00
Yureka 504a443acc adjust hydra-gc numbers
we want to see how garbage collection would behave on a 480GB drive
2024-07-31 23:44:08 +02:00
emily 96d58bbd41
forgejo: disable users explore page
This was requested and should make it a decent bit more difficult to get
a somewhat complete list of users on this instance.

We are, however, aware of other endpoints that can be used to get to a
similar result. Those just aren't as convenient nor obvious.

https://forgejo.org/docs/latest/admin/config-cheat-sheet/#service---explore-serviceexplore
2024-07-31 01:42:05 +02:00
Yureka 5154906aac fix eval in assignments.nix 2024-07-30 17:23:54 +02:00
Yureka f3828368e6 hydra: set reasonable max-jobs and cores 2024-07-30 17:03:12 +02:00
Yureka 314f1cb363 fix buildbot-nix reference
accidentally committed the lockfile which points to my local checkout
2024-07-30 14:02:26 +02:00
Yureka 4e2d21930f baremetal-builders: detect percent_filled for the correct partition 2024-07-30 13:59:46 +02:00
Yureka dd81b78f7a add nixos-main jobset 2024-07-28 23:40:36 +02:00
Yureka 537b3b978c remove yureka-staging-test jobset
I have no idea how, but it seems I accidentally deleted this jobset
2024-07-28 23:39:57 +02:00
Yureka 99259356f2 make buildbot-signing-key accessible to buildbot-worker 2024-07-28 23:30:38 +02:00
Yureka 924b4e7913 flake.lock: Update
Flake lock file updates:

• Updated input 'buildbot-nix':
    'git+file:///home/yuka/proj/buildbot-nix' (2024-07-22)
  → 'git+https://git.lix.systems/lix-project/buildbot-nix.git?ref=refs/heads/non-flakes&rev=8f5ad30cb7df5afbc4df1370a79bf3825c60f8b1' (2024-07-28)
2024-07-28 20:18:36 +02:00
Yureka 5474832b07 baremetal builders: filesystem optimizations 2024-07-28 19:20:23 +02:00
Yureka f737c957a5 add staging next jobsets 2024-07-26 21:17:55 +02:00
Yureka 15a684c5d7 baremetal-builders: more 'intelligent' gc 2024-07-26 12:17:27 +02:00
raito bd8aa2eb08 gerrit01: adjustments for master → main OWS
Due to rename, we need a `mkNixpkgsJob` slightly more complicated.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-25 23:35:06 +02:00
raito 22a10e158f hosts/public01: init
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-25 20:46:20 +02:00
raito b8a4cd928d tf/dns: prepare public01 DNS records
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-25 20:40:17 +02:00
Luke Granger-Brown 7f29885597 flake: support aarch64-linux
...I don't know how to remove the mention of x86_64-linux for colmena,
or if it actually matters, so I'm just leaving that there for now.
2024-07-24 09:37:15 +02:00
Yureka 74e06ac6d0 hydra gc every 20h
metrics analysis has showed that this is unlikely to fill up the builders
2024-07-24 09:35:18 +02:00
hexchen 3ff9d00f7f Add a wrapper to colmena that stops unintended toe-stepping
Taken from lix/web-services, commit hash 6d29ce968e64225faf03450c063d11a0a5c89cac

Co-authored-by: Jade Lovelace <lix@jade.fyi>
2024-07-24 07:25:25 +00:00
raito e5a3ce2283 buildbot fixes (#76)
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
Signed-off-by: Yureka <yureka@forkos.org>
Co-authored-by: raito <raito@noreply.git.lix.systems>
Co-committed-by: raito <raito@noreply.git.lix.systems>
2024-07-24 06:44:25 +00:00
Tom Hubrecht 8390caee53
users: Add thubrecht 2024-07-23 23:14:39 +02:00
hexchen 1b82c2f8fd common/{admin,ssh-keys}: add hexchen 2024-07-23 23:07:12 +02:00
hexchen 26c5e56605 common/{admins,ssh-keys}: sort users 2024-07-23 23:06:17 +02:00
raito 6ad9e0416d tf/dns: cache.forkos.org will be born
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-23 17:28:17 +02:00
Ilya K bebc7f2586 We have nothing to hide 2024-07-23 18:09:49 +03:00
Yureka 297ddbb28c one-way-sync: master -> main 2024-07-23 16:24:36 +02:00
Yureka eedc719889 add one-way-sync jobs for staging branches 2024-07-23 11:15:27 +02:00
Pierre Bourdon d3a8d21429
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=4b886d9c45cd2d7fe9b0a8dbc05c7318d46f615d' (2024-07-22)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=4b107e6ff36bd89958fba36e0fe0340903e7cd13' (2024-07-22)
2024-07-22 23:17:21 +02:00
Pierre Bourdon 608c0e5973
hydra: bump to 16 evaluation workers, we have enough RAM and cores to afford it 2024-07-22 23:13:33 +02:00
Pierre Bourdon 30b05d29f5
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=abc9f11417e2de515006e0fe8dd345f815dc92a7' (2024-07-20)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=4b886d9c45cd2d7fe9b0a8dbc05c7318d46f615d' (2024-07-22)
2024-07-22 22:36:31 +02:00
raito 62ccc0282b fix(ows): per-job runtime directories + proper local refspec
The local refspec was weird and exploiting a edge case for the nixpkgs
jobs where local and from were the same.

We are more explicit now, which fixes the sandbox jobs.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-22 15:41:47 +02:00
Yureka d84a43b781 builders: run gc 3x per day
We can still adjust it if the disks fill up, but currently it is too frequent
2024-07-21 19:49:21 +02:00
Yureka 555728ca0f point k900 experiments jobset at nixos/release.nix 2024-07-21 19:41:17 +02:00
raito 60654e45d9 tf/hydra: use that weird commit for testing purpose
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-21 19:18:42 +02:00
raito 8aa5761660 tf/hydra: add k900 experiment jobset
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-21 19:16:20 +02:00
Yureka 2dc5899660 baremetal: run hydra store gc as builder user 2024-07-20 17:00:39 +02:00
Yureka adaf4b0aef baremetal: tmp on the same filesystem as hydra store 2024-07-20 17:00:39 +02:00
Pierre Bourdon f33d828552
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=9a4a5dd624a1cedc7cdc40687815739b228e5c77' (2024-07-20)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=abc9f11417e2de515006e0fe8dd345f815dc92a7' (2024-07-20)
2024-07-20 16:09:57 +02:00
Yureka 5bde7e2358 use dedicated store partition for hydra builds 2024-07-20 15:14:00 +02:00
Yureka d4f8cb6c87 add jobset for yureka-staging-test 2024-07-20 15:14:00 +02:00
Yureka 95ec496227 bagel-box: bump number of builders to 10 2024-07-20 15:14:00 +02:00
Yureka d9809e1e78 gerrit-one-way-sync: disallow auto-merging a staging iteration into master 2024-07-20 15:14:00 +02:00
Yureka 3fa4a25d87 gerrit-one-way-sync: set git user info 2024-07-20 15:14:00 +02:00
Yureka 0ff5eea4ed gerrit-one-way-sync: merge instead of rebase 2024-07-20 15:14:00 +02:00
Pierre Bourdon 03b53234d3
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=b0e9b4b2f99f9d8f5c4e780e89f955c394b5ced4' (2024-07-17)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=9a4a5dd624a1cedc7cdc40687815739b228e5c77' (2024-07-20)
2024-07-20 13:16:47 +02:00
Yureka 287a9dc400
flake.lock: update invalid buildbot-nix reference 2024-07-20 13:16:47 +02:00
raito 80c4757571 gerrit01: add a one-way-sync service
It's basic and does not handle conflicts which needs to be manually
managed.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-19 17:52:44 +02:00
raito 99649eeb6c hotfix(buildbot): fix local machine parametrization
buildbot-nix was passing the wrong Python structure.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-19 16:05:13 +02:00
Ilya K d1e64b6610 Fix eval warning here too 2024-07-19 12:06:03 +03:00
Ilya K 766dc4c383 Mimir also wants network-online.target
Thank you helpful eval warning
2024-07-19 12:03:55 +03:00
Ilya K 65b07a936b Make sure Mimir starts after network is up 2024-07-19 12:00:52 +03:00
Janik Haag cfa6d79b75
infra: fix warnings 2024-07-19 09:16:15 +02:00
raito cd846260e4 flake: add buildbot jobs entrypoints
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-18 12:18:12 +02:00
raito 8afcf249d6 buildbot: upgrade to local machine specifications
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-18 12:18:02 +02:00
raito 25feb3c9f1 bagel-box: add a proper FQDN
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-18 11:43:05 +02:00
raito 56a04a6faf buildbot: init
Reviewed-on: the-distro/infra#68
2024-07-18 08:57:56 +00:00
raito 4473717e9f gerrit: introduce buildbot checks plugin
It's a modified version of @puck's Lix buildbot checks for
gerrit.lix.systems with a slight generalization in the configuration for
many repositories.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-18 10:56:46 +02:00
raito da7175303c buildbot: add support for remote builders via baremetal machines
For now, only builder-3 is used.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 18:28:26 +02:00
raito e00d0331ec common/known-ssh-keys: init
Let's ensure that all our servers are aware of all host keys to avoid
host key verification issues when needed.

(example: buildbot → gerrit)

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 18:00:51 +02:00
raito a56426e6c9 secrets: rekey for new machine (buildbot)
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 18:00:51 +02:00
raito c3394264ba hosts/buildbot: init
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 18:00:51 +02:00
raito 7789e9ce75 services/buildbot: init
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 18:00:51 +02:00
raito fda59ee6c0 gerrit: factor more configuration in the NixOS module for external consumption
Other modules may require information to configure themselves from the
Gerrit module.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 15:43:35 +02:00
emily cc1e3f2e14
systems/git: make sshd startup less racy and flaky 2024-07-17 15:39:50 +02:00
raito 68d956f1ba flake: add buildbot-nix on the refactor branch
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 14:57:17 +02:00
raito 81fc914d79 feat: change the default shell to zsh
Reviewed-on: the-distro/infra#59
2024-07-17 12:56:45 +00:00
raito 87bd42cf1d tf/dns: pre-add buildbot.forkos.org
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 14:44:18 +02:00
raito 34e8b4b98a tf/dns: rework the forgejo DNS for the 2 servers
git.forkos.org → Forgejo
git.infra.forkos.org → OpenSSH

(with the .p. variants for the IPv4→IPv6 SNI proxies)

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-17 14:44:11 +02:00
Pierre Bourdon 5a05e44a95
tf/hydra: add a project for our hydra fork 2024-07-17 13:34:10 +02:00
Pierre Bourdon 234522cc3b
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=fb9e29d4d0f2f591cd1d706fd3b7334af7d34b84' (2024-07-13)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=b0e9b4b2f99f9d8f5c4e780e89f955c394b5ced4' (2024-07-17)
• Added input 'hydra/lix':
    'git+https://git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=6b4d46e9e0e1dd80e0977684ab20d14bcd1a6bc3' (2024-07-16)
• Added input 'hydra/lix/flake-compat':
    'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33' (2023-10-04)
• Added input 'hydra/lix/nix2container':
    'github:nlewo/nix2container/20aad300c925639d5d6cbe30013c8357ce9f2a2e' (2024-04-13)
• Added input 'hydra/lix/nixpkgs':
    follows 'hydra/nixpkgs'
• Added input 'hydra/lix/nixpkgs-regression':
    'github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2' (2022-01-24)
• Added input 'hydra/lix/pre-commit-hooks':
    'github:cachix/git-hooks.nix/e35aed5fda3cc79f88ed7f1795021e559582093a' (2024-04-02)
• Removed input 'hydra/nix'
• Removed input 'hydra/nix/flake-compat'
• Removed input 'hydra/nix/nix2container'
• Removed input 'hydra/nix/nixpkgs'
• Removed input 'hydra/nix/nixpkgs-regression'
• Removed input 'hydra/nix/pre-commit-hooks'
• Added input 'hydra/nix-eval-jobs':
    'git+https://git.lix.systems/lix-project/nix-eval-jobs?ref=refs/heads/main&rev=c057494450f2d1420726ddb0bab145a5ff4ddfdd' (2024-07-17)
• Added input 'hydra/nix-eval-jobs/flake-parts':
    'github:hercules-ci/flake-parts/9227223f6d922fee3c7b190b2cc238a99527bbb7' (2024-07-03)
• Added input 'hydra/nix-eval-jobs/flake-parts/nixpkgs-lib':
    follows 'hydra/nix-eval-jobs/nixpkgs'
• Added input 'hydra/nix-eval-jobs/lix':
    follows 'hydra/lix'
• Added input 'hydra/nix-eval-jobs/nix-github-actions':
    'github:nix-community/nix-github-actions/622f829f5fe69310a866c8a6cd07e747c44ef820' (2024-07-04)
• Added input 'hydra/nix-eval-jobs/nix-github-actions/nixpkgs':
    follows 'hydra/nix-eval-jobs/nixpkgs'
• Added input 'hydra/nix-eval-jobs/nixpkgs':
    follows 'hydra/nixpkgs'
• Added input 'hydra/nix-eval-jobs/treefmt-nix':
    'github:numtide/treefmt-nix/0fb28f237f83295b4dd05e342f333b447c097398' (2024-07-15)
• Added input 'hydra/nix-eval-jobs/treefmt-nix/nixpkgs':
    follows 'hydra/nix-eval-jobs/nixpkgs'
• Updated input 'lix':
    follows 'hydra/nix'
  → follows 'hydra/lix'
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/6794d064edc69918bb0fc0e0eda33ece324be17a' (2024-07-12)
  → 'github:NixOS/nixpkgs/9355fa86e6f27422963132c2c9aeedb0fb963d93' (2024-07-16)
2024-07-17 13:11:07 +02:00
Luke Granger-Brown c296d0d46d Merge pull request 'forgejo: init, admins: add emilylange' (#62) from forgejo into main
Reviewed-on: the-distro/infra#62
2024-07-16 23:11:55 +00:00
emily 95b58de737
forgejo: use redis as cache and session provider 2024-07-16 20:09:15 +02:00
emily 8b9d33d70c
forgejo: disable registrations, enable auto-registration for SSO 2024-07-16 17:14:23 +02:00
emily ab9caaf520
systems: add git.forkos.org 2024-07-16 15:44:08 +02:00
emily dd069c40d7
forgejo: init service 2024-07-16 15:44:06 +02:00
emily 9899b083ad
forgejo: init custom Forgejo patchset 2024-07-16 15:44:01 +02:00
emily d4caf7b71a
admins: add emilylange 2024-07-16 15:43:58 +02:00
raito 37ec674984 dns: pre-add git.forkos.org
Reserved for a Forgejo instances with Emily's optimizations.
Plans: a mirror, code search and will see how it goes!

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-16 11:54:09 +02:00
Luke Granger-Brown e3e60a5e72 services/monitoring: add scraping of Gerrit's internal metrics 2024-07-15 11:02:54 +00:00
Luke Granger-Brown 2e86babc8a services/gerrit: add metrics-prometheus-exporter 2024-07-15 11:02:54 +00:00
Luke Granger-Brown 2b8f42dcda secrets: add gerrit-prometheus-bearer-token 2024-07-15 11:02:54 +00:00
Luke Granger-Brown f14bba14a3 gitignore: add secrets (but not encrypted secrets) to gitignore 2024-07-15 11:02:54 +00:00
raito 0723b7de42 Merge pull request 'terraform/gandi: more sniproxying for bagel-box,meta-01' (#67) from ckie/moarr-v4 into main
Reviewed-on: the-distro/infra#67
Reviewed-by: raito <raito@noreply.git.lix.systems>
2024-07-14 18:44:21 +00:00
mei (ckie) 3c2691d9e2
terraform/gandi: introduce proxyRecords and proxy web services 2024-07-14 21:39:42 +03:00
Luke Granger-Brown a44196fc3c flake: update nix-gerrit 2024-07-13 18:24:05 +01:00
Ilya K 7a937e837a Unlimit Mimir max series 2024-07-13 15:52:46 +03:00
Pierre Bourdon ecfe0ec886
flake.lock: Update
Flake lock file updates:

• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=05d620a54f38f3764a643d824b55f7790736bb14' (2024-07-13)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=fb9e29d4d0f2f591cd1d706fd3b7334af7d34b84' (2024-07-13)
2024-07-13 06:13:22 +02:00
Pierre Bourdon 7d9461808c
builders: configure a swapfile + zswap 2024-07-13 04:40:51 +02:00
Pierre Bourdon 293bc52ace
hydra: reduce number of parallel builds per builder to limit RAM consumption 2024-07-13 04:38:24 +02:00
Pierre Bourdon 64079be3c0
flake.lock: Update
Flake lock file updates:

• Updated input 'agenix':
    'github:ryantm/agenix/3a56735779db467538fb2e577eda28a9daacaca6' (2024-06-14)
  → 'github:ryantm/agenix/de96bd907d5fbc3b14fc33ad37d1b9a3cb15edc6' (2024-07-09)
• Updated input 'hydra':
    'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=a9a2679793a17325c966dec4cbb27d44b0531694' (2024-06-24)
  → 'git+https://git.lix.systems/lix-project/hydra.git?ref=refs/heads/main&rev=05d620a54f38f3764a643d824b55f7790736bb14' (2024-07-13)
• Updated input 'hydra/nix':
    'git+https://git@git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=4c3d93611f2848c56ebc69c85f2b1e18001ed3c7' (2024-06-24)
  → 'git+https://git@git.lix.systems/lix-project/lix?ref=refs/heads/main&rev=4b109ec1a8fc4550150f56f0f46f2f41d844bda8' (2024-07-11)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/ab82a9612aa45284d4adf69ee81871a389669a9e' (2024-07-07)
  → 'github:NixOS/nixpkgs/6794d064edc69918bb0fc0e0eda33ece324be17a' (2024-07-12)
2024-07-13 03:12:13 +02:00
Janik Haag 9189b73a5f devShell: change colmena to the nixpkgs version
this is done to avoid unnecessarily recompiling colmena
2024-07-13 01:10:59 +00:00
Janik Haag af515792cc admins: add janik 2024-07-13 01:10:39 +00:00
Janik Haag b4deee29af editorconfig: init
Add a barebones `.editorconfig` to at least trim whitspaces and enforce some minimal norms
2024-07-13 01:10:18 +00:00
Pierre Bourdon 756341ea4c
builders: tune sshd MaxStartups to avoid rate limiting Hydra 2024-07-12 21:57:04 +02:00
Janik Haag bed5ef022f
change the default user shell to zsh 2024-07-12 19:50:34 +02:00
Yureka e6ead602f0 builders get a special treatment for dns64 2024-07-11 02:05:58 +02:00
Yureka 329f267b02 enable nftables on all hosts 2024-07-11 02:05:35 +02:00
Yureka b14f155d55 add ipmitool on vpn-gw and builders 2024-07-10 20:49:17 +02:00
Pierre Bourdon c8208f42ef
flake: attempt to fix the hydraJobs definition 2024-07-10 19:03:18 +02:00
Pierre Bourdon 087d17c681
tf/hydra: add a project/jobset for infra machine configurations 2024-07-10 18:52:43 +02:00
Pierre Bourdon d2336262fb
hydra: set allowed URIs in restricted mode for flake inputs 2024-07-10 18:52:22 +02:00
Pierre Bourdon f35cfbd567
flake: configure some hydra jobs (all machine configurations) 2024-07-10 18:43:54 +02:00
Pierre Bourdon 58325e30dd
common/nix: use bagel-cache by default 2024-07-10 18:17:30 +02:00
Pierre Bourdon 411d514ab9
hydra: user hydra-www needs nix-daemon access too 2024-07-10 17:36:39 +02:00
Pierre Bourdon f74d1ca0f6
hydra: start signing paths 2024-07-10 17:34:57 +02:00
Pierre Bourdon 70e608a8f7
common: provide a pinned nixpkgs on all infra machines 2024-07-10 17:17:18 +02:00
Yureka 4e869a9f43 fix bmc dhcp 2024-07-10 15:54:46 +02:00
Yureka 3cbdbc45f7 more quality of life improvements... 2024-07-10 15:54:30 +02:00
Yureka 7ba42d99d1 reduce hydra builders to 4 2024-07-10 15:08:28 +02:00
Ilya K 254e161c07 Give wob-vpn-gw a proper hostname 2024-07-10 15:34:05 +03:00
Ilya K a9f45daac8 Rename machine folders, clean up flake 2024-07-10 15:24:47 +03:00
Ilya K 787b3af638 Add wob-vpn-gw key, rekey metrics push password for it 2024-07-10 15:13:05 +03:00
Ilya K e608b92e4f Add htop and btop to default machine config 2024-07-10 15:01:09 +03:00
Ilya K e84b362b7a Allow 12 hour of backfill for metrics
This is somewhat experimental and may explode, but we'll see, I guess
2024-07-10 14:59:09 +03:00
Ilya K 9e7e6d42ab Make nginx/loki/mimir go fast 2024-07-10 14:55:28 +03:00
Pierre Bourdon f2c2bc5ab6
hydra: output machine host key as base64 in the generated machines.conf 2024-07-10 02:16:45 +02:00
Pierre Bourdon f214da9228
hydra: add hydra to nix trusted-users 2024-07-10 02:03:33 +02:00
Pierre Bourdon 0e24c18815
tf/hydra: add a test staging-small nixpkgs jobset 2024-07-10 01:57:12 +02:00
Pierre Bourdon 2ac0a599fb
bagel-box: fix missing toString 2024-07-10 01:51:31 +02:00
raito 0ccf0b023e Merge pull request 'hydra: moar power' (#51) from moar-builders into main
Reviewed-on: the-distro/infra#51
Reviewed-by: Luke Granger-Brown <lukegb@noreply.git.lix.systems>
2024-07-09 23:32:38 +00:00
Luke Granger-Brown 82db8f7f1e gerrit01: some more tuning
* flip off proxy_buffering again
* enable REVWALK_USE_PRIORITY_QUEUE
* enable delta compression, because that's not a bottleneck and it's
  nicer on bandwidth
2024-07-10 00:27:36 +01:00
raito 7b7a645cfc hydra: moar power
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 01:27:35 +02:00
Yureka 39d2352bbc general quality of life improvements 2024-07-09 23:26:12 +00:00
Yureka a7d21e96a0 add global hardening options 2024-07-09 23:26:12 +00:00
raito c51676a560 Merge pull request 'hydra: unplug the EPYC' (#49) from unplug-epyc into main
Reviewed-on: the-distro/infra#49
2024-07-09 23:26:08 +00:00
raito 9988811be5 hydra: unplug the EPYC
thank you for your testing services

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 01:13:10 +02:00
Pierre Bourdon afaf49eb97
secrets: rekey 2024-07-10 01:05:05 +02:00
Pierre Bourdon bc8ef7b5fc
ssh-keys: remove raito's key which is too NSA'd for agenix 2024-07-10 01:04:48 +02:00
Pierre Bourdon 61e8048445
sysadmin: remove pwru, does not build on latest nixpkgs 2024-07-10 01:01:27 +02:00
Pierre Bourdon 2ebb0e82e8
flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/9693852a2070b398ee123a329e68f0dab5526681' (2024-06-22)
  → 'github:NixOS/nixpkgs/ab82a9612aa45284d4adf69ee81871a389669a9e' (2024-07-07)
2024-07-10 01:01:17 +02:00
raito 664fa033aa Merge pull request 'hydra: wire up new builders' (#47) from hydra-wire-up into main
Reviewed-on: the-distro/infra#47
2024-07-09 23:00:27 +00:00
raito 2308870aa5 builders: add a nice tag to deploy all of them at once
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 00:59:31 +02:00
raito f9f955214f ssh-keys: add raito to secrets set
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 00:59:22 +02:00
raito 90e54d7292 terraform: add DNS records for VPN-GW & builders
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 00:55:42 +02:00
raito 645ad7d062 builders: add builder user
currently hardcoded to hydra's coordinator public key

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 00:55:25 +02:00
raito a30c1f7d78 hydra: wire up new builders
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-10 00:45:02 +02:00
Yureka eb21cb6916 add baremetal builders 2024-07-10 00:35:01 +02:00
Yureka 62af42fc97 init wob-vpn-gw host 2024-07-09 23:42:20 +02:00
Yureka 7396107bf4 add a shim to provide nixosConfigurations from colmena hive 2024-07-09 10:49:29 +02:00
Yureka c0e1d05b3c admins: add yuka 2024-07-09 10:34:30 +02:00
raito 3828721e4f services/netbox: enable OIDC via Lix SSO
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-09 02:45:58 +02:00
Luke Granger-Brown 8a9ff8c40d services/gerrit: migrate to Gerrit from the-distro/nix-gerrit flake 2024-07-08 23:30:59 +01:00
raito 48579e8818 feat: add gdb to sysadmin tooling
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-08 22:10:06 +00:00
raito 8fe33b4e46 feat: add perf, pwru and various sysadmin tools to bagel-box
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-08 22:10:06 +00:00
Luke Granger-Brown d4e9dcc2a6 admins: provision lukegb
hello I can be trusted with your infrastructure
2024-07-08 21:55:41 +00:00
Pierre Bourdon 7f46e5d9a4
services: add ofborg, currently running rabbitmq only 2024-07-08 23:55:11 +02:00
raito 512cfdb43e fix: downgrade mina sshd due to broken PQC algorithm
https://cl.tvl.fyi/c/depot/+/11965

This breaks it with "ssh_dispatch_run_fatal: Connection to
2a01:4f8:242:5b21:0:feed:edef:beef port 29418: incorrect signature"

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-08 15:59:31 +02:00
raito 82395ec8ce Merge pull request 'pkgs/gerrit: update to 3.10.0' (#34) from upgrade-gerrit-differently into main
Reviewed-on: the-distro/bagel-infra#34
2024-07-08 12:21:21 +00:00
Ilya K 82e074881f DNS: clean up a bit, add root level record for future Matrix shenanigans 2024-07-08 13:54:15 +03:00
Ilya K b55475c12e Fix up the rest of the dashboards 2024-07-08 11:43:57 +03:00
Ilya K 9f0e601d84 Scrape grafana/loki/mimir own metrics 2024-07-08 10:25:15 +03:00
Ilya K 209f71c63a Update node_exporter dashboard for new metrics structure 2024-07-08 10:16:37 +03:00
Ilya K 563e0685d4 Metrics fixups
- fix grafana-agent config format
- rekey metrics-push-password for fodwatch
2024-07-08 10:01:25 +03:00
emily 8d2a367e92 grafana-agent: make bagel.monitoring.grafana-agent.exporters an attrset
This allows us to use multiple jobs, one for each additional exporter,
and set their `job_name` accordingly.

`job_name` is exported as `job` label on the resulting metrics.
This allows us to quickly get an understanding what metrics of an
exporter are actually available by simply filtering all metrics by
`{job="$jobname"}`
2024-07-08 09:34:26 +03:00
emily db8c831c2f grafana-agent: set hostname label on all metrics
This is handy to quickly see all metrics exported by a node, without
having to mangle with the already existing `instance` label.

`hostname` is essentially a variant of `instance` but without ports.
2024-07-08 09:34:26 +03:00
Ilya K ba0d50624d Switch to push metrics with Grafana Agent 2024-07-08 09:34:24 +03:00
Ilya K 40ba3c4ae7 Prepare for remote push metrics 2024-07-08 09:33:59 +03:00
Ilya K 346a74eabc Wire up Grafana to Alertmanager 2024-07-08 09:33:59 +03:00
Ilya K e8e262c6a4 Enable Mimir Alertmanager, add example alert
Still TODO: actually connect it to Matrix
2024-07-08 09:33:59 +03:00
Luke Granger-Brown dd6ee53bfe pkgs/gerrit: update to 3.10.0
This does a bit more than advertised, since this also switches to a
different set of Bazel package building infrastructure that I'm hoping
will be more extensible than buildBazelPackage as it exists in nixpkgs
today.

In any case, the FOD here _seems_ to be much more stable than that
previously produced by the old approach, but no promises :)
2024-07-08 02:44:05 +01:00
Pierre Bourdon 5ebd71e4d5
tf/hydra: change Hydra URL 2024-07-08 00:01:24 +02:00
Pierre Bourdon 2700ac5efc
tf/dns: fix hydra CNAME 2024-07-08 00:01:14 +02:00
Pierre Bourdon caa1fce74e
hydra: move to hydra.forkos.org 2024-07-07 23:53:21 +02:00
Pierre Bourdon 5f8228536c
bagel-box: switch to forkos.org DNS root 2024-07-07 23:52:40 +02:00
Pierre Bourdon 078f298b8c
tf/dns: add bagel-box and hydra 2024-07-07 23:48:23 +02:00
Pierre Bourdon 4b0a2cd7e5
tf: add DNS management via Gandi 2024-07-07 20:43:05 +02:00
Pierre Bourdon dcd5f68545
tf: store hydra credentials in state via numtide/secret 2024-07-07 19:18:30 +02:00
Pierre Bourdon 7c6780a2a3
gitignore: add terraform lock file 2024-07-07 19:18:30 +02:00
Pierre Bourdon dd72904bf1
flake: replace tf wrappers with a single '.#tf' command 2024-07-07 19:18:30 +02:00
Pierre Bourdon 2e9483936e
tf/hydra: fix project owner to use an automation account 2024-07-07 18:44:17 +02:00
Pierre Bourdon 30859b2872
terraform: store state on S3 2024-07-07 18:22:41 +02:00
Pierre Bourdon 0c68a23275
flake: fix 'nix flake check' 2024-07-07 18:02:55 +02:00
raito 8dc7ee9864
hydra: add declarative controls via terranix
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-07 17:59:56 +02:00
raito e803c198c1 admins: provision jade
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-07 13:15:27 +00:00
raito 578e24e634 systems: add fodwatch.forkos.org
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-07-07 13:15:27 +00:00
raito e1a034927c Merge pull request 'Split node_exporter and cadvisor config, disable cadvisor for nodes that are themselves containers' (#25) from cadvisor-containers into main
Reviewed-on: delroth/bagel-infra#25
Reviewed-by: raito <raito@noreply.git.lix.systems>
2024-07-05 17:21:27 +00:00
Ilya K 5b0f3c4541 Split node_exporter and cadvisor config, disable cadvisor for nodes that are themselves containers 2024-07-05 20:06:43 +03:00
174 changed files with 14811 additions and 9905 deletions

7
.editorconfig Normal file
View file

@ -0,0 +1,7 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

6
.gitignore vendored
View file

@ -1,4 +1,8 @@
result
.gcroots
config.tf.json
.direnv
.direnv
.terraform
.terraform.lock.hcl
secrets/*
!secrets/*.age

View file

@ -1 +1,32 @@
Infrastructure for the donut shaped thing that is absolutely not a donut.
# Infrastructure for the donut shaped thing that is absolutely not a donut.
## Quick start
### Build the infrastructure
```
$ colmena build --on @localboot
```
Notice that `@localboot` is load-bearing as we have some machines that _cannot be_ deployed with vanilla Colmena. Fixing this is welcome.
### Recommended deploy process
```
$ colmena apply dry-activate $machine # Verify that the nvd log is reasonable.
$ colmena apply $machine
```
### Recommended upgrade process
```
$ nix flake update
$ colmena apply dry-activate --on @localboot # Verify that the nvd log is reasonable. Run it twice to get only NVD logs shown.
$ colmena apply --on @localboot
```
## Troubleshooting
### I failed to deploy `gerrit01`
Our Gerrit source build is known to have some hiccups sometimes, we are always interested in build logs, feel free to attach information in a new issue so we can make it more reliable.

View file

@ -1,16 +1,45 @@
{ lib, ... }:
let
keys = import ./ssh-keys.nix;
in {
users.users.root.openssh.authorizedKeys.keys =
keys.users.delroth ++
keys.users.k900 ++
keys.users.raito ++
keys.users.maxine ++
[
# more raito
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU"
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJFsZ7PMDt80tYXHyScQajNhqH4wuYg/o0OxfOHaZD4rXuT0VIKflKH1M9LslfHWIEH3XNeqhQOziH9r+Ny5JcM="
inherit (lib) genAttrs;
in
# Note: to add somefew in this list.
# Ensure their SSH key is already in common/ssh-keys.nix with
# the same username for here, so that the keys is automatically added.
{
bagel.groups = {
floral-infra.members = [
"delroth"
"emilylange"
"hexchen"
"jade"
"janik"
"k900"
"maxine"
"raito"
"thubrecht"
"winter"
"yuka"
"ckie"
];
lix-infra.members = [
"raito"
"hexchen"
"jade"
];
};
bagel.users = genAttrs [
"delroth"
"emilylange"
"hexchen"
"jade"
"janik"
"k900"
"maxine"
"raito"
"thubrecht"
"winter"
"yuka"
"ckie"
] (name: {});
}

View file

@ -1,9 +1,15 @@
{ lib, pkgs, ... }: {
imports = [
./known-ssh-keys.nix
./cgroups.nix
];
nixpkgs.overlays = import ../overlays;
nix.package = lib.mkDefault pkgs.lix;
services.openssh.enable = lib.mkForce true;
networking.nftables.enable = true;
networking.firewall.enable = true;
networking.firewall.logRefusedConnections = false;
networking.firewall.logReversePathDrops = true;
@ -13,12 +19,56 @@
recommendedTlsSettings = lib.mkDefault true;
recommendedProxySettings = lib.mkDefault true;
recommendedGzipSettings = lib.mkDefault true;
eventsConfig = ''
worker_connections 8192;
'';
appendConfig = ''
worker_rlimit_nofile 16384;
'';
};
nix.gc = {
automatic = true;
persistent = true;
dates = "daily";
options = "--delete-older-than 30d";
dates = lib.mkDefault "daily";
options = lib.mkDefault "--delete-older-than 30d";
};
services.journald.extraConfig = "SystemMaxUse=512M";
boot.kernelParams = [
"panic=30" "boot.panic_on_fail"
];
boot.kernel.sysctl = {
# Set default TCP congestion control algorithm
"net.ipv4.tcp_congestion_control" = "bbr";
# Enable ECN
"net.ipv4.tcp_ecn" = 1;
# Enable TCP fast open
"net.ipv4.tcp_fastopen" = 3;
};
# reduce closure size, feel free to add your locale here
i18n.supportedLocales = [
"en_US.UTF-8/UTF-8"
"fr_FR.UTF-8/UTF-8"
];
time.timeZone = "UTC";
security.acme.acceptTerms = true;
security.acme.defaults.email = "infra@forkos.org";
# Enable system diffs.
system.activationScripts.system-diff = {
supportsDryActivation = true; # safe: only outputs to stdout
text = ''
if [ -e /run/current-system ]; then
PATH=$PATH:${pkgs.nix}/bin ${pkgs.nvd}/bin/nvd diff /run/current-system $systemConfig
fi
'';
};
}

83
common/cgroups.nix Normal file
View file

@ -0,0 +1,83 @@
# Relatively inspired by fbtax2:
# https://facebookmicrosites.github.io/cgroup2/docs/fbtax-results.html
#
# See also the Chris Down talk at LISA'21:
# https://www.usenix.org/conference/lisa21/presentation/down
{ ... }:
let
systemCriticalSliceConfig = {
ManagedOOMMemoryPressure = "kill";
# guarantee availability of memory
MemoryMin = "192M";
# default 100
IOWeight = 1000;
# default 100
CPUWeight = 1000;
};
in
{
systemd.oomd = {
enable = true;
# why not, we have cgroups at user level now so it'll just kill the
# terminal
enableRootSlice = true;
enableSystemSlice = true;
enableUserSlices = true;
};
systemd.enableCgroupAccounting = true;
systemd.services.nix-daemon = {
serviceConfig = {
# FIXME: how do i deprioritize this for memory
CPUWeight = 10;
IOWeight = 10;
};
};
systemd.slices.hostcritical = {
description = "Ensures that services to keep the system alive remain alive";
unitConfig = {
# required to avoid a dependency cycle on systemd-oomd. systemd will
# actually guess this right but we should fix it anyway.
DefaultDependencies = false;
};
sliceConfig = systemCriticalSliceConfig;
};
# make root logins higher priority for resources
systemd.slices."user-0" = {
sliceConfig = systemCriticalSliceConfig;
};
systemd.slices.system = {
sliceConfig = {
ManagedOOMMemoryPressure = "kill";
ManagedOOMMemoryPressureLimit = "50%";
IOWeight = 100;
};
};
systemd.services.sshd = {
serviceConfig = {
Slice = "hostcritical.slice";
};
};
systemd.services.systemd-oomd = {
serviceConfig = {
Slice = "hostcritical.slice";
};
};
systemd.services.systemd-journald = {
serviceConfig = {
Slice = "hostcritical.slice";
};
};
}

32
common/channels.nix Normal file
View file

@ -0,0 +1,32 @@
# Taken from https://github.com/NixOS/infra/blob/master/channels.nix
{
# "Channel name" = {
# # This should be the <value> part of
# # https://hydra.forkos.org/job/<value>/latest-finished
# job = "project/jobset/jobname";
#
# # When adding a new version, determine if it needs to be tagged as a
# # variant -- for example:
# # nixos-xx.xx => primary
# # nixos-xx.xx-small => small
# # nixos-xx.xx-darwin => darwin
# # nixos-xx.xx-aarch64 => aarch64
# variant = "primary";
#
# # Channel Status:
# # '*-unstable' channels are always "rolling"
# # Otherwise a release generally progresses through the following phases:
# #
# # - Directly after branch off => "beta"
# # - Once the channel is released => "stable"
# # - Once the next channel is released => "deprecated"
# # - N months after the next channel is released => "unmaintained"
# # (check the release notes for when this should happen)
# status = "beta";
# };
"forkos-unstable" = {
job = "forkos/nixos-main/tested";
variant = "primary";
status = "rolling";
};
}

View file

@ -1,9 +1,14 @@
{
imports = [
./admins.nix
./raito-vm.nix
./raito-proxy-aware-nginx.nix
./server-acl.nix
./base-server.nix
./hardening.nix
./nix.nix
./raito-proxy-aware-nginx.nix
./sysadmin
./hardware
./zsh.nix
./secrets.nix
];
}

23
common/hardening.nix Normal file
View file

@ -0,0 +1,23 @@
{ config, lib, ... }:
{
nix.settings.allowed-users = [ "root" ];
boot.specialFileSystems = lib.mkIf (!config.security.rtkit.enable && !config.security.polkit.enable) {
"/proc".options = [ "hidepid=2" ];
};
boot.kernel.sysctl."kernel.dmesg_restrict" = 1;
services.openssh = {
settings.PasswordAuthentication = false;
settings.KbdInteractiveAuthentication = false;
# prevents mutable /home/$user/.ssh/authorized_keys from being loaded to ensure that all user keys are config managed
authorizedKeysFiles = lib.mkForce [
"/etc/ssh/authorized_keys.d/%u"
];
};
users.mutableUsers = false;
}

View file

@ -0,0 +1,7 @@
{ ... }: {
imports = [
./raito-vm.nix
./oracle-vm.nix
./hetzner.nix
];
}

View file

@ -0,0 +1,76 @@
{ lib, config, ... }:
let
cfg = config.bagel.hardware.hetzner;
inherit (lib) mkEnableOption mkIf mkOption types;
in
{
options.bagel.hardware.hetzner = {
enable = mkEnableOption "Hetzner's hardware defaults";
platformType = mkOption {
# Only VMs are supported.
type = types.enum [ "virtual-machine" ];
};
system = mkOption {
# Only the aarch64-linux VM Hetzner is supported.
type = types.enum [ "aarch64-linux" ];
};
networking.wan = {
mac = mkOption {
type = types.str;
description = "MAC address of the WAN interface in the Hetzner machine";
};
address = mkOption {
type = types.listOf types.str;
description = "List of static addresses attached to the WAN interface";
};
};
};
config = mkIf cfg.enable {
# A bunch of stuff is virtio.
boot.initrd.availableKernelModules = [
"xhci_pci"
"usbhid"
"sr_mod"
"virtio_gpu"
"virtio_scsi"
"virtio_rng"
"virtio_pci"
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.useDHCP = lib.mkDefault false;
# Stolen from the netplan provided by aarch64 Ubuntu images.
systemd.network.enable = true;
systemd.network.links."10-wan" = {
linkConfig.Name = "wan";
matchConfig.MACAddress = cfg.networking.mac;
};
systemd.network.networks."10-wan" = {
matchConfig.Name = "wan";
networkingConfig.Address = cfg.networking.address;
linkConfig.RequiredForOnline = true;
DHCP = "ipv4";
routes = [
{
routeConfig = {
Destination = "::/0";
GatewayOnLink = true;
Gateway = "fe80::1";
};
}
];
dhcpV4Config = {
RouteMetric = 100;
UseMTU = true;
};
};
};
}

View file

@ -0,0 +1,52 @@
{ lib, config, modulesPath, ... }:
let
cfg = config.bagel.hardware.oracle-vm;
inherit (lib) mkEnableOption mkIf mkOption types;
in
{
options.bagel.hardware.oracle-vm = {
enable = mkEnableOption "Oracle's VM hardware defaults";
system = mkOption {
# Only the free Oracle VMs are supported.
type = types.enum [ "aarch64-linux" ];
};
};
# Imports a bunch of virtio modules.
imports = [
"${modulesPath}/profiles/qemu-guest.nix"
];
config = mkIf cfg.enable {
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.systemd.enable = true;
boot.initrd.availableKernelModules = [
"xhci_pci" "virtio_pci" "usbhid" "sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
nixpkgs.hostPlatform = cfg.system;
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault false;
# Examples:
# 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
# link/ether 02:00:17:00:91:6e brd ff:ff:ff:ff:ff:ff
# inet 10.0.0.94/24 brd 10.0.0.255 scope global dynamic noprefixroute enp0s3
# valid_lft 44162sec preferred_lft 33362sec
# inet6 fe80::17ff:fe00:916e/64 scope link
# valid_lft forever preferred_lft forever
# [root@build02-aarch64-lahfa:~]# ip r
# default via 10.0.0.1 dev enp0s3 proto dhcp src 10.0.0.94 metric 1002 mtu 9000
networking.interfaces.enp0s3.useDHCP = lib.mkDefault true;
};
}

View file

@ -30,8 +30,6 @@ in
config = mkIf cfg.enable {
services.qemuGuest.enable = true;
systemd.network.enable = true;
security.acme.defaults.email = "bagel-acme@lahfa.xyz";
security.acme.acceptTerms = true;
networking.useDHCP = lib.mkDefault false;
systemd.network.networks."10-nat-lan" = {

View file

@ -0,0 +1,7 @@
{ ... }:
{
programs.ssh.knownHosts = {
"[cl.forkos.org]:29418".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM82mJ259C8Nc+BHHNBeRWXWhL3dfirQhmFbDAwHMle3";
"[gerrit.lix.systems]:2022".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICC/S6Z56uhv7zBMutkV0nU8eDuRcl3trykGWBch4L/l";
};
}

21
common/nix.nix Normal file
View file

@ -0,0 +1,21 @@
{ lib, pkgs, ... }:
{
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
# Provision a useful nixpkgs in NIX_PATH and flake registry on infra
# machines.
nixpkgs.flake = {
source = lib.cleanSource pkgs.path;
setNixPath = true;
setFlakeRegistry = true;
};
# Use our cache and trust its signing key. Still use cache.nixos.org as
# fallback.
nix.settings.substituters = [ "https://cache.forkos.org/" ];
nix.settings.trusted-public-keys = [
"cache.forkos.org:xfXIUJO1yiEITJmYsVmNDa9BFSlgTh/YqZ+4ei1EhQg="
];
}

View file

@ -1,9 +1,10 @@
# This enables an IPv6-only server which is proxied by kurisu.lahfa.xyz to have proper IPv4 logs via PROXY protocol.
{ config, lib, ... }:
let
inherit (lib) mkEnableOption mkIf;
inherit (lib) mkEnableOption mkIf concatStringsSep;
cfg = config.bagel.raito.v6-proxy-awareness;
allowedUpstream = "2001:bc8:38ee:99::1/128";
# outside of raito infra inside of raito infra
allowedUpstreams = [ "2001:bc8:38ee::1/128" "2001:bc8:38ee:99::1/128" ];
in
{
options.bagel.raito.v6-proxy-awareness.enable = mkEnableOption "the kurisu.lahfa.xyz's sniproxy awareness for NGINX";
@ -20,8 +21,8 @@ in
];
appendHttpConfig = ''
# Kurisu node
set_real_ip_from ${allowedUpstream};
# Kurisu nodes
${concatStringsSep "\n" (map (up: "set_real_ip_from ${up};") allowedUpstreams)}
real_ip_header proxy_protocol;
'';
};
@ -29,7 +30,7 @@ in
# Move to nftables if firewall is enabled.
networking.nftables.enable = true;
networking.firewall.extraInputRules = ''
ip6 saddr ${allowedUpstream} tcp dport 444 accept
${concatStringsSep "\n" (map (up: "ip6 saddr ${up} tcp dport 444 accept") allowedUpstreams)}
'';
};
}

22
common/secrets.nix Normal file
View file

@ -0,0 +1,22 @@
## This is a simple secret abstraction with multi-tenancy awareness.
{ config, lib, ... }:
let
cfg = config.bagel.secrets;
inherit (lib) mkOption types genAttrs;
in
{
options.bagel.secrets = {
tenant = mkOption {
type = types.enum [ "lix" "floral" ];
};
files = mkOption {
type = types.listOf types.str;
default = [ ];
};
};
config.age.secrets = genAttrs cfg.files (secretFile: {
file = ../secrets/${cfg.tenant}/${secretFile}.age;
});
}

69
common/server-acl.nix Normal file
View file

@ -0,0 +1,69 @@
{ lib, config, ... }:
let
keys = import ./ssh-keys.nix;
inherit (lib) mkOption types length concatMap listToAttrs catAttrs attrValues;
cfgAdmins = config.bagel.admins;
cfgGroups = config.bagel.groups;
cfgUsers = config.bagel.users;
userOpts = { name, ... }: {
options = {
sshKeys = mkOption {
type = types.listOf types.str;
description = "List of SSH keys associated to this user, defaults to `ssh-keys.nix` entries.";
default = keys.users.${name} or [ ];
};
};
};
groupOpts = { name, ... }: {
options = {
members = mkOption {
type = types.listOf types.str;
description = "List of users member of this group";
example = [ "raito" ];
default = [ ];
};
};
};
# There might be duplicate in that list. We will turn it into an attribute set.
allowedMembers = listToAttrs (
map (member: {
name = member;
value = cfgUsers.${member};
}) (concatMap (allowedGroup: cfgGroups.${allowedGroup}.members) cfgAdmins.allowedGroups));
rootKeys = concatMap ({ sshKeys, ... }: sshKeys) (attrValues allowedMembers);
in
{
options.bagel.users = mkOption {
type = types.attrsOf (types.submodule userOpts);
description = "User configuration for server ACLs";
};
options.bagel.groups = mkOption {
type = types.attrsOf (types.submodule groupOpts);
description = "Group configuration for server ACLs";
};
options.bagel.admins = {
allowedGroups = mkOption {
type = types.listOf types.str;
default = [ "catch-all" ];
description = "List of groups which are allowed to admin this machine.";
example = [ "lix" "build-infra" ];
};
};
config = {
assertions = [
{ assertion = length config.users.users.root.openssh.authorizedKeys.keys > 0;
# TODO: you can add printing of `concatStringsSep ", " cfg.allowedGroups` to diagnose
# which are the allowed groups and existing admins.
message = "root@${config.networking.fqdnOrHostName} has no SSH key attached, this machine will lose its access if you deploy it successfully! Set a valid `bagel.admins.allowedGroups` or ensure you have at least one administrator of the relevant group registered";
}
];
users.users.root.openssh.authorizedKeys.keys = rootKeys;
};
}

View file

@ -1,14 +1,68 @@
{
machines = {
# Floral
bagel-box = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAsO4bNqY04uG13Pg3ubHfRDssTphDLzZ4YUniE5/p+M";
meta01 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5t9gYorOWgpCFDJgb24pyCKIabGpeI2H/UfdvXODcT";
public01 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPBy8G8rfLA6E9i+t5kjVafxU1c2NXATXKxoXTH4Kgtm";
gerrit01 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA+eSZu+u9sCynrMlsmFzQHLIELQAuVg0Cs1pBvwb4+A";
fodwatch = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFRyTNfvKl5FcSyzGzw+h+bNFNOxdhvI67WdUZ2iIJ1L";
buildbot = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJgIu6ouagYqBeMLfmn1CbaDJMuZcPH9bnUhkht8GfuB";
git = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQJcpkCUOx8+5oukMX6lxrYcIX8FyHu8Mc/3+ieKMUn";
build-coord = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpAEJP7F+XtJBpQP1jTzwXwQgJrFxwEJjPf/rnCXkJA";
builder-0 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBHSNcDGctvlG6BHcJuYIzW9WsBJsts2vpwSketsbXoL";
builder-1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIQOGUjERK7Mx8UPM/rbOdMqVyn1sbWqYOG6CbOzH2wm";
builder-2 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMKzXIqCoYElEKIYgjbSpqEcDeOvV+Wo3Agq3jba83cB";
builder-3 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGq0A5233XGt34T097KaEKBUqFvaa7a6nYZRsSO0166l";
builder-4 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB9dVo2xZhgIMDgB1rUj5ApmppL39BtYu/+OFHeduvXr";
builder-5 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE7vZTBxrVHmHpv7slQ8A8XwjjbfN+ZJA0V5C3k0wNBD";
builder-6 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOt1qR/2BRtc6PABuSBulowwJVO6wBNDyEFzh0qsTeOF";
builder-7 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFinAAw1v8TJB8/wcmTVBbHHc4LCYh6z4TO6ViwUPkoh";
builder-8 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKGSWHNeqT0kF/e4yVy2ieW98X5QMyCYIYZh9WTmQDs1";
builder-9 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOhws9zGgocVY36dMtOL+CXadpvRMffxoWMkfEcTBJm7";
builder-10 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE7sgIuTSqZiZhp8TvObSbIEhcHHsL5hcmYA22uzwxth";
wob-vpn-gw = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINVytPPW8XnXf/rD5TFzsw//CZc2lBjQLmDzlVGPZsjh";
# Lix
build01-aarch64-lix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICC69NZD/zhIB/wUb5odg46bss5g8hH2fDl22bk4qeSW";
build02-aarch64-lix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGdJE375pe58RJbhKwXRp3D//+SJ3ssiVZrLsM9CLHn0";
build01-aarch64-darwin-lix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVf1uO0lv5UBti/naW/+amqLxvWZg+StXk9aM+lJ7e4";
buildbot-lix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFoVSh35UqNQZ6ZZ1c6CzqERC40ovQ/KDXz8pC7nNlkR";
# Raito infrastructure
epyc-newtype-fr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOXT9Init1MhKt4rjBANLq0t0bPww/WQZ96uB4AEDrml";
};
users = {
delroth = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3tjB4KYDok3KlWxdBp/yEmqhhmybd+w0VO4xUwLKKV" ];
raito = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaw9ihTG7ucB8P38XdalEWev8+q96e2yNm4B+/I9IJp" ];
emilylange = [ "no-touch-required sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIL7jgq3i+N3gVJhs4shm7Kmw6dIocs2OuR0GBMG1RxfKAAAABHNzaDo=" ];
hexchen = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINJ0tCxsEilAzV6LaNpUpcjzyEn4ptw8kFz3R+Z3YjEF hexchen@backup"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDI3T1eFS77URHZ/HVWkMOqx7W1U54zJtn9C7QWsHOtyH72i/4EVj8SxYqLllElh1kuKUXSUipPeEzVsipFVvfH0wEuTDgFffiSQ3a8lfUgdEBuoySwceEoPgc5deapkOmiDIDeeWlrRe3nqspLRrSWU1DirMxoFPbwqJXRvpl6qJPxRg+2IolDcXlZ6yxB4Vv48vzRfVzZNUz7Pjmy2ebU8PbDoFWL/S3m7yOzQpv3L7KYBz7+rkjuF3AU2vy6CAfIySkVpspZZLtkTGCIJF228ev0e8NvhuN6ZnjzXxVTQOy32HCdPdbBbicu0uHfZ5O7JX9DjGd8kk1r2dnZwwy/ hexchen@yubi5"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4CLJ+mFfq5XiBXROKewmN9WYmj+79bj/AoaR6Iud2pirulot3tkrrLe2cMjiNWFX8CGVqrsAELKUA8EyUTJfStlcTE0/QNESTRmdDaC+lZL41pWUO9KOiD6/0axAhHXrSJ0ScvbqtD0CtpnCKKxtuOflVPoUGZsH9cLKJNRKfEka0H0GgeKb5Tp618R/WNAQOwaCcXzg/nG4Bgv3gJW4Nm9IKy/MwRZqtILi8Mtd+2diTqpMwyNRmbenmRHCQ1vRw46joYkledVqrmSlfSMFgIHI1zRSBXb/JkG2IvIyB5TGbTkC4N2fqJNpH8wnCKuOvs46xmgdiRA26P48C2em3 hexchen@yubi5c"
];
jade = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNldAg4t13/i69TD786The+U3wbiNUdW2Kc9KNWvEhgpf4y4x4Sft0oYfkPw5cjX4H3APqfD+b7ItAG0GCbwHw6KMYPoVMNK08zBMJUqt1XExbqGeFLqBaeqDsmEAYXJRbjMTAorpOCtgQdoCKK/DvZ51zUWXxT8UBNHSl19Ryv5Ry5VVdbAE35rqs57DQ9+ma6htXnsBEmmnC+1Zv1FE956m/OpBTId50mor7nS2FguAtPZnDPpTd5zl9kZmJEuWCrmy6iinw5V4Uy1mLeZkQv+/FtozbyifCRCvps9nHpv4mBSU5ABLgnRRvXs+D41Jx7xloNADr1nNgpsNrYaTh hed-bot-ssh-tpm-rsa"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKYljH8iPMrH00lOb3ETxRrZimdKzPPEdsJQ5D5ovtOwAAAACnNzaDpzc2hrZXk= ssh:sshkey"
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBO4idMfdJxDJuBNOid60d4I+qxj09RHt+YkCYV2eXt6tGrEXg+S8hTQusy/SqooiXUH9pt4tea2RuBPN9+UwrH0= type-a yubikey slot 9a"
];
janik = [
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJ4yq7oHBO2iPs4xj797a//0ypnBr27sSadKUeL2NsK6AAAABHNzaDo="
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOYg513QZsVzoyVycXZjg4F3T3+OwtcY3WAhrlfyLgLTAAAABHNzaDo="
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBLZxVITpJ8xbiCa/u2gjSSIupeiqOnRh+8tFIoVhCON"
];
k900 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOi9vgVGs+S5kEsUqHPvyMMh1Q9gqL4TcbHoe5d73tun" ];
lukegb = [ ''cert-authority,principals="lukegb" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqNOwlR7Qa8cbGpDfSCOweDPbAGQOZIcoRgh6s/J8DR'' ];
maxine = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILpWQfhNFdrxMTP/1DwBVuk49f3df9iH7Tbdu8ltIKjr" ];
raito = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaw9ihTG7ucB8P38XdalEWev8+q96e2yNm4B+/I9IJp"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU"
];
thubrecht = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPM1jpXR7BWQa7Sed7ii3SbvIPRRlKb3G91qC0vOwfJn" ];
yuka = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxQ3NYBi8v1f/vhxLKDcA6upmX0pctRDbnK6SER5OUR yureka" ];
winter = [ "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIH/LDRUG+U+++UmlxvA2kspioTjktQZ8taDcHq8gVlkfAAAABHNzaDo=" ];
ckie = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH3uTwzSSMAPg84fwbNp2cq9+BdLFeA1VzDGth4zCAbz https://mei.puppycat.house" ];
};
}

View file

@ -13,13 +13,21 @@ in
tmux
rsync
fd
eza
grc
ripgrep
delta
tshark
pv
kitty.terminfo
config.boot.kernelPackages.perf
bcc
tcpdump
ncdu
] ++ lib.optional (lib.hasAttr "pwru" pkgs) pkgs.pwru;
# Useful to invoke `coredumpctl gdb`
gdb
htop
btop
];
};
}

16
common/zsh.nix Normal file
View file

@ -0,0 +1,16 @@
{ lib, pkgs, config, ... }: {
users.defaultUserShell = pkgs.zsh;
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestions.enable = true;
interactiveShellInit = ''
${lib.getExe pkgs.nix-your-shell} zsh | source /dev/stdin
'';
promptInit = ''
# https://grml.org/zsh/grml-zsh-refcard.pdf
source ${pkgs.grml-zsh-config}/etc/zsh/zshrc
PS1='%n@${config.networking.fqdn} %/ \$ '
'';
};
}

43
dashboards/default.nix Normal file
View file

@ -0,0 +1,43 @@
{ gerrit-dashboard, stdenv, symlinkJoin, jsonnet, fetchFromGitHub, lib, ... }:
let
inherit (lib) concatMapStringsSep;
datasource-id = "mimir";
in
rec {
grafonnet = fetchFromGitHub {
owner = "grafana";
repo = "grafonnet-lib";
# TODO: figure out how to read the jsonnet lockfile
# and propagate this a bit cleverly.
rev = "a1d61cce1da59c71409b99b5c7568511fec661ea";
hash = "sha256-fs5JZJbcL6sQXBjYhp5eeRtjTFw0J1O/BcwBC8Vm9EM=";
};
buildJsonnetDashboards = dashboardSrc: targets: stdenv.mkDerivation {
name = "jsonnet-grafana-dashboards";
src = dashboardSrc;
buildInputs = [ jsonnet ];
buildPhase = ''
runHook preBuild
mkdir -p $out
${concatMapStringsSep "\n" (target: "jsonnet -J ${grafonnet} --ext-str datasource=${datasource-id} --ext-code publish=true $src/${target} > $out/${baseNameOf target}.json") targets}
runHook postBuild
'';
};
allDashboards = symlinkJoin {
name = "all-jsonnet-dashboards";
paths = [
(buildJsonnetDashboards gerrit-dashboard [
"dashboards/gerrit/caches/gerrit-caches.jsonnet"
"dashboards/gerrit/fetch-clone/gerrit-fetch-clone.jsonnet"
"dashboards/gerrit/fetch-clone/gerrit-phases.jsonnet"
"dashboards/gerrit/healthcheck/gerrit-healthcheck.jsonnet"
"dashboards/gerrit/latency/gerrit-push-latency.jsonnet"
"dashboards/gerrit/latency/gerrit-ui-actions-latency.jsonnet"
"dashboards/gerrit/overview/gerrit-overview.jsonnet"
"dashboards/gerrit/process/gerrit-process.jsonnet"
"dashboards/gerrit/queues/gerrit-queues.jsonnet"
])
];
};
}

View file

@ -10,11 +10,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1718371084,
"narHash": "sha256-abpBi61mg0g+lFFU0zY4C6oP6fBwPzbHPKBGw676xsA=",
"lastModified": 1723293904,
"narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=",
"owner": "ryantm",
"repo": "agenix",
"rev": "3a56735779db467538fb2e577eda28a9daacaca6",
"rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41",
"type": "github"
},
"original": {
@ -23,6 +23,29 @@
"type": "github"
}
},
"attic": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat_2",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1711742460,
"narHash": "sha256-0O4v6e4a1toxXZ2gf5INhg4WPE5C5T+SVvsBt+45Mcc=",
"owner": "zhaofengli",
"repo": "attic",
"rev": "4dbdbee45728d8ce5788db6461aaaa89d98081f0",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"ref": "main",
"repo": "attic",
"type": "github"
}
},
"bats-assert": {
"flake": false,
"locked": {
@ -55,6 +78,49 @@
"type": "github"
}
},
"buildbot-nix": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": [
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1728837991,
"narHash": "sha256-+jXVHPmX9eUtH2JhMKye0Tm2KMQTmD8FlHHfbcaXMOI=",
"ref": "refs/heads/bring-back-old-gerrit-reporting",
"rev": "879e9cdcdf2d7e6566ee512d015acc4d23f35517",
"revCount": 302,
"type": "git",
"url": "https://git.lix.systems/lix-project/buildbot-nix.git"
},
"original": {
"ref": "refs/heads/bring-back-old-gerrit-reporting",
"type": "git",
"url": "https://git.lix.systems/lix-project/buildbot-nix.git"
}
},
"channel-scripts": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1725128016,
"narHash": "sha256-4TvaXELsl+1OcGNgqB/5HVXVxBvdIQkhJsY4FyiDcNU=",
"ref": "refs/heads/main",
"rev": "23b6c38ed7e11417bf624f6e4fb6cde0d2be6400",
"revCount": 261,
"type": "git",
"url": "https://git.lix.systems/the-distro/channel-scripts.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/the-distro/channel-scripts.git"
}
},
"colmena": {
"inputs": {
"flake-compat": "flake-compat",
@ -78,6 +144,50 @@
"type": "github"
}
},
"crane": {
"inputs": {
"nixpkgs": [
"grapevine",
"attic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1702918879,
"narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=",
"owner": "ipetkov",
"repo": "crane",
"rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"crane_2": {
"inputs": {
"nixpkgs": [
"grapevine",
"nixpkgs"
]
},
"locked": {
"lastModified": 1716569590,
"narHash": "sha256-5eDbq8TuXFGGO3mqJFzhUbt5zHVTf5zilQoyW5jnJwo=",
"owner": "ipetkov",
"repo": "crane",
"rev": "109987da061a1bf452f435f1653c47511587d919",
"type": "github"
},
"original": {
"owner": "ipetkov",
"ref": "master",
"repo": "crane",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
@ -100,6 +210,29 @@
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
"grapevine",
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1716359173,
"narHash": "sha256-pYcjP6Gy7i6jPWrjiWAVV0BCQp+DdmGaI/k65lBb/kM=",
"owner": "nix-community",
"repo": "fenix",
"rev": "b6fc5035b28e36a98370d0eac44f4ef3fd323df6",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "main",
"repo": "fenix",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
@ -117,6 +250,39 @@
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_3": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"ref": "master",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_4": {
"flake": false,
"locked": {
"lastModified": 1696426674,
@ -132,6 +298,49 @@
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"buildbot-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1706830856,
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"hydra",
"nix-eval-jobs",
"nixpkgs"
]
},
"locked": {
"lastModified": 1722555600,
"narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "8471fe90ad337a8074e957b69ca4d0089218391d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1659877975,
@ -148,6 +357,40 @@
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"ref": "main",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"locked": {
"lastModified": 1634851050,
"narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=",
@ -162,6 +405,51 @@
"type": "github"
}
},
"gerrit-dashboard": {
"flake": false,
"locked": {
"lastModified": 1724509518,
"narHash": "sha256-fwYXZVddxfzrlDa3QnFCwHqrbEX+3PrWy0QOlbO+8jk=",
"ref": "refs/heads/master",
"rev": "e544abac81c581558d68abb2a8dd583049073939",
"revCount": 75,
"type": "git",
"url": "https://git.lix.systems/the-distro/gerrit-monitoring.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/the-distro/gerrit-monitoring.git"
}
},
"grapevine": {
"inputs": {
"attic": "attic",
"crane": "crane_2",
"fenix": "fenix",
"flake-compat": "flake-compat_3",
"flake-utils": "flake-utils_3",
"nix-filter": "nix-filter",
"nixpkgs": [
"nixpkgs"
],
"rust-manifest": "rust-manifest"
},
"locked": {
"host": "gitlab.computer.surgery",
"lastModified": 1727994504,
"narHash": "sha256-FC6M1KKX58HbU9LG+cG6EJRr02J9lE/o0iiDi6m1gv8=",
"owner": "matrix",
"repo": "grapevine-fork",
"rev": "5a490a4397f0c6a36dab1cb631dadc67a849deab",
"type": "gitlab"
},
"original": {
"host": "gitlab.computer.surgery",
"owner": "matrix",
"repo": "grapevine-fork",
"type": "gitlab"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
@ -185,17 +473,18 @@
},
"hydra": {
"inputs": {
"nix": "nix",
"lix": "lix",
"nix-eval-jobs": "nix-eval-jobs",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1719258100,
"narHash": "sha256-Eu8ausj0RsXV5MraCPezwX+j51iZD0ukif110Yj2+6k=",
"lastModified": 1728321752,
"narHash": "sha256-GbBAoBF7ZObz0IP+g0LZKxMafpMvNKjTEu9haiZbV54=",
"ref": "refs/heads/main",
"rev": "a9a2679793a17325c966dec4cbb27d44b0531694",
"revCount": 4172,
"rev": "ee1234c15cdcb427dbd4828e0add09d02cd606c9",
"revCount": 4220,
"type": "git",
"url": "https://git.lix.systems/lix-project/hydra.git"
},
@ -204,9 +493,9 @@
"url": "https://git.lix.systems/lix-project/hydra.git"
}
},
"nix": {
"lix": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-compat": "flake-compat_4",
"nix2container": "nix2container",
"nixpkgs": [
"hydra",
@ -216,27 +505,113 @@
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1719211568,
"narHash": "sha256-oIgmvhe3CV/36LC0KXgqWnKXma39wabks8U9JBMDfO4=",
"lastModified": 1728163191,
"narHash": "sha256-SW0IEBsPN1EysqzvfDT+8Kimtzy03O1BxQQm7ZB6fRY=",
"ref": "refs/heads/main",
"rev": "4c3d93611f2848c56ebc69c85f2b1e18001ed3c7",
"revCount": 15877,
"rev": "ed9b7f4f84fd60ad8618645cc1bae2d686ff0db6",
"revCount": 16323,
"type": "git",
"url": "https://git@git.lix.systems/lix-project/lix"
"url": "https://git.lix.systems/lix-project/lix"
},
"original": {
"type": "git",
"url": "https://git@git.lix.systems/lix-project/lix"
"url": "https://git.lix.systems/lix-project/lix"
}
},
"nix-eval-jobs": {
"inputs": {
"flake-parts": "flake-parts_2",
"lix": [
"hydra",
"lix"
],
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"hydra",
"nixpkgs"
],
"treefmt-nix": "treefmt-nix_2"
},
"locked": {
"lastModified": 1723579251,
"narHash": "sha256-xnHtfw0gRhV+2S9U7hQwvp2klTy1Iv7FlMMO0/WiMVc=",
"ref": "refs/heads/main",
"rev": "42a160bce2fd9ffebc3809746bc80cc7208f9b08",
"revCount": 609,
"type": "git",
"url": "https://git.lix.systems/lix-project/nix-eval-jobs"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/lix-project/nix-eval-jobs"
}
},
"nix-filter": {
"locked": {
"lastModified": 1710156097,
"narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=",
"owner": "numtide",
"repo": "nix-filter",
"rev": "3342559a24e85fc164b295c3444e8a139924675b",
"type": "github"
},
"original": {
"owner": "numtide",
"ref": "main",
"repo": "nix-filter",
"type": "github"
}
},
"nix-gerrit": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1720891381,
"narHash": "sha256-bdZRPgnkROSejmwMOrlcqHMWmuPIVIzjk6r5FbS+fqU=",
"ref": "refs/heads/main",
"rev": "23dd318e6741ff686d3069c53ecf475eac8a0565",
"revCount": 5,
"type": "git",
"url": "https://git.lix.systems/the-distro/nix-gerrit.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/the-distro/nix-gerrit.git"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"hydra",
"nix-eval-jobs",
"nixpkgs"
]
},
"locked": {
"lastModified": 1720066371,
"narHash": "sha256-uPlLYH2S0ACj0IcgaK9Lsf4spmJoGejR9DotXiXSBZQ=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "622f829f5fe69310a866c8a6cd07e747c44ef820",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix2container": {
"flake": false,
"locked": {
"lastModified": 1712990762,
"narHash": "sha256-hO9W3w7NcnYeX8u8cleHiSpK2YJo7ecarFTUlbybl7k=",
"lastModified": 1720642556,
"narHash": "sha256-qsnqk13UmREKmRT7c8hEnz26X3GFFyIQrqx4EaRc1Is=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "20aad300c925639d5d6cbe30013c8357ce9f2a2e",
"rev": "3853e5caf9ad24103b13aa6e0e8bcebb47649fe4",
"type": "github"
},
"original": {
@ -247,11 +622,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1719082008,
"narHash": "sha256-jHJSUH619zBQ6WdC21fFAlDxHErKVDJ5fpN0Hgx4sjs=",
"lastModified": 1711401922,
"narHash": "sha256-QoQqXoj8ClGo0sqD/qWKFWezgEwUL0SUh37/vY2jNhc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9693852a2070b398ee123a329e68f0dab5526681",
"rev": "07262b18b97000d16a4bdb003418bd2fb067a932",
"type": "github"
},
"original": {
@ -277,17 +652,34 @@
"type": "github"
}
},
"nixpkgs_2": {
"nixpkgs-stable": {
"locked": {
"lastModified": 1636823747,
"narHash": "sha256-oWo1nElRAOZqEf90Yek2ixdHyjD+gqtS/pAgwaQ9UhQ=",
"owner": "nixos",
"lastModified": 1711460390,
"narHash": "sha256-akSgjDZL6pVHEfSE6sz1DNSXuYX6hq+P/1Z5IoYWs7E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f6a2ed2082d9a51668c86ba27d0b5496f7a2ea93",
"rev": "44733514b72e732bd49f5511bd0203dea9b9a434",
"type": "github"
},
"original": {
"owner": "nixos",
"owner": "NixOS",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1728093190,
"narHash": "sha256-CAZF2NRuHmqTtRTNAruWpHA43Gg2UvuCNEIzabP0l6M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e2f08f4d8b3ecb5cf5c9fd9cb2d53bb3c71807da",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
@ -295,11 +687,11 @@
"pre-commit-hooks": {
"flake": false,
"locked": {
"lastModified": 1712055707,
"narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=",
"lastModified": 1721042469,
"narHash": "sha256-6FPUl7HVtvRHCCBQne7Ylp4p+dpP3P/OYuzjztZ4s70=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "e35aed5fda3cc79f88ed7f1795021e559582093a",
"rev": "f451c19376071a90d8c58ab1a953c6e9840527fd",
"type": "github"
},
"original": {
@ -311,16 +703,51 @@
"root": {
"inputs": {
"agenix": "agenix",
"buildbot-nix": "buildbot-nix",
"channel-scripts": "channel-scripts",
"colmena": "colmena",
"gerrit-dashboard": "gerrit-dashboard",
"grapevine": "grapevine",
"hydra": "hydra",
"lix": [
"hydra",
"nix"
"lix"
],
"nixpkgs": "nixpkgs",
"nix-gerrit": "nix-gerrit",
"nixpkgs": "nixpkgs_2",
"stateless-uptime-kuma": "stateless-uptime-kuma",
"terranix": "terranix"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1716107283,
"narHash": "sha256-NJgrwLiLGHDrCia5AeIvZUHUY7xYGVryee0/9D3Ir1I=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "21ec8f523812b88418b2bfc64240c62b3dd967bd",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
"rust-manifest": {
"flake": false,
"locked": {
"narHash": "sha256-tB9BZB6nRHDk5ELIVlGYlIjViLKBjQl52nC1avhcCwA=",
"type": "file",
"url": "https://static.rust-lang.org/dist/channel-rust-1.81.0.toml"
},
"original": {
"type": "file",
"url": "https://static.rust-lang.org/dist/channel-rust-1.81.0.toml"
}
},
"stable": {
"locked": {
"lastModified": 1696039360,
@ -337,6 +764,22 @@
"type": "github"
}
},
"stateless-uptime-kuma": {
"flake": false,
"locked": {
"lastModified": 1728243069,
"narHash": "sha256-l9fgwesnmFxasCaYUCD7L9bGGJXytLuwtx3CZMgpwJg=",
"ref": "refs/heads/master",
"rev": "880f444ff7862d6127b051cf1a993ad1585b1652",
"revCount": 25,
"type": "git",
"url": "https://git.dgnum.eu/DGNum/stateless-uptime-kuma.git"
},
"original": {
"type": "git",
"url": "https://git.dgnum.eu/DGNum/stateless-uptime-kuma.git"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
@ -352,12 +795,29 @@
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"terranix": {
"inputs": {
"bats-assert": "bats-assert",
"bats-support": "bats-support",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2",
"flake-utils": "flake-utils_4",
"nixpkgs": [
"nixpkgs"
],
"terranix-examples": "terranix-examples"
},
"locked": {
@ -388,6 +848,49 @@
"repo": "terranix-examples",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"buildbot-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1708897213,
"narHash": "sha256-QECZB+Hgz/2F/8lWvHNk05N6NU/rD9bWzuNn6Cv8oUk=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "e497a9ddecff769c2a7cbab51e1ed7a8501e7a3a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"treefmt-nix_2": {
"inputs": {
"nixpkgs": [
"hydra",
"nix-eval-jobs",
"nixpkgs"
]
},
"locked": {
"lastModified": 1723454642,
"narHash": "sha256-S0Gvsenh0II7EAaoc9158ZB4vYyuycvMGKGxIbERNAM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "349de7bc435bdff37785c2466f054ed1766173be",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",

256
flake.nix
View file

@ -3,7 +3,9 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
terranix.url = "github:terranix/terranix";
terranix.inputs.nixpkgs.follows = "nixpkgs";
agenix.url = "github:ryantm/agenix";
agenix.inputs.nixpkgs.follows = "nixpkgs";
@ -14,100 +16,192 @@
hydra.url = "git+https://git.lix.systems/lix-project/hydra.git";
hydra.inputs.nixpkgs.follows = "nixpkgs";
lix.follows = "hydra/nix";
nix-gerrit.url = "git+https://git.lix.systems/the-distro/nix-gerrit.git";
nix-gerrit.inputs.nixpkgs.follows = "nixpkgs";
gerrit-dashboard.url = "git+https://git.lix.systems/the-distro/gerrit-monitoring.git";
gerrit-dashboard.flake = false;
buildbot-nix.url = "git+https://git.lix.systems/lix-project/buildbot-nix.git?ref=refs/heads/bring-back-old-gerrit-reporting";
buildbot-nix.inputs.nixpkgs.follows = "nixpkgs";
channel-scripts.url = "git+https://git.lix.systems/the-distro/channel-scripts.git";
channel-scripts.inputs.nixpkgs.follows = "nixpkgs";
stateless-uptime-kuma.url = "git+https://git.dgnum.eu/DGNum/stateless-uptime-kuma.git";
stateless-uptime-kuma.flake = false;
lix.follows = "hydra/lix";
grapevine = {
type = "gitlab";
host = "gitlab.computer.surgery";
owner = "matrix";
repo = "grapevine-fork";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, terranix, ... } @ inputs:
outputs = { self, nixpkgs, terranix, colmena, ... } @ inputs:
let
system = "x86_64-linux";
pkgs = import nixpkgs {
localSystem = system;
overlays = [
inputs.hydra.overlays.default
inputs.lix.overlays.default
];
};
lib = pkgs.lib;
terraform = pkgs.opentofu;
terraformCfg = terranix.lib.terranixConfiguration {
supportedSystems = [ "x86_64-linux" "aarch64-linux" ];
forEachSystem = f: builtins.listToAttrs (map (system: {
name = system;
value = f system;
}) supportedSystems);
systemBits = forEachSystem (system: rec {
inherit system;
modules = [ ];
};
in
{
apps.${system} = {
apply = {
type = "app";
program = toString (pkgs.writers.writeBash "apply" ''
set -eo pipefail
rm -f config.tf.json
cp ${terraformCfg} config.tf.json
${lib.getExe terraform} init
${lib.getExe terraform} apply
'');
};
# nix run ".#destroy"
destroy = {
type = "app";
program = toString (pkgs.writers.writeBash "destroy" ''
set -eo pipefail
ln -snf ${terraformCfg} config.tf.json
${lib.getExe terraform} init
${lib.getExe terraform} destroy
'');
};
};
apps.${system}.default = self.apps.${system}.apply;
devShells.${system}.default = pkgs.mkShell {
packages = [
inputs.agenix.packages.${system}.agenix
inputs.colmena.packages.${system}.colmena
];
};
colmena = {
meta.nixpkgs = import nixpkgs {
pkgs = import nixpkgs {
localSystem = system;
overlays = [
inputs.hydra.overlays.default
inputs.lix.overlays.default
inputs.nix-gerrit.overlays.default
inputs.channel-scripts.overlays.default
(import "${inputs.stateless-uptime-kuma}/overlay.nix")
];
};
terraform = pkgs.opentofu;
terraformCfg = terranix.lib.terranixConfiguration {
inherit system;
modules = [
./terraform
{
bagel.dnsimple.enable = true;
bagel.hydra.enable = true;
}
];
};
});
forEachSystem' = f: forEachSystem (system: (f systemBits.${system}));
inherit (nixpkgs) lib;
in
{
apps = forEachSystem' ({ system, pkgs, terraformCfg, terraform, ... }: {
tf = {
type = "app";
program = toString (pkgs.writers.writeBash "tf" ''
set -eo pipefail
ln -snf ${terraformCfg} config.tf.json
exec ${lib.getExe terraform} "$@"
'');
};
default = self.apps.${system}.tf;
});
devShells = forEachSystem' ({ system, pkgs, ... }: {
default = pkgs.mkShell {
packages = [
inputs.agenix.packages.${system}.agenix
pkgs.opentofu
(pkgs.callPackage ./lib/colmena-wrapper.nix { })
];
};
});
nixosConfigurations = (colmena.lib.makeHive self.outputs.colmena).nodes;
colmena = let
commonModules = [
inputs.agenix.nixosModules.default
inputs.hydra.nixosModules.hydra
inputs.buildbot-nix.nixosModules.buildbot-coordinator
inputs.buildbot-nix.nixosModules.buildbot-worker
./services
./common
];
floralInfraModules = commonModules ++ [
({ config, lib, ... }: {
# This means that anyone with @floral-infra permissions
# can ssh on root of every machines handled here.
bagel.admins.allowedGroups = [
"floral-infra"
];
# Tag all machines which have local boot as local bootables.
deployment.tags = lib.mkMerge [
[ "floral" ]
(lib.mkIf (config.bagel.baremetal.builders.enable -> !config.bagel.baremetal.builders.netboot)
[ "localboot" ]
)
];
bagel.monitoring.grafana-agent.tenant = "floral";
bagel.secrets.tenant = "floral";
bagel.builders.extra-build-capacity.provider.tenant = "floral";
bagel.services.buildbot.tenant = "floral";
})
];
# These are Floral baremetal builders.
makeBuilder = i:
let
enableNetboot = i >= 6;
in
lib.nameValuePair "builder-${toString i}" {
imports = floralInfraModules;
bagel.baremetal.builders = { enable = true; num = i; netboot = enableNetboot; };
};
lixInfraModules = commonModules ++ [
{
# This means that anyone with @lix-infra permissions
# can ssh on root of every machines handled here.
bagel.admins.allowedGroups = [
"lix-infra"
];
# Tag all machines which have local boot as local bootables.
# Lix has no netbootable machine.
deployment.tags = [ "localboot" "lix" ];
bagel.monitoring.grafana-agent.tenant = "lix";
bagel.secrets.tenant = "lix";
bagel.builders.extra-build-capacity.provider = {
tenant = "lix";
buildfarmPublicKeys = [
# buildbot.lix.systems SSH key
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDu4cEqZzAI/1vZjSQkTJ4ijIg9nuloOuSKUrnkJIOFn"
];
};
bagel.services.buildbot.tenant = "lix";
}
];
builders = lib.listToAttrs (lib.genList makeBuilder 11);
in {
meta.nixpkgs = systemBits.x86_64-linux.pkgs;
# Add any non-x86_64 native systems here.
# Cross compilation is not supported yet.
meta.nodeNixpkgs =
let
aarch64-systems = systems: lib.genAttrs systems (system: systemBits.aarch64-linux.pkgs);
in
aarch64-systems [
"build01-aarch64-lix"
];
meta.specialArgs.inputs = inputs;
bagel-box = {
imports = [
inputs.agenix.nixosModules.default
inputs.hydra.nixosModules.hydra
bagel-box.imports = floralInfraModules ++ [ ./hosts/bagel-box ];
meta01.imports = floralInfraModules ++ [ ./hosts/meta01 ];
gerrit01.imports = floralInfraModules ++ [ ./hosts/gerrit01 ];
fodwatch.imports = floralInfraModules ++ [ ./hosts/fodwatch ];
git.imports = floralInfraModules ++ [ ./hosts/git ];
wob-vpn-gw.imports = floralInfraModules ++ [ ./hosts/wob-vpn-gw ];
buildbot.imports = floralInfraModules ++ [ ./hosts/buildbot ];
public01.imports = floralInfraModules ++ [ ./hosts/public01 ];
build-coord.imports = floralInfraModules ++ [ ./hosts/build-coord ];
./services
./common
./hosts/bagel-box
];
};
build01-aarch64-lix.imports = lixInfraModules ++ [ ./hosts/build01-aarch64-lix ];
buildbot-lix.imports = lixInfraModules ++ [ ./hosts/buildbot-lix ];
} // builders;
meta01 = {
imports = [
inputs.agenix.nixosModules.default
inputs.hydra.nixosModules.hydra
./services
./common
./hosts/meta01.nixpkgs.lahfa.xyz
];
};
gerrit01 = {
imports = [
inputs.agenix.nixosModules.default
inputs.hydra.nixosModules.hydra
./services
./common
./hosts/cl.forkos.org
];
};
};
hydraJobs = builtins.mapAttrs (n: v: v.config.system.build.netbootDir or v.config.system.build.toplevel) self.nixosConfigurations;
buildbotJobs = builtins.mapAttrs (_: v: v.config.system.build.toplevel) self.nixosConfigurations;
};
}

View file

@ -20,6 +20,7 @@
useHostResolvConf = false;
hostName = "bagel-box";
domain = "infra.forkos.org";
nameservers = [ "2001:4860:4860::8844" ];
interfaces.host0.ipv6.addresses = [
@ -36,16 +37,13 @@
bagel.services = {
postgres.enable = true;
hydra.enable = true;
hydra.dbi = "dbi:Pg:dbname=hydra;user=hydra";
ofborg.enable = true;
};
bagel.meta.monitoring.address = "bagel-box.delroth.net";
security.acme.acceptTerms = true;
security.acme.defaults.email = "bagel@delroth.net";
bagel.sysadmin.enable = true;
services.openssh.enable = true;
deployment.targetHost = "bagel-box.delroth.net";
system.stateVersion = "24.11";
deployment.targetHost = "bagel-box.infra.forkos.org";
}

View file

@ -0,0 +1,23 @@
{ lib, ... }:
{
imports = [ ./hardware.nix ];
networking.hostName = "build-coord";
networking.domain = "wob01.infra.forkos.org";
bagel.sysadmin.enable = true;
bagel.services = {
hydra.enable = true;
# Takes 10 builders (0 → 9).
hydra.builders = lib.genList (i: "builder-${builtins.toString i}") 10;
};
bagel.monitoring.exporters.hydra.enable = true;
# Hydra is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
system.stateVersion = "24.05";
deployment.targetHost = "build-coord.wob01.infra.forkos.org";
}

View file

@ -0,0 +1,87 @@
{
boot.initrd.availableKernelModules = [ "ahci" "ehci_pci" "usb_storage" "usbhid" "sd_mod" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
nixpkgs.hostPlatform = "x86_64-linux";
hardware.cpu.intel.updateMicrocode = true;
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.systemd.enable = true;
boot.initrd.services.lvm.enable = true;
boot.kernelParams = [
"console=tty1"
"console=ttyS0,115200"
];
fileSystems = {
"/" = {
device = "/dev/disk/by-label/root";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
};
swapDevices = [
{
device = "/swapfile";
size = 20 * 1024; # 50GiB
}
];
zramSwap = {
enable = true;
memoryPercent = 25;
};
networking.useNetworkd = true;
systemd.network = {
netdevs = {
"40-uplink" = {
netdevConfig = {
Kind = "bond";
Name = "uplink";
};
bondConfig = {
Mode = "802.3ad";
TransmitHashPolicy = "layer3+4";
};
};
};
networks = {
"40-eno1" = {
name = "eno1";
bond = [ "uplink" ];
};
"40-eno2" = {
name = "eno2";
bond = [ "uplink" ];
};
};
};
networking.interfaces.uplink.ipv6.addresses = [
{ address = "2a01:584:11::1:11"; prefixLength = 64; }
];
networking.defaultGateway6 = { interface = "uplink"; address = "2a01:584:11::1"; };
services.coredns = {
enable = true;
config = ''
. {
bind lo
forward . 2001:4860:4860::6464
template ANY A { rcode NOERROR }
}
'';
};
services.resolved.enable = false;
networking.resolvconf.useLocalResolver = true;
}

View file

@ -0,0 +1,27 @@
{ ... }: {
networking.hostName = "build01";
networking.domain = "aarch64.lix.systems";
# Those free sweet VMs.
bagel.hardware.oracle-vm = {
enable = true;
system = "aarch64-linux";
};
fileSystems."/" =
{ device = "/dev/disk/by-uuid/a333323c-99f0-4258-8f68-496858d56f71";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/3E74-C937";
fsType = "vfat";
};
swapDevices = [ ];
bagel.builders.extra-build-capacity.provider.enable = true;
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "build01.aarch64.lix.systems";
}

View file

@ -0,0 +1,71 @@
# Configuration for a virtual machine in Raito's micro-DC basement.
# 32 vCPU (2014 grade Xeon though)
# 32GB RAM
# 30GB SSD
# 500GB HDD
# All specifications can be upgraded to a certain extent, just ask Raito.
# Hosts the coordinator for Buildbot.
#
# vim: et:ts=2:sw=2:
#
{ lib, modulesPath, ... }: {
networking.hostName = "buildbot";
networking.domain = "lix.systems";
zramSwap.enable = true;
bagel.sysadmin.enable = true;
# Buildbot is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "BC:24:11:75:62:42";
wan = {
mac = "BC:24:11:B2:5F:2E";
address = "2001:bc8:38ee:100::200/56";
};
};
};
i18n.defaultLocale = "en_US.UTF-8";
bagel.services.buildbot = {
enable = true;
domain = "buildbot.lix.systems";
gerrit =
{
domain = "gerrit.lix.systems";
port = 2022;
username = "buildbot";
};
cors.allowedOrigins = [
"https://*.lix.systems"
];
projects = [
"lix"
"lix-installer"
];
buildSystems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
# Too slow.
/* "x86_64-darwin" */
];
# Lix is not allowed to use yet Floral's x86_64 builders for now.
builders = [ ];
};
# This machine does not use /nix from btrfs, and instead uses a store on a bigger disk.
fileSystems."/nix" =
lib.mkForce
{ device = "/dev/disk/by-uuid/1815ca49-d0b0-4b99-8aec-0d790498ba6f";
fsType = "xfs";
neededForBoot = true;
options = [ "relatime" ];
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
system.stateVersion = "24.05";
deployment.targetHost = "buildbot.lix.systems";
}

54
hosts/buildbot/default.nix Executable file
View file

@ -0,0 +1,54 @@
{
config,
lib,
pkgs,
nodes,
...
}:
{
networking.hostName = "buildbot";
# TODO: make it the default
networking.domain = "infra.forkos.org";
bagel.sysadmin.enable = true;
# Buildbot is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "BC:24:11:E7:42:8B";
wan = {
address = "2001:bc8:38ee:100:1000::50/64";
mac = "BC:24:11:C9:BA:6C";
};
};
};
bagel.services.buildbot = {
enable = true;
domain = "buildbot.forkos.org";
gerrit =
let
cfgGerrit = nodes.gerrit01.config.bagel.services.gerrit;
in
{
domain = cfgGerrit.canonicalDomain;
port = cfgGerrit.port;
username = "buildbot";
};
cors.allowedOrigins = [
"https://*.forkos.org"
];
projects = [
"buildbot-test"
"nixpkgs"
"infra"
];
builders = [ "builder-9" ];
};
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "buildbot.infra.forkos.org";
}

View file

@ -1,46 +0,0 @@
{
config,
lib,
pkgs,
...
}:
{
networking.hostName = "gerrit01";
# TODO: make it the default
networking.domain = "infra.forkos.org";
time.timeZone = "Europe/Paris";
bagel.sysadmin.enable = true;
# Gerrit is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "bc:24:11:f7:29:6c";
wan = {
address = "2001:bc8:38ee:100:1000::10/64";
mac = "bc:24:11:4a:9d:32";
};
};
};
bagel.meta.monitoring.address = "gerrit01.infra.forkos.org";
fileSystems."/gerrit-data" = {
device = "/dev/disk/by-uuid/d1062305-0dea-4740-9a27-b6b1691862a4";
fsType = "ext4";
};
bagel.services.gerrit = {
enable = true;
domains = [
"cl.forkos.org"
];
data = "/gerrit-data";
};
i18n.defaultLocale = "fr_FR.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "gerrit01.infra.forkos.org";
}

29
hosts/fodwatch/default.nix Executable file
View file

@ -0,0 +1,29 @@
{
config,
lib,
pkgs,
...
}:
{
networking.hostName = "fodwatch";
networking.domain = "infra.forkos.org";
bagel.sysadmin.enable = true;
# Fodwatch will be proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "BC:24:11:F2:17:F8";
wan = {
address = "2001:bc8:38ee:100:1000::30/64";
mac = "BC:24:11:69:74:D0";
};
};
};
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "fodwatch.infra.forkos.org";
}

151
hosts/gerrit01/default.nix Executable file
View file

@ -0,0 +1,151 @@
{
config,
lib,
pkgs,
...
}:
{
networking.hostName = "gerrit01";
# TODO: make it the default
networking.domain = "infra.forkos.org";
bagel.sysadmin.enable = true;
# Gerrit is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "bc:24:11:f7:29:6c";
wan = {
address = "2001:bc8:38ee:100:1000::10/64";
mac = "bc:24:11:4a:9d:32";
};
};
};
# Block all these crawlers!!
bagel.services.nginx.crawler-blocker.enable = true;
fileSystems."/gerrit-data" = {
device = "/dev/disk/by-uuid/d1062305-0dea-4740-9a27-b6b1691862a4";
fsType = "ext4";
};
bagel.services.gerrit = {
enable = true;
pyroscope.enable = true;
domains = [
"cl.forkos.org"
];
canonicalDomain = "cl.forkos.org";
data = "/gerrit-data";
};
age.secrets.ows-deploy-key = {
file = ../../secrets/floral/ows-deploy-key.age;
mode = "0600";
owner = "git";
group = "git";
};
bagel.nixpkgs.one-way-sync =
let
mkNixpkgsJob = { timer, fromRefspec, localRefspec ? fromRefspec }: {
fromUri = "https://github.com/NixOS/nixpkgs";
inherit fromRefspec localRefspec timer;
};
mkLocalJob = { timer, fromRefspec, localRefspec }: {
fromUri = "https://cl.forkos.org/nixpkgs";
inherit fromRefspec localRefspec timer;
};
in
{
enable = true;
pushUrl = "ssh://ows_bot@cl.forkos.org:29418/nixpkgs";
deployKeyPath = config.age.secrets.ows-deploy-key.path;
# Sync main -> staging-next -> staging
branches."main-to-staging-next" = mkLocalJob {
timer = "00/8:20:00"; # every 8 hours, 20 minutes past the full hour
fromRefspec = "main";
localRefspec = "staging-next";
};
branches."staging-next-to-staging" = mkLocalJob {
timer = "00/8:40:00"; # every 8 hours, 40 minutes past the full hour
fromRefspec = "staging-next";
localRefspec = "staging";
};
# Sync nixpkgs -> fork
branches."nixpkgs-master" = mkNixpkgsJob {
timer = "hourly";
fromRefspec = "master";
localRefspec = "main";
};
branches."nixpkgs-staging" = mkNixpkgsJob {
timer = "hourly";
fromRefspec = "staging";
};
branches."nixpkgs-release-24.05" = mkNixpkgsJob {
timer = "hourly";
fromRefspec = "release-24.05";
};
branches."nixpkgs-staging-24.05" = mkNixpkgsJob {
timer = "hourly";
fromRefspec = "staging-24.05";
};
branches."nixpkgs-release-23.11" = mkNixpkgsJob {
timer = "hourly";
fromRefspec = "release-23.11";
};
branches."nixpkgs-staging-23.11" = mkNixpkgsJob {
timer = "hourly";
fromRefspec = "staging-23.11";
};
# Testing jobs for personal sandbox branches
branches."raito-unstable-sync" = {
fromUri = "https://github.com/NixOS/nixpkgs";
fromRefspec = "nixos-unstable-small";
localRefspec = "sandbox/raito/raito-unstable-small";
timer = "*-*-* 12:00:00";
};
branches."raito-release-sync" = {
fromUri = "https://github.com/NixOS/nixpkgs";
fromRefspec = "nixos-24.05";
localRefspec = "sandbox/raito/raito-nixos-24.05";
timer = "daily";
};
};
age.secrets.s3-channel-staging-keys.file = ../../secrets/floral/s3-channel-staging-keys.age;
bagel.nixpkgs.channel-scripts = {
enable = true;
otlp.enable = true;
nixpkgsUrl = "https://cl.forkos.org/nixpkgs.git";
hydraUrl = "https://hydra.forkos.org";
binaryCacheUrl = "https://cache.forkos.org";
baseUriForGitRevisions = "https://cl.forkos.org/plugins/gitiles/nixpkgs/+";
s3 = {
release = "bagel-channel-scripts-test";
channel = "bagel-channel-scripts-test";
};
releaseBucketCredentialsFile = config.age.secrets.s3-channel-staging-keys.path;
deployKeyFile = config.age.secrets.priv-ssh-key.path;
extraArgs = [
"--bypass-preflight-checks"
];
channels = import ../../common/channels.nix;
};
i18n.defaultLocale = "fr_FR.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "gerrit01.infra.forkos.org";
}

47
hosts/git/default.nix Normal file
View file

@ -0,0 +1,47 @@
let
ipv6 = {
openssh ="2001:bc8:38ee:100:1000::41";
forgejo = "2001:bc8:38ee:100:1000::40";
};
in
{
networking.hostName = "git";
networking.domain = "infra.forkos.org";
bagel.sysadmin.enable = true;
# Forgejo will be proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "BC:24:11:83:71:56";
wan = {
address = "${ipv6.forgejo}/64";
mac = "BC:24:11:0B:8A:81";
};
};
};
# Add one additional IPv6, so we can have both OpenSSH and
# Forgejo's built-in server bind on port :22.
systemd.network.networks."10-wan".networkConfig.Address = [ "${ipv6.openssh}/64" ];
services.openssh.listenAddresses = [{
addr = "[${ipv6.openssh}]";
}];
# Defaults to network.target, but networkd may take a while to settle and set up
# the required (additional) IPv6 address, leading to sshd to not being able to
# bind to the requested IP, crashing 5 times and running into the default
# restart counter limit (5).
systemd.services.sshd.wants = [ "network-online.target" ];
systemd.services.sshd.after = [ "network-online.target" ];
bagel.services.forgejo = {
enable = true;
sshBindAddr = ipv6.forgejo;
};
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "git.infra.forkos.org";
}

View file

@ -2,8 +2,6 @@
networking.hostName = "meta01";
networking.domain = "infra.forkos.org";
time.timeZone = "Europe/Paris";
bagel.sysadmin.enable = true;
# netbox is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
@ -21,10 +19,18 @@
enable = true;
domain = "netbox.forkos.org";
};
bagel.meta.monitoring.address = "meta01.infra.forkos.org";
bagel.services.prometheus.enable = true;
bagel.services.loki.enable = true;
bagel.services.grafana.enable = true;
bagel.services.grapevine.enable = true;
bagel.services.pyroscope.enable = true;
bagel.services.tempo.enable = true;
bagel.services.hookshot = {
enable = true;
admins = [
"@k900:0upti.me"
];
};
i18n.defaultLocale = "fr_FR.UTF-8";

50
hosts/public01/default.nix Executable file
View file

@ -0,0 +1,50 @@
{
config,
lib,
pkgs,
...
}:
{
networking.hostName = "public01";
# TODO: make it the default
networking.domain = "infra.forkos.org";
bagel.status = {
enable = true;
domain = "status.forkos.org";
};
bagel.sysadmin.enable = true;
# Newsletter is proxied.
bagel.raito.v6-proxy-awareness.enable = true;
bagel.newsletter = {
enable = true;
domain = "news.forkos.org";
};
bagel.hardware.raito-vm = {
enable = true;
networking = {
nat-lan-mac = "BC:24:11:A4:F7:D3";
wan = {
address = "2001:bc8:38ee:100:1000::60/64";
mac = "BC:24:11:DB:B8:10";
};
};
};
bagel.services.s3-revproxy = {
enable = true;
domain = "forkos.org";
s3.apiUrl = "s3.delroth.net";
targets = {
channels = "bagel-channels";
releases = "bagel-releases";
channel-scripts-test = "bagel-channel-scripts-test";
};
};
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "24.05";
deployment.targetHost = "public01.infra.forkos.org";
}

View file

@ -0,0 +1,126 @@
{ pkgs, lib, ... }:
{
imports = [
./netboot.nix
];
###### Hardware ######
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "sd_mod" "sdhci_pci" ];
boot.kernelModules = [ "kvm-amd" ];
boot.loader.grub.device = "/dev/sda";
fileSystems."/" =
{ device = "/dev/disk/by-uuid/58688a5c-e3ce-4868-804b-4e34d1370f36";
fsType = "f2fs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/38caa628-3b6d-4fb4-8767-beee09a196a6";
fsType = "ext2";
};
nixpkgs.hostPlatform = "x86_64-linux";
hardware.cpu.amd.updateMicrocode = true;
# Enable serial output
boot.loader.grub.extraConfig = ''
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
terminal_input serial
terminal_output serial
'';
boot.kernelParams = [
"console=ttyS0,115200"
"console=tty1"
];
###### Config #######
boot.initrd.systemd.enable = true;
networking.useNetworkd = true;
systemd.network = {
netdevs = {
"40-uplink" = {
netdevConfig = {
Kind = "bond";
Name = "uplink";
};
bondConfig = {
Mode = "802.3ad";
TransmitHashPolicy = "layer3+4";
};
};
"40-oob" = {
netdevConfig = {
Kind = "bond";
Name = "oob";
};
bondConfig = {
Mode = "802.3ad";
TransmitHashPolicy = "layer3+4";
};
};
};
networks = {
"40-enp1s0" = {
name = "enp1s0";
bond = [ "uplink" ];
};
"40-enp2s0" = {
name = "enp2s0";
bond = [ "uplink" ];
};
"40-enp3s0" = {
name = "enp3s0";
bond = [ "oob" ];
};
"40-enp4s0" = {
name = "enp4s0";
bond = [ "oob" ];
};
} // lib.listToAttrs (map (x: lib.nameValuePair "40-bmc${toString x}" {
name = "bmc${toString x}";
address = [ "192.168.1.${toString (x*4 + 1)}/30" ];
#address = [ "192.168.${toString x}.1/24" ];
networkConfig.DHCPServer = true;
}) (lib.genList lib.id 12));
};
networking.nftables.enable = true;
networking.firewall.extraInputRules = ''
iifname { "bmc*" } meta nfproto ipv4 udp dport 67 accept comment "DHCP server"
'';
networking.vlans = lib.listToAttrs (map (x: lib.nameValuePair "bmc${toString x}" {
interface = "oob";
id = 101 + x;
}) (lib.genList lib.id 12));
networking.interfaces = {
uplink = {
ipv6.addresses = [
{
address = "2a01:584:11::2";
prefixLength = 64;
}
];
};
};
networking.defaultGateway6 = { interface = "uplink"; address = "2a01:584:11::1"; };
networking.hostName = "vpn-gw";
networking.domain = "wob01.infra.forkos.org";
deployment.targetHost = "2a01:584:11::2";
bagel.sysadmin.enable = true;
environment.systemPackages = [ pkgs.ipmitool ];
system.stateVersion = "24.05";
}

View file

@ -0,0 +1,61 @@
{ config, lib, pkgs, nodes, modulesPath, ... }:
# The way the connection is established is specific to the wob01 site and the Intel S2600KPR blades.
# Proper netboot is not possible, because while the blades and the APU board (which is the netboot
# server here) are in the same L2 network, the uplink connection of each blade is an LACP LAG,
# meaning that the switch on the other side will only enable the port if it sees valid LACP packets.
# We work around this by presenting a virtual floppy drive using the "IUSB" protocol of the BMC.
# This virtual floppy drive contains an per-blade customized initramfs which will initialize the
# network connection including IP configuration and load the actual image off hydra.
let
netboot-server-ip = "2a01:584:11::2";
netbootNodes = lib.filterAttrs (_: node: node.config.bagel.baremetal.builders.enable && node.config.bagel.baremetal.builders.netboot) nodes;
in {
assertions = [
{
assertion = !(lib.elem 443 config.networking.firewall.allowedTCPPorts);
message = ''
Port 443 is in networking.firewalls.allowedTCPPorts, but should be only manually
allowed for specific IPs and source ports in ${builtins.toJSON __curPos}
'';
}
];
systemd.services = lib.mapAttrs' (nodename: node: let
bmcIp = "192.168.1.${toString (node.config.bagel.baremetal.builders.num * 4 + 2)}";
notipxe = node.config.system.build.notipxe.config.system.build.usbImage;
in lib.nameValuePair "iusb-spoof-${nodename}" {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Restart = "always";
};
script = ''
AUTH_TOKEN=$(${pkgs.iusb-spoof}/bin/make-token ${bmcIp})
exec ${pkgs.iusb-spoof}/bin/iusb-spoof -r ${bmcIp} 5123 $AUTH_TOKEN ${notipxe}
'';
}) netbootNodes;
# Since the builders are stateless, they can not store their ssh hostkeys
networking.firewall.allowedTCPPorts = [ 80 ]; # for ACME
networking.firewall.extraInputRules = ''
ip6 saddr 2a01:584:11::/64 tcp sport < 1024 tcp dport 443 accept;
'';
services.nginx = {
enable = true;
virtualHosts."vpn-gw.wob01.infra.forkos.org" = {
enableACME = true;
forceSSL = true;
locations = lib.mapAttrs' (nodename: node: let
ip = "2a01:584:11::1:${toString node.config.bagel.baremetal.builders.num}";
in lib.nameValuePair "/${nodename}/" {
root = "/var/www";
extraConfig = ''
allow ${ip};
deny all;
'';
}) netbootNodes;
};
};
}

14
lib/colmena-wrapper.nix Normal file
View file

@ -0,0 +1,14 @@
# A wrapper for colmena that prevents accidentally deploying changes without
# having pulled.
{ colmena, runCommandNoCC }:
runCommandNoCC "colmena-wrapper"
{
env.colmena = "${colmena}/bin/colmena";
} ''
mkdir -p $out
ln -s ${colmena}/share $out/share
mkdir $out/bin
substituteAll ${./colmena-wrapper.sh.in} $out/bin/colmena
chmod +x $out/bin/colmena
''

29
lib/colmena-wrapper.sh.in Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env bash
doChecks() {
# creates refs in the refs/prefetch/remotes/origin namespace
echo "Prefetching repo changes..." >&2
git fetch --quiet --prefetch --no-write-fetch-head origin
diffs=$(git rev-list --left-right --count HEAD...refs/prefetch/remotes/origin/main)
only_in_local=$(echo "$diffs" | cut -f1)
only_in_main=$(echo "$diffs" | cut -f2)
if [[ $only_in_main -gt 0 && ! -v $FOOTGUN_ME_UWU ]]; then
echo >&2
echo "Attempting to deploy when main has $only_in_main commits not in your branch!" >&2
echo "This will probably revert someone's changes. Consider merging them." >&2
echo "If you really mean it, set the environment variable FOOTGUN_ME_UWU" >&2
exit 1
fi
if [[ $only_in_local -gt 0 ]]; then
echo "You have $only_in_local commits not yet pushed to main. Reminder to push them after :)" >&2
fi
}
if [[ $1 == 'apply' ]]; then
doChecks
fi
exec @colmena@ "$@"

View file

@ -1,3 +1,9 @@
[
(import ./gerrit.nix)
(final: prev: {
iusb-spoof = final.callPackage ./iusb-spoof.nix {};
u-root = final.callPackage ./u-root {};
pyroscope = final.callPackage ./pyroscope {};
s3-revproxy = final.callPackage ./s3-revproxy {};
git-gc-preserve = final.callPackage ./git-gc-preserve {};
})
]

View file

@ -1,11 +0,0 @@
self: super: {
buildGerrit = self.callPackage ../pkgs/gerrit { };
gerrit = self.buildGerrit { };
buildGerritBazelPlugin = self.callPackage ../pkgs/gerrit_plugins/builder.nix {
inherit (self) buildGerrit;
};
gerritPlugins = {
code-owners = self.callPackage ../pkgs/gerrit_plugins/code-owners { };
oauth = self.callPackage ../pkgs/gerrit_plugins/oauth { };
};
}

View file

@ -0,0 +1,9 @@
{ writeShellApplication, git, nettools }:
writeShellApplication {
name = "git-gc-preserve";
runtimeInputs = [ git nettools ];
text = (builtins.readFile ./script.sh);
}

View file

@ -0,0 +1,132 @@
#!/usr/bin/env bash
set +o errexit
# Copyright (C) 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
usage() { # exit code
cat <<-EOF
NAME
git-gc-preserve - Run git gc and preserve old packs to avoid races for JGit
SYNOPSIS
git gc-preserve
DESCRIPTION
Runs git gc and can preserve old packs to avoid races with concurrently
executed commands in JGit.
This command uses custom git config options to configure if preserved packs
from the last run of git gc should be pruned and if packs should be preserved.
This is similar to the implementation in JGit [1] which is used by
JGit to avoid errors [2] in such situations.
The command prevents concurrent runs of the command on the same repository
by acquiring an exclusive file lock on the file
"\$repopath/gc-preserve.pid"
If it cannot acquire the lock it fails immediately with exit code 3.
Failure Exit Codes
1: General failure
2: Couldn't determine repository path. If the current working directory
is outside of the working tree of the git repository use git option
--git-dir to pass the root path of the repository.
E.g.
$ git --git-dir ~/git/foo gc-preserve
3: Another process already runs $0 on the same repository
[1] https://git.eclipse.org/r/c/jgit/jgit/+/87969
[2] https://git.eclipse.org/r/c/jgit/jgit/+/122288
CONFIGURATION
"pack.prunepreserved": if set to "true" preserved packs from the last gc run
are pruned before current packs are preserved.
"pack.preserveoldpacks": if set to "true" current packs will be hard linked
to objects/pack/preserved before git gc is executed. JGit will
fallback to the preserved packs in this directory in case it comes
across missing objects which might be caused by a concurrent run of
git gc.
EOF
exit "$1"
}
# acquire file lock, unlock when the script exits
lock() { # repo
readonly LOCKFILE="$1/gc-preserve.pid"
test -f "$LOCKFILE" || touch "$LOCKFILE"
exec 9> "$LOCKFILE"
if flock -nx 9; then
echo -n "$$ $USER@$(hostname)" >&9
trap unlock EXIT
else
echo "$0 is already running"
exit 3
fi
}
unlock() {
# only delete if the file descriptor 9 is open
if { : >&9 ; } &> /dev/null; then
rm -f "$LOCKFILE"
fi
# close the file handle to release file lock
exec 9>&-
}
# prune preserved packs if pack.prunepreserved == true
prune_preserved() { # repo
configured=$(git --git-dir="$1" config --get pack.prunepreserved)
if [ "$configured" != "true" ]; then
return 0
fi
local preserved=$1/objects/pack/preserved
if [ -d "$preserved" ]; then
printf "Pruning old preserved packs: "
count=$(find "$preserved" -name "*.old-pack" | wc -l)
rm -rf "$preserved"
echo "$count, done."
fi
}
# preserve packs if pack.preserveoldpacks == true
preserve_packs() { # repo
configured=$(git --git-dir="$1" config --get pack.preserveoldpacks)
if [ "$configured" != "true" ]; then
return 0
fi
local packdir=$1/objects/pack
pushd "$packdir" >/dev/null || exit 1
mkdir -p preserved
printf "Preserving packs: "
count=0
for file in pack-*{.pack,.idx} ; do
ln -f "$file" preserved/"$(get_preserved_packfile_name "$file")"
if [[ "$file" == pack-*.pack ]]; then
((count++))
fi
done
echo "$count, done."
popd >/dev/null || exit 1
}
# pack-0...2.pack to pack-0...2.old-pack
# pack-0...2.idx to pack-0...2.old-idx
get_preserved_packfile_name() { # packfile > preserved_packfile
local old=${1/%\.pack/.old-pack}
old=${old/%\.idx/.old-idx}
echo "$old"
}
# main
while [ $# -gt 0 ] ; do
case "$1" in
-u|-h) usage 0 ;;
esac
shift
done
args=$(git rev-parse --sq-quote "$@")
repopath=$(git rev-parse --git-dir)
if [ -z "$repopath" ]; then
usage 2
fi
lock "$repopath"
prune_preserved "$repopath"
preserve_packs "$repopath"
git gc ${args:+"$args"} || { EXIT_CODE="$?"; echo "git gc failed"; exit "$EXIT_CODE"; }

23
overlays/iusb-spoof.nix Normal file
View file

@ -0,0 +1,23 @@
{ rustPlatform, python3, makeWrapper }:
let
pythonEnv = python3.withPackages (p: with p; [ requests ]);
in
rustPlatform.buildRustPackage rec {
pname = "iusb-spoof";
version = "0.1.0";
src = builtins.fetchGit {
url = "https://git.lix.systems/the-distro/iusb-spoof/";
rev = "fafd47986239cc2f4dfbbae74b17555608806581";
};
cargoLock.lockFile = src + "/Cargo.lock";
nativeBuildInputs = [ makeWrapper ];
postInstall = ''
install -Dm644 $src/make-token.py $out/opt/make-token.py
makeWrapper ${pythonEnv.interpreter} $out/bin/make-token --add-flags "$out/opt/make-token.py"
'';
}

View file

@ -0,0 +1,42 @@
{ lib
, buildGoModule
, fetchFromGitHub
}:
buildGoModule rec {
pname = "pyroscope";
version = "1.7.1";
src = fetchFromGitHub {
owner = "grafana";
repo = "pyroscope";
rev = "v${version}";
hash = "sha256-iMP67J0Q8Cgo52iImMzAM3PEkk6uLF7r6v9TyXZVaIE=";
};
env.GOWORK = "off";
vendorHash = "sha256-ggntpnU9s2rpkv6S0LnZNexrdkBsdsUrGPc93SVrK4M=";
subPackages = [ "cmd/profilecli" "cmd/pyroscope" ];
ldflags = [
"-extldflags"
"-static"
"-s"
"-w"
"-X=github.com/grafana/pyroscope/pkg/util/build.Branch=${src.rev}"
"-X=github.com/grafana/pyroscope/pkg/util/build.Version=${version}"
"-X=github.com/grafana/pyroscope/pkg/util/build.Revision=${src.rev}"
"-X=github.com/grafana/pyroscope/pkg/util/build.BuildDate=1970-01-01T00:00:00Z"
];
meta = with lib; {
description = "Continuous profiling platform";
homepage = "https://github.com/grafana/pyroscope";
changelog = "https://github.com/grafana/pyroscope/blob/${src.rev}/CHANGELOG.md";
license = licenses.agpl3Only;
maintainers = with maintainers; [ raitobezarius ];
mainProgram = "pyroscope";
};
}

View file

@ -0,0 +1,39 @@
# Originally written by Jade Lovelace for Lix.
{ lib, buildGoModule, fetchFromGitHub }:
buildGoModule rec {
pname = "s3-revproxy";
version = "4.15.0";
src = fetchFromGitHub {
owner = "oxyno-zeta";
repo = "s3-proxy";
rev = "v${version}";
hash = "sha256-q0cfAo8Uz7wtKljmSDaJ320bjg2yXydvvxubAsMKzbc=";
};
vendorHash = "sha256-dOwNQtTfOCQcjgNBV/FeWdwbW9xi1OK5YD7PBPPDKOQ=";
ldflags = [
"-X github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/version.Version=${version}"
"-X github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/version.Metadata="
];
postPatch = ''
# Refer to the included templates in the package instead of cwd-relative
sed -i "s#Path = \"templates/#Path = \"$out/share/s3-revproxy/templates/#" pkg/s3-proxy/config/config.go
'';
postInstall = ''
mkdir -p $out/share/s3-revproxy
cp -r templates/ $out/share/s3-revproxy/templates
'';
meta = {
description = "S3 Reverse Proxy with GET, PUT and DELETE methods and authentication (OpenID Connect and Basic Auth)";
homepage = "https://oxyno-zeta.github.io/s3-proxy";
# hm, not having a maintainers entry is kind of inconvenient
maintainers = [ ];
licenses = lib.licenses.asl20;
mainProgram = "s3-proxy";
};
}

View file

@ -0,0 +1,20 @@
{ buildGoModule, fetchFromGitHub }:
buildGoModule rec {
pname = "u-root";
version = "0.14.0";
src = fetchFromGitHub {
owner = "u-root";
repo = "u-root";
rev = "v${version}";
hash = "sha256-8zA3pHf45MdUcq/MA/mf0KCTxB1viHieU/oigYwIPgo=";
};
patches = [
./u-root-allow-https.patch
];
vendorHash = null;
doCheck = false;
}

View file

@ -0,0 +1,12 @@
diff --git a/pkg/curl/schemes.go b/pkg/curl/schemes.go
index 8bac3bc0..cd396cbc 100644
--- a/pkg/curl/schemes.go
+++ b/pkg/curl/schemes.go
@@ -81,6 +81,7 @@ var (
DefaultSchemes = Schemes{
"tftp": DefaultTFTPClient,
"http": DefaultHTTPClient,
+ "https": DefaultHTTPClient,
"file": &LocalFileClient{},
}
)

View file

@ -0,0 +1,59 @@
diff --git a/services/repository/branch.go b/services/repository/branch.go
index e1a313749f..5a8d823eef 100644
--- a/services/repository/branch.go
+++ b/services/repository/branch.go
@@ -26,7 +26,6 @@ import (
"code.gitea.io/gitea/modules/timeutil"
webhook_module "code.gitea.io/gitea/modules/webhook"
notify_service "code.gitea.io/gitea/services/notify"
- files_service "code.gitea.io/gitea/services/repository/files"
"xorm.io/builder"
)
@@ -129,21 +128,7 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g
p := protectedBranches.GetFirstMatched(branchName)
isProtected := p != nil
- var divergence *git.DivergeObject
-
- // it's not default branch
- if repo.DefaultBranch != dbBranch.Name && !dbBranch.IsDeleted {
- var err error
- divergence, err = files_service.CountDivergingCommits(ctx, repo, git.BranchPrefix+branchName)
- if err != nil {
- return nil, fmt.Errorf("CountDivergingCommits: %v", err)
- }
- }
-
- if divergence == nil {
- // tolerate the error that we cannot get divergence
- divergence = &git.DivergeObject{Ahead: -1, Behind: -1}
- }
+ divergence := &git.DivergeObject{Ahead: -1, Behind: -1}
pr, err := issues_model.GetLatestPullRequestByHeadInfo(ctx, repo.ID, branchName)
if err != nil {
diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl
index a577fed450..e102796315 100644
--- a/templates/repo/branch/list.tmpl
+++ b/templates/repo/branch/list.tmpl
@@ -102,19 +102,6 @@
{{end}}
</td>
<td class="two wide ui">
- {{if and (not .DBBranch.IsDeleted) $.DefaultBranchBranch}}
- <div class="commit-divergence">
- <div class="bar-group">
- <div class="count count-behind">{{.CommitsBehind}}</div>
- {{/* old code bears 0/0.0 = NaN output, so it might output invalid "width: NaNpx", it just works and doesn't caues any problem. */}}
- <div class="bar bar-behind" style="width: {{Eval 100 "*" .CommitsBehind "/" "(" .CommitsBehind "+" .CommitsAhead "+" 0.0 ")"}}%"></div>
- </div>
- <div class="bar-group">
- <div class="count count-ahead">{{.CommitsAhead}}</div>
- <div class="bar bar-ahead" style="width: {{Eval 100 "*" .CommitsAhead "/" "(" .CommitsBehind "+" .CommitsAhead "+" 0.0 ")"}}%"></div>
- </div>
- </div>
- {{end}}
</td>
<td class="two wide right aligned">
{{if not .LatestPullRequest}}

View file

@ -0,0 +1,32 @@
diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go
index 718454e063..8fa299710c 100644
--- a/routers/web/repo/commit.go
+++ b/routers/web/repo/commit.go
@@ -408,12 +408,6 @@ func Diff(ctx *context.Context) {
}
}
- ctx.Data["BranchName"], err = commit.GetBranchName()
- if err != nil {
- ctx.ServerError("commit.GetBranchName", err)
- return
- }
-
ctx.HTML(http.StatusOK, tplCommitPage)
}
diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl
index c37fb46975..18c9cf18f8 100644
--- a/templates/repo/commit_page.tmpl
+++ b/templates/repo/commit_page.tmpl
@@ -71,8 +71,8 @@
"branchForm" "branch-dropdown-form"
"branchURLPrefix" (printf "%s/_cherrypick/%s/" $.RepoLink .CommitID) "branchURLSuffix" ""
"setAction" true "submitForm" true}}
- <form method="get" action="{{$.RepoLink}}/_cherrypick/{{.CommitID}}/{{if $.BranchName}}{{PathEscapeSegments $.BranchName}}{{else}}{{PathEscapeSegments $.Repository.DefaultBranch}}{{end}}" id="branch-dropdown-form">
- <input type="hidden" name="ref" value="{{if $.BranchName}}{{$.BranchName}}{{else}}{{$.Repository.DefaultBranch}}{{end}}">
+ <form method="get" action="{{$.RepoLink}}/_cherrypick/{{.CommitID}}/{{PathEscapeSegments $.Repository.DefaultBranch}}" id="branch-dropdown-form">
+ <input type="hidden" name="ref" value="{{$.Repository.DefaultBranch}}">
<input type="hidden" name="refType" value="branch">
<input type="hidden" id="cherry-pick-type" name="cherry-pick-type"><br>
<button type="submit" id="cherry-pick-submit" class="ui primary button"></button>

40
pkgs/forgejo/default.nix Normal file
View file

@ -0,0 +1,40 @@
{ forgejo-lts }:
forgejo-lts.overrideAttrs (prev: {
patches = [
# Branch divergence calculations for a single branch may take 100-200ms on something as big
# as nixpkgs. The branch view defaults to 20 branches for each page, taking roughtly 3s to
# calculate each branch sequentially and render, while consuming a single core at 100%.
# The idea is to look into making this less expensive or async.
# But for now, to get this going, we will simply drop that metric.
./branch-view_remove-expensive-commit-divergence-metric.patch
# This is literally broken and eats resources for nothing of value.
# We should upstream this.
# The tl;dr is: It calculates the nearest branch for the requested commit at
# /:owner/:repo/commit/:commit to use it as the default cherry-pick target branch
# selection in a drop-down only users with commit perms can actually view and use.
# It's expensive to calculate and happens on every request to /commit/:commit.
# To add insult to injury, it's hardly of any use: The nearest branch of a commit
# will almost always be a branch that already carries the commit. The branch you
# most likely don't want to cherry-pick to.
./commit-view_fix-broken-and-expensive-cherry-pick-default-branch-selection.patch
# Disable various /:owner/:repo/activity/ sub-views. They are expensive, which is
# totally fine and expected. There is even proper caching in place.
# However, on a scale of nixpkgs, those calculations take ages, while, of course,
# pinning a single CPU core at 100%.
# For now, we will simply disable this feature.
# Due to the 501 status code it returns, the frontend prints a "Not implemented"
# error, saving us from patching the frontend while still providing a helpful
# user-facing error text.
# It should be noted that this particular status code has the downside of being
# in the 5xx range, meaning it will show up as such in our prometheus metrics.
./disable-expensive-repository-activity-stats.patch
# Migrations and pull-mirrors are something easily abused to bring a public instance to a complete halt.
# Both features can be disabled via repository.DISABLE_MIGRATIONS and mirror.ENABLE, but we want to keep
# this functionality for admins.
./limit-migrations-and-pull-mirrors-to-admins.patch
];
})

View file

@ -0,0 +1,34 @@
diff --git a/routers/web/web.go b/routers/web/web.go
index ee9694f41c..f55b8d6f62 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -57,6 +57,10 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
+func endpointNotImplemented(ctx *context.Context) {
+ ctx.JSON(http.StatusNotImplemented, "This endpoint has been removed due to performance issues with it and as such is not longer implemented.")
+}
+
// optionsCorsHandler return a http handler which sets CORS options if enabled by config, it blocks non-CORS OPTIONS requests.
func optionsCorsHandler() func(next http.Handler) http.Handler {
var corsHandler func(next http.Handler) http.Handler
@@ -1425,15 +1429,15 @@ func registerRoutes(m *web.Route) {
m.Get("/{period}", repo.Activity)
m.Group("/contributors", func() {
m.Get("", repo.Contributors)
- m.Get("/data", repo.ContributorsData)
+ m.Get("/data", endpointNotImplemented)
}, repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode))
m.Group("/code-frequency", func() {
m.Get("", repo.CodeFrequency)
- m.Get("/data", repo.CodeFrequencyData)
+ m.Get("/data", endpointNotImplemented)
}, repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode))
m.Group("/recent-commits", func() {
m.Get("", repo.RecentCommits)
- m.Get("/data", repo.RecentCommitsData)
+ m.Get("/data", endpointNotImplemented)
}, repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode))
}, context.RepoRef(), context.RequireRepoReaderOr(unit.TypeCode, unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases))

View file

@ -0,0 +1,53 @@
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index 2caaa130e8..455e89e93e 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -12,7 +12,6 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
@@ -86,22 +85,7 @@ func Migrate(ctx *context.APIContext) {
}
if !ctx.Doer.IsAdmin {
- if !repoOwner.IsOrganization() && ctx.Doer.ID != repoOwner.ID {
- ctx.Error(http.StatusForbidden, "", "Given user is not an organization.")
- return
- }
-
- if repoOwner.IsOrganization() {
- // Check ownership of organization.
- isOwner, err := organization.OrgFromUser(repoOwner).IsOwnedBy(ctx, ctx.Doer.ID)
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "IsOwnedBy", err)
- return
- } else if !isOwner {
- ctx.Error(http.StatusForbidden, "", "Given user is not owner of organization.")
- return
- }
- }
+ ctx.Error(http.StatusForbidden, "", "You need to be administrator of this Forgejo instance to be able to create mirrors.")
}
remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go
index 97b0c425ea..554a470eab 100644
--- a/routers/web/repo/migrate.go
+++ b/routers/web/repo/migrate.go
@@ -150,6 +150,12 @@ func handleMigrateRemoteAddrError(ctx *context.Context, err error, tpl base.TplN
// MigratePost response for migrating from external git repository
func MigratePost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.MigrateRepoForm)
+
+ if !ctx.Doer.IsAdmin {
+ ctx.Error(http.StatusForbidden, "MigratePost: you need to be site administrator to use migrations and mirrors")
+ return
+ }
+
if setting.Repository.DisableMigrations {
ctx.Error(http.StatusForbidden, "MigratePost: the site administrator has disabled migrations")
return

View file

@ -1,37 +0,0 @@
From 084e4f92fb58f7cd85303ba602fb3c40133c8fcc Mon Sep 17 00:00:00 2001
From: Luke Granger-Brown <git@lukegb.com>
Date: Thu, 2 Jul 2020 23:02:32 +0100
Subject: [PATCH 1/3] Syntax highlight nix
---
.../app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts | 1 +
resources/com/google/gerrit/server/mime/mime-types.properties | 1 +
2 files changed, 2 insertions(+)
diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
index a9f88bdd81..385249f280 100644
--- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
+++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
@@ -93,6 +93,7 @@ const LANGUAGE_MAP = new Map<string, string>([
['text/x-vhdl', 'vhdl'],
['text/x-yaml', 'yaml'],
['text/vbscript', 'vbscript'],
+ ['text/x-nix', 'nix'],
]);
const CLASS_PREFIX = 'gr-diff gr-syntax gr-syntax-';
diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties
index 2f9561ba2e..739818ec05 100644
--- a/resources/com/google/gerrit/server/mime/mime-types.properties
+++ b/resources/com/google/gerrit/server/mime/mime-types.properties
@@ -149,6 +149,7 @@ mscin = text/x-mscgen
msgenny = text/x-msgenny
nb = text/x-mathematica
nginx.conf = text/x-nginx-conf
+nix = text/x-nix
nsh = text/x-nsis
nsi = text/x-nsis
nt = text/n-triples
--
2.37.3

View file

@ -1,37 +0,0 @@
From aedf8ac8fa5113843bcd83ff85e2d9f3bffdb16c Mon Sep 17 00:00:00 2001
From: Luke Granger-Brown <git@lukegb.com>
Date: Thu, 2 Jul 2020 23:02:43 +0100
Subject: [PATCH 2/3] Syntax highlight rules.pl
---
.../app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts | 1 +
resources/com/google/gerrit/server/mime/mime-types.properties | 1 +
2 files changed, 2 insertions(+)
diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
index 385249f280..7cb3068494 100644
--- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
+++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
@@ -68,6 +68,7 @@ const LANGUAGE_MAP = new Map<string, string>([
['text/x-perl', 'perl'],
['text/x-pgsql', 'pgsql'], // postgresql
['text/x-php', 'php'],
+ ['text/x-prolog', 'prolog'],
['text/x-properties', 'properties'],
['text/x-protobuf', 'protobuf'],
['text/x-puppet', 'puppet'],
diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties
index 739818ec05..58eb727bf9 100644
--- a/resources/com/google/gerrit/server/mime/mime-types.properties
+++ b/resources/com/google/gerrit/server/mime/mime-types.properties
@@ -200,6 +200,7 @@ rq = application/sparql-query
rs = text/x-rustsrc
rss = application/xml
rst = text/x-rst
+rules.pl = text/x-prolog
README.md = text/x-gfm
s = text/x-gas
sas = text/x-sas
--
2.37.3

View file

@ -1,215 +0,0 @@
From f49c50ca9a84ca374b7bd91c171bbea0457f2c7a Mon Sep 17 00:00:00 2001
From: Luke Granger-Brown <git@lukegb.com>
Date: Thu, 2 Jul 2020 23:03:02 +0100
Subject: [PATCH 3/3] Add titles to CLs over HTTP
---
.../gerrit/httpd/raw/IndexHtmlUtil.java | 13 +++-
.../google/gerrit/httpd/raw/IndexServlet.java | 8 ++-
.../google/gerrit/httpd/raw/StaticModule.java | 5 +-
.../gerrit/httpd/raw/TitleComputer.java | 67 +++++++++++++++++++
.../gerrit/httpd/raw/PolyGerritIndexHtml.soy | 4 +-
5 files changed, 89 insertions(+), 8 deletions(-)
create mode 100644 java/com/google/gerrit/httpd/raw/TitleComputer.java
diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
index 72bfe40c3b..439bd73b44 100644
--- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
+++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
@@ -41,6 +41,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@@ -62,13 +63,14 @@ public class IndexHtmlUtil {
String faviconPath,
Map<String, String[]> urlParameterMap,
Function<String, SanitizedContent> urlInScriptTagOrdainer,
- String requestedURL)
+ String requestedURL,
+ TitleComputer titleComputer)
throws URISyntaxException, RestApiException {
ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
data.putAll(
staticTemplateData(
canonicalURL, cdnPath, faviconPath, urlParameterMap, urlInScriptTagOrdainer))
- .putAll(dynamicTemplateData(gerritApi, requestedURL));
+ .putAll(dynamicTemplateData(gerritApi, requestedURL, titleComputer));
Set<String> enabledExperiments = new HashSet<>();
enabledExperiments.addAll(experimentFeatures.getEnabledExperimentFeatures());
// Add all experiments enabled through url
@@ -81,7 +83,8 @@ public class IndexHtmlUtil {
/** Returns dynamic parameters of {@code index.html}. */
public static ImmutableMap<String, Object> dynamicTemplateData(
- GerritApi gerritApi, String requestedURL) throws RestApiException, URISyntaxException {
+ GerritApi gerritApi, String requestedURL, TitleComputer titleComputer)
+ throws RestApiException, URISyntaxException {
ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
Map<String, SanitizedContent> initialData = new HashMap<>();
Server serverApi = gerritApi.config().server();
@@ -129,6 +132,10 @@ public class IndexHtmlUtil {
}
data.put("gerritInitialData", initialData);
+
+ Optional<String> title = titleComputer.computeTitle(requestedURL);
+ title.ifPresent(s -> data.put("title", s));
+
return data.build();
}
diff --git a/java/com/google/gerrit/httpd/raw/IndexServlet.java b/java/com/google/gerrit/httpd/raw/IndexServlet.java
index fcb821e5ae..e1464b992b 100644
--- a/java/com/google/gerrit/httpd/raw/IndexServlet.java
+++ b/java/com/google/gerrit/httpd/raw/IndexServlet.java
@@ -48,13 +48,15 @@ public class IndexServlet extends HttpServlet {
private final ExperimentFeatures experimentFeatures;
private final SoySauce soySauce;
private final Function<String, SanitizedContent> urlOrdainer;
+ private TitleComputer titleComputer;
IndexServlet(
@Nullable String canonicalUrl,
@Nullable String cdnPath,
@Nullable String faviconPath,
GerritApi gerritApi,
- ExperimentFeatures experimentFeatures) {
+ ExperimentFeatures experimentFeatures,
+ TitleComputer titleComputer) {
this.canonicalUrl = canonicalUrl;
this.cdnPath = cdnPath;
this.faviconPath = faviconPath;
@@ -69,6 +71,7 @@ public class IndexServlet extends HttpServlet {
(s) ->
UnsafeSanitizedContentOrdainer.ordainAsSafe(
s, SanitizedContent.ContentKind.TRUSTED_RESOURCE_URI);
+ this.titleComputer = titleComputer;
}
@Override
@@ -86,7 +89,8 @@ public class IndexServlet extends HttpServlet {
faviconPath,
parameterMap,
urlOrdainer,
- getRequestUrl(req));
+ getRequestUrl(req),
+ titleComputer);
renderer = soySauce.renderTemplate("com.google.gerrit.httpd.raw.Index").setData(templateData);
} catch (URISyntaxException | RestApiException e) {
throw new IOException(e);
diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
index 15dcf42e0e..9f56bf33ce 100644
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
@@ -241,10 +241,11 @@ public class StaticModule extends ServletModule {
@CanonicalWebUrl @Nullable String canonicalUrl,
@GerritServerConfig Config cfg,
GerritApi gerritApi,
- ExperimentFeatures experimentFeatures) {
+ ExperimentFeatures experimentFeatures,
+ TitleComputer titleComputer) {
String cdnPath = options.devCdn().orElse(cfg.getString("gerrit", null, "cdnPath"));
String faviconPath = cfg.getString("gerrit", null, "faviconPath");
- return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures);
+ return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures, titleComputer);
}
@Provides
diff --git a/java/com/google/gerrit/httpd/raw/TitleComputer.java b/java/com/google/gerrit/httpd/raw/TitleComputer.java
new file mode 100644
index 0000000000..8fd2053ad0
--- /dev/null
+++ b/java/com/google/gerrit/httpd/raw/TitleComputer.java
@@ -0,0 +1,67 @@
+package com.google.gerrit.httpd.raw;
+
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.Change;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.restapi.change.ChangesCollection;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Singleton
+public class TitleComputer {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ @Inject
+ public TitleComputer(Provider<ChangesCollection> changes) {
+ this.changes = changes;
+ }
+
+ public Optional<String> computeTitle(String requestedURI) {
+ URL url = null;
+ try {
+ url = new URL(requestedURI);
+ } catch (MalformedURLException e) {
+ logger.atWarning().log("Failed to turn %s into a URL.", requestedURI);
+ return Optional.empty();
+ }
+
+ // Try to turn this into a change.
+ Optional<Change.Id> changeId = tryExtractChange(url.getPath());
+ if (changeId.isPresent()) {
+ return titleFromChangeId(changeId.get());
+ }
+
+ return Optional.empty();
+ }
+
+ private static final Pattern extractChangeIdRegex = Pattern.compile("^/(?:c/.*/\\+/)?(?<changeId>[0-9]+)(?:/[0-9]+)?(?:/.*)?$");
+ private final Provider<ChangesCollection> changes;
+
+ private Optional<Change.Id> tryExtractChange(String path) {
+ Matcher m = extractChangeIdRegex.matcher(path);
+ if (!m.matches()) {
+ return Optional.empty();
+ }
+ return Change.Id.tryParse(m.group("changeId"));
+ }
+
+ private Optional<String> titleFromChangeId(Change.Id changeId) {
+ ChangesCollection changesCollection = changes.get();
+ try {
+ ChangeResource changeResource = changesCollection.parse(changeId);
+ return Optional.of(changeResource.getChange().getSubject());
+ } catch (ResourceConflictException | ResourceNotFoundException | PermissionBackendException e) {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
index dbfef44dfe..347ee75aab 100644
--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
+++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
@@ -33,10 +33,12 @@
{@param? defaultDashboardHex: ?}
{@param? dashboardQuery: ?}
{@param? userIsAuthenticated: ?}
+ {@param? title: ?}
<!DOCTYPE html>{\n}
<html lang="en">{\n}
<meta charset="utf-8">{\n}
- <meta name="description" content="Gerrit Code Review">{\n}
+ {if $title}<title>{$title} · Gerrit Code Review</title>{\n}{/if}
+ <meta name="description" content="{if $title}{$title} · {/if}Gerrit Code Review">{\n}
<meta name="referrer" content="never">{\n}
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">{\n}
--
2.37.3

View file

@ -1,152 +0,0 @@
{ buildFHSUserEnv, writeShellScriptBin, buildBazelPackage, fetchgit, unzip }:
{ name ? "gerrit-${version}", version ? "3.9.1", src ? (fetchgit {
url = "https://gerrit.googlesource.com/gerrit";
rev = "620a819cbf3c64fff7a66798822775ad42c91d8e";
branchName = "v${version}";
sha256 = "sha256:1mdxbgnx3mpxand4wq96ic38bb4yh45q271h40jrk7dk23sgmz02";
fetchSubmodules = true;
}), bazelTargets ? [ "release" "api-skip-javadoc" ]
}:
let
bazelRunScript = writeShellScriptBin "bazel-run" ''
yarn config set cache-folder "$bazelOut/external/yarn_cache"
export HOME="$bazelOut/external/home"
mkdir -p "$bazelOut/external/home"
exec /bin/bazel "$@"
'';
bazelTop = buildFHSUserEnv {
name = "bazel";
targetPkgs = pkgs: [
(pkgs.bazel_5.override { enableNixHacks = true; })
pkgs.jdk17_headless
pkgs.zlib
pkgs.python3
pkgs.curl
pkgs.nodejs
pkgs.yarn
pkgs.git
bazelRunScript
];
runScript = "/bin/bazel-run";
};
bazel = bazelTop // { override = x: bazelTop; };
in
buildBazelPackage {
inherit name version src;
patches = [
./0001-Syntax-highlight-nix.patch
./0002-Syntax-highlight-rules.pl.patch
./0003-Add-titles-to-CLs-over-HTTP.patch
];
inherit bazel bazelTargets;
bazelFlags = [
"--repository_cache="
"--disk_cache="
];
removeRulesCC = false;
fetchConfigured = true;
fetchAttrs = {
sha256 = "sha256-rsYQR6/RO5NM3/fnB3lEmbz876B59QWxWpE3M/Z4rK4=";
preBuild = ''
rm .bazelversion
'';
installPhase = ''
runHook preInstall
# Remove all built in external workspaces, Bazel will recreate them when building
rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker}
rm -rf $bazelOut/external/{embedded_jdk,\@embedded_jdk.marker}
rm -rf $bazelOut/external/{local_config_cc,\@local_config_cc.marker}
rm -rf $bazelOut/external/{local_*,\@local_*.marker}
# Clear markers
find $bazelOut/external -name '@*\.marker' -exec sh -c 'echo > {}' \;
# Remove all vcs files
rm -rf $(find $bazelOut/external -type d -name .git)
rm -rf $(find $bazelOut/external -type d -name .svn)
rm -rf $(find $bazelOut/external -type d -name .hg)
# Removing top-level symlinks along with their markers.
# This is needed because they sometimes point to temporary paths (?).
# For example, in Tensorflow-gpu build:
#sha256:06bmzbcb9717s4b016kcbn8nr9pgaz04i8bnzg7ybkbdwpl8vxvv"; platforms -> NIX_BUILD_TOP/tmp/install/35282f5123611afa742331368e9ae529/_embedded_binaries/platforms
find $bazelOut/external -maxdepth 1 -type l | while read symlink; do
name="$(basename "$symlink")"
rm -rf "$symlink" "$bazelOut/external/@$name.marker"
done
# Patching symlinks to remove build directory reference
find $bazelOut/external -type l | while read symlink; do
new_target="$(readlink "$symlink" | sed "s,$NIX_BUILD_TOP,NIX_BUILD_TOP,")"
rm "$symlink"
ln -sf "$new_target" "$symlink"
done
echo '${bazel.name}' > $bazelOut/external/.nix-bazel-version
# Gerrit fixups:
# Normalize permissions on .yarn-{tarball,metadata} files
test -d $bazelOut/external/yarn_cache && find $bazelOut/external/yarn_cache \( -name .yarn-tarball.tgz -or -name .yarn-metadata.json \) -exec chmod 644 {} +
mkdir $bazelOut/_bits/
find . -name node_modules -prune -print | while read d; do
echo "$d" "$(dirname $d)"
mkdir -p $bazelOut/_bits/$(dirname $d)
cp -R "$d" "$bazelOut/_bits/$(dirname $d)/node_modules"
done
(cd $bazelOut/ && tar czf $out --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner external/ _bits/)
runHook postInstall
'';
};
buildAttrs = {
preConfigure = ''
rm .bazelversion
[ "$(ls -A $bazelOut/_bits)" ] && cp -R $bazelOut/_bits/* ./ || true
'';
postPatch = ''
# Disable all errorprone checks, since we might be using a different version.
sed -i \
-e '/-Xep:/d' \
-e '/-XepExcludedPaths:/a "-XepDisableAllChecks",' \
tools/BUILD
'';
installPhase = ''
mkdir -p "$out"/webapps/ "$out"/share/api/
cp bazel-bin/release.war "$out"/webapps/gerrit-${version}.war
unzip bazel-bin/api-skip-javadoc.zip -d "$out"/share/api
'';
nativeBuildInputs = [
unzip
];
};
passthru = {
# A list of plugins that are part of the gerrit.war file.
# Use `java -jar gerrit.war ls | grep -Po '(?<=plugins/)[^.]+' | sed -e 's,^,",' -e 's,$,",' | sort` to generate that list.
plugins = [
"codemirror-editor"
"commit-message-length-validator"
"delete-project"
"download-commands"
"gitiles"
"hooks"
"plugin-manager"
"replication"
"reviewnotes"
"singleusergroup"
"webhooks"
];
};
}

View file

@ -1,97 +0,0 @@
package main
import (
"archive/zip"
"flag"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sort"
"strings"
)
var (
exclude = flag.String("exclude", "", "comma-separated list of filenames to exclude (in any directory)")
)
func init() {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s [zip file] [directory]:\n", os.Args[0])
flag.PrintDefaults()
}
}
func listToMap(ss []string) map[string]bool {
m := make(map[string]bool)
for _, s := range ss {
m[s] = true
}
return m
}
func main() {
flag.Parse()
if flag.NArg() != 2 {
flag.Usage()
os.Exit(1)
}
outPath := flag.Arg(0)
dirPath := flag.Arg(1)
excludeFiles := listToMap(strings.Split(*exclude, ","))
// Aggregate all files first.
var files []string
filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if excludeFiles[info.Name()] {
return nil
}
files = append(files, path)
return nil
})
// Create zip
outW, err := os.Create(outPath)
if err != nil {
log.Fatalf("Create(%q): %v", outPath, err)
}
zipW := zip.NewWriter(outW)
// Output files in alphabetical order
sort.Strings(files)
for _, f := range files {
fw, err := zipW.CreateHeader(&zip.FileHeader{
Name: f,
Method: zip.Store,
})
if err != nil {
log.Fatalf("creating %q in zip: %v", f, err)
}
ff, err := os.Open(f)
if err != nil {
log.Fatalf("opening %q: %v", f, err)
}
if _, err := io.Copy(fw, ff); err != nil {
log.Fatalf("copying %q to zip: %v", f, err)
}
ff.Close()
}
if err := zipW.Close(); err != nil {
log.Fatalf("writing ZIP central directory: %v", err)
}
if err := outW.Close(); err != nil {
log.Fatalf("closing ZIP file: %v", err)
}
}

View file

@ -1,36 +0,0 @@
{ buildGerrit, gerrit, runCommandLocal, lib }:
{ name
, src
, depsOutputHash
, overlayPluginCmd ? ''
cp -R "${src}" "$out/plugins/${name}"
''
, postPatch ? ""
, patches ? [ ]
}: (buildGerrit {
name = "${name}.jar";
src = runCommandLocal "${name}-src" { } ''
cp -R "${gerrit.src}" "$out"
chmod +w "$out/plugins"
${overlayPluginCmd}
'';
bazelTargets = [ "//plugins/${name}" ];
}).overrideAttrs (super: {
deps = super.deps.overrideAttrs (superDeps: {
outputHash = depsOutputHash;
});
installPhase = ''
cp "bazel-bin/plugins/${name}/${name}.jar" "$out"
'';
postPatch = ''
${super.postPatch or ""}
pushd "plugins/${name}"
${lib.concatMapStringsSep "\n" (patch: ''
patch -p1 < ${patch}
'') patches}
popd
${postPatch}
'';
})

View file

@ -1,14 +0,0 @@
{ fetchgit, buildGerritBazelPlugin, lib }:
buildGerritBazelPlugin {
name = "code-owners";
depsOutputHash = "sha256-Ee2n7R/vi91drR+dNYB0QnGiiqcmz9/pynHhV9yDxdE=";
src = fetchgit {
url = "https://gerrit.googlesource.com/plugins/code-owners";
rev = "e654ae5bda2085bce9a99942bec440e004a114f3";
sha256 = "sha256:14d3x3iqskgw16pvyaa0swh252agj84p9pzlf24l8lgx9d7y4biz";
};
patches = [
./using-usernames.patch
];
}

View file

@ -1,472 +0,0 @@
commit 29ace6c38ac513f7ec56ca425230d5712c081043
Author: Luke Granger-Brown <git@lukegb.com>
Date: Wed Sep 21 03:15:38 2022 +0100
Add support for usernames and groups
Change-Id: I3ba8527f66216d08e555a6ac4451fe0d1e090de5
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
index 70009591..6dc596c9 100644
--- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
+++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
@@ -17,6 +17,8 @@ package com.google.gerrit.plugins.codeowners.backend;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
+import static com.google.common.collect.ImmutableSetMultimap.flatteningToImmutableSetMultimap;
+import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
import static com.google.gerrit.plugins.codeowners.backend.CodeOwnersInternalServerErrorException.newInternalServerError;
import static java.util.Objects.requireNonNull;
@@ -25,6 +27,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
@@ -33,17 +36,24 @@ import com.google.gerrit.entities.Project;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
+import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountControl;
import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.GroupBackends;
+import com.google.gerrit.server.account.InternalGroupBackend;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdCache;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.util.RequestContext;
+import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.inject.Inject;
+import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import java.io.IOException;
import java.nio.file.Path;
@@ -102,6 +112,8 @@ public class CodeOwnerResolver {
@VisibleForTesting public static final String ALL_USERS_WILDCARD = "*";
+ public static final String GROUP_PREFIX = "group:";
+
private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
private final PermissionBackend permissionBackend;
private final Provider<CurrentUser> currentUser;
@@ -112,6 +124,8 @@ public class CodeOwnerResolver {
private final CodeOwnerMetrics codeOwnerMetrics;
private final UnresolvedImportFormatter unresolvedImportFormatter;
private final TransientCodeOwnerCache transientCodeOwnerCache;
+ private final InternalGroupBackend groupBackend;
+ private final ThreadLocalRequestContext context;
// Enforce visibility by default.
private boolean enforceVisibility = true;
@@ -132,7 +146,9 @@ public class CodeOwnerResolver {
PathCodeOwners.Factory pathCodeOwnersFactory,
CodeOwnerMetrics codeOwnerMetrics,
UnresolvedImportFormatter unresolvedImportFormatter,
- TransientCodeOwnerCache transientCodeOwnerCache) {
+ TransientCodeOwnerCache transientCodeOwnerCache,
+ InternalGroupBackend groupBackend,
+ ThreadLocalRequestContext context) {
this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
this.permissionBackend = permissionBackend;
this.currentUser = currentUser;
@@ -143,6 +159,8 @@ public class CodeOwnerResolver {
this.codeOwnerMetrics = codeOwnerMetrics;
this.unresolvedImportFormatter = unresolvedImportFormatter;
this.transientCodeOwnerCache = transientCodeOwnerCache;
+ this.groupBackend = groupBackend;
+ this.context = context;
}
/**
@@ -361,6 +379,12 @@ public class CodeOwnerResolver {
"cannot resolve code owner email %s: no account with this email exists",
CodeOwnerResolver.ALL_USERS_WILDCARD));
}
+ if (codeOwnerReference.email().startsWith(GROUP_PREFIX)) {
+ return OptionalResultWithMessages.createEmpty(
+ String.format(
+ "cannot resolve code owner email %s: this is a group",
+ codeOwnerReference.email()));
+ }
ImmutableList.Builder<String> messageBuilder = ImmutableList.builder();
AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
@@ -405,9 +429,53 @@ public class CodeOwnerResolver {
ImmutableMultimap<CodeOwnerReference, CodeOwnerAnnotation> annotations) {
requireNonNull(codeOwnerReferences, "codeOwnerReferences");
+ ImmutableSet<String> groupsToResolve =
+ codeOwnerReferences.stream()
+ .map(CodeOwnerReference::email)
+ .filter(ref -> ref.startsWith(GROUP_PREFIX))
+ .map(ref -> ref.substring(GROUP_PREFIX.length()))
+ .collect(toImmutableSet());
+
+ // When we call GroupBackends.findExactSuggestion we need to ensure that we
+ // have a user in context. This is because the suggestion backend is
+ // likely to want to try to check that we can actually see the group it's
+ // returning (which we also check for explicitly, because I have trust
+ // issues).
+ RequestContext oldCtx = context.getContext();
+ // Check if we have a user in the context at all...
+ try {
+ oldCtx.getUser();
+ } catch (OutOfScopeException | NullPointerException e) {
+ // Nope.
+ RequestContext newCtx = () -> {
+ return new AnonymousUser();
+ };
+ context.setContext(newCtx);
+ }
+ ImmutableSetMultimap<String, CodeOwner> resolvedGroups = null;
+ try {
+ resolvedGroups =
+ groupsToResolve.stream()
+ .map(groupName -> GroupBackends.findExactSuggestion(groupBackend, groupName))
+ .filter(groupRef -> groupRef != null)
+ .filter(groupRef -> groupBackend.isVisibleToAll(groupRef.getUUID()))
+ .map(groupRef -> groupBackend.get(groupRef.getUUID()))
+ .collect(flatteningToImmutableSetMultimap(
+ groupRef -> GROUP_PREFIX + groupRef.getName(),
+ groupRef -> accountCache
+ .get(ImmutableSet.copyOf(groupRef.getMembers()))
+ .values().stream()
+ .map(accountState -> CodeOwner.create(accountState.account().id()))));
+ } finally {
+ context.setContext(oldCtx);
+ }
+ ImmutableSetMultimap<CodeOwner, String> usersToGroups =
+ resolvedGroups.inverse();
+
ImmutableSet<String> emailsToResolve =
codeOwnerReferences.stream()
.map(CodeOwnerReference::email)
+ .filter(ref -> !ref.startsWith(GROUP_PREFIX))
.filter(filterOutAllUsersWildCard(ownedByAllUsers))
.collect(toImmutableSet());
@@ -442,7 +510,8 @@ public class CodeOwnerResolver {
ImmutableMap<String, CodeOwner> codeOwnersByEmail =
accountsByEmail.map(mapToCodeOwner()).collect(toImmutableMap(Pair::key, Pair::value));
- if (codeOwnersByEmail.keySet().size() < emailsToResolve.size()) {
+ if (codeOwnersByEmail.keySet().size() < emailsToResolve.size() ||
+ resolvedGroups.keySet().size() < groupsToResolve.size()) {
hasUnresolvedCodeOwners.set(true);
}
@@ -456,7 +525,9 @@ public class CodeOwnerResolver {
cachedCodeOwnersByEmail.entrySet().stream()
.filter(e -> e.getValue().isPresent())
.map(e -> Pair.of(e.getKey(), e.getValue().get()));
- Streams.concat(newlyResolvedCodeOwnersStream, cachedCodeOwnersStream)
+ Stream<Pair<String, CodeOwner>> resolvedGroupsCodeOwnersStream =
+ resolvedGroups.entries().stream().map(e -> Pair.of(e.getKey(), e.getValue()));
+ Streams.concat(Streams.concat(newlyResolvedCodeOwnersStream, cachedCodeOwnersStream), resolvedGroupsCodeOwnersStream)
.forEach(
p -> {
ImmutableSet.Builder<CodeOwnerAnnotation> annotationBuilder = ImmutableSet.builder();
@@ -467,6 +538,12 @@ public class CodeOwnerResolver {
annotationBuilder.addAll(
annotations.get(CodeOwnerReference.create(ALL_USERS_WILDCARD)));
+ // annotations for the groups this user is in apply as well
+ for (String group : usersToGroups.get(p.value())) {
+ annotationBuilder.addAll(
+ annotations.get(CodeOwnerReference.create(group)));
+ }
+
if (!codeOwnersWithAnnotations.containsKey(p.value())) {
codeOwnersWithAnnotations.put(p.value(), new HashSet<>());
}
@@ -570,7 +647,7 @@ public class CodeOwnerResolver {
}
messages.add(String.format("email %s has no domain", email));
- return false;
+ return true; // TVL: we allow domain-less strings which are treated as usernames.
}
/**
@@ -585,11 +662,29 @@ public class CodeOwnerResolver {
*/
private ImmutableMap<String, Collection<ExternalId>> lookupExternalIds(
ImmutableList.Builder<String> messages, ImmutableSet<String> emails) {
+ String[] actualEmails = emails.stream()
+ .filter(email -> email.contains("@"))
+ .toArray(String[]::new);
+ ImmutableSet<String> usernames = emails.stream()
+ .filter(email -> !email.contains("@"))
+ .collect(ImmutableSet.toImmutableSet());
try {
- ImmutableMap<String, Collection<ExternalId>> extIdsByEmail =
- externalIdCache.byEmails(emails.toArray(new String[0])).asMap();
+ ImmutableMap<String, Collection<ExternalId>> extIds =
+ new ImmutableMap.Builder<String, Collection<ExternalId>>()
+ .putAll(externalIdCache.byEmails(actualEmails).asMap())
+ .putAll(externalIdCache.allByAccount().entries().stream()
+ .map(entry -> entry.getValue())
+ .filter(externalId ->
+ externalId.key().scheme() != null &&
+ externalId.key().isScheme(ExternalId.SCHEME_USERNAME) &&
+ usernames.contains(externalId.key().id()))
+ .collect(toImmutableSetMultimap(
+ externalId -> externalId.key().id(),
+ externalId -> externalId))
+ .asMap())
+ .build();
emails.stream()
- .filter(email -> !extIdsByEmail.containsKey(email))
+ .filter(email -> !extIds.containsKey(email))
.forEach(
email -> {
transientCodeOwnerCache.cacheNonResolvable(email);
@@ -598,7 +693,7 @@ public class CodeOwnerResolver {
"cannot resolve code owner email %s: no account with this email exists",
email));
});
- return extIdsByEmail;
+ return extIds;
} catch (IOException e) {
throw newInternalServerError(
String.format("cannot resolve code owner emails: %s", emails), e);
@@ -815,6 +910,15 @@ public class CodeOwnerResolver {
user != null ? user.getLoggableName() : currentUser.get().getLoggableName()));
return true;
}
+ if (!email.contains("@")) {
+ // the email is the username of the account, or a group, or something else.
+ messages.add(
+ String.format(
+ "account %s is visible to user %s",
+ accountState.account().id(),
+ user != null ? user.getLoggableName() : currentUser.get().getLoggableName()));
+ return true;
+ }
if (user != null) {
if (user.hasEmailAddress(email)) {
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParser.java b/java/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParser.java
index 5f350998..7977ba55 100644
--- a/java/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParser.java
+++ b/java/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParser.java
@@ -149,7 +149,8 @@ public class FindOwnersCodeOwnerConfigParser implements CodeOwnerConfigParser {
private static final String EOL = "[\\s]*(#.*)?$"; // end-of-line
private static final String GLOB = "[^\\s,=]+"; // a file glob
- private static final String EMAIL_OR_STAR = "([^\\s<>@,]+@[^\\s<>@#,]+|\\*)";
+ // Also allows usernames, and group:$GROUP_NAME.
+ private static final String EMAIL_OR_STAR = "([^\\s<>@,]+@[^\\s<>@#,]+?|\\*|[a-zA-Z0-9_\\-]+|group:[a-zA-Z0-9_\\-]+)";
private static final String EMAIL_LIST =
"(" + EMAIL_OR_STAR + "(" + COMMA + EMAIL_OR_STAR + ")*)";
diff --git a/javatests/com/google/gerrit/plugins/codeowners/backend/AbstractFileBasedCodeOwnerBackendTest.java b/javatests/com/google/gerrit/plugins/codeowners/backend/AbstractFileBasedCodeOwnerBackendTest.java
index 7ec92959..59cf7e05 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/backend/AbstractFileBasedCodeOwnerBackendTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/backend/AbstractFileBasedCodeOwnerBackendTest.java
@@ -424,7 +424,7 @@ public abstract class AbstractFileBasedCodeOwnerBackendTest extends AbstractCode
.commit()
.parent(head)
.message("Add invalid test code owner config")
- .add(JgitPath.of(codeOwnerConfigKey.filePath(getFileName())).get(), "INVALID"));
+ .add(JgitPath.of(codeOwnerConfigKey.filePath(getFileName())).get(), "INVALID!"));
}
// Try to update the code owner config.
diff --git a/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java b/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
index 6171aca9..37699012 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
@@ -24,8 +24,10 @@ import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestMetricMaker;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
+import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountsUpdate;
@@ -51,6 +53,7 @@ public class CodeOwnerResolverTest extends AbstractCodeOwnersTest {
@Inject private RequestScopeOperations requestScopeOperations;
@Inject @ServerInitiated private Provider<AccountsUpdate> accountsUpdate;
@Inject private AccountOperations accountOperations;
+ @Inject private GroupOperations groupOperations;
@Inject private ExternalIdNotes.Factory externalIdNotesFactory;
@Inject private TestMetricMaker testMetricMaker;
@Inject private ExternalIdFactory externalIdFactory;
@@ -112,6 +115,18 @@ public class CodeOwnerResolverTest extends AbstractCodeOwnersTest {
.contains(String.format("account %s is visible to user %s", admin.id(), admin.username()));
}
+ @Test
+ public void resolveCodeOwnerReferenceForUsername() throws Exception {
+ OptionalResultWithMessages<CodeOwner> result =
+ codeOwnerResolverProvider
+ .get()
+ .resolveWithMessages(CodeOwnerReference.create(admin.username()));
+ assertThat(result.get()).hasAccountIdThat().isEqualTo(admin.id());
+ assertThat(result)
+ .hasMessagesThat()
+ .contains(String.format("account %s is visible to user %s", admin.id(), admin.username()));
+ }
+
@Test
public void cannotResolveCodeOwnerReferenceForStarAsEmail() throws Exception {
OptionalResultWithMessages<CodeOwner> result =
@@ -127,6 +142,18 @@ public class CodeOwnerResolverTest extends AbstractCodeOwnersTest {
CodeOwnerResolver.ALL_USERS_WILDCARD));
}
+ @Test
+ public void cannotResolveCodeOwnerReferenceForGroup() throws Exception {
+ OptionalResultWithMessages<CodeOwner> result =
+ codeOwnerResolverProvider
+ .get()
+ .resolveWithMessages(CodeOwnerReference.create("group:Administrators"));
+ assertThat(result).isEmpty();
+ assertThat(result)
+ .hasMessagesThat()
+ .contains("cannot resolve code owner email group:Administrators: this is a group");
+ }
+
@Test
public void resolveCodeOwnerReferenceForAmbiguousEmailIfOtherAccountIsInactive()
throws Exception {
@@ -397,6 +424,64 @@ public class CodeOwnerResolverTest extends AbstractCodeOwnersTest {
assertThat(result.hasUnresolvedCodeOwners()).isFalse();
}
+ @Test
+ public void resolvePathCodeOwnersWhenNonVisibleGroupIsUsed() throws Exception {
+ CodeOwnerConfig codeOwnerConfig =
+ CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
+ .addCodeOwnerSet(
+ CodeOwnerSet.createWithoutPathExpressions("group:Administrators"))
+ .build();
+
+ CodeOwnerResolverResult result =
+ codeOwnerResolverProvider
+ .get()
+ .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
+ assertThat(result.codeOwnersAccountIds()).isEmpty();
+ assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isTrue();
+ }
+
+ @Test
+ public void resolvePathCodeOwnersWhenVisibleGroupIsUsed() throws Exception {
+ AccountGroup.UUID createdGroupUUID = groupOperations
+ .newGroup()
+ .name("VisibleGroup")
+ .visibleToAll(true)
+ .addMember(admin.id())
+ .create();
+
+ CodeOwnerConfig codeOwnerConfig =
+ CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
+ .addCodeOwnerSet(
+ CodeOwnerSet.createWithoutPathExpressions("group:VisibleGroup"))
+ .build();
+
+ CodeOwnerResolverResult result =
+ codeOwnerResolverProvider
+ .get()
+ .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
+ assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
+ assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isFalse();
+ }
+
+ @Test
+ public void resolvePathCodeOwnersWhenUsernameIsUsed() throws Exception {
+ CodeOwnerConfig codeOwnerConfig =
+ CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
+ .addCodeOwnerSet(
+ CodeOwnerSet.createWithoutPathExpressions(admin.username()))
+ .build();
+
+ CodeOwnerResolverResult result =
+ codeOwnerResolverProvider
+ .get()
+ .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
+ assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
+ assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isFalse();
+ }
+
@Test
public void resolvePathCodeOwnersNonResolvableCodeOwnersAreFilteredOut() throws Exception {
CodeOwnerConfig codeOwnerConfig =
@@ -655,7 +740,7 @@ public class CodeOwnerResolverTest extends AbstractCodeOwnersTest {
"domain example.com of email foo@example.org@example.com is allowed");
assertIsEmailDomainAllowed(
"foo@example.org", false, "domain example.org of email foo@example.org is not allowed");
- assertIsEmailDomainAllowed("foo", false, "email foo has no domain");
+ assertIsEmailDomainAllowed("foo", true, "email foo has no domain");
assertIsEmailDomainAllowed(
"foo@example.com@example.org",
false,
diff --git a/javatests/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParserTest.java b/javatests/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParserTest.java
index 260e635e..7aab99d0 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParserTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/backend/findowners/FindOwnersCodeOwnerConfigParserTest.java
@@ -158,16 +158,42 @@ public class FindOwnersCodeOwnerConfigParserTest extends AbstractCodeOwnerConfig
codeOwnerConfigParser.parse(
TEST_REVISION,
CodeOwnerConfig.Key.create(project, "master", "/"),
- getCodeOwnerConfig(EMAIL_1, "INVALID", "NOT_AN_EMAIL", EMAIL_2)));
+ getCodeOwnerConfig(EMAIL_1, "INVALID!", "NOT!AN_EMAIL", EMAIL_2)));
assertThat(exception.getFullMessage(FindOwnersBackend.CODE_OWNER_CONFIG_FILE_NAME))
.isEqualTo(
String.format(
"invalid code owner config file '/OWNERS' (project = %s, branch = master):\n"
- + " invalid line: INVALID\n"
- + " invalid line: NOT_AN_EMAIL",
+ + " invalid line: INVALID!\n"
+ + " invalid line: NOT!AN_EMAIL",
project));
}
+ @Test
+ public void codeOwnerConfigWithUsernames() throws Exception {
+ assertParseAndFormat(
+ getCodeOwnerConfig(EMAIL_1, "USERNAME", EMAIL_2),
+ codeOwnerConfig ->
+ assertThat(codeOwnerConfig)
+ .hasCodeOwnerSetsThat()
+ .onlyElement()
+ .hasCodeOwnersEmailsThat()
+ .containsExactly(EMAIL_1, "USERNAME", EMAIL_2),
+ getCodeOwnerConfig(EMAIL_1, "USERNAME", EMAIL_2));
+ }
+
+ @Test
+ public void codeOwnerConfigWithGroups() throws Exception {
+ assertParseAndFormat(
+ getCodeOwnerConfig(EMAIL_1, "group:tvl-employees", EMAIL_2),
+ codeOwnerConfig ->
+ assertThat(codeOwnerConfig)
+ .hasCodeOwnerSetsThat()
+ .onlyElement()
+ .hasCodeOwnersEmailsThat()
+ .containsExactly(EMAIL_1, "group:tvl-employees", EMAIL_2),
+ getCodeOwnerConfig(EMAIL_1, "group:tvl-employees", EMAIL_2));
+ }
+
@Test
public void codeOwnerConfigWithComment() throws Exception {
assertParseAndFormat(

View file

@ -1,16 +0,0 @@
{ buildGerritBazelPlugin, fetchgit }:
buildGerritBazelPlugin rec {
name = "oauth";
depsOutputHash = "sha256-4/+E0BwkA+rYYCy7y3G9xF86DJj+CFzPZUNXC5HN5wc=";
src = fetchgit {
url = "https://gerrit.googlesource.com/plugins/oauth";
rev = "b27cf3ea820eec2ddd22d217fc839261692ccdb0";
sha256 = "1m654ibgzprrhcl0wpzqrmq8drpgx6rzlw0ha16l1fi2zv5idkk2";
};
overlayPluginCmd = ''
chmod +w "$out" "$out/plugins/external_plugin_deps.bzl"
cp -R "${src}" "$out/plugins/${name}"
cp "${src}/external_plugin_deps.bzl" "$out/plugins/external_plugin_deps.bzl"
'';
}

View file

@ -1,24 +1,76 @@
let
keys = import common/ssh-keys.nix;
commonKeys = keys.users.delroth;
commonKeys = {
# WARNING: `keys.users.*` are *lists*, so you need concatenate them, don't put them into lists!
# Otherwise, agenix will be confused!
global = keys.users.raito;
lix = keys.users.hexchen ++ keys.users.jade;
floral = keys.users.delroth;
};
secrets = with keys; {
hydra-s3-credentials = [ machines.bagel-box ];
hydra-ssh-key-priv = [ machines.bagel-box ];
netbox-environment = [ machines.meta01 ];
mimir-environment = [ machines.meta01 ];
grafana-oauth-secret = [ machines.meta01 ];
loki-environment = [ machines.meta01 ];
floral = {
hydra-postgres-key = [ machines.build-coord ];
hydra-s3-credentials = [ machines.build-coord ];
hydra-signing-priv = [ machines.build-coord ];
hydra-ssh-key-priv = [ machines.build-coord ];
# These are the same password, but nginx wants it in htpasswd format
loki-htpasswd = [ machines.meta01 ];
promtail-password = builtins.attrValues machines;
netbox-environment = [ machines.meta01 ];
mimir-environment = [ machines.meta01 ];
mimir-webhook-url = [ machines.meta01 ];
grafana-oauth-secret = [ machines.meta01 ];
loki-environment = [ machines.meta01 ];
gerrit-prometheus-bearer-token = [ machines.gerrit01 machines.meta01 ];
pyroscope-secrets = [ machines.meta01 ];
tempo-environment = [ machines.meta01 ];
buildbot-worker-password = [ machines.buildbot ];
buildbot-oauth-secret = [ machines.buildbot ];
buildbot-workers = [ machines.buildbot ];
# Private SSH key to Gerrit
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHx52RUPWzTa2rBA96xcnGjjzAboNN/hm6gW+Q6JiSos
buildbot-service-key = [ machines.buildbot ];
# Signing key for Buildbot's specific cache
buildbot-signing-key = [ machines.buildbot ];
buildbot-remote-builder-key = [ machines.buildbot ];
# These are the same password, but nginx wants it in htpasswd format
metrics-push-htpasswd = [ machines.meta01 ];
# Yes, even Lix machines are included in this monitoring infrastructure.
metrics-push-password = builtins.attrValues machines;
ows-deploy-key = [ machines.gerrit01 ];
s3-channel-staging-keys = [ machines.gerrit01 ];
s3-channel-keys = [ machines.gerrit01 ];
postgres-ca-priv = [ machines.bagel-box ];
postgres-tls-priv = [ machines.bagel-box ];
newsletter-secrets = [ machines.public01 ];
s3-revproxy-api-keys = [ machines.public01 ];
stateless-uptime-kuma-password = [ machines.public01 ];
};
lix = {
buildbot-worker-password = [ machines.buildbot-lix ];
buildbot-oauth-secret = [ machines.buildbot-lix ];
buildbot-workers = [ machines.buildbot-lix ];
# Private SSH key to Gerrit
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHx52RUPWzTa2rBA96xcnGjjzAboNN/hm6gW+Q6JiSos
buildbot-service-key = [ machines.buildbot-lix ];
# Signing key for Buildbot's specific cache
buildbot-signing-key = [ machines.buildbot-lix ];
buildbot-remote-builder-key = [ machines.buildbot-lix ];
};
};
mkSecretListFor = tenant:
map (secretName: {
name = "secrets/${tenant}/${secretName}.age";
value.publicKeys = secrets.${tenant}."${secretName}" ++ commonKeys.global ++ commonKeys.${tenant};
}) (builtins.attrNames secrets.${tenant});
in
builtins.listToAttrs (
map (secretName: {
name = "secrets/${secretName}.age";
value.publicKeys = secrets."${secretName}" ++ commonKeys;
}) (builtins.attrNames secrets)
(mkSecretListFor "floral") ++ (mkSecretListFor "lix")
)

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 87T2Ig tzPD1x6XKuDfgJ8jkQnwW/ALp2pkANCeNoO8xdUqq30
QSsuO6Dwc8QJuY92gXRnWB5aJ2SU9X2uFh01GmLVaQE
-> ssh-ed25519 K3b7BA 9G9Uw1xY8hq//xphNWrPn5y7vG2o8/kwkC8cJGuf/mI
Ip0019OUaFq2ZDFI3i77hdsp9IqFV2qqYIB/TnDSXgo
-> ssh-ed25519 +qVung dx22ef+x9X5mr73L8NUzxYQa640M2XViELjJcpgF3go
CXyit7pk8SPNHBgULlMQUAasGAn4C36zcwOBDI46nU4
-> ssh-rsa krWCLQ
NlGh0hM10NOuek7MbrFo0iul0kQQtDFmZIhgpyqaATMdCDRBXJOyhASHU5N0zDDJ
MLaJUV0l2o1ghBF9RhSKdoUPVEn8Cce/nfQepYzMlfc4UG3qWXwabwR6EtqqCZCJ
jAEWZ8taTKDmzoXwuygCW+bRBuoMMrcfzu7V90N+mQpZWtOScatb6E7d5VRqjlar
st1ZQu5ccghufyQSUmOC7GpojOyutX5EvbMGn84X4ouZRHRX/8fTgaqicV+aeAIb
QyXisOrO6C+Jle5qfxzMSe8c/TCyF2574kD6F1BQ9Kpkinn8v7OWcIXtkNmZ5hzK
vs0Bej8yZVsoBkj1vWAM0A
-> ssh-ed25519 /vwQcQ n+hr1cV1zRs1S86YnA+0oRB8SCaPKtkoMNe15ZsVVwM
fdFtUqno07ik6FpW5zMImIjd8wM8dMgwU+RqjeT2PiI
-> ssh-ed25519 0R97PA ddPILw57gkuKvAqlmpa+MnV/LSEdyQzQaAarCUqQ1xE
ozK5a6uXZDc17OrX0OZun9hmZwP3H3rYQiNuKnukqsg
--- f7yGgKQpCPj64Ps0HfMcToYircGH5SPqMzVZrUMB8ZI
føv[iY\ÅšMP,¯Ùh°Èxb—Ðÿ«J<C2AB>*ºË" ”+¬ÒA0T˜?KmˆPÈË2¹'2±µ³Ø=¯êÚÏŸj”

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 87T2Ig p8lEB5da4fIfLH/HKBsghzq5mvQLB69UB4+uAi3DGCw
NeZ3jPTUKa7MiqjrFPrYuP4VneytQPdBNqf+omPZJYM
-> ssh-ed25519 K3b7BA uP2K1hU7uLmiHXmmoUdsB7CHQq61ZkEAjG/aK863RDw
0chTczEMXASdYiwqNxDQ+vMXXhjOf64oIQ2ULZmQI8Y
-> ssh-ed25519 +qVung jUgEqz3+ypL7mwJ1R7lfeOMhkon/aRrNSJUJT3X7vmU
pgOiwrp9JiA20yw9bsxi8eiQ9/23CYXKRBGF1pea9eI
-> ssh-rsa krWCLQ
snCHrLHzkjimwIxKO90IjnHwOArlozO9kd/aCdZZnYNgh/QG3rUSceSn9yTHbtMV
izv0SU51LrRU+JyE+a524AxKhyPBvGDig20j7hMy5fVxZqeunztqtlha5gaYYaQg
Tbfs9tDP+pCIgzMVNqYf6EJ4MK7qjNf9DE5I490Eta5YZxAi/3To3BmZmIYtCz6l
1kNRiSmWCbZqE25keFgPCgRMFXAFK9W6NmL+HamqCUhjPoJg/Gd4sf39EONT0PYg
7BpCOAnwwfECHPxpM3qv0h2kJXTb4DZ715cFReSVyQe5fvKv8hoWhl/S+++pEYT8
u/LKBx/o7e3Kd7cm2RGnBw
-> ssh-ed25519 /vwQcQ 4+IQPRsMMHmuSGL7T7IbRkTTuL+TTqgdQp5FSbyt8Dw
KOI0LKQ0oA5XtxaW7wftlEJB0BGVnx41HUJMG92SRUA
-> ssh-ed25519 0R97PA l1aWUEv8nLEtYnpY1gjTJqk5UYm51NDqOjYmL83rZ10
B7qDZwCpolkIajqCXeOepwmF6ciJfKvr+AN7VouMUvA
--- lz/IMMPxBpD3Bzuv9Wl23+swBQHlblhlAO/ZXAgN0hU
µoÍüÌ<EFBFBD>²-Īr °eó|Í?ït èìÎZ<C38E>¬sÒì!ŸƒÁ<>@Ï'ìèz6UöÎgJøÑOµs13<31>š8<î’%-·Ô‡Eÿ }Šdm9¿å¢Óoæ

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 j2r2qQ vwcaLpvGJ9swXnV8idDwi9jdRPSj38As9p2QFkIJ1Xc
FLnZeblHDQQcWjFm1iaghbvuFgOG3miwtkRE5sz1+X0
-> ssh-ed25519 K3b7BA 9VRe2rBwg3G9lxxfxL/yLob2NZmLJTBMxzx0Ew8VwmY
/I2W80UykNvll5o98OPeMpIsddOel9B7uQlio0X3gcs
-> ssh-ed25519 +qVung VsqKzMD85aps4PIx2zqae2Dj7YWibiaKYb5z7ws8ggM
Y9dRd/hOz8h4avlutBQ1YZgHIAf/AuTr5WaByKlFbLE
-> ssh-rsa krWCLQ
gjyaUFrIIbZnFTGVw4XEZzkTIP/+qXV6/q0W8Wb4EtqQXDRISFT+bwxQU/S2p5hf
7+JGcn4BZg6puOJ5BBABWtpn6gcX5OFfga5azIdioF/R19XByT+0SK5njw8g1VPS
R7o8kQt2yvKWayoq9Cis5XRg+4KANkwOQaNTO8AdiCwgq9nc0Cd9avk8QhaFoR74
D5cf8jPsufp744rQqwhWDoG533LS1WUUuYZqRmtp2Vz+r583RhSscaNyA7ddr7o6
e9ZQJyL5bKiN8qe3Xm76lLypf/wg7+aGn8HHnO6GA65g+VYfjLMODEqCN/+uDJtB
g8v2wzKIGYlZiV1hEjH8nw
-> ssh-ed25519 /vwQcQ 4pU5JGK5vpZbFgq01a9YY8VmSJvPSHPSZD50TLJwKHc
L46UA/p+bNSR8cLmL8G7VpmAcZ+sy5AROc4yj2ABOWg
-> ssh-ed25519 0R97PA Tk00kYLhsEy1HJcmKLgaLWTdNP8XV/cdKHMLzyK6glk
kwyQZr/h6MutROJmjVfPWGcf9xN5Uc5w5mVyuKcK64g
--- E0vVtBqbjNkZY0/1dFJ53uVAR7IGPO+OMmXkpJcKmlw
{ÐQê%èõY•B,isr¥1<31>yLÕ'7?¶iŠM…¶MU]×ê/d2¸I1u¶2hZjHåh &¥

Binary file not shown.

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 +uvEmw Kuduppyhz98frjlV96R/WcmPdaWmHbNKZhQs76GGTx8
7zpedlPflGOi6FqkpswAJflx77yde7M2XlTw/8mz2tU
-> ssh-ed25519 K3b7BA TPNmUK38+TR58MpsgxIe91bY6E1j9HecIFn0AKdat20
MjXh06xd3mkPcK+iEonx+itsHvEGHSknzO6Sgh5WdZ4
-> ssh-ed25519 +qVung KereHQ3Kl0f7O0xzl2s4Yu4KX7OOA17R7p/w8uRx/AQ
3aOqUoBCDurkh5jT2fq5MDPQKIDISQdXBhF+qeRppnA
-> ssh-rsa krWCLQ
TVlmM2LYR339Aglo2D4j/Itr0E+mg7UEaV9n+sUYyit0phWS1zMI2YMc78Xbmn73
6U0VYi/3hpesD6/8uA5sywuueOMntlL32aECz/DJPC71feMjvHTxiJpqnFw6DQYJ
FvERtvJ2U7QiStv6UeS1vOucP1/om0Qj4smTXBWYsDglTSLx56/bghCsM21RNZZb
yd8JE5CEdtCHduj+uRHbnEYsnGYM7R/Gw9XAuajFLw6BxqEtHi5xOivQ2P0Tm+Bc
SVHW48iF8S3q1tx5QU7oIMZcCobOeHb6w+C1GHiSeJy3R8hWkEwfNxCCc0rSItKd
edqO4YPz/zT2DWoUx+n0Og
-> ssh-ed25519 /vwQcQ TLa0Xty2LlqBiP9Lk0lC+S/BoVT+VbRhY3qPHIGf20E
3mzqkwT8dvP11GAVJiVIc+MiN/pLP2b6KbC+1F86tg8
-> ssh-ed25519 0R97PA pbGz7e6nU4M4cpJRmmxWxUV3O2rWytIP18M7OpMpa04
doSBv72rqS5gNusMjKw8KwzXHbzoLlFUSdLqp/f5aRM
--- beE6zNg+kY7jke/79FGZoNTq7Wbe3eqNWvLD3igQJdg
bÓÿ¾ ¾ÿÔáïØÉmÿŠ$Ÿ–‡¸’Ý={6 eÿ¨SIîumT8”äÿÁ{òo<C3B2>Ë3Ý&¾12¡p¶ œZ÷³4zx¡8B˜¤a@â(_Þ7(‚Ñ^tµä±Á<C381>g“Ùà4Ö*&Á`*øäNšB÷$ÉÆ ò£§m<C2A7>"ÓtD$Î5‡ku˜eÎ+X@LJüç£h2ü£Þ*H¥ ÂåaÚ¢

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 +uvEmw TNYFQxSUv5yMmlTWoIxCOlv6UR+RA50cb5aJbo0yEE0
Yw3sTPqYf7A33RI87CqoPWe2gh0FuvdBGGKqHV55Atc
-> ssh-ed25519 K3b7BA vMlHenY6jSIfnxQD6xh09cwwV+YVBkLuSMHcyKD+dCk
heXkAEqRawBlHqcr6ldmhWmk7qPtGLMDFC3QT79vdMM
-> ssh-ed25519 +qVung fgimLW5X0z4Eh2u3fIr5bgR5/c1SKam9CKW/2mqtTik
8VKJJr+FRE0j5YvjfdMXugNA4UwUebKrkeAe+9LYBnQ
-> ssh-rsa krWCLQ
sa3fA4GglovY8H6jimpTvQPW/axun8WADPlIXzpX/Zeshkzem+pQoQqptzDlnmH8
8AngqXgFYrmHgNNAylavgcrxbjNrtlJU24ldF1YIubz7VsU1678F27LCd9B0c2dn
X+0CccH19lM8Q+zVI2Wrq9R83MEP/5uOOc+eXXnvNSGqfKgZ2OplG/HUllFS13j6
uiQy5zwJJKkII7KUThcGteux7NONoLeUqRE8CW2uSeY9fXBWKgxeENKgiT7PEAAo
nvwWa+GatEYf6eUz8Lph8lETorgP+7JS2VQRAkmhDbjQLTYzfFmiJGE/mzyobslf
ZEq6Oj5UNgnzdWmK5ZYKPg
-> ssh-ed25519 /vwQcQ 9EG/cydlzlLd6cFed7DzmwzubzJUXvD9mX3WKDyFD1s
3Emj+tVZmnsC/YZdChvyaxeObbBsri347vZl0ff9kH4
-> ssh-ed25519 0R97PA kcIYyWKxpJmjcrel+YodZQiR2zGPqfjzMyJXsz2XOzM
SUlgGGs2BVRzTHT/ULNo1AiN5SY1BETFtJRY6LDr4JI
--- l87sO6IuwSeCeQ8ktvYFI0xr4Utcl8KfpAV7WePc1y4
÷ÚÖ~÷J3¦Œ§ÍÇè²ù<º?%×ý<0E>Á‡ÉÒ\—\Ï7\»Ú¨åU-&W'd”{իɼ½u "Û#Ž}¯õ…xìšz¥®Nj„!éfUqDG<é<7F>Ñca<63> '´+ ¸Ï±]Pó»ö€DÕ¸´þ<C2B4>£¼­ŽÿÂç Ì\¦<>

View file

@ -0,0 +1,22 @@
age-encryption.org/v1
-> ssh-ed25519 +uvEmw BoYFUISKrlypCBQW/fA9UNRSnxQ93FkQupWUWAeOd3c
wQH9gNk8TtjOgrwYwCuedPBbmftd7JhJk53ga2qo2iE
-> ssh-ed25519 K3b7BA vyQIsvbNrHI0Mui5UdLz2mWcYvnTQBupWiAfEP5NfXk
WeHg0PyfuaSJVzuiBPa1Tanj4NdqHvnZFWhXhIgbWc0
-> ssh-ed25519 +qVung LneEmMhBqJxN0bgM7/Z+jJ8U8MJmCgE2EghBmDJ/aT4
nd3B7afUNX1ZLCjHdoJ8+tabXmi38lQkLlhthYjIplI
-> ssh-rsa krWCLQ
krJRF4AvwfEFro4uiLIBB2RQTwO9COSyAqkjOi6jgLzJFMaU62EZrgfSYu24a6zs
JyAHQ5k78uh3EhhbSzu6U65fComCbRAo+NiN2BJU7jb28y64suJbezJ+LE4P35CX
biVgycaSc+OCrb1F6e6QOREi7+YjK3VrI4ZVCu93hSQNNRi/U5bbigQXt7NwcSIJ
bY93sset4wg9Zwjk7tFg1bHiyOK3ZvYYQGlMjUxiWGl4Qch1fpL2CJNR32mZybps
GZc7x69E8EhoHvdI0u1AXwS2raLhyRBPxFzu0r7nPlSi17TnLnU3Ux3BkVEDa6bh
eVHqAB4dudNCC4wOY/ZE+Q
-> ssh-ed25519 /vwQcQ scOp+aVA3TfY269EzQ6E4YX0uAu7qVVVIDmBvFGaYk8
AYqW8+A7oxH/0m8OUReWxto1xWcnOnZOkX45ejuFJiM
-> ssh-ed25519 0R97PA YqfHMAAiMcH/efJ0K5URDJkdLqlJIlQ+pSnuGUOJzjI
v6BujlFcBF71SzvlZzA+tWku/A8bZzLkRfHtoCdbCO4
--- PeORL3PTxYsxaY6GliSm1dRAH+hxf1n5LNeRYDq+poM
­Ñ_÷l꺓CqyƹÚ@Ýç¾Wï;äù¹¨<ñÛ5ÅF¼·Ee7þ11=ø‰øQ<pmƒ¬ì¼^²<>òŸµÉÑÃÙƒ¨[†GÞ½÷$j†©<E280A0>±¨m±‡I×ñí¶\«•ÉO§ëÇBdÜÛ< Oª$ª „5£ãÒ¼âá‰õw˜REŽ3Y×ë!Ïd4ŒBFõ‡>ªŠÈ˜\EKËhægôÙ^f;ˆ1>tk ™‹£{ª»ÓMð³ š³87®\uÄ,íSáÕIinÀ:ø¢z"“Æ<1E> -XBñíÀ<C3AD>‰u<E280B0>jš C5Õ­Ðï,Âg“*\]ÒO†îÇye5ïQîÄ !‰$þ.‹†+ù¦²¶zÀF¨ÑŠ^¨·SµµL<11>äÍB+óÓ¼ËR“Hxö6ÿåʉ1f<31>=jú8¾!o¿@Rzrü5p´(#‰w|Gd­×¼O@>²0ã{$ËhE°Ä<C2B0>ÕûS ê_¦æš^#Oÿžò 2c¹ŽŸ#G<>ž'º?e9yÂ)ô ªÅ–Ì~ÑÓ¤
Ìtl#­#„»I³>o½Å³°)ˆóu

View file

@ -0,0 +1,20 @@
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>

Binary file not shown.

View file

@ -0,0 +1,68 @@
age-encryption.org/v1
-> ssh-ed25519 +HUDfA d5f2ESneC0wsoc9rwTjNfNXMBjCbjAQ7euthH2Buq1E
5CynaQ8zhDRBvcmifhCsiDtllztCVAqs8rU36DOxgPw
-> ssh-ed25519 +uvEmw EtYRis2LP0jv1W8mx8vFYNzkgi8OoqnA8cM2huS6NBk
ll1csFIO+hVYk+I0uSVJmlDKj9aTWvf4kaYI5LJcm7w
-> ssh-ed25519 DMaM1w ex4QJN8CG99J15i+yvqGEiEZn9OlGIC+cmLHL4u8ZEI
VXnOv4CGK68q5t6hUV3oKAtxGZ+4FVbrmE1yMn16A0Q
-> ssh-ed25519 sixKXw drXN6+q1y7L7ZU4chTfHfelu5GcTdff+i/UMFV0+3RQ
+8jmgnMh2OpQ3vhAuyQYWslfx7KO84a8KsCpoRD3Yl8
-> ssh-ed25519 aHbF7w Af7NgjZ/Nvh5FHrX2VlF5riTIhJ+fdxTo6OR+8PcNwA
ktKpm/HnOnw2Ym7xee3N1rneEX7+/xDhcp71N1NNHAA
-> ssh-ed25519 87T2Ig 8mEUxJ/5NUvV+qQCDQH2Tm6Ryr5hf4xgsQlqXGf03Fw
EavMcnsg/3EYBLQEBHX+0oTDKq5ZL4vj+mZntPM8UMU
-> ssh-ed25519 Ao+7Wg UphWbatIaa+R1oZbfHazFhrawf0vax/3ZZS7YuX03Hs
dwBbwoV0jpjiKr+nj+CRfUDgDl7ISpsCintVAzHnIFQ
-> ssh-ed25519 wIR2ZA ZM58Nq7eJX9JVeYkoJf+mw8hxhYGoTx042ow1u3mJkw
UtEaf7e4xsPO0ISlIF9LF+GcwTBqw4AXdMO4MASfgLQ
-> ssh-ed25519 oGiV/Q G5KX/Eox+9md0yFRUZvGIsio2gWM17soHsL6H6zEX2g
vI8jPjBAoFF0xhvRRLPzCMSiQOQ0fKuRb3CYVu3KUUo
-> ssh-ed25519 gO3aog p9nZtjzoA0zJM+7Y6R16mpdub3dhu67yOYTUNKRytgI
YL9vAp1+CK7jgmXkB47ufZMz+/swngkdUvEGR1zFZwc
-> ssh-ed25519 N/+Clw 6LzFdtNsWewuJK2r97ZXJbRazvK3raN78UGanR/zWVU
WT0y+sfDP3ffVwRcbYw51ArFR3OzXnoyi9IXwZZKEL8
-> ssh-ed25519 CtkSZw CV0jQ5dIbgFtMxGK1X9b1qJOKmske8VgIPW5NW9mAwc
clv7P3de61nZmXrvbOgL7Llw8ZqBMm2WFqgpznDwKv8
-> ssh-ed25519 keg2lg 3Nk40ByQj8RThj4QDY2BdAkw55mXAJprXQRGjQqGvz0
f8OFszJ8p90crFd+awEE12CNd7b22zgpH2XRKmH/Hf0
-> ssh-ed25519 H885DA GDiJYH+gaC++TSqfoPDOTFcsCZRhEl0EeTeab7tgcWU
kMILmwNMnMS7rgC3kKsAksu4Txn5owPU2y09h4aHKY8
-> ssh-ed25519 Rq7K4Q VCNxGtCSCD2OYSWWwl0+yf189xV3QwRiwo80h4NPTkE
hHkgYHLbISdl/RRdlInp9ub854M9ZKFSXpLgKW2YkmQ
-> ssh-ed25519 vvyRpw XSCCrqEOtvzQRssI0U1DHirKoPgbOUKJxNKnioHhT2Y
HGey1j0Kxae5Qs0aw6eqFziQGiRmNA+lEwbRdf5hhbM
-> ssh-ed25519 aSEktQ mXY70Lgl76J4O5dPdDcIqmJ40EinigDuZrUghpGOq2I
U2qeVFxGCYCEFWU+7vHc5Mu9EuzScowrjnwUyoqPj5U
-> ssh-ed25519 cD6JxA at89poimBZyeeM8CQrxDxN0yCNDT2k04++py1fFycj8
cQV/K5zc5x/oYnJ4N0MX3sTboT4G4ZNvVUVdHuJRzbA
-> ssh-ed25519 ec6XRQ spJtb/xy4k4dmwKz8R2CPhC1WcuNV/rnDT978GkjHHk
KrGEVGts/AhzbRNreqQ/CVanXL3l/9oMWxnpBLj23qU
-> ssh-ed25519 1qYEfw KRkTYlvvnsCIExKQNmCyU7YxnGZsiI03kzecXNpLzUQ
h2YagV7BzlsF7banzwXbOudTdlFzT7LC8PvtxAsX36U
-> ssh-ed25519 2D+APA 4hdYlOnNIT9Q6tyKwXzy+u66Ti2EJopK43Sipebd0As
tuesc9/QcEu4q9bTFJ5zJr0qvgLcmpn4at4cYtHrtbE
-> ssh-ed25519 eTSU6g i1qT6PtepHXnoLCqDbhk86QG+SR9luQaw34a34gy5mw
YE9VBAT5SLW2ECHRU+dMg9na6OQNVRVGuhY8vOdmE/Q
-> ssh-ed25519 j2r2qQ TTTbSB/8UIDmmI3C9+u24PYZNfjl9jGADKHNWIwLfGE
SNDforwii/GFp82TpyOcVIVrZWCe2QQKrjzPA6XA7Jc
-> ssh-ed25519 CyxfgQ P5EiJ54v65Sz1gHuI0s170Z7c1WjcZLlb7NYigElfVs
iYJUGpoE9LBIlv+O1navSSsy3EJ8tusXXX+/QAQvjNI
-> ssh-ed25519 C/bBAQ hlBDpQRkcVCr3B6TCrBjxauhUX6Ndpm0s6x8W4hU6gM
OFG3EuGJkSoEEXhbJ/Tp2DBdnBcs+hzxjNRdvcOSpQs
-> ssh-ed25519 +qVung cGEGpO8NJfpj9ixAH9lhYkPKPDdQWryVxSOhMGQdnWM
+MycbIEab3P/AOS9i/YmPBDXB76hp3xUcWI4VMihV2w
-> ssh-rsa krWCLQ
Zv3dPYERlX1MaVaJTBDwIcjt1yLmu4Z7MovPgjGg01p+XsdBXeepTyOl+gRBwGgo
AW5CIuaChYxtSNJ6nOgSaUpqzILycUF1xE1jROe3MIX2MZ4KGD1qoqcHbiCAng+a
RqYrwAKnNea9FQMVfhYZBkRoYE6ne1R+0G6BoFM/okz24pAAFPBx+sMMhfTkt0uV
kHVx0dgRw1pxa7Na98WH/7E0zp9VuBvVHGXfk1rfW/UQlbIO5RP3nldFoa6OmOWS
JZ022UvjyC1re0KCurka4y+qmaiRKnTBmpIXxJFMwNCAQ8O8SeAQ3DHKHmXNMOIL
ZVICtRRk0uX36AVU8DWDog
-> ssh-ed25519 /vwQcQ kF8+hsA+0Msjd3q0SL52cae5RDqx4ls5kPKnc3UZyms
Q33kIKJL3Vjxu7LQ5l4M3tlEuj+OW4uGh1x+JxthW8A
-> ssh-ed25519 0R97PA gWBH71l6w9upTE0DwqOMSvWXc5VyJiKFAQLaSpWQ43E
IrOrvzEa0bABw6UOpP8pM8WhuRNMaWJ2khljJIKwOS8
-> ssh-ed25519 K3b7BA oS14iav9pSioLecMkOanJz89OJygLugvrnnTs5pKzz8
akupMSiqXussXJyHwFm/f0imKALjowJVqd8/LFcC/58
--- bCJXTEDaKg4FF2dQp2zFMU4Zm0zACekCuDvthcAyncM
&­Ÿ €WaïãàBD R(¯¥Ñ”ufj<>úVÁ8nÆ>ßøëæðZúâ{Idƒ„©,³*„%Ç“È

Binary file not shown.

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 j2r2qQ uYhcMpOER5j/SWUX1mNvkOU9Rumr0CgVBuGv9EHGpFY
6kAgrwjgB7C1cMd410EpUegcxxGRcNOwCMJPXppepvE
-> ssh-ed25519 K3b7BA 57GDNt5nwxgzCV5bnMPEPUeyZNG1U+zajCIjeoHjLAE
rFCbfodjXHZ0aVLtW6xtoh6e/VH/HwFdFzjnQ2QEEXQ
-> ssh-ed25519 +qVung DnLKAJPnUDpZ2+wXDZWpxwZkvv8oDyu3xxObTMT9W1I
vh59DYoQLpiro5eBjwgNH2YHRsGY/i6TB7zPfQicOEU
-> ssh-rsa krWCLQ
ekvGooB5sCmAniHU7hlk+iCkYMQ7Rw2SJx8tp4FnpfAWJbRMH8CpTFYFiDvlHfFy
Ce1OpkNkkipzBge0OCrfn6Y5iVz2CZHYHf8Ul5ueHwmb5fS7seT3yMoWhhSw/zE/
G3snrBORT9S9+KTRnVnKiy+O3CaMZY+q41RR35Fs3mmVc/of2ILc/Jj3a3t+uBTX
axkOMU6z6R6i3Ps5SbwJTaB9q2kMPvZFOO9Nmku1wohjetz64wvm+fDx0XVRPe4A
jDQRPKAMIZK68SYHk/9azmlBtJSJnvxcxyj3IaU9MBskUCldWi8CQ9jQ+1XAIuHX
0Etcsx7MhzBpuhx2xZ+dyg
-> ssh-ed25519 /vwQcQ uW41w2RAtfMaOm1wJktMcbVporqKgdGA5SY03OcPmlM
WgL8DWPU735Ysowq0HtvbrT6Tc3XEpwws3AycqpBgtM
-> ssh-ed25519 0R97PA 59AFQx8ngDwQUdmfOeOFUARQQqaAdLA5WH67Wsld4yM
o6jSWtlidZssWsJsI8xAaASi8p1sirLJFJwizzPXIBM
--- scUnldbU89ICZYlniDbGEqeUF7QUoO1kcZLl8abyttk
öR{p@IµþOlKKõŒ§!<01>œWÎÅœ[R<-AÐbÔ<¯·÷0õÐu¹øµñUgBÏF~µ«=ÊõeQò}î4Ø:ô²¢5ƯŠtaØ™û”<C3BB>æ·<C3A6>§°x±Më?Ew0<77>8.

Binary file not shown.

View file

@ -0,0 +1,21 @@
age-encryption.org/v1
-> ssh-ed25519 CyxfgQ fWH/o2+Uf0i/JFIuVjCnkhDIfYndtL8EeDcxSxhKVH8
ShSPmdwnxzDuUe/kCx8e61JJAoHMwguNydn+5OIGuAg
-> ssh-ed25519 K3b7BA p+wXAGvPqTX63dlZNCTIq3F4QFMWEJH1R+Ex4SJ5UTk
1sFqFqnUM8YvZy7BEBArg3eLxCCsLXq2jNI7XLKq/Ww
-> ssh-ed25519 +qVung rcpgzVQ1PmoNF2i0K0nAknzZwPXICBggzqhIZwO+8xY
9rjsTwLm5u1GOJmnJYriXXAY1unG7y+WJ4G2ltxX34U
-> ssh-rsa krWCLQ
seXsQjs62kxn/agyKda2l19PI4xzDl1gM7rEnaEBV8UNLOPNxh41HTnP2etgDXSc
4eyS3ntHXIOHmN4+JBn+Q/wuhzMGQmAcoFWbjqVVPOrpPYjgCG7q/iUD8kULxLB9
UpF0gLsg1TnvrkTwlpxr8rP/PM+ZgyQAA84S96j9TW0coyTUoH/ZX1wWGtS4aalm
aTrOMZGScZu7onTg+tYvR+aBKlFL28h08I5nqbA39srnCNuU68+OUhLgLUfiTscl
umwNh/C4BP2Tmc6gxQiY8o3tGqGBssGH5+WqKzbK151vJjq80RKAS1HCaSSfmxkP
vWkXWN3NQkJyqCBpuPYilg
-> ssh-ed25519 /vwQcQ eUH0B+cCoUubIKbG+bA25kRj0TnZabB6t8jVK04NrFs
ovkI0C4W5CJXMZIZdpaTtQNc+TGkQ3Yq87Dei3BMUsA
-> ssh-ed25519 0R97PA u/I45pxH3Bnja/Jw/6IukINRuC0e1IKu8UVygVgIomc
xyHuiHf1/nJirnhXbGHJnextGQa95tDo/RPRRnDCkIg
--- LGqO4Bsa8bofD1W5YrQp75SlGLNg1XaFZ0rPUuvLPTo
Êçã ‹ÜmlW£{@I3…*¹ŒÇ™@ÞªL7Wª ¤ÝŒY
n õö~Tb\V•ÜvPÙpPôïoÌS"ôm/Ûµ/bÝpÄžêq¸£¦šeDj6ÆþTì)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 CyxfgQ D2o8bUccO13DKF4COLBQ9mJbACsE2XsRa5S+N71WnTk
ZaldT7HhQxbxf2ptIwdMYkC60eGtzihc7uwcAkq7s00
-> ssh-ed25519 K3b7BA AiUCG5CnNyv1DPu+iEwEgW9GqZ8zgpgxKJTAp350ADc
cUVaDv7F1haQIF11/UhhDAR5DrfJlPttGfDjkv+z9vY
-> ssh-ed25519 +qVung 1JXeXyea+2Pcwoln/NLRiR8IPPIiB3gaFCP4imyv4DA
JWmAY6ZnyU46KxzhRrQigGmUPba9lJDDyRQ2GjQShqc
-> ssh-rsa krWCLQ
ciLu/+cXfQrB1ms8oTv+xi4eADyL4j0qwnY/6TE0wAXkQHuNXDmpF6ccWZoS2DqN
NcnGXL6+WyWxmwlyBEq/rsBPvi1g0M6Md7Z4gXn2UvjJ+S7WyA8QEwkxoTDkJS7x
k/NvtunmggVsWVK4Xdi5DKRw+f32qr/8GysDhIPrTt43iReBKNbyuYWmC5Ec85ep
JU4JzCNZjJ07kixS5Y9BhaJbpEr47lCXE/KtJUvm3VAxS9IwfUn7KHHdFWynbExi
F898j3zOR/kgYmeA0oTiexRD3Y2LCvjXIHQZ3MobbZ/PBrjWxe78Sw2vy2t5JLtB
gFG0K8M1z8DT6a8TtvXEgg
-> ssh-ed25519 /vwQcQ kUM21TO9iSa8oVXMlNxR7Kc+8TV4C/uTzyQ+t3xnARA
oXt+egWWONsKT48H4vZ2CPdy3Zfb2QeQVe9l7dDyO/w
-> ssh-ed25519 0R97PA e/piqf2RD5QgPaQs6jsJdzJgfZR9n1JDIWpbvLZErSs
UTJH8POFdZ4+N9WkLoNESl1pvcVD0MS1qn7AdS/mg34
--- 9aYEP0eHDKMacIf09h+OJqIYw+N99+FrW/x/do8Lbo4
$ ÖëWÛ\zú—¾=s/à@.Ç,?ƒW6n^ù#i!§Ãï¶1]±Nvù±Ž 'Ï¥¹6?'mµpPÒqýŸº

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 j2r2qQ kbi4mciOrjd7/X86xfmkDaMZhvZakoSJ6qjqLF3ljkE
Q2BsgMLJ8AmjhnggRi+wkICj18NCA2HW1t8clemReUw
-> ssh-ed25519 K3b7BA wNGmX9S9bJgd2JDte9QoNDfyycgmq4JMu2bc5nyYYik
uUiutxAI3nI0M51W97aPRVE/l4dV2PEjph8eWOMLHIE
-> ssh-ed25519 +qVung raYJ5vwMP9JopSdfa+ofkLY/gc0zcW4wTNBFTca+MXw
sa/rWGSYrI4y6rn4JSboldWKUGvx6HbtsYo78AFOkBo
-> ssh-rsa krWCLQ
FLq8NwkiGw2gXptVVY393f0p9hFom57xHWPxtAlzOcRT8gvWu/uwgV+0raOcOcJa
xxr5Sib+2D3UnUhprVPmH5Os9bI2seFAiej1MVVWLqvMtQHLFwnrzZTyZpxsXpQq
5qQhNEADuQc4uD/ELVjGHKt6nF1Cl/GbgNLIOF/ITZ0pm1O1MjtT6MYJhQJhc6sb
sno/wQyTXjj7rC06nyLX/rgOWrJSOeaz9eVp0A8k8/I0TXu/vRCW9gqWtv2m8sbh
1uUHIm0l8f3z+zrL6OlZnpMFw4jpiiGoCYKPzD17I0onDYIjtdVS5iO9BsckxV/a
wQWbyONUwbGCfeNSVAzZbg
-> ssh-ed25519 /vwQcQ jwf7fwy4wKz7q761DNu8SyFHGgFlwq4P/Pn44Nido3E
1q/jvt/vtD4ziY3eCDqk1XwMPpNUd80POTV2VVsumCE
-> ssh-ed25519 0R97PA XeuziQ+wsoh0KSHXk5Qkl1kQOsAu1Ax1zTg13+XWd3M
B1KHKm3tx/EsnE6hY+w7ya1ilhYiUs9AbwARHNkJi90
--- JgQA6gCYZu8xcbXEl9VypccEIBO6uAJIdhBefr4doRQ
V3ZðõÚ<EFBFBD>ç-·Ý.ê«sòÀ³3 ÎiS‰a5#¿Ð{åÔÈ®Dý˜YêNèãëù«ýoL+ÔÝ#M<sws P»¢+í¢Ó‰ïBDoÊξÆÏuFí”Ç^Â¥•<C2A5>ÝG@ÍM×ÛãÐØì q¦ºG^Qb s<;ÂÒnC+ÖÊxª_­Úì]S<16>Ð

View file

@ -1,7 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 j2r2qQ Xl0fSOuF0xNTJrtVGdRLRIszd15LFrG5KCFNvSBK4Go
qSEMBBw90jz4j8elpoUeyS4CTLBhZtNDhLNigesJq+0
-> ssh-ed25519 K3b7BA cKI0twKiuuTKv1Js4jqt5v8cOqpxEMY9dmVghgJtbzw
K5o31XP/nLsswsrMaxnIzCXVUtJqmJWoFglWFsV7+AQ
--- X8pvqCHeCQ0LjzcjIHThkqp6YeOOT8dBMLuktgdgeY4
sZÓ¸ŠíØ[þ²X<C2B2>“¡èÅ®Š5°=÷6)ÇT¿Q†N{•x³I1ƒ!ÓÜøB ƒzš*×íåL~K

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,7 @@
age-encryption.org/v1
-> ssh-ed25519 Ao+7Wg q7oRHUUlAvD8OUbpPT7d6eLMPWU0YS/verYTDE5BCkY
/87/1uqOvRYeqel9IjnFmGyF9SXUQD8MTgfcj91b/Fs
--- ulIeB91NJ7z/64h9BCLSD9/RW/zwv3m1Zo2ovNuInv8
Îœç}³Óš#épÇ o>ä·*vµ÷ÄåŽs?[¦º´L
<EFBFBD>þz™rý‰?R±Ñó7<Ê
æi!€{X„¾òÓ

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,6 @@
age-encryption.org/v1
-> ssh-ed25519 Ao+7Wg EMpfs0EpWwaIKAoUBfEkyAHLIwi6JnGG6RvUWM5LjnU
LKiwUBNc791U/GVRNlRPZE/TEMJjcFFrLruFJhiyiOI
--- 0khp8u+4vHgGyQqP05m473Eo09eyOUZLI5+EK4olzoc
N3(
ª•ûxRq°<71>f<EFBFBD>Ó;ͼ3¬~RˆÓC^ñ +fœš1”®˜xˆ÷ÅëñSØ— hâ £ÖË°GˆÓnYIûµ:7¾!°u×Hþy/‰Øð‰™.¯¤á^¹lC™ôUÈËþ5cž:]ÿNž&'MÎè¶É-˜ÆHF¦D0 cjô ‹Ð~

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more