45 Commits

Author SHA1 Message Date
self 7cfd7568a7 fix: raise Parrhesia sync read pool
Live mixed-provider supertest runs showed control-lane SYNC-PAGE handlers timing out while waiting for Parrhesia DB read connections under catch-up load. Set larger Parrhesia main/read pool sizes in the Tribes service environment so sync-page queries can proceed concurrently during node joins.
2026-06-09 09:43:59 +02:00
self ffbd62593c chore: sync supertest dev channel to master
Source: guix-tribes master 54f23bc863
Base: previous supertest-dev 593745da5e
Mode: tree sync, preserving dev channel authorization
2026-06-09 09:43:46 +02:00
self 593745da5e fix: normalize channel signer fingerprints
Trust checks now compare compact uppercase fingerprints so spaced OpenPGP fingerprints in channel introductions match stored TrustedSigner rows.
2026-06-08 09:35:56 +02:00
self eb3a319744 chore: update dev pins for supertest plugin 2026-06-08 08:03:10 +02:00
self 7dec823794 chore: sync supertest dev channel to master
Source: guix-tribes master 2ea4cae872
Base: previous supertest-dev 4fee530b68
Mode: tree sync, preserving dev channel authorization
2026-06-08 08:02:39 +02:00
self 4fee530b68 fix: preserve core guix channel for rollouts
When local-control writes rollout channels from a SystemTarget plan, preserve the current core guix channel if the plan only contains the Tribes plugin channel.\n\nGuix pull requires a channel named guix; SystemTarget channel entries currently model the Tribes channel selected for plugin/package resolution, so overwriting channels.scm with only that channel breaks prepare.
2026-05-28 19:10:56 +02:00
self 2658774d20 chore: update dev pins for supertest plugin 2026-05-28 18:44:07 +02:00
self f2cdcd10a0 fix: discover plugin packages from channel modules
Limit plugin catalog discovery to tribes/plugins modules present on the active Guix load path.\n\nThe local-control catalog path runs under guix repl where channel modules are available on %load-path but not necessarily in %package-module-path, causing fold-packages to return an empty catalog.\n\nAlso update the deploy executor test expectation for the current aether registry version.
2026-05-28 18:42:55 +02:00
self 894a90016d chore: sync supertest dev channel to master
Source: guix-tribes master 5393a19225
Base: previous supertest-dev 357a2a3a10
Mode: tree sync, preserving dev channel authorization
2026-05-28 18:42:43 +02:00
self 357a2a3a10 fix: discover plugin packages from channel modules
Limit plugin catalog discovery to tribes/plugins modules present on the active Guix load path.\n\nThe local-control catalog path runs under guix repl where channel modules are available on %load-path but not necessarily in %package-module-path, causing fold-packages to return an empty catalog.\n\nAlso update the deploy executor test expectation for the current aether registry version.
2026-05-28 18:40:52 +02:00
self 9f069ab068 chore: update dev pins for supertest plugin 2026-05-28 17:54:25 +02:00
self add6e5cb5d chore: sync supertest dev channel to master
Source: guix-tribes master be00553503
Base: previous supertest-dev ca19fa2d73
Mode: tree sync, preserving dev channel authorization
2026-05-28 16:57:33 +02:00
self ca19fa2d73 chore: update dev Tribes pin 2026-05-21 11:40:25 +02:00
self ce1e21195d chore: sync supertest dev channel to master
Source: guix-tribes master fff523d732
Base: previous supertest-dev 7025abef29
Mode: tree sync, preserving dev channel authorization
2026-05-21 11:39:46 +02:00
self 7025abef29 chore: update dev pins for sender plugin 2026-05-17 18:57:08 +02:00
self d5a4180f6c fix: trust forwarded IPs for vinyl exporter
Bump vinyl-exporter to v0.2.0 and expose trusted proxy configuration so HLS IP fallback can use X-Forwarded-For from the local HAProxy/Vinyl edge path.
2026-05-17 18:54:56 +02:00
self cabe37f995 chore: sync supertest dev channel to master
Source: guix-tribes master ae6968c5b8
Base: previous supertest-dev 0632428e43
Mode: tree sync, preserving dev channel authorization
2026-05-17 18:54:48 +02:00
self 0632428e43 chore: sync supertest dev channel to master
Source: guix-tribes master ae6968c5b8
Base: previous supertest-dev 8845eb4c07
Mode: tree sync, preserving dev channel authorization
2026-05-17 17:08:38 +02:00
self 8845eb4c07 feat: link HAProxy QUIC against AWS-LC
Add a scoped AWS-LC 1.73.0 package for HAProxy and build HAProxy's QUIC support against it instead of OpenSSL compatibility mode.\n\nRemove the limited-quic runtime knob and update the rendered node config test to assert native QUIC configuration.
2026-05-12 02:55:26 +02:00
self f26511015d chore: sync supertest dev channel to master
Source: guix-tribes master b0d3b184cc
Base: previous supertest-dev aec441e50e
Mode: tree sync, preserving dev channel authorization
2026-05-12 02:55:14 +02:00
self aec441e50e feat: enable HAProxy QUIC listener
Upgrade the HAProxy package to 3.3.10 and build it with QUIC support via the OpenSSL compatibility layer used by the current Guix OpenSSL 3.0 input.\n\nExpose default HTTP/3 UDP listeners, advertise h3 through Alt-Svc, and cover the generated edge proxy config in the node system tests.
2026-05-12 02:00:55 +02:00
self 5ed36e7f21 chore: sync supertest dev channel to master
Source: guix-tribes master b68182c838
Base: previous supertest-dev 802327d325
Mode: tree sync, preserving dev channel authorization
2026-05-12 02:00:27 +02:00
self 802327d325 refactor: route HTTP edge traffic through HAProxy
Let HAProxy own both public edge listeners so ACME challenge paths are proxied directly to Lego's standalone challenge server while all other HTTP traffic redirects to HTTPS. Remove the HTTP-only Vinyl instance and keep Vinyl focused on the private cache backend.
2026-05-11 23:44:14 +02:00
self 7288e75f61 chore: sync supertest dev channel to master
Source: guix-tribes master bade8dd709
Base: previous supertest-dev 4c31c41d85
Mode: tree sync, preserving dev channel authorization
2026-05-11 23:44:01 +02:00
self 4c31c41d85 feat: replace edge TLS proxy with HAProxy
Add HAProxy 3.3.9 to the Tribes Guix channel and introduce a Shepherd service for the public TLS edge. Wire node edge deployments and Lego reloads to HAProxy while keeping Vinyl's HTTP challenge and cache topology unchanged.
2026-05-11 22:59:05 +02:00
self 076cc7ea70 chore: sync supertest dev channel to master
Source: guix-tribes master e00e40e61e
Base: previous supertest-dev 8b433f9d90
Mode: tree sync, preserving dev channel authorization
2026-05-11 22:58:53 +02:00
self 8b433f9d90 fix: avoid textual-ports in plugin assembly
Replace the assembled plugin package builder's get-string-all dependency with a local read-char loop. This keeps the builder module closure compatible with node-side Guix builds that use the rollout Guile package and avoids failures resolving (ice-9 custom-ports).
2026-05-11 14:37:10 +02:00
self 402b3edad5 fix: include guix build output in rollout failures
Return a bounded tail of captured guix system build output in local-control build_failed frames. This keeps rollout diagnostics actionable when the node is destroyed before the full helper stderr can be inspected.
2026-05-11 14:21:07 +02:00
self 9a11577ec1 fix: resolve plugins against built-in ui provider
Treat capabilities provided by built-in Tribes plugins as baseline resolver capabilities so channel plugins that require ui@1 can be previewed and rolled out without adding a separate external UI plugin. Add a sender regression case to the deploy executor tests.
2026-05-11 13:53:31 +02:00
self b5e548c7f7 build: package sender muontrap binary
Port the sender pin bump and muontrap executable assertion onto the supertest dev channel so live sender runs exercise the same native Mix dependency packaging path as the master-side fix.
2026-05-11 13:40:39 +02:00
self d97681e35f chore: sync supertest dev channel to master
Source: guix-tribes master 0723473037
Base: previous supertest-dev d6f13b27c8
Mode: tree sync, preserving dev channel authorization
2026-05-11 13:40:26 +02:00
self d6f13b27c8 fix: expose plugin runtime binaries to Tribes
Add the effective Tribes package and plugin extra package bin directories to the Tribes launcher PATH. This lets runtime plugin code find executables, such as sender resolving ffmpeg from its Guix extra package, after a rollout switches to the plugin-enabled system generation.
2026-05-09 22:50:40 +02:00
self 0b2e2dd80a chore: update dev pins for sender plugin 2026-05-09 22:28:54 +02:00
self 7d8c5b27ba fix: avoid host textual ports in plugin assembly
The external plugin assembly builder only needed to read .app files for OTP version validation. Importing ice-9 textual-ports into the isolated trivial builder made Guix copy host Guile modules and failed when the closure missed ice-9 custom-ports.

Use a local reader instead so sender and other external plugin rollouts can build the assembled release package reliably.
2026-05-09 21:51:52 +02:00
self 5c886872ac fix: expose host ui capability
Use ui@1 as the Guix deployment resolver host capability so plugins that depend on the core UI contract can be installed without a separate provider plugin.
2026-05-09 21:19:40 +02:00
self 889e871b7f chore: update dev pins for sender plugin 2026-05-09 21:04:23 +02:00
self e635b7af84 chore: sync supertest dev channel to master
Source: guix-tribes master 419bea8fe5
Base: previous supertest-dev b378db1e22
Mode: tree sync, preserving dev channel authorization
2026-05-09 21:02:52 +02:00
self b378db1e22 fix: compile built-in Tribes plugins 2026-05-09 14:45:53 +02:00
self 2f791c889b chore: update dev Tribes pin 2026-05-09 14:18:08 +02:00
self 6911d8bd49 chore: refresh supertest dev baseline 2026-05-02 19:26:55 +02:00
self f1cc7a369f fix: bring no-wx OTP baseline into supertest dev 2026-05-01 13:56:27 +02:00
self 2af29c91ce fix: slim plugin build toolchain
Avoid pulling wx/GUI dependencies into the OTP toolchain used for plugin builds, route rebar through the OTP 28 toolchain, and vendor libsecp256k1 sources during plugin compilation so rollout nodes do not fetch them at build time.
2026-04-30 14:59:35 +02:00
self 47997b4cde feat: run plugin down migrations on rollback
Add a rollback-only migration service and invoke it before switching to an earlier system generation. This lets plugin uninstall rollbacks run destructive down migrations while the current generation still contains the plugin code.
2026-04-30 11:38:44 +02:00
self 92e969e34b feat: package supertest plugin
Add the migration-bearing supertest fixture to the Guix plugin registry so rollout scenarios can enable it through the normal system target path.
2026-04-30 11:29:28 +02:00
self 7c4f9d3b34 build: authorize supertest dev signing key
Add a dedicated local development signing key for the supertest dev channel branch. This branch is intended for explicit test/dev rollout runs and does not alter the externally signed master workflow.
2026-04-30 11:20:12 +02:00
46 changed files with 419 additions and 837 deletions
+3 -1
View File
@@ -5,4 +5,6 @@
(version 0) (version 0)
(("6688 9153 C51C 4613 A493 A525 2F0D FD14 EF99 DAC3" (("6688 9153 C51C 4613 A493 A525 2F0D FD14 EF99 DAC3"
(name "steffen")))) (name "steffen")) ("F29B A6DA 96E5 EC29 FDDE D994 8F4F 75B3 B19D 4784"
(name "tribes-supertest-dev"))
))
+7
View File
@@ -0,0 +1,7 @@
{
"mode" : "tree-sync",
"previous_dev_commit" : "593745da5e4135abc63956442e853dd2643e46ae",
"source_branch" : "origin/master",
"source_commit" : "54f23bc863ebef8173faf2aaf21801050e09fb53",
"synced_at" : "2026-06-09T07:43:46Z"
}
-29
View File
@@ -111,35 +111,6 @@ generation `channels` are the preferred source for the currently installed
channel commit; callers can fall back to top-level `current_channels` for the channel commit; callers can fall back to top-level `current_channels` for the
initial non-local-control install. initial non-local-control install.
### `POST /v1/certificates/edge/install`
Synchronous. Installs a Tribes-issued public edge certificate for HAProxy and
reloads HAProxy. This endpoint is intended for the Tribes ACME renewal worker;
it does not store desired certificate configuration.
Body:
```json
{
"fullchain_path": "/var/lib/tribes/acme/edge.fullchain.pem",
"private_key_path": "/var/lib/tribes/acme/edge.key"
}
```
Rules:
- Both paths must be under `/var/lib/tribes/acme/`.
- Both files must already exist.
- local-control writes `/var/lib/tribes/acme/edge.full.pem` as fullchain plus
private key for HAProxy.
- local-control reloads `haproxy` after the file swap.
Successful response:
```json
{"ok": true}
```
### `POST /v1/channels/updates` ### `POST /v1/channels/updates`
Synchronous. Discovers update candidates for configured channels by using the Synchronous. Discovers update candidates for configured channels by using the
+6 -5
View File
@@ -4,15 +4,15 @@
"workingDirectory": "/var/lib/tribes", "workingDirectory": "/var/lib/tribes",
"serviceUser": "tribes", "serviceUser": "tribes",
"serviceGroup": "tribes", "serviceGroup": "tribes",
"host": "203.0.113.10", "host": "node1.example.invalid",
"listenAddress": "127.0.0.1", "listenAddress": "127.0.0.1",
"listenPort": 4000, "listenPort": 4000,
"scheme": "https", "scheme": "https",
"port": 443, "port": 443,
"syncHost": "203.0.113.10", "syncHost": "node1.example.invalid",
"syncPort": 4413, "syncPort": 4413,
"syncBindAddress": "0.0.0.0", "syncBindAddress": "0.0.0.0",
"syncUrl": "wss://203.0.113.10:4413/relay", "syncUrl": "wss://node1.example.invalid:4413/relay",
"syncTlsCertFile": "/var/lib/tribes/secrets/sync/node.pem", "syncTlsCertFile": "/var/lib/tribes/secrets/sync/node.pem",
"syncTlsKeyFile": "/var/lib/tribes/secrets/sync/node-key.pem", "syncTlsKeyFile": "/var/lib/tribes/secrets/sync/node-key.pem",
"syncTlsCaCertFile": "/var/lib/tribes/secrets/sync/ca.pem", "syncTlsCaCertFile": "/var/lib/tribes/secrets/sync/ca.pem",
@@ -32,8 +32,9 @@
"logFile": "/var/log/tribes/tribes.log" "logFile": "/var/log/tribes/tribes.log"
}, },
"edge": { "edge": {
"certificateName": "203-0-113-10", "certificateName": "node1-example-invalid",
"certificateSubjects": ["203.0.113.10"], "certificateSubjects": ["node1.example.invalid"],
"certificateEmail": "ops@example.invalid",
"certificateProfile": "shortlived", "certificateProfile": "shortlived",
"renewDays": 4, "renewDays": 4,
"httpPort": 80, "httpPort": 80,
-54
View File
@@ -1,54 +0,0 @@
;;; Manifest of upstream source origins for every package defined by the
;;; tribes channel. Consumed by Cuirass's `manifests' build type as a
;;; network-bound canary: fast-fails when an upstream URL or commit ref
;;; becomes unreachable, without depending on any actual package build.
(define-module (manifests sources)
#:use-module (gnu packages)
#:use-module (guix discovery)
#:use-module (guix packages)
#:use-module (guix profiles)
#:use-module (ice-9 match)
#:use-module (ice-9 vlist)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:export (sources-manifest))
(define (channel-module-path prefix)
(delete-duplicates
(filter-map (lambda (dir)
(let ((path (string-append dir "/" prefix)))
(and (file-exists? path) (cons dir prefix))))
%load-path)
equal?))
(define (channel-packages)
(fold-packages cons '()
(append (all-modules (channel-module-path "tribes/packages"))
(all-modules (channel-module-path "nbde/packages")))))
(define (upstream-origin source)
(origin (inherit source) (snippet #f) (patches '())))
(define (channel-origins)
(let loop ((packages (channel-packages))
(origins '())
(visited vlist-null))
(match packages
((head . tail)
(let ((new (remove (cut vhash-assq <> visited)
(package-direct-sources head))))
(loop tail (append new origins)
(fold (cut vhash-consq <> #t <>)
visited new))))
(() origins))))
(define sources-manifest
(manifest (map (lambda (origin)
(manifest-entry
(name (or (origin-actual-file-name origin) "origin"))
(version "0")
(item (upstream-origin origin))))
(channel-origins))))
sources-manifest
+49
View File
@@ -0,0 +1,49 @@
(define-module (manifests substitutes base)
#:use-module (gnu packages)
#:use-module (gnu packages elixir)
#:use-module (gnu packages erlang)
#:use-module (guix profiles)
#:use-module (nbde packages crypto)
#:use-module (tribes packages terminals)
#:export (base-manifest))
(define %base-specifications
'("bash-minimal"
"coreutils"
"diffutils"
"findutils"
"gawk"
"grep"
"gzip"
"inetutils"
"iproute2"
"less"
"nss-certs"
"openssh"
"postgresql"
"procps"
"rsync"
"sed"
"tar"
"which"
"xz"
"cryptsetup"
"dosfstools"
"e2fsprogs"
"gptfdisk"
"kmod"
"parted"
"util-linux"))
(define base-manifest
(packages->manifest
(append (map specification->package %base-specifications)
(list clevis
tang
luksmeta
erlang
elixir
elixir-hex
ghostty-terminfo))))
base-manifest
+48
View File
@@ -0,0 +1,48 @@
(define-module (manifests substitutes installer)
#:use-module (gnu packages)
#:use-module (guix profiles)
#:use-module (nbde packages crypto)
#:export (installer-manifest))
(define %installer-specifications
'("bash-minimal"
"coreutils"
"diffutils"
"findutils"
"gawk"
"git-minimal"
"grep"
"gzip"
"guix"
"inetutils"
"iproute2"
"kexec-tools"
"less"
"curl"
"nss-certs"
"procps"
"rsync"
"sed"
"tar"
"which"
"zstd"
"xz"
"console-setup"
"cryptsetup"
"dosfstools"
"grub-efi"
"grub-pc"
"mdadm"
"e2fsprogs"
"gptfdisk"
"kmod"
"parted"
"util-linux"))
(define installer-manifest
(packages->manifest
(append (map specification->package %installer-specifications)
(list clevis
luksmeta))))
installer-manifest
+60
View File
@@ -0,0 +1,60 @@
(define-module (manifests substitutes tribes-node)
#:use-module (gnu packages)
#:use-module (gnu packages elixir)
#:use-module (gnu packages erlang)
#:use-module (gnu packages monitoring)
#:use-module (guix profiles)
#:use-module (tribes packages monitoring)
#:use-module (tribes packages source)
#:use-module (tribes packages terminals)
#:use-module (tribes packages web)
#:use-module (tribes plugins registry)
#:export (tribes-node-manifest
make-tribes-node-manifest))
(define %tribes-node-specifications
'("nss-certs"
"openssh"
"postgresql"
"rsync"
"ripgrep"
"fd"
"tmux"
"neovim"
"btop"))
(define (getenv/default name default)
(or (getenv name) default))
(define (tribes-node-package)
(let ((source-directory (getenv "TRIBES_SOURCE_DIRECTORY")))
(if source-directory
(local-tribes-package
source-directory
#:version (getenv/default "TRIBES_RELEASE_VERSION" "dev")
#:mix-deps-sha256 (getenv "TRIBES_MIX_DEPS_SHA256")
#:raw-mix-deps-sha256 (getenv "TRIBES_RAW_MIX_DEPS_SHA256")
#:npm-deps-sha256 (getenv "TRIBES_NPM_DEPS_SHA256"))
tribes-package)))
(define (make-tribes-node-manifest)
(packages->manifest
(append
(map specification->package %tribes-node-specifications)
(list erlang
elixir
elixir-hex
ghostty-terminfo
haproxy
vinyl
lego
prometheus-node-exporter
victoriametrics
vinyl-exporter
(tribes-node-package))
(guix-tribes-plugin-substitute-packages))))
(define tribes-node-manifest
(make-tribes-node-manifest))
tribes-node-manifest
+3 -13
View File
@@ -55,10 +55,7 @@
util-linux))) util-linux)))
(define %build-host-kexec-initrd-modules (define %build-host-kexec-initrd-modules
'(;; Common block/storage basics. '("ahci"
"ahci"
"ata_piix"
"cdrom"
"dm-crypt" "dm-crypt"
"fat" "fat"
"loop" "loop"
@@ -67,19 +64,13 @@
"nvme" "nvme"
"overlay" "overlay"
"sd_mod" "sd_mod"
"sr_mod"
"squashfs" "squashfs"
"vfat" "vfat"
;; KVM/QEMU and common emulated or non-virtio NICs.
"virtio_blk" "virtio_blk"
"virtio_console" "virtio_console"
"virtio_net" "virtio_net"
"virtio_pci" "virtio_pci"
"virtio_scsi" "virtio_scsi"))
"e1000"
"e1000e"
"r8169"))
(define build-host-kexec-installer-os (define build-host-kexec-installer-os
(operating-system (operating-system
@@ -93,10 +84,9 @@
(initrd kexec-installer-initrd) (initrd kexec-installer-initrd)
(kernel-arguments (kernel-arguments
'("console=ttyS0,115200n8" '("console=ttyS0,115200n8"
"console=tty0"
"net.ifnames=0" "net.ifnames=0"
"panic=30" "panic=30"
"loglevel=6")) "loglevel=4"))
(bootloader (bootloader
(bootloader-configuration (bootloader-configuration
(bootloader grub-bootloader) (bootloader grub-bootloader)
+2 -3
View File
@@ -28,9 +28,8 @@
(locale "en_US.UTF-8") (locale "en_US.UTF-8")
(kernel tribes-linux) (kernel tribes-linux)
(kernel-arguments (kernel-arguments
(list "console=ttyS0,115200n8" (list "console=tty0"
"console=tty0" "console=ttyS0,115200n8"))
"net.ifnames=0"))
(initrd (initrd
(lambda (file-systems . rest) (lambda (file-systems . rest)
(apply base-initrd (apply base-initrd
+3 -6
View File
@@ -48,9 +48,8 @@
(locale "en_US.UTF-8") (locale "en_US.UTF-8")
(kernel tribes-linux) (kernel tribes-linux)
(kernel-arguments (kernel-arguments
(list "console=ttyS0,115200n8" (list "console=tty0"
"console=tty0" "console=ttyS0,115200n8"))
"net.ifnames=0"))
(initrd-modules (initrd-modules
(append %nbde-initrd-modules (append %nbde-initrd-modules
%base-initrd-modules)) %base-initrd-modules))
@@ -73,9 +72,7 @@ runtime-discovered boot and filesystem values from the installer."
(append (append
extra-services extra-services
(list (boot-store-staging-service) (list (boot-store-staging-service)
(service dhcpcd-service-type (service dhcpcd-service-type)
(dhcpcd-configuration
(interfaces (list interface))))
(service elogind-service-type) (service elogind-service-type)
(service agetty-service-type (service agetty-service-type
(agetty-configuration (agetty-configuration
+3 -3
View File
@@ -1,10 +1,10 @@
(list (channel (list (channel
(name 'guix) (name 'guix)
(url "https://git.teralink.net/tribes/guix-fork.git") (url "https://git.teralink.net/tribes/guix-fork.git")
(branch "feature/substitute-read-timeout") (branch "refactor/substituter-trace-framing")
;; guix-fork feature/substitute-read-timeout ;; guix-fork refactor/substituter-trace-framing
(commit (commit
"4574af27f27c7a5d2dc4d4823ef4518a392dc973") "8514f9c1a98468c044e8b5f65e4a90d097a63a47")
(introduction (introduction
(make-channel-introduction (make-channel-introduction
"093f27dde01cdbda68f2ec4b81e5a34ae180aab9" "093f27dde01cdbda68f2ec4b81e5a34ae180aab9"
+3 -3
View File
@@ -2,10 +2,10 @@
(channel (channel
(name 'guix) (name 'guix)
(url "https://git.teralink.net/tribes/guix-fork.git") (url "https://git.teralink.net/tribes/guix-fork.git")
(branch "feature/substitute-read-timeout") (branch "refactor/substituter-trace-framing")
;; guix-fork feature/substitute-read-timeout ;; guix-fork refactor/substituter-trace-framing
(commit (commit
"4574af27f27c7a5d2dc4d4823ef4518a392dc973") "8514f9c1a98468c044e8b5f65e4a90d097a63a47")
(introduction (introduction
(make-channel-introduction (make-channel-introduction
"093f27dde01cdbda68f2ec4b81e5a34ae180aab9" "093f27dde01cdbda68f2ec4b81e5a34ae180aab9"
-1
View File
@@ -109,7 +109,6 @@ load_guix_env
require_tool guix require_tool guix
require_tool guile require_tool guile
require_tool mksquashfs require_tool mksquashfs
require_tool cpio
require_file "$channels" "channels file" require_file "$channels" "channels file"
require_file "$script_dir/kexec-run" "kexec runner" require_file "$script_dir/kexec-run" "kexec runner"
require_file "$root_dir/examples/build-host-kexec-installer.scm" "system file" require_file "$root_dir/examples/build-host-kexec-installer.scm" "system file"
+2 -2
View File
@@ -7,11 +7,11 @@ base_output="${NBDE_BASE_CHANNELS_OUTPUT:-$root_dir/pins/base-channels.sexp}"
legion_output="${NBDE_LEGION_CHANNELS_OUTPUT:-$root_dir/pins/legion-channels.sexp}" legion_output="${NBDE_LEGION_CHANNELS_OUTPUT:-$root_dir/pins/legion-channels.sexp}"
fork_url="https://git.teralink.net/tribes/guix-fork.git" fork_url="https://git.teralink.net/tribes/guix-fork.git"
fork_branch="feature/substitute-read-timeout" fork_branch="refactor/substituter-trace-framing"
fork_introduction_commit="093f27dde01cdbda68f2ec4b81e5a34ae180aab9" fork_introduction_commit="093f27dde01cdbda68f2ec4b81e5a34ae180aab9"
fork_introduction_signer="6688 9153 C51C 4613 A493 A525 2F0D FD14 EF99 DAC3" fork_introduction_signer="6688 9153 C51C 4613 A493 A525 2F0D FD14 EF99 DAC3"
fork_checkout="$root_dir/../guix-fork" fork_checkout="$root_dir/../guix-fork"
fork_comment="guix-fork feature/substitute-read-timeout" fork_comment="guix-fork refactor/substituter-trace-framing"
official_url="https://git.teralink.net/tribes/guix.git" official_url="https://git.teralink.net/tribes/guix.git"
official_branch="master" official_branch="master"
+10 -46
View File
@@ -16,19 +16,13 @@ Usage: update-plugin-pin [options] plugin [rev]
Pin a Tribes external plugin and refresh fixed-output hashes. Pin a Tribes external plugin and refresh fixed-output hashes.
PLUGIN is the canonical plugin slug or, for older plugin layouts, the source PLUGIN is the plugin slug. REV defaults to "master" resolved from the
repository basename. REV defaults to "master" resolved from the plugin checkout. plugin checkout. The plugin manifest.json is the source of truth for plugin
The plugin manifest.json is the source of truth for plugin id, slug, version, id, slug, version, provides, and requires metadata. By default the script expects
provides, and requires metadata. By default the script expects the plugin the plugin checkout at ../tribes-plugin-$PLUGIN and the Guix plugin file at
checkout at ../tribes-plugin-$PLUGIN and the Guix plugin file at tribes/plugins/$PLUGIN.scm relative to the guix-tribes checkout.
tribes/plugins/$PLUGIN.scm relative to the guix-tribes checkout. If those do not
exist and PLUGIN starts with tribe-one-, it also tries the unprefixed source
basename. Use --plugin-source-name when the source repository and Guix file
basename differ from the canonical slug.
Options: Options:
--plugin-source-name NAME
Source repository, Guix file, package, and Scheme symbol basename
--plugin-repo PATH Local plugin git checkout --plugin-repo PATH Local plugin git checkout
--plugin-file PATH Guix plugin definition file to update --plugin-file PATH Guix plugin definition file to update
--tribes-repo PATH Local Tribes git checkout used for the host plugin API --tribes-repo PATH Local Tribes git checkout used for the host plugin API
@@ -139,7 +133,6 @@ my %opts;
GetOptionsFromArray( GetOptionsFromArray(
\@argv, \@argv,
'plugin-source-name=s' => \$opts{plugin_source_name},
'plugin-repo=s' => \$opts{plugin_repo}, 'plugin-repo=s' => \$opts{plugin_repo},
'plugin-file=s' => \$opts{plugin_file}, 'plugin-file=s' => \$opts{plugin_file},
'tribes-repo=s' => \$opts{tribes_repo}, 'tribes-repo=s' => \$opts{tribes_repo},
@@ -175,37 +168,16 @@ my $default_tribes_repo = abs_path(File::Spec->catdir($default_guix_repo, '..',
my $guix_repo = $opts{guix_repo} ? abs_path($opts{guix_repo}) : $default_guix_repo; my $guix_repo = $opts{guix_repo} ? abs_path($opts{guix_repo}) : $default_guix_repo;
my $tribes_repo = $opts{tribes_repo} ? abs_path($opts{tribes_repo}) : $default_tribes_repo; my $tribes_repo = $opts{tribes_repo} ? abs_path($opts{tribes_repo}) : $default_tribes_repo;
sub default_plugin_source_name {
my ($plugin, $guix_repo) = @_;
my @candidates = ($plugin);
if ($plugin =~ /^tribe-one-(.+)$/) {
push @candidates, $1;
}
for my $candidate (@candidates) {
my $repo = File::Spec->catdir($guix_repo, '..', "tribes-plugin-$candidate");
my $file = File::Spec->catfile($guix_repo, 'tribes', 'plugins', "$candidate.scm");
return $candidate if -d File::Spec->catdir($repo, '.git') && -f $file;
}
return $plugin;
}
my $plugin_source_name = $opts{plugin_source_name} // default_plugin_source_name($plugin, $guix_repo);
$plugin_source_name =~ /^[A-Za-z0-9._+-]+$/ or fail("Invalid plugin source name: $plugin_source_name");
my $plugin_repo = my $plugin_repo =
$opts{plugin_repo} $opts{plugin_repo}
? abs_path($opts{plugin_repo}) ? abs_path($opts{plugin_repo})
: abs_path(File::Spec->catdir($guix_repo, '..', "tribes-plugin-$plugin_source_name")); : abs_path(File::Spec->catdir($guix_repo, '..', "tribes-plugin-$plugin"));
my $plugin_file = my $plugin_file =
$opts{plugin_file} $opts{plugin_file}
? abs_path($opts{plugin_file}) ? abs_path($opts{plugin_file})
: File::Spec->catfile($guix_repo, 'tribes', 'plugins', "$plugin_source_name.scm"); : File::Spec->catfile($guix_repo, 'tribes', 'plugins', "$plugin.scm");
my $source_file = File::Spec->catfile($guix_repo, 'tribes', 'packages', 'source.scm'); my $source_file = File::Spec->catfile($guix_repo, 'tribes', 'packages', 'source.scm');
my $plugin_package_name = "tribes-plugin-$plugin_source_name"; my $plugin_package_name = "tribes-plugin-$plugin";
-d File::Spec->catdir($plugin_repo, '.git') or fail("Plugin repo not found: $plugin_repo"); -d File::Spec->catdir($plugin_repo, '.git') or fail("Plugin repo not found: $plugin_repo");
-d File::Spec->catdir($tribes_repo, '.git') or fail("Tribes repo not found: $tribes_repo"); -d File::Spec->catdir($tribes_repo, '.git') or fail("Tribes repo not found: $tribes_repo");
@@ -281,14 +253,7 @@ my $version = $manifest->{version};
my $provides_joined = join("\037", @{ $manifest->{provides} }); my $provides_joined = join("\037", @{ $manifest->{provides} });
my $requires_joined = join("\037", @{ $manifest->{requires} }); my $requires_joined = join("\037", @{ $manifest->{requires} });
if ($plugin_slug ne $plugin) { $plugin_slug eq $plugin or fail("Plugin manifest slug mismatch: expected $plugin, got $plugin_slug");
if (!defined($opts{plugin_source_name}) && $plugin eq $plugin_source_name) {
print STDERR "Plugin argument '$plugin' matched source name; using manifest slug '$plugin_slug'.\n";
$plugin = $plugin_slug;
} else {
fail("Plugin manifest slug mismatch: expected $plugin, got $plugin_slug");
}
}
my ($plugin_source_for_scheme, $tribes_source_for_scheme, $guix_load_path); my ($plugin_source_for_scheme, $tribes_source_for_scheme, $guix_load_path);
my $source_hash; my $source_hash;
@@ -383,7 +348,7 @@ my $dummy_hash = '0' x 52;
my $text = read_file($plugin_file); my $text = read_file($plugin_file);
my @candidates; my @candidates;
for my $candidate ($plugin_source_name, ($plugin_source_name =~ tr/_/-/r)) { for my $candidate ($plugin, ($plugin =~ tr/_/-/r)) {
push @candidates, $candidate unless grep { $_ eq $candidate } @candidates; push @candidates, $candidate unless grep { $_ eq $candidate } @candidates;
} }
@@ -537,7 +502,6 @@ write_file($plugin_file, $text);
print "Updated $plugin_file\n"; print "Updated $plugin_file\n";
print "plugin: $plugin\n"; print "plugin: $plugin\n";
print "plugin source name: $plugin_source_name\n" if $plugin_source_name ne $plugin;
print "plugin id: $plugin_id\n"; print "plugin id: $plugin_id\n";
print "commit: $commit\n"; print "commit: $commit\n";
print "host tribes commit: $host_commit\n"; print "host tribes commit: $host_commit\n";
+7 -12
View File
@@ -2,10 +2,10 @@
set -eu set -eu
# External plugin pins to refresh. Each entry is canonical-slug:source-name. # External plugin pins to refresh. Each name maps to ../tribes-plugin-$name
# The source name maps to ../tribes-plugin-$source_name and # and tribes/plugins/$name.scm unless update-plugin-pin is called with
# tribes/plugins/$source_name.scm. # different defaults in the future.
plugins="tribe-one-sender:sender tribe-one-aether:aether tribe-one-supertest:supertest tribe-one-kobold:kobold tribe-one-trust:trust" plugins="sender aether supertest kobold trust"
usage() { usage() {
cat <<'EOF' cat <<'EOF'
@@ -86,15 +86,11 @@ fi
--tribes-repo "$tribes_repo" \ --tribes-repo "$tribes_repo" \
$build_host_args $build_host_args
for plugin_entry in $plugins; do for plugin in $plugins; do
plugin=${plugin_entry%%:*}
plugin_source_name=${plugin_entry#*:}
# shellcheck disable=SC2086 # shellcheck disable=SC2086
"$update_plugin_pin" \ "$update_plugin_pin" \
--guix-repo "$guix_repo" \ --guix-repo "$guix_repo" \
--tribes-repo "$tribes_repo" \ --tribes-repo "$tribes_repo" \
--plugin-source-name "$plugin_source_name" \
$build_host_args \ $build_host_args \
"$plugin" "$plugin"
done done
@@ -103,9 +99,8 @@ if [ "$commit_after" = true ]; then
git -C "$guix_repo" add -- \ git -C "$guix_repo" add -- \
tribes/packages/source.scm tribes/packages/source.scm
for plugin_entry in $plugins; do for plugin in $plugins; do
plugin_source_name=${plugin_entry#*:} git -C "$guix_repo" add -- "tribes/plugins/$plugin.scm"
git -C "$guix_repo" add -- "tribes/plugins/$plugin_source_name.scm"
done done
if git -C "$guix_repo" diff --cached --quiet; then if git -C "$guix_repo" diff --cached --quiet; then
+11
View File
@@ -0,0 +1,11 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEafMY7xYJKwYBBAHaRw8BAQdAX7Cs0UPcvEpHOwmTDkjNBfeH6/FH6sqKZbRi
sd3oBCy0U1RyaWJlcyBTdXBlcnRlc3QgRGV2IChBSSBsb2NhbCBkZXZlbG9wbWVu
dCBrZXkpIDx0cmliZXMtc3VwZXJ0ZXN0LWRldkB0ZXJhbGluay5uZXQ+iJYEExYK
AD4WIQTym6baluXsKf3e2ZSPT3WzsZ1HhAUCafMY7wIbAwUJAeEzgAULCQgHAgYV
CgkICwIEFgIDAQIeAQIXgAAKCRCPT3WzsZ1HhMp8AP4gGrPkBoGLKMyubISESFpH
fnqYUGDGucIoLRvtbl+ULQD/SlC9u/Ek9WSYvsskd0jD09lc2TxBnubl8yRi3bTM
sA8=
=JA7U
-----END PGP PUBLIC KEY BLOCK-----
+1 -1
View File
@@ -58,7 +58,7 @@
(operating-system-host-name kobold-edge-operating-system)) (operating-system-host-name kobold-edge-operating-system))
(test-equal "kobold target includes trust provider" (test-equal "kobold target includes trust provider"
'("tribe-one-trust" "tribe-one-kobold") '("trust" "kobold")
(target-plugin-names kobold-edge-operating-system)) (target-plugin-names kobold-edge-operating-system))
(test-equal "sender target has expected host name" (test-equal "sender target has expected host name"
+18 -21
View File
@@ -1,6 +1,5 @@
(define-module (tests tribes-deploy-executor) (define-module (tests tribes-deploy-executor)
#:use-module (srfi srfi-64) #:use-module (srfi srfi-64)
#:use-module (tests support)
#:use-module (tribes deploy executor) #:use-module (tribes deploy executor)
#:use-module (tribes deploy plan) #:use-module (tribes deploy plan)
#:use-module (tribes packages plugins) #:use-module (tribes packages plugins)
@@ -26,7 +25,7 @@
(define valid-target (define valid-target
`(("trusted_signers" . (,valid-signer)) `(("trusted_signers" . (,valid-signer))
("channels" . (,valid-channel)) ("channels" . (,valid-channel))
("plugins" . ((("plugin_name" . "tribe-one-aether") ("plugins" . ((("plugin_name" . "aether")
("channel_id" . "guix-tribes") ("channel_id" . "guix-tribes")
("enabled" . #t)))))) ("enabled" . #t))))))
@@ -44,16 +43,16 @@
("action" . "apply")))) ("action" . "apply"))))
(test-equal "deployment request plugins preserve names" (test-equal "deployment request plugins preserve names"
'("tribe-one-aether") '("aether")
(deployment-request-plugins (deployment-request-plugins
'(("schemaVersion" . "1") '(("schemaVersion" . "1")
("action" . "apply") ("action" . "apply")
("plugins" . ("tribe-one-aether"))))) ("plugins" . ("aether")))))
(test-equal "host config plugins are updated in tribes block" (test-equal "host config plugins are updated in tribes block"
'(("schemaVersion" . "1") '(("schemaVersion" . "1")
("tribes" . (("host" . "example.com") ("tribes" . (("host" . "example.com")
("plugins" . ("tribe-one-aether")) ("plugins" . ("aether"))
("disabledPlugins" . ()))) ("disabledPlugins" . ())))
("edge" . (("certificateName" . "tribes")))) ("edge" . (("certificateName" . "tribes"))))
(host-config-with-plugins (host-config-with-plugins
@@ -61,12 +60,12 @@
("tribes" . (("host" . "example.com") ("tribes" . (("host" . "example.com")
("plugins" . ()))) ("plugins" . ())))
("edge" . (("certificateName" . "tribes")))) ("edge" . (("certificateName" . "tribes"))))
'("tribe-one-aether"))) '("aether")))
(test-equal "system target plugin names include installed plugins" (test-equal "system target plugin names include installed plugins"
'("disabled" "tribe-one-aether") '("aether" "disabled")
(system-target-plugin-names (system-target-plugin-names
'(("plugins" . ((("plugin_name" . "tribe-one-aether") '(("plugins" . ((("plugin_name" . "aether")
("enabled" . #t)) ("enabled" . #t))
(("plugin_name" . "disabled") (("plugin_name" . "disabled")
("enabled" . #f))))))) ("enabled" . #f)))))))
@@ -74,7 +73,7 @@
(test-equal "system target disabled plugin names include disabled plugins" (test-equal "system target disabled plugin names include disabled plugins"
'("disabled") '("disabled")
(system-target-disabled-plugin-names (system-target-disabled-plugin-names
'(("plugins" . ((("plugin_name" . "tribe-one-aether") '(("plugins" . ((("plugin_name" . "aether")
("enabled" . #t)) ("enabled" . #t))
(("plugin_name" . "disabled") (("plugin_name" . "disabled")
("enabled" . #f))))))) ("enabled" . #f)))))))
@@ -102,7 +101,7 @@
guix-tribes-runtime-missing-capabilities) guix-tribes-runtime-missing-capabilities)
(test-equal "resolve-target emits channel-aware plugin package refs" (test-equal "resolve-target emits channel-aware plugin package refs"
'("tribe-one-aether") '("aether")
(let* ((plan (resolve-target valid-target)) (let* ((plan (resolve-target valid-target))
(hash-value (json-ref plan "plan_hash")) (hash-value (json-ref plan "plan_hash"))
(resolved-plugins (resolved-plugins
@@ -120,7 +119,7 @@
(plan-plugins plan))) (plan-plugins plan)))
(test-equal "resolve-target accepts spaced introduction fingerprints" (test-equal "resolve-target accepts spaced introduction fingerprints"
'("tribe-one-sender") '("sender")
(let* ((spaced-channel (let* ((spaced-channel
`(("id" . "guix-tribes") `(("id" . "guix-tribes")
("channel_id" . "guix-tribes") ("channel_id" . "guix-tribes")
@@ -135,29 +134,29 @@
(resolve-target (resolve-target
`(("trusted_signers" . (,valid-signer)) `(("trusted_signers" . (,valid-signer))
("channels" . (,spaced-channel)) ("channels" . (,spaced-channel))
("plugins" . ((("plugin_name" . "tribe-one-sender") ("plugins" . ((("plugin_name" . "sender")
("channel_id" . "guix-tribes") ("channel_id" . "guix-tribes")
("enabled" . #t)))))))) ("enabled" . #t))))))))
(plan-plugins plan))) (plan-plugins plan)))
(test-equal "resolve-target satisfies org.tribe-one.caps.ui@1 from built-in Tribes UI" (test-equal "resolve-target satisfies org.tribe-one.caps.ui@1 from built-in Tribes UI"
'("tribe-one-sender") '("sender")
(let ((plan (let ((plan
(resolve-target (resolve-target
`(("trusted_signers" . (,valid-signer)) `(("trusted_signers" . (,valid-signer))
("channels" . (,valid-channel)) ("channels" . (,valid-channel))
("plugins" . ((("plugin_name" . "tribe-one-sender") ("plugins" . ((("plugin_name" . "sender")
("channel_id" . "guix-tribes") ("channel_id" . "guix-tribes")
("enabled" . #t)))))))) ("enabled" . #t))))))))
(plan-plugins plan))) (plan-plugins plan)))
(test-equal "resolve-target keeps disabled plugins installed but runtime-disabled" (test-equal "resolve-target keeps disabled plugins installed but runtime-disabled"
'(("tribe-one-aether") ("tribe-one-aether")) '(("aether") ("aether"))
(let ((plan (let ((plan
(resolve-target (resolve-target
`(("trusted_signers" . (,valid-signer)) `(("trusted_signers" . (,valid-signer))
("channels" . (,valid-channel)) ("channels" . (,valid-channel))
("plugins" . ((("plugin_name" . "tribe-one-aether") ("plugins" . ((("plugin_name" . "aether")
("channel_id" . "guix-tribes") ("channel_id" . "guix-tribes")
("enabled" . #f)))))))) ("enabled" . #f))))))))
(list (plan-plugins plan) (plan-disabled-plugins plan)))) (list (plan-plugins plan) (plan-disabled-plugins plan))))
@@ -168,8 +167,8 @@
(resolve-target (resolve-target
`(("trusted_signers" . (,valid-signer)) `(("trusted_signers" . (,valid-signer))
("channels" . (,valid-channel)) ("channels" . (,valid-channel))
("plugins" . ((("plugin_name" . "tribe-one-aether") ("enabled" . #t)) ("plugins" . ((("plugin_name" . "aether") ("enabled" . #t))
(("plugin_name" . "tribe-one-aether") ("enabled" . #t)))))))) (("plugin_name" . "aether") ("enabled" . #t))))))))
(test-equal "resolve-target rejects unknown plugins" (test-equal "resolve-target rejects unknown plugins"
"manifest_invalid" "manifest_invalid"
@@ -194,10 +193,8 @@
("allowed_signer_ids" . ("signer-1")) ("allowed_signer_ids" . ("signer-1"))
("introduction" . (("commit" . "intro123") ("introduction" . (("commit" . "intro123")
("fingerprint" . "0123456789ABCDEF0123456789ABCDEF01234567")))))) ("fingerprint" . "0123456789ABCDEF0123456789ABCDEF01234567"))))))
("plugins" . ((("plugin_name" . "tribe-one-aether") ("plugins" . ((("plugin_name" . "aether")
("channel_id" . "guix-tribes") ("channel_id" . "guix-tribes")
("enabled" . #t)))))))) ("enabled" . #t))))))))
(test-end "tribes-deploy-executor")) (test-end "tribes-deploy-executor"))
(run-tests-when-script "tests/tribes-deploy-executor.scm" run-tests)
+7 -7
View File
@@ -19,16 +19,16 @@
(define plan-a (define plan-a
'(("plan_hash" . "plan-a") '(("plan_hash" . "plan-a")
("resolved_plugins" . ((("name" . "tribe-one-aether")))))) ("resolved_plugins" . ((("name" . "aether"))))))
(define plan-b (define plan-b
'(("plan_hash" . "plan-b") '(("plan_hash" . "plan-b")
("resolved_plugins" . ((("name" . "tribe-one-aether")))))) ("resolved_plugins" . ((("name" . "aether"))))))
(define plan-without-channel-delta (define plan-without-channel-delta
'(("plan_hash" . "plan-without-channel-delta") '(("plan_hash" . "plan-without-channel-delta")
("resolved_channels" . #()) ("resolved_channels" . #())
("resolved_plugins" . ((("name" . "tribe-one-supertest")))))) ("resolved_plugins" . ((("name" . "supertest"))))))
(define plan-with-channel-pin (define plan-with-channel-pin
'(("plan_hash" . "plan-with-channel-pin") '(("plan_hash" . "plan-with-channel-pin")
@@ -38,7 +38,7 @@
("branch" . "master") ("branch" . "master")
("commit" . "abc123") ("commit" . "abc123")
("position" . 10)))) ("position" . 10))))
("resolved_plugins" . ((("name" . "tribe-one-supertest")))))) ("resolved_plugins" . ((("name" . "supertest"))))))
(define plan-with-branch-channel (define plan-with-branch-channel
'(("plan_hash" . "plan-with-branch-channel") '(("plan_hash" . "plan-with-branch-channel")
("resolved_channels" . #((("channel_id" . "guix-tribes") ("resolved_channels" . #((("channel_id" . "guix-tribes")
@@ -47,7 +47,7 @@
("branch" . "master") ("branch" . "master")
("commit" . #f) ("commit" . #f)
("position" . 10)))) ("position" . 10))))
("resolved_plugins" . ((("name" . "tribe-one-supertest")))))) ("resolved_plugins" . ((("name" . "supertest"))))))
(define (delete-if-present path) (define (delete-if-present path)
(when (false-if-exception (lstat path)) (when (false-if-exception (lstat path))
@@ -516,8 +516,8 @@
(call-with-values (call-with-values
(lambda () (lambda ()
(resolve-deployment (resolve-deployment
'(("plugins" . ((("plugin_name" . "tribe-one-aether") ("enabled" . #t)) '(("plugins" . ((("plugin_name" . "aether") ("enabled" . #t))
(("plugin_name" . "tribe-one-aether") ("enabled" . #t))))))) (("plugin_name" . "aether") ("enabled" . #t)))))))
(lambda (status payload) (lambda (status payload)
(test-equal "resolve-deployment returns 409 for explicit resolver errors" (test-equal "resolve-deployment returns 409 for explicit resolver errors"
409 status) 409 status)
+17 -94
View File
@@ -1,7 +1,5 @@
(define-module (tests tribes-system-node) (define-module (tests tribes-system-node)
#:use-module (gnu packages databases)
#:use-module (gnu services) #:use-module (gnu services)
#:use-module (gnu services databases)
#:use-module (gnu services monitoring) #:use-module (gnu services monitoring)
#:use-module (gnu services shepherd) #:use-module (gnu services shepherd)
#:use-module (guix gexp) #:use-module (guix gexp)
@@ -10,7 +8,6 @@
#:use-module (srfi srfi-13) #:use-module (srfi srfi-13)
#:use-module (srfi srfi-64) #:use-module (srfi srfi-64)
#:use-module (tests support) #:use-module (tests support)
#:use-module (tribes config host)
#:use-module (tribes plugins sender) #:use-module (tribes plugins sender)
#:use-module (tribes services chrony) #:use-module (tribes services chrony)
#:use-module (tribes services haproxy) #:use-module (tribes services haproxy)
@@ -24,7 +21,6 @@
#:export (run-tests)) #:export (run-tests))
(define node-module (resolve-module '(tribes system node))) (define node-module (resolve-module '(tribes system node)))
(define lego-module (resolve-module '(tribes services lego)))
(define chrony-module (resolve-module '(tribes services chrony))) (define chrony-module (resolve-module '(tribes services chrony)))
(define haproxy-module (resolve-module '(tribes services haproxy))) (define haproxy-module (resolve-module '(tribes services haproxy)))
(define logging-module (resolve-module '(tribes services logging))) (define logging-module (resolve-module '(tribes services logging)))
@@ -33,7 +29,6 @@
(define edge-cache-vcl-text (module-ref node-module 'edge-cache-vcl-text)) (define edge-cache-vcl-text (module-ref node-module 'edge-cache-vcl-text))
(define edge-cache-vcl (module-ref node-module 'edge-cache-vcl)) (define edge-cache-vcl (module-ref node-module 'edge-cache-vcl))
(define edge-services (module-ref node-module 'edge-services)) (define edge-services (module-ref node-module 'edge-services))
(define lego-common-arguments (module-ref lego-module 'lego-common-arguments))
(define chrony-shepherd-services (define chrony-shepherd-services
(module-ref chrony-module 'chrony-shepherd-services)) (module-ref chrony-module 'chrony-shepherd-services))
(define haproxy-config-file (module-ref haproxy-module 'haproxy-config-file)) (define haproxy-config-file (module-ref haproxy-module 'haproxy-config-file))
@@ -67,9 +62,6 @@
(contains? vcl ".connect_timeout = 1s;")) (contains? vcl ".connect_timeout = 1s;"))
(test-assert "edge cache backend uses bounded first-byte timeout" (test-assert "edge cache backend uses bounded first-byte timeout"
(contains? vcl ".first_byte_timeout = 5s;")) (contains? vcl ".first_byte_timeout = 5s;"))
(test-assert "edge cache gives admin API requests longer backend timeouts"
(contains? vcl
"sub vcl_backend_fetch {\n if (bereq.url ~ \"^/api/admin/\") {\n set bereq.connect_timeout = 1s;\n set bereq.first_byte_timeout = 35s;\n set bereq.between_bytes_timeout = 35s;"))
(test-assert "edge cache retries only GET/HEAD 5xx backend responses" (test-assert "edge cache retries only GET/HEAD 5xx backend responses"
(contains? vcl (contains? vcl
"if ((bereq.method == \"GET\" || bereq.method == \"HEAD\") &&\n beresp.status >= 500 && beresp.status <= 599 &&\n bereq.retries < 5)")) "if ((bereq.method == \"GET\" || bereq.method == \"HEAD\") &&\n beresp.status >= 500 && beresp.status <= 599 &&\n bereq.retries < 5)"))
@@ -95,10 +87,6 @@
(tribes (tribes-configuration (tribes (tribes-configuration
(host "example.invalid"))))) (host "example.invalid")))))
(services (tribes-node-services config)) (services (tribes-node-services config))
(postgresql-service
(find (lambda (service)
(eq? (service-kind service) postgresql-service-type))
services))
(chrony-service (chrony-service
(find (lambda (service) (find (lambda (service)
(eq? (service-kind service) chrony-service-type)) (eq? (service-kind service) chrony-service-type))
@@ -118,9 +106,6 @@
services))) services)))
(test-assert "node profile includes nftables for sync partition tests" (test-assert "node profile includes nftables for sync partition tests"
network-tools-service) network-tools-service)
(test-eq "node uses PostgreSQL 17"
postgresql-17
(postgresql-configuration-postgresql (service-value postgresql-service)))
(test-assert "node includes Chrony service" (test-assert "node includes Chrony service"
chrony-service) chrony-service)
(test-assert "node includes Prometheus node exporter service" (test-assert "node includes Prometheus node exporter service"
@@ -264,9 +249,9 @@
(let* ((config (tribes-node-configuration (let* ((config (tribes-node-configuration
(tribes (tribes-configuration (tribes (tribes-configuration
(host "203.0.113.10"))) (host "example.invalid")))
(edge (tribes-edge-configuration (edge (tribes-edge-configuration
(certificate-subjects '("203.0.113.10")))))) (certificate-email "ops@example.invalid")))))
(services (edge-services config)) (services (edge-services config))
(vinyl-service (find (lambda (service) (vinyl-service (find (lambda (service)
(eq? (service-kind service) vinyl-service-type)) (eq? (service-kind service) vinyl-service-type))
@@ -285,6 +270,8 @@
(service-value vinyl-service))) (service-value vinyl-service)))
(vinyl-exporter-config (and vinyl-exporter-service (vinyl-exporter-config (and vinyl-exporter-service
(service-value vinyl-exporter-service))) (service-value vinyl-exporter-service)))
(lego-config (and lego-service
(service-value lego-service)))
(edge-vinyl (and vinyl-configs (edge-vinyl (and vinyl-configs
(find (lambda (config) (find (lambda (config)
(string=? (vinyl-configuration-name config) (string=? (vinyl-configuration-name config)
@@ -320,80 +307,20 @@
'((max_retries . 5)) '((max_retries . 5))
(and edge-vinyl (and edge-vinyl
(vinyl-configuration-parameters edge-vinyl))) (vinyl-configuration-parameters edge-vinyl)))
(test-equal "edge no longer starts lego for public ACME" (test-equal "lego waits for haproxy challenge routing"
#f '(haproxy)
lego-service) (and lego-config
(lego-certificate-configuration-requirement
(car (lego-configuration-certificates lego-config)))))
(test-assert "edge uses haproxy for TLS termination" (test-assert "edge uses haproxy for TLS termination"
haproxy-service)) haproxy-service))
(let* ((certificate (lego-certificate-configuration
(name "tribes")
(subjects '("203.0.113.10" "2001:db8::73be"))
(listen-http "127.0.0.1:8080")))
(args (lego-common-arguments certificate)))
(test-assert "lego HTTP challenge includes HTTP validation"
(member "--http" args))
(test-assert "lego HTTP challenge does not include DNS validation"
(not (member "--dns" args)))
(test-assert "lego HTTP challenge disables CN for IP identifiers"
(member "--disable-cn" args)))
(let* ((config (tribes-node-configuration
(tribes (tribes-configuration
(host "203.0.113.10")))
(edge (tribes-edge-configuration
(certificate-name "tribes")
(certificate-subjects
'("203.0.113.10" "2001:db8::73be"))))))
(services (edge-services config))
(lego-service (find (lambda (service)
(eq? (service-kind service) lego-service-type))
services))
(haproxy-service (find (lambda (service)
(eq? (service-kind service) haproxy-service-type))
services))
(haproxy-config (and haproxy-service
(service-value haproxy-service)))
(haproxy-text (and haproxy-config
(plain-file-content
(haproxy-config-file haproxy-config)))))
(test-equal "IP-only edge certificate does not create lego certificates"
#f
lego-service)
(test-equal "IP-only edge passes Tribes-managed cert to haproxy"
'("/var/lib/tribes/acme/edge.full.pem")
(haproxy-configuration-pem-files haproxy-config))
(test-assert "IP-only edge renders one bind with one cert"
(contains? haproxy-text
"bind 0.0.0.0:443 ssl crt /var/lib/tribes/acme/edge.full.pem alpn h2,http/1.1")))
(let* ((host-config
(json-scm->tribes-host-configuration
'(("schemaVersion" . "1")
("tribes" . (("workingDirectory" . "/var/lib/tribes")
("serviceUser" . "tribes")
("serviceGroup" . "tribes")
("host" . "203.0.113.10")
("listenAddress" . "127.0.0.1")
("listenPort" . 4000)
("scheme" . "https")
("port" . 443)
("syncHost" . "127.0.0.1")
("syncPort" . 4848)
("syncBindAddress" . "127.0.0.1")))
("edge" . (("certificateName" . "tribes")
("certificateSubjects" . ("203.0.113.10" "2001:db8::73be")))))))
(edge (tribes-host-configuration-edge host-config)))
(test-equal "host config parses IP certificate subjects"
'("203.0.113.10" "2001:db8::73be")
(tribes-edge-configuration-certificate-subjects edge)))
(let* ((config (haproxy-configuration (let* ((config (haproxy-configuration
(backend "127.0.0.1:6081") (backend "127.0.0.1:6081")
(frontends '("0.0.0.0:443" "[::]:443 v6only")) (frontends '("0.0.0.0:443" "[::]:443 v6only"))
(http-frontends '("0.0.0.0:80" "[::]:80 v6only")) (http-frontends '("0.0.0.0:80" "[::]:80 v6only"))
(acme-backend "127.0.0.1:8080") (acme-backend "127.0.0.1:8080")
(pem-files '("/var/lib/tribes/acme/edge.full.pem")))) (pem-files '("/var/lib/lego/tribes/full.pem"))))
(rendered (haproxy-config-file config)) (rendered (haproxy-config-file config))
(text (plain-file-content rendered))) (text (plain-file-content rendered)))
(test-equal "haproxy renders expected configuration file name" (test-equal "haproxy renders expected configuration file name"
@@ -405,30 +332,26 @@
(not (contains? text "limited-quic"))) (not (contains? text "limited-quic")))
(test-assert "haproxy logs to syslog-ng" (test-assert "haproxy logs to syslog-ng"
(contains? text "log /dev/log local0")) (contains? text "log /dev/log local0"))
(test-assert "haproxy preserves privileged bind capability for QUIC"
(contains? text "setcap cap_net_bind_service"))
(test-assert "haproxy binds configured certificate" (test-assert "haproxy binds configured certificate"
(contains? text (contains? text
"bind 0.0.0.0:443 ssl crt /var/lib/tribes/acme/edge.full.pem alpn h2,http/1.1")) "bind 0.0.0.0:443 ssl crt /var/lib/lego/tribes/full.pem alpn h2,http/1.1"))
(test-assert "haproxy binds QUIC over IPv4" (test-assert "haproxy binds QUIC over IPv4"
(contains? text (contains? text
"bind quic4@0.0.0.0:443 ssl crt /var/lib/tribes/acme/edge.full.pem alpn h3")) "bind quic4@0.0.0.0:443 ssl crt /var/lib/lego/tribes/full.pem alpn h3"))
(test-assert "haproxy binds QUIC over IPv6" (test-assert "haproxy binds QUIC over IPv6"
(contains? text (contains? text
"bind quic6@[::]:443 v6only ssl crt /var/lib/tribes/acme/edge.full.pem alpn h3")) "bind quic6@[::]:443 v6only ssl crt /var/lib/lego/tribes/full.pem alpn h3"))
(test-assert "haproxy advertises HTTP/3" (test-assert "haproxy advertises HTTP/3"
(contains? text "http-response set-header alt-svc 'h3=\":443\"; ma=86400'")) (contains? text "http-response set-header alt-svc 'h3=\":443\"; ma=86400'"))
(test-assert "haproxy owns public HSTS"
(contains? text "http-response set-header strict-transport-security \"max-age=31536000\""))
(test-assert "haproxy binds public HTTP" (test-assert "haproxy binds public HTTP"
(contains? text "bind 0.0.0.0:80")) (contains? text "bind 0.0.0.0:80"))
(test-assert "haproxy routes ACME challenges to Tribes" (test-assert "haproxy routes ACME challenges to lego"
(contains? text "use_backend tribes_acme if acme_challenge")) (contains? text "use_backend lego_acme if acme_challenge"))
(test-assert "haproxy redirects non-ACME HTTP traffic" (test-assert "haproxy redirects non-ACME HTTP traffic"
(contains? text (contains? text
"http-request redirect scheme https code 308 unless acme_challenge")) "http-request redirect scheme https code 308 unless acme_challenge"))
(test-assert "haproxy forwards ACME requests to Tribes" (test-assert "haproxy forwards ACME requests to lego challenge server"
(contains? text "server tribes 127.0.0.1:8080")) (contains? text "server lego 127.0.0.1:8080"))
(test-assert "haproxy forwards to vinyl cache backend" (test-assert "haproxy forwards to vinyl cache backend"
(contains? text "server vinyl 127.0.0.1:6081 check"))) (contains? text "server vinyl 127.0.0.1:6081 check")))
+18 -17
View File
@@ -3,25 +3,26 @@
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:export (cuirass-jobs)) #:export (cuirass-jobs))
;; Publishable artifacts: the debug Docker image and the Sender runtime pack.
;; Node operating-system closures and bootloader files are warmed by the
;; dedicated (tribes ci artifacts-substitutes) jobset instead.
(define (cuirass-jobs store arguments) (define (cuirass-jobs store arguments)
(let ((tribes-commit (arguments->channel-commit arguments 'tribes))) (let ((tribes-commit (arguments->channel-commit arguments 'tribes)))
(append-map (append-map
(lambda (system) (lambda (system)
(list (artifact-job store (append
"tribes-debug-docker" (list (artifact-job store
(lambda () "tribes-debug-docker"
(tribes-debug-docker-image (lambda ()
#:image-tag (tribes-debug-docker-image
(if tribes-commit #:image-tag
(string-append "tribes-guix-debug:" (if tribes-commit
tribes-commit) (string-append "tribes-guix-debug:"
"tribes-guix-debug:latest"))) tribes-commit)
system) "tribes-guix-debug:latest")))
(artifact-job store system)
"tribes-sender-runtime" (artifact-job store
tribes-sender-runtime-pack "tribes-sender-runtime"
system))) tribes-sender-runtime-pack
system))
(substitute-manifest-jobs store system)
(substitute-system-jobs store system)
(substitute-file-jobs store system)))
(arguments->systems arguments)))) (arguments->systems arguments))))
-21
View File
@@ -1,21 +0,0 @@
(define-module (tribes ci artifacts-substitutes)
#:use-module (tribes ci artifacts)
#:use-module (srfi srfi-1)
#:export (cuirass-jobs))
;; Warm the substitute mirror with the closures of the real Tribes node
;; operating-systems and their bootloader files, so deployed nodes pull every
;; required store path from guix.tribe-one.org during `guix system
;; init'/reconfigure without depending on upstream availability. This is the
;; authoritative substitute set: it is computed from the very operating-systems
;; nodes materialize, so it cannot drift the way the hand-curated
;; manifests/substitutes/*.scm package lists did, and it transitively covers
;; everything the node closure contains -- including the operator toolkit now
;; carried in the node system profile and the upstream dependencies pulled in
;; while building the closure.
(define (cuirass-jobs store arguments)
(append-map
(lambda (system)
(append (substitute-system-jobs store system)
(substitute-file-jobs store system)))
(arguments->systems arguments)))
+26 -53
View File
@@ -9,7 +9,6 @@
#:use-module (gnu packages nss) #:use-module (gnu packages nss)
#:use-module (gnu system) #:use-module (gnu system)
#:use-module (guix build-system gnu) #:use-module (guix build-system gnu)
#:use-module (guix channels)
#:use-module (guix derivations) #:use-module (guix derivations)
#:use-module (guix gexp) #:use-module (guix gexp)
#:use-module (guix monads) #:use-module (guix monads)
@@ -18,6 +17,9 @@
#:use-module (guix scripts pack) #:use-module (guix scripts pack)
#:use-module (guix store) #:use-module (guix store)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (manifests substitutes base)
#:use-module (manifests substitutes installer)
#:use-module (manifests substitutes tribes-node)
#:use-module (nbde system build-host-kexec-installer) #:use-module (nbde system build-host-kexec-installer)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (tribes ci substitutes) #:use-module (tribes ci substitutes)
@@ -31,7 +33,7 @@
artifact-job artifact-job
arguments->systems arguments->systems
arguments->channel-commit arguments->channel-commit
substitute-channel-profile-jobs substitute-manifest-jobs
substitute-system-jobs substitute-system-jobs
substitute-file-jobs)) substitute-file-jobs))
@@ -171,8 +173,7 @@
(file-exists? path)) (file-exists? path))
(copy-recursively path (copy-recursively path
(string-append squashfs-root "/" (string-append squashfs-root "/"
(basename path)) (basename path)))))
#:keep-mtime? #t)))
(delete-duplicates (delete-duplicates
(append (list system boot-path) (append (list system boot-path)
(read-lines "system-graph")))) (read-lines "system-graph"))))
@@ -248,55 +249,10 @@
(repository (repository
(repository-field 'commit repository)))) (repository-field 'commit repository))))
(define (arguments->channels arguments) (define %substitute-manifest-targets
(filter-map sexp->channel (or (assoc-ref arguments 'channels) '()))) `((base . ,base-manifest)
(installer . ,installer-manifest)
(define (canonical-time-machine-channel channel) (tribes-node . ,tribes-node-manifest)))
;; Cuirass passes channel sexps whose URLs point at its pre-fetched
;; /gnu/store checkouts and whose introductions were dropped when Cuirass
;; created channel instances from those checkouts. That is correct for
;; evaluating custom jobs inside Cuirass, but it does not match the profile
;; computed by `guix time-machine -C channels.scm` on Legion installers,
;; where the channel URLs and introductions come from the public channel
;; file. Reconstruct those canonical fields while preserving the evaluated
;; commits.
(let* ((channel-name* (channel-name channel))
(canonical-url (match channel-name*
('guix "https://git.teralink.net/tribes/guix-fork.git")
('tribes "https://git.teralink.net/tribes/guix-tribes.git")
(_ (channel-url channel))))
(canonical-introduction
(or (channel-introduction channel)
(match channel-name*
('guix
(make-channel-introduction
"093f27dde01cdbda68f2ec4b81e5a34ae180aab9"
(openpgp-fingerprint
"6688 9153 C51C 4613 A493 A525 2F0D FD14 EF99 DAC3")))
('tribes
(make-channel-introduction
"607c69a5c1662acca07ad72c3e18646c73500856"
(openpgp-fingerprint
"6688 9153 C51C 4613 A493 A525 2F0D FD14 EF99 DAC3")))
(_ #f)))))
((@@ (guix channels) make-channel)
channel-name*
canonical-url
(channel-branch channel)
(channel-commit channel)
canonical-introduction
#f)))
(define (substitute-channel-profile-jobs store arguments system)
(let ((channels (map canonical-time-machine-channel
(arguments->channels arguments))))
(if (null? channels)
'()
(list (artifact-job store
"substitute-channel-profile"
(lambda ()
(latest-channel-derivation channels))
system)))))
(define %substitute-file-targets (define %substitute-file-targets
`((bios-bootloader-configuration . ,bios-bootloader-configuration) `((bios-bootloader-configuration . ,bios-bootloader-configuration)
@@ -304,6 +260,12 @@
(efi-bootloader-configuration . ,efi-bootloader-configuration) (efi-bootloader-configuration . ,efi-bootloader-configuration)
(efi-bootloader-configuration-installer . ,efi-bootloader-configuration-installer))) (efi-bootloader-configuration-installer . ,efi-bootloader-configuration-installer)))
(define (manifest-profile manifest)
(profile
(content manifest)
(hooks %default-profile-hooks)
(locales? #t)))
(define (artifact-job store name proc system) (define (artifact-job store name proc system)
(let ((drv (parameterize ((%current-system system) (let ((drv (parameterize ((%current-system system)
(%graft? #f)) (%graft? #f))
@@ -317,6 +279,17 @@
#:max-silent-time 3600 #:max-silent-time 3600
#:timeout 72000))) #:timeout 72000)))
(define (substitute-manifest-jobs store system)
(map (match-lambda
((name . manifest)
(artifact-job store
(string-append "substitute-manifest-"
(symbol->string name))
(lambda ()
(lower-object (manifest-profile manifest)))
system)))
%substitute-manifest-targets))
(define (substitute-system-jobs store system) (define (substitute-system-jobs store system)
(map (match-lambda (map (match-lambda
((name . os) ((name . os)
-12
View File
@@ -1,12 +0,0 @@
(define-module (tribes ci channel)
#:use-module (srfi srfi-1)
#:use-module (tribes ci artifacts)
#:export (cuirass-jobs))
;; Cheap canary spec: emit only the channel-instance derivation, so a
;; "tribes modules compile and the checkout is reachable" signal is
;; independent of any package or system build.
(define (cuirass-jobs store arguments)
(append-map (lambda (system)
(substitute-channel-profile-jobs store arguments system))
(arguments->systems arguments)))
-1
View File
@@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestLegionSharedBuilder legion@example.invalid
+9 -33
View File
@@ -15,13 +15,11 @@
#:use-module (nbde system initrd) #:use-module (nbde system initrd)
#:use-module (nbde system mapped-devices) #:use-module (nbde system mapped-devices)
#:use-module (tribes config host) #:use-module (tribes config host)
#:use-module (tribes config system-facts)
#:use-module (tribes packages plugins) #:use-module (tribes packages plugins)
#:use-module (tribes packages source) #:use-module (tribes packages source)
#:use-module (tribes plugins registry) #:use-module (tribes plugins registry)
#:use-module (tribes services tribes) #:use-module (tribes services tribes)
#:use-module (tribes system installer) #:use-module (tribes system installer)
#:use-module (tribes system materialize)
#:use-module (tribes system node) #:use-module (tribes system node)
#:export (phase1-operating-system #:export (phase1-operating-system
base-edge-operating-system base-edge-operating-system
@@ -142,8 +140,9 @@
(tribes (ci-tribes-configuration plugins)) (tribes (ci-tribes-configuration plugins))
(edge (edge
(tribes-edge-configuration (tribes-edge-configuration
(certificate-name "203-0-113-10") (certificate-name "node1-example-invalid")
(certificate-subjects '("203.0.113.10")) (certificate-subjects '("node1.example.invalid"))
(certificate-email "ops@example.invalid")
(certificate-profile "shortlived") (certificate-profile "shortlived")
(renew-days 4) (renew-days 4)
(http-port 80) (http-port 80)
@@ -154,25 +153,6 @@
(cache-port 6081) (cache-port 6081)
(cache-storage '("malloc,256M")))))) (cache-storage '("malloc,256M"))))))
(define (ci-authorized-keys-file-name)
(or (search-path %load-path "tribes/ci/fixtures/root-authorized_keys")
(error "failed to locate CI authorized_keys fixture")))
(define %ci-system-facts
(tribes-system-facts
(host-name "tribes-ci-base-edge")
(interface "eth0")
(boot-mode "bios")
(bootloader-targets (list "/dev/sda"))
(boot-partition-uuid "11111111-2222-3333-4444-555555555555")
(boot-partition-file-system-type "ext4")
(root-luks-uuid "66666666-7777-8888-9999-aaaaaaaaaaaa")
(root-mapper-name "cryptroot")
(root-file-system-type "ext4")
(authorized-keys-file (ci-authorized-keys-file-name))
(local-boot-key-file "/boot/nbde/local-boot.key")
(tang-port 7654)
(initrd-network-timeout-seconds 20)
(enable-bbr? #t)))
(define* (ci-operating-system name plugins (define* (ci-operating-system name plugins
#:key #:key
(bootloader (bootloader
@@ -190,10 +170,6 @@
#:interface "eth0" #:interface "eth0"
#:authorized-keys-file %ci-authorized-keys-file #:authorized-keys-file %ci-authorized-keys-file
#:extra-services %ci-nbde-services)) #:extra-services %ci-nbde-services))
(define (ci-materialized-operating-system plugins)
(tribes-host-configuration+system-facts->operating-system
(ci-host-configuration plugins)
%ci-system-facts))
(define* (bootloader-ci-operating-system name bootloader file-systems) (define* (bootloader-ci-operating-system name bootloader file-systems)
(operating-system (operating-system
@@ -252,24 +228,24 @@
(ci-operating-system "tribes-ci-phase1" '())) (ci-operating-system "tribes-ci-phase1" '()))
(define base-edge-operating-system (define base-edge-operating-system
(ci-materialized-operating-system '())) (ci-operating-system "tribes-ci-base-edge" '()))
(define aether-edge-operating-system (define aether-edge-operating-system
(ci-operating-system "tribes-ci-aether-edge" (ci-operating-system "tribes-ci-aether-edge"
(list (plugin-by-name "tribe-one-aether")))) (list (plugin-by-name "aether"))))
(define kobold-edge-operating-system (define kobold-edge-operating-system
(ci-operating-system "tribes-ci-kobold-edge" (ci-operating-system "tribes-ci-kobold-edge"
(list (plugin-by-name "tribe-one-trust") (list (plugin-by-name "trust")
(plugin-by-name "tribe-one-kobold")))) (plugin-by-name "kobold"))))
(define sender-edge-operating-system (define sender-edge-operating-system
(ci-operating-system "tribes-ci-sender-edge" (ci-operating-system "tribes-ci-sender-edge"
(list (plugin-by-name "tribe-one-sender")))) (list (plugin-by-name "sender"))))
(define supertest-edge-operating-system (define supertest-edge-operating-system
(ci-operating-system "tribes-ci-supertest-edge" (ci-operating-system "tribes-ci-supertest-edge"
(list (plugin-by-name "tribe-one-supertest")))) (list (plugin-by-name "supertest"))))
(define %substitute-operating-system-targets (define %substitute-operating-system-targets
`((phase1 . ,phase1-operating-system) `((phase1 . ,phase1-operating-system)
+2
View File
@@ -173,6 +173,8 @@
(certificate-subjects (certificate-subjects
(optional-string-list edge-json "certificateSubjects" (optional-string-list edge-json "certificateSubjects"
(tribes-edge-configuration-certificate-subjects edge-defaults))) (tribes-edge-configuration-certificate-subjects edge-defaults)))
(certificate-email
(required-string edge-json "certificateEmail"))
(certificate-profile (certificate-profile
(optional-string edge-json "certificateProfile" (optional-string edge-json "certificateProfile"
(tribes-edge-configuration-certificate-profile edge-defaults))) (tribes-edge-configuration-certificate-profile edge-defaults)))
+1 -62
View File
@@ -1,7 +1,6 @@
(define-module (tribes deploy handlers) (define-module (tribes deploy handlers)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (ice-9 regex) #:use-module (ice-9 regex)
#:use-module (ice-9 textual-ports)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (tribes deploy channel-updates) #:use-module (tribes deploy channel-updates)
#:use-module (tribes deploy config) #:use-module (tribes deploy config)
@@ -19,14 +18,12 @@
handle-commit handle-commit
handle-rollback handle-rollback
handle-abort handle-abort
handle-install-edge-certificate
error-payload error-payload
validate-channel-updates-input validate-channel-updates-input
validate-resolve-input validate-resolve-input
validate-prepare-input validate-prepare-input
validate-commit-input validate-commit-input
validate-rollback-input validate-rollback-input))
validate-install-edge-certificate-input))
;; --------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------
;; Validation — applied before dispatching to operations.scm. ;; Validation — applied before dispatching to operations.scm.
@@ -96,18 +93,6 @@
"rollback payload is missing store_path") "rollback payload is missing store_path")
(else #f))) (else #f)))
(define (validate-install-edge-certificate-input payload)
(cond
((not (json-object-with-string-keys? payload))
"certificate install payload must be a JSON object")
((not (string? (or (json-ref payload "fullchain_path")
(json-ref payload "fullchainPath"))))
"certificate install payload is missing fullchain_path")
((not (string? (or (json-ref payload "private_key_path")
(json-ref payload "privateKeyPath"))))
"certificate install payload is missing private_key_path")
(else #f)))
(define (error-payload code reason . details) (define (error-payload code reason . details)
`(("schemaVersion" . "2") `(("schemaVersion" . "2")
("ok" . #f) ("ok" . #f)
@@ -174,51 +159,5 @@
(json-ref payload "target_plan")))) (json-ref payload "target_plan"))))
(submit-rollback! state worker helper store-path plan)))))) (submit-rollback! state worker helper store-path plan))))))
(define (safe-acme-path? path)
(and (string? path)
(string-prefix? "/var/lib/tribes/acme/" path)
(not (string-contains path "/../"))
(not (string-suffix? "/.." path))))
(define (install-edge-certificate! fullchain-path private-key-path)
(let* ((target-dir "/var/lib/tribes/acme")
(target-pem (string-append target-dir "/edge.full.pem"))
(tmp-pem (string-append target-pem ".tmp")))
(unless (file-exists? target-dir)
(mkdir target-dir))
(chmod target-dir #o700)
(call-with-output-file tmp-pem
(lambda (port)
(display (call-with-input-file fullchain-path get-string-all) port)
(newline port)
(display (call-with-input-file private-key-path get-string-all) port)))
(chmod tmp-pem #o600)
(rename-file tmp-pem target-pem)
(zero? (system* "/run/current-system/profile/bin/herd" "reload" "haproxy"))))
(define (handle-install-edge-certificate payload)
(let ((err (validate-install-edge-certificate-input payload)))
(cond
(err (values 400 (error-payload "invalid_request" err)))
(else
(let ((fullchain-path (or (json-ref payload "fullchain_path")
(json-ref payload "fullchainPath")))
(private-key-path (or (json-ref payload "private_key_path")
(json-ref payload "privateKeyPath"))))
(cond
((not (and (safe-acme-path? fullchain-path)
(safe-acme-path? private-key-path)))
(values 400 (error-payload "invalid_request"
"certificate paths must be under /var/lib/tribes/acme")))
((not (and (file-exists? fullchain-path)
(file-exists? private-key-path)))
(values 400 (error-payload "invalid_request"
"certificate source files do not exist")))
((install-edge-certificate! fullchain-path private-key-path)
(values 200 '(("ok" . #t))))
(else
(values 500 (error-payload "install_failed"
"failed to reload haproxy after certificate install")))))))))
(define (handle-abort state worker) (define (handle-abort state worker)
(values 200 (abort-prepare! state worker))) (values 200 (abort-prepare! state worker)))
+1 -8
View File
@@ -120,14 +120,7 @@
((POST . "/v1/deployment/abort") ((POST . "/v1/deployment/abort")
. ,(lambda (_request _body) . ,(lambda (_request _body)
(call-with-values (lambda () (handle-abort state worker)) (call-with-values (lambda () (handle-abort state worker))
json-response))) json-response)))))
((POST . "/v1/certificates/edge/install")
. ,(lambda (request body)
(with-json-body cfg request body
(lambda (payload)
(call-with-values
(lambda () (handle-install-edge-certificate payload))
json-response)))))))
(define (route-lookup table method path) (define (route-lookup table method path)
(find (lambda (entry) (find (lambda (entry)
+3 -4
View File
@@ -33,10 +33,9 @@
"CONFIG_X86_USER_SHADOW_STACK=y")) "CONFIG_X86_USER_SHADOW_STACK=y"))
(define %tribes-linux-disabled-options (define %tribes-linux-disabled-options
'(;; Keep DRM/KMS enabled so the installer has a local console on generic '(;; Headless/text-console targets: keep VGA/framebuffer consoles, but drop
;; virtual and real hardware. This costs roughly 15 MiB in the kexec image ;; DRM/KMS GPU drivers and display acceleration stacks.
;; compared to disabling DRM wholesale, but preserves Proxmox/QEMU VGA and "DRM"
;; common real-hardware GPU/BMC consoles.
;; No audio output/input stack on Tribes server deployments. ;; No audio output/input stack on Tribes server deployments.
"SOUND" "SOUND"
+18 -17
View File
@@ -8,11 +8,12 @@
#:use-module (gnu packages bash) #:use-module (gnu packages bash)
#:use-module (gnu packages base) #:use-module (gnu packages base)
#:use-module (gnu packages compression) #:use-module (gnu packages compression)
#:use-module (gnu packages elixir)
#:use-module (gnu packages erlang)
#:use-module (gnu packages node) #:use-module (gnu packages node)
#:use-module (gnu packages certs) #:use-module (gnu packages certs)
#:use-module (gnu packages nss) #:use-module (gnu packages nss)
#:use-module (gnu packages version-control) #:use-module (gnu packages version-control)
#:use-module (tribes packages otp)
#:export (fetch-mix-deps #:export (fetch-mix-deps
fetch-npm-deps fetch-npm-deps
mix-release-package)) mix-release-package))
@@ -43,14 +44,14 @@ SOURCE according to mix.lock."
(string-append work "/ca-certificates.crt")) (string-append work "/ca-certificates.crt"))
(define hex-lib-dir (define hex-lib-dir
(string-append (string-append
#$(file-append elixir-hex-otp28 "/lib/elixir/1.19") #$(file-append elixir-hex "/lib/elixir/1.19")
":" ":"
#$(file-append elixir-hex-otp28 "/lib/elixir/1.18"))) #$(file-append elixir-hex "/lib/elixir/1.18")))
(define path (define path
(string-join (string-join
(list #$(file-append elixir-otp28 "/bin") (list #$(file-append elixir "/bin")
#$(file-append elixir-hex-otp28 "/bin") #$(file-append elixir-hex "/bin")
#$(file-append rebar3-otp28 "/bin") #$(file-append rebar3 "/bin")
#$(file-append bash-minimal "/bin") #$(file-append bash-minimal "/bin")
#$(file-append coreutils "/bin") #$(file-append coreutils "/bin")
#$(file-append findutils "/bin") #$(file-append findutils "/bin")
@@ -81,7 +82,7 @@ SOURCE according to mix.lock."
(setenv "MIX_ENV" #$mix-env) (setenv "MIX_ENV" #$mix-env)
(setenv "MIX_TARGET" #$mix-target) (setenv "MIX_TARGET" #$mix-target)
(setenv "MIX_OS_CONCURRENCY_LOCK" "0") (setenv "MIX_OS_CONCURRENCY_LOCK" "0")
(setenv "MIX_REBAR3" #$(file-append rebar3-otp28 "/bin/rebar3")) (setenv "MIX_REBAR3" #$(file-append rebar3 "/bin/rebar3"))
(setenv "REBAR_GLOBAL_CONFIG_DIR" (string-append work "/rebar3")) (setenv "REBAR_GLOBAL_CONFIG_DIR" (string-append work "/rebar3"))
(setenv "REBAR_CACHE_DIR" (string-append work "/rebar3.cache")) (setenv "REBAR_CACHE_DIR" (string-append work "/rebar3.cache"))
(setenv "LANG" "C.UTF-8") (setenv "LANG" "C.UTF-8")
@@ -279,16 +280,16 @@ MIX-FOD-DEPS as a pre-fetched dependency tree."
(string-append work "/ca-certificates.crt")) (string-append work "/ca-certificates.crt"))
(define hex-lib-dir (define hex-lib-dir
(string-append (string-append
#$(file-append elixir-hex-otp28 "/lib/elixir/1.19") #$(file-append elixir-hex "/lib/elixir/1.19")
":" ":"
#$(file-append elixir-hex-otp28 "/lib/elixir/1.18"))) #$(file-append elixir-hex "/lib/elixir/1.18")))
(define aclocal-path (define aclocal-path
(string-join (list #$@aclocal-dirs) ":")) (string-join (list #$@aclocal-dirs) ":"))
(define path (define path
(string-join (string-join
(list #$(file-append elixir-otp28 "/bin") (list #$(file-append elixir "/bin")
#$(file-append elixir-hex-otp28 "/bin") #$(file-append elixir-hex "/bin")
#$(file-append rebar3-otp28 "/bin") #$(file-append rebar3 "/bin")
#$(file-append bash-minimal "/bin") #$(file-append bash-minimal "/bin")
#$(file-append coreutils "/bin") #$(file-append coreutils "/bin")
#$(file-append findutils "/bin") #$(file-append findutils "/bin")
@@ -329,8 +330,8 @@ MIX-FOD-DEPS as a pre-fetched dependency tree."
(setenv "MIX_OS_CONCURRENCY_LOCK" "0") (setenv "MIX_OS_CONCURRENCY_LOCK" "0")
(setenv "MIX_OS_DEPS_COMPILE_PARTITION_COUNT" "6") (setenv "MIX_OS_DEPS_COMPILE_PARTITION_COUNT" "6")
(setenv "HEX_OFFLINE" "1") (setenv "HEX_OFFLINE" "1")
(setenv "MIX_REBAR" #$(file-append rebar3-otp28 "/bin/rebar3")) (setenv "MIX_REBAR" #$(file-append rebar3 "/bin/rebar3"))
(setenv "MIX_REBAR3" #$(file-append rebar3-otp28 "/bin/rebar3")) (setenv "MIX_REBAR3" #$(file-append rebar3 "/bin/rebar3"))
(setenv "REBAR_GLOBAL_CONFIG_DIR" (string-append work "/rebar3")) (setenv "REBAR_GLOBAL_CONFIG_DIR" (string-append work "/rebar3"))
(setenv "REBAR_CACHE_DIR" (string-append work "/rebar3.cache")) (setenv "REBAR_CACHE_DIR" (string-append work "/rebar3.cache"))
(setenv "SHELL" #$(file-append bash-minimal "/bin/sh")) (setenv "SHELL" #$(file-append bash-minimal "/bin/sh"))
@@ -385,9 +386,9 @@ MIX-FOD-DEPS as a pre-fetched dependency tree."
findutils findutils
git-minimal git-minimal
nss-certs nss-certs
rebar3-otp28 rebar3
elixir-otp28 elixir
elixir-hex-otp28) elixir-hex)
native-inputs)) native-inputs))
(inputs inputs) (inputs inputs)
(arguments package-arguments) (arguments package-arguments)
-97
View File
@@ -1,97 +0,0 @@
(define-module (tribes packages otp)
#:use-module (guix base32)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix packages)
#:use-module (guix utils)
#:use-module (gnu packages)
#:use-module (gnu packages elixir)
#:use-module (gnu packages erlang)
#:use-module (gnu packages perl)
#:export (erlang-28
rebar3-otp28
elixir-otp28
elixir-hex-otp28))
(define-public erlang-28
(package
(inherit erlang)
(name "erlang-28")
(version "28.5.0.2")
(source
(origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/erlang/otp")
(commit (string-append "OTP-" version))))
(file-name (git-file-name name version))
(sha256
(base32
"0far6szk9h85njn7vwpg4pp9zkxrbyak0w7cr8iymg90s693c34q"))
(patches (search-patches "erlang-man-path.patch"))))
(arguments
(substitute-keyword-arguments (package-arguments erlang)
((#:configure-flags flags)
`(append
(map (lambda (flag)
(if (string=? flag "--enable-wx")
"--without-wx"
flag))
,flags)
;; OTP does not automatically skip applications that depend on wx.
'("--without-debugger"
"--without-observer"
"--without-et"
"--without-reltool")))
((#:phases phases)
`(modify-phases ,phases
;; OTP 28.5.0.2 no longer creates this directory during the first
;; pass, but the inherited second-pass clean target still rmdirs it.
(add-after 'copy-modified-compiler
'create-erl-interface-erts-clean-dir
(lambda _
(mkdir-p "lib/erl_interface/src/erts")))))))
(inputs
(modify-inputs (package-inputs erlang)
(delete "wxwidgets")))
(propagated-inputs '())
(native-inputs
`(("perl" ,perl)
("erlang-manpages"
,(origin
(method url-fetch)
(uri (string-append
"https://github.com/erlang/otp/releases/download"
"/OTP-" version "/otp_doc_man_" version ".tar.gz"))
(sha256
(base32
"02k1dvjfqq4pml8p789spkpj99szsiqqbzhd8kmb9dx30g565mzy"))))))))
(define-public rebar3-otp28
(package
(inherit rebar3)
(name "rebar3-otp28")
(native-inputs
(modify-inputs (package-native-inputs rebar3)
(replace "erlang" erlang-28)))))
(define-public elixir-otp28
(package
(inherit elixir)
(name "elixir-otp28")
(arguments
(substitute-keyword-arguments (package-arguments elixir)
((#:tests? _ #f)
#f)))
(inputs
(modify-inputs (package-inputs elixir)
(replace "erlang" erlang-28)
(replace "rebar3" rebar3-otp28)))))
(define-public elixir-hex-otp28
(package
(inherit elixir-hex)
(name "elixir-hex-otp28")
(inputs
(modify-inputs (package-inputs elixir-hex)
(replace "elixir" elixir-otp28)))))
+2 -2
View File
@@ -54,7 +54,7 @@
"https://git.teralink.net/tribes/tribes.git") "https://git.teralink.net/tribes/tribes.git")
(define %tribes-commit (define %tribes-commit
"4b6d7ebf97473c71cb0b2c8c78bccd155b2ec0f0") "408c39553e4258dd75409eebfa0ffa4380591be0")
(define %tribes-revision "1") (define %tribes-revision "1")
@@ -62,7 +62,7 @@
(git-version "0.2.0" %tribes-revision %tribes-commit)) (git-version "0.2.0" %tribes-revision %tribes-commit))
(define %tribes-source-sha256 (define %tribes-source-sha256
"0s0pvwk6b39s64myn86av09j1768hrrhffh7lnivzym3ffqk3cf1") "16xn3vs6py74z4wrclwapzh18frrp5i663clvwid4l4kmivz833y")
(define %tribes-upstream-source (define %tribes-upstream-source
(origin (origin
-1
View File
@@ -79,7 +79,6 @@ QUIC support.")
#:make-flags #:make-flags
#~(list "LUA_LIB_NAME=lua" #~(list "LUA_LIB_NAME=lua"
"TARGET=linux-glibc" "TARGET=linux-glibc"
"USE_LINUX_CAP=1"
"USE_LUA=1" "USE_LUA=1"
"USE_OPENSSL_AWSLC=1" "USE_OPENSSL_AWSLC=1"
"USE_PCRE2=1" "USE_PCRE2=1"
+4 -4
View File
@@ -16,7 +16,7 @@
%aether-home-page) %aether-home-page)
(define %aether-commit (define %aether-commit
"995160f95e31efe4d026662885d4b016f144ce9a") "80101b7e78808cea9151f1827777edea5c08ba1f")
(define %aether-revision "1") (define %aether-revision "1")
@@ -24,7 +24,7 @@
(git-version "0.2.0" %aether-revision %aether-commit)) (git-version "0.2.0" %aether-revision %aether-commit))
(define %aether-source-sha256 (define %aether-source-sha256
"1jp52q70z1djiglm03b81zh7zgn87gbf207xwih24h6a0zddsmgs") "0shylw4s75djanqm7h82j8advjg96im6n4wr6fz6kwbj5hs8aq4b")
(define %aether-mix-deps-sha256 (define %aether-mix-deps-sha256
"1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb") "1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb")
@@ -68,7 +68,7 @@
"External Tribes plugin artifact for Aether, packaged as a Guix-managed "External Tribes plugin artifact for Aether, packaged as a Guix-managed
plugin directory." plugin directory."
#:plugin-id "org.tribe-one.plugins.aether" #:plugin-id "org.tribe-one.plugins.aether"
#:plugin-slug "tribe-one-aether" #:plugin-slug "aether"
#:display-name "Aether" #:display-name "Aether"
#:provides '("org.tribe-one.caps.social@1" "org.tribe-one.caps.chat@1") #:provides '("org.tribe-one.caps.social@1" "org.tribe-one.caps.chat@1")
#:requires '("org.tribe-one.caps.ui@1") #:requires '("org.tribe-one.caps.ui@1")
@@ -104,7 +104,7 @@ artifact."
"External Tribes plugin artifact for Aether, packaged as a Guix-managed "External Tribes plugin artifact for Aether, packaged as a Guix-managed
plugin directory." plugin directory."
#:plugin-id "org.tribe-one.plugins.aether" #:plugin-id "org.tribe-one.plugins.aether"
#:plugin-slug "tribe-one-aether" #:plugin-slug "aether"
#:display-name "Aether" #:display-name "Aether"
#:provides '("org.tribe-one.caps.social@1" "org.tribe-one.caps.chat@1") #:provides '("org.tribe-one.caps.social@1" "org.tribe-one.caps.chat@1")
#:requires '("org.tribe-one.caps.ui@1") #:requires '("org.tribe-one.caps.ui@1")
+1 -1
View File
@@ -27,7 +27,7 @@
(define guix-tribes-built-in-plugin-definitions (define guix-tribes-built-in-plugin-definitions
(list (list
(tribes-plugin-definition (tribes-plugin-definition
(name "tribe-one-tribes-ui") (name "tribes_ui")
(package-name "tribes") (package-name "tribes")
(version "0.1.0") (version "0.1.0")
(synopsis "Default Tribes UI capability provider") (synopsis "Default Tribes UI capability provider")
+4 -4
View File
@@ -16,7 +16,7 @@
%kobold-home-page) %kobold-home-page)
(define %kobold-commit (define %kobold-commit
"4658b762411f014b531d4acc5aaea05463dbfca3") "74b6c44e4dcfbeaf02f77620b5675f11781ad1eb")
(define %kobold-revision "1") (define %kobold-revision "1")
@@ -24,7 +24,7 @@
(git-version "0.1.0" %kobold-revision %kobold-commit)) (git-version "0.1.0" %kobold-revision %kobold-commit))
(define %kobold-source-sha256 (define %kobold-source-sha256
"0qrssm32apandr2m4fsh56v6ay7b31630k7g033f17fwxlrlbq34") "1xxysbslh1fa57873n4669mi874byv861w934mz9g3zszr120ijn")
(define %kobold-mix-deps-sha256 (define %kobold-mix-deps-sha256
"1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb") "1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb")
@@ -68,7 +68,7 @@
"External Tribes plugin artifact for Kobold distributed datasets, "External Tribes plugin artifact for Kobold distributed datasets,
packaged as a Guix-managed plugin directory." packaged as a Guix-managed plugin directory."
#:plugin-id "org.tribe-one.plugins.kobold" #:plugin-id "org.tribe-one.plugins.kobold"
#:plugin-slug "tribe-one-kobold" #:plugin-slug "kobold"
#:display-name "Kobold" #:display-name "Kobold"
#:provides '("org.tribes.kobold.dataset@1") #:provides '("org.tribes.kobold.dataset@1")
#:requires '("org.tribe-one.caps.ui@1" "org.tribes.alliance.trust@1") #:requires '("org.tribe-one.caps.ui@1" "org.tribes.alliance.trust@1")
@@ -103,7 +103,7 @@ packaged as a Guix-managed plugin directory."
"External Tribes plugin artifact for Kobold distributed datasets, "External Tribes plugin artifact for Kobold distributed datasets,
packaged as a Guix-managed plugin directory." packaged as a Guix-managed plugin directory."
#:plugin-id "org.tribe-one.plugins.kobold" #:plugin-id "org.tribe-one.plugins.kobold"
#:plugin-slug "tribe-one-kobold" #:plugin-slug "kobold"
#:display-name "Kobold" #:display-name "Kobold"
#:provides '("org.tribes.kobold.dataset@1") #:provides '("org.tribes.kobold.dataset@1")
#:requires '("org.tribe-one.caps.ui@1" "org.tribes.alliance.trust@1") #:requires '("org.tribe-one.caps.ui@1" "org.tribes.alliance.trust@1")
+4 -4
View File
@@ -17,7 +17,7 @@
%sender-home-page) %sender-home-page)
(define %sender-commit (define %sender-commit
"cdbfef7cd300c581b74b7aa61e7c35fb52e7ccff") "ee7d0ac29fb583e1c5f75001984622c2ba7e56b1")
(define %sender-revision "1") (define %sender-revision "1")
@@ -25,7 +25,7 @@
(git-version "0.1.0" %sender-revision %sender-commit)) (git-version "0.1.0" %sender-revision %sender-commit))
(define %sender-source-sha256 (define %sender-source-sha256
"1nbybxiyihqv0avjkrl4x1k0iz5cyljcs38zvb6kln474v6qz0ly") "1bbgi20j99ym9yiv78w3j590wpf400bdkfiqf9s1ra31dgfzzq4v")
(define %sender-mix-deps-sha256 (define %sender-mix-deps-sha256
"08mdy38247dqni8f84y09m8vz6hvjakvc4ml28x1jxqvq53s4nq3") "08mdy38247dqni8f84y09m8vz6hvjakvc4ml28x1jxqvq53s4nq3")
@@ -72,7 +72,7 @@
"External Tribes plugin artifact for RTMP ingest and HLS streaming, "External Tribes plugin artifact for RTMP ingest and HLS streaming,
packaged as a Guix-managed plugin directory." packaged as a Guix-managed plugin directory."
#:plugin-id "org.tribe-one.plugins.sender" #:plugin-id "org.tribe-one.plugins.sender"
#:plugin-slug "tribe-one-sender" #:plugin-slug "sender"
#:display-name "Sender" #:display-name "Sender"
#:provides '("org.tribe-one.caps.sender@1") #:provides '("org.tribe-one.caps.sender@1")
#:requires '("org.tribe-one.caps.ui@1") #:requires '("org.tribe-one.caps.ui@1")
@@ -112,7 +112,7 @@ artifact."
"External Tribes plugin artifact for RTMP ingest and HLS streaming, "External Tribes plugin artifact for RTMP ingest and HLS streaming,
packaged as a Guix-managed plugin directory." packaged as a Guix-managed plugin directory."
#:plugin-id "org.tribe-one.plugins.sender" #:plugin-id "org.tribe-one.plugins.sender"
#:plugin-slug "tribe-one-sender" #:plugin-slug "sender"
#:display-name "Sender" #:display-name "Sender"
#:provides '("org.tribe-one.caps.sender@1") #:provides '("org.tribe-one.caps.sender@1")
#:requires '("org.tribe-one.caps.ui@1") #:requires '("org.tribe-one.caps.ui@1")
+4 -4
View File
@@ -16,7 +16,7 @@
%supertest-home-page) %supertest-home-page)
(define %supertest-commit (define %supertest-commit
"982243e64a132c4ae082234e775fa9f0e98b8eb4") "afc38412c4362ea2e5b1fe9fe08f1cffe60edf34")
(define %supertest-revision "1") (define %supertest-revision "1")
@@ -24,7 +24,7 @@
(git-version "0.1.1" %supertest-revision %supertest-commit)) (git-version "0.1.1" %supertest-revision %supertest-commit))
(define %supertest-source-sha256 (define %supertest-source-sha256
"0mk4ph2ibnqvcca55n9dnlmfg6abm9p8bz3wsq8913crk55hw2qa") "1si0bis5k47j22cv7cbbah86ilrxvrbncld4isvyb17zan7ig0q6")
(define %supertest-mix-deps-sha256 (define %supertest-mix-deps-sha256
"1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb") "1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb")
@@ -65,7 +65,7 @@
#:description #:description
"External Tribes plugin artifact used by live rollout and sync tests." "External Tribes plugin artifact used by live rollout and sync tests."
#:plugin-id "org.tribe-one.plugins.supertest" #:plugin-id "org.tribe-one.plugins.supertest"
#:plugin-slug "tribe-one-supertest" #:plugin-slug "supertest"
#:display-name "Supertest" #:display-name "Supertest"
#:provides '() #:provides '()
#:requires '() #:requires '()
@@ -95,7 +95,7 @@
#:description #:description
"External Tribes plugin artifact used by live rollout and sync tests." "External Tribes plugin artifact used by live rollout and sync tests."
#:plugin-id "org.tribe-one.plugins.supertest" #:plugin-id "org.tribe-one.plugins.supertest"
#:plugin-slug "tribe-one-supertest" #:plugin-slug "supertest"
#:display-name "Supertest" #:display-name "Supertest"
#:provides '() #:provides '()
#:requires '() #:requires '()
+4 -4
View File
@@ -16,7 +16,7 @@
%trust-home-page) %trust-home-page)
(define %trust-commit (define %trust-commit
"157106aa66ecd7ce5f7f5a8a90c30a1f22e2fe74") "f08af20cd5cd2dbbb50e4472bf1a5d8ed1b73c21")
(define %trust-revision "1") (define %trust-revision "1")
@@ -24,7 +24,7 @@
(git-version "0.1.0" %trust-revision %trust-commit)) (git-version "0.1.0" %trust-revision %trust-commit))
(define %trust-source-sha256 (define %trust-source-sha256
"0k1gzpd5f5q3mczmxw0rwx7zwqxkspzk0zfpm1a130fd4dqc9y5z") "1zsg57mr3bjxrxvim77z2as1jqr8a3anfp0jgqz0ycz6rzai58dp")
(define %trust-mix-deps-sha256 (define %trust-mix-deps-sha256
"1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb") "1pk1qv8skbgzi0wg59zj9aiyxx2hxl2k6ngxqqbwvj7wsbiz95bb")
@@ -67,7 +67,7 @@
#:description #:description
"External Tribes plugin artifact for tribe-to-tribe trust, alliance, and federation provider behavior." "External Tribes plugin artifact for tribe-to-tribe trust, alliance, and federation provider behavior."
#:plugin-id "org.tribe-one.plugins.trust" #:plugin-id "org.tribe-one.plugins.trust"
#:plugin-slug "tribe-one-trust" #:plugin-slug "trust"
#:display-name "Trust" #:display-name "Trust"
#:provides '("org.tribes.alliance.trust@1" "org.tribes.federation.provider@1" "org.tribes.access.trust_provider@1") #:provides '("org.tribes.alliance.trust@1" "org.tribes.federation.provider@1" "org.tribes.access.trust_provider@1")
#:requires '("org.tribe-one.caps.ui@1") #:requires '("org.tribe-one.caps.ui@1")
@@ -101,7 +101,7 @@
#:description #:description
"External Tribes plugin artifact for tribe-to-tribe trust, alliance, and federation provider behavior." "External Tribes plugin artifact for tribe-to-tribe trust, alliance, and federation provider behavior."
#:plugin-id "org.tribe-one.plugins.trust" #:plugin-id "org.tribe-one.plugins.trust"
#:plugin-slug "tribe-one-trust" #:plugin-slug "trust"
#:display-name "Trust" #:display-name "Trust"
#:provides '("org.tribes.alliance.trust@1" "org.tribes.federation.provider@1" "org.tribes.access.trust_provider@1") #:provides '("org.tribes.alliance.trust@1" "org.tribes.federation.provider@1" "org.tribes.access.trust_provider@1")
#:requires '("org.tribe-one.caps.ui@1") #:requires '("org.tribe-one.caps.ui@1")
+21 -27
View File
@@ -83,19 +83,6 @@
(define (haproxy-lines lines) (define (haproxy-lines lines)
(string-concatenate (map haproxy-indent lines))) (string-concatenate (map haproxy-indent lines)))
(define (haproxy-crt-arguments pem-files)
(string-join
(append-map (lambda (pem-file)
(list "crt" pem-file))
pem-files)
" "))
(define (haproxy-tls-bind-line frontend pem-files alpn)
(string-append "bind " frontend
" ssl "
(haproxy-crt-arguments pem-files)
" alpn " alpn))
(define (haproxy-http-frontend http-frontends acme-backend) (define (haproxy-http-frontend http-frontends acme-backend)
(if (null? http-frontends) (if (null? http-frontends)
"" ""
@@ -109,14 +96,14 @@
(if acme-backend (if acme-backend
'("acl acme_challenge path_beg /.well-known/acme-challenge/" '("acl acme_challenge path_beg /.well-known/acme-challenge/"
"http-request redirect scheme https code 308 unless acme_challenge" "http-request redirect scheme https code 308 unless acme_challenge"
"use_backend tribes_acme if acme_challenge") "use_backend lego_acme if acme_challenge")
'("http-request redirect scheme https code 308")))) '("http-request redirect scheme https code 308"))))
"\n" "\n"
(if acme-backend (if acme-backend
(string-append (string-append
"backend tribes_acme\n" "backend lego_acme\n"
(haproxy-lines (haproxy-lines
(list (string-append "server tribes " acme-backend))) (list (string-append "server lego " acme-backend)))
"\n") "\n")
"")))) ""))))
@@ -132,7 +119,6 @@
(haproxy-lines (haproxy-lines
(append (append
(list "log /dev/log local0" (list "log /dev/log local0"
"setcap cap_net_bind_service"
(string-append "user " user) (string-append "user " user)
(string-append "group " group) (string-append "group " group)
"maxconn 32768" "maxconn 32768"
@@ -158,17 +144,25 @@
"frontend tribes_tls\n" "frontend tribes_tls\n"
(haproxy-lines (haproxy-lines
(append (append
(if (null? pem-files) (append-map
'() (lambda (frontend)
(append (map
(map (lambda (frontend) (lambda (pem-file)
(haproxy-tls-bind-line frontend pem-files "h2,http/1.1")) (string-append "bind " frontend
frontends) " ssl crt " pem-file
(map (lambda (frontend) " alpn h2,http/1.1"))
(haproxy-tls-bind-line frontend pem-files "h3")) pem-files))
quic-frontends))) frontends)
(append-map
(lambda (frontend)
(map
(lambda (pem-file)
(string-append "bind " frontend
" ssl crt " pem-file
" alpn h3"))
pem-files))
quic-frontends)
'("http-response set-header alt-svc 'h3=\":443\"; ma=86400'") '("http-response set-header alt-svc 'h3=\":443\"; ma=86400'")
'("http-response set-header strict-transport-security \"max-age=31536000\"")
'("default_backend tribes_edge_cache") '("default_backend tribes_edge_cache")
extra-frontend)) extra-frontend))
"\n" "\n"
-26
View File
@@ -22,8 +22,6 @@
lego-certificate-configuration-profile lego-certificate-configuration-profile
lego-certificate-configuration-listen-http lego-certificate-configuration-listen-http
lego-certificate-configuration-webroot lego-certificate-configuration-webroot
lego-certificate-configuration-dns-provider
lego-certificate-configuration-environment-variables
lego-certificate-configuration-key-type lego-certificate-configuration-key-type
lego-certificate-configuration-acme-enabled? lego-certificate-configuration-acme-enabled?
lego-certificate-configuration-renew-days lego-certificate-configuration-renew-days
@@ -31,7 +29,6 @@
lego-certificate-configuration-reload-services lego-certificate-configuration-reload-services
lego-certificate-directory lego-certificate-directory
lego-certificate-full-pem lego-certificate-full-pem
subject-is-ip?
lego-configuration lego-configuration
lego-configuration? lego-configuration?
lego-configuration-package lego-configuration-package
@@ -55,10 +52,6 @@
(default #f)) (default #f))
(webroot lego-certificate-configuration-webroot (webroot lego-certificate-configuration-webroot
(default #f)) (default #f))
(dns-provider lego-certificate-configuration-dns-provider
(default #f))
(environment-variables lego-certificate-configuration-environment-variables
(default '()))
(key-type lego-certificate-configuration-key-type (key-type lego-certificate-configuration-key-type
(default "ec384")) (default "ec384"))
(acme-enabled? lego-certificate-configuration-acme-enabled? (acme-enabled? lego-certificate-configuration-acme-enabled?
@@ -113,7 +106,6 @@
(define (lego-common-arguments certificate) (define (lego-common-arguments certificate)
(let ((listen-http (lego-certificate-configuration-listen-http certificate)) (let ((listen-http (lego-certificate-configuration-listen-http certificate))
(webroot (lego-certificate-configuration-webroot certificate)) (webroot (lego-certificate-configuration-webroot certificate))
(dns-provider (lego-certificate-configuration-dns-provider certificate))
(subjects (lego-certificate-configuration-subjects certificate)) (subjects (lego-certificate-configuration-subjects certificate))
(email (lego-certificate-configuration-email certificate)) (email (lego-certificate-configuration-email certificate))
(server (lego-certificate-configuration-server certificate)) (server (lego-certificate-configuration-server certificate))
@@ -129,17 +121,11 @@
(error "lego certificate cannot use both listen-http and webroot" (error "lego certificate cannot use both listen-http and webroot"
(lego-certificate-configuration-name certificate)) (lego-certificate-configuration-name certificate))
'()) '())
(if (and dns-provider (or listen-http webroot))
(error "lego certificate cannot combine HTTP and DNS challenge modes"
(lego-certificate-configuration-name certificate))
'())
(cond (cond
(listen-http (listen-http
(list "--http" "--http.port" listen-http)) (list "--http" "--http.port" listen-http))
(webroot (webroot
(list "--http" "--http.webroot" webroot)) (list "--http" "--http.webroot" webroot))
(dns-provider
(list "--dns" dns-provider))
(else (else
(list "--http"))) (list "--http")))
(if server (if server
@@ -210,8 +196,6 @@
(key-output (string-append state-dir "/key.pem")) (key-output (string-append state-dir "/key.pem"))
(full-pem (string-append state-dir "/full.pem")) (full-pem (string-append state-dir "/full.pem"))
(last-run-log (lego-certificate-last-run-log certificate)) (last-run-log (lego-certificate-last-run-log certificate))
(environment-variables
(lego-certificate-configuration-environment-variables certificate))
(run-arguments (run-arguments
(append (lego-common-arguments certificate) (append (lego-common-arguments certificate)
(list "run") (list "run")
@@ -254,15 +238,6 @@
(new (file-contents #$certificate-file))) (new (file-contents #$certificate-file)))
(not (equal? old new)))) (not (equal? old new))))
(define (apply-environment! variables)
(for-each
(lambda (variable)
(let ((separator (string-index variable #\=)))
(when separator
(setenv (substring variable 0 separator)
(substring variable (+ separator 1))))))
variables))
(define (run-lego lego args) (define (run-lego lego args)
(let* ((log-port (open-output-file #$last-run-log)) (let* ((log-port (open-output-file #$last-run-log))
(port (apply open-pipe* OPEN_READ (port (apply open-pipe* OPEN_READ
@@ -289,7 +264,6 @@
(run-lego lego args)))) (run-lego lego args))))
(mkdir-p #$state-dir) (mkdir-p #$state-dir)
(apply-environment! '#$environment-variables)
(let ((lego #$(file-append (let ((lego #$(file-append
(lego-configuration-package config) (lego-configuration-package config)
+1 -1
View File
@@ -24,7 +24,7 @@ Tribes service using an explicit host configuration record."
(let* ((node-config (let* ((node-config
(tribes-node-configuration (tribes-node-configuration
(postgresql (postgresql-configuration (postgresql (postgresql-configuration
(postgresql postgresql-17))) (postgresql postgresql)))
(tribes (tribes-host-configuration-tribes host-configuration)) (tribes (tribes-host-configuration-tribes host-configuration))
(edge (tribes-host-configuration-edge host-configuration)) (edge (tribes-host-configuration-edge host-configuration))
(enable-bbr? enable-bbr?)))) (enable-bbr? enable-bbr?))))
+36 -133
View File
@@ -1,9 +1,7 @@
(define-module (tribes system node) (define-module (tribes system node)
#:use-module (gnu packages)
#:use-module (gnu packages databases) #:use-module (gnu packages databases)
#:use-module (gnu packages linux) #:use-module (gnu packages linux)
#:use-module (gnu packages monitoring) #:use-module (gnu packages monitoring)
#:use-module (gnu packages tls)
#:use-module (gnu services) #:use-module (gnu services)
#:use-module (gnu services databases) #:use-module (gnu services databases)
#:use-module (gnu services linux) #:use-module (gnu services linux)
@@ -16,6 +14,7 @@
#:use-module (tribes packages plugins) #:use-module (tribes packages plugins)
#:use-module (tribes services chrony) #:use-module (tribes services chrony)
#:use-module (tribes services haproxy) #:use-module (tribes services haproxy)
#:use-module (tribes services lego)
#:use-module (tribes services tribes) #:use-module (tribes services tribes)
#:use-module (tribes services vinyl) #:use-module (tribes services vinyl)
#:use-module (tribes services vinyl-exporter) #:use-module (tribes services vinyl-exporter)
@@ -24,6 +23,7 @@
tribes-edge-configuration? tribes-edge-configuration?
tribes-edge-configuration-certificate-name tribes-edge-configuration-certificate-name
tribes-edge-configuration-certificate-subjects tribes-edge-configuration-certificate-subjects
tribes-edge-configuration-certificate-email
tribes-edge-configuration-certificate-profile tribes-edge-configuration-certificate-profile
tribes-edge-configuration-renew-days tribes-edge-configuration-renew-days
tribes-edge-configuration-http-port tribes-edge-configuration-http-port
@@ -48,6 +48,8 @@
(default "tribes")) (default "tribes"))
(certificate-subjects tribes-edge-configuration-certificate-subjects (certificate-subjects tribes-edge-configuration-certificate-subjects
(default '())) (default '()))
(certificate-email tribes-edge-configuration-certificate-email
(default #f))
(certificate-profile tribes-edge-configuration-certificate-profile (certificate-profile tribes-edge-configuration-certificate-profile
(default "shortlived")) (default "shortlived"))
(renew-days tribes-edge-configuration-renew-days (renew-days tribes-edge-configuration-renew-days
@@ -72,12 +74,7 @@
tribes-node-configuration? tribes-node-configuration?
(postgresql tribes-node-configuration-postgresql (postgresql tribes-node-configuration-postgresql
(default (postgresql-configuration (default (postgresql-configuration
(postgresql postgresql-17) (postgresql postgresql))))
(config-file
(postgresql-config-file
(extra-config
'(("log_min_duration_statement" 1000)
("log_line_prefix" "%m [%p] user=%u db=%d app=%a client=%h "))))))))
(tribes tribes-node-configuration-tribes (tribes tribes-node-configuration-tribes
(default (tribes-configuration))) (default (tribes-configuration)))
(edge tribes-node-configuration-edge (edge tribes-node-configuration-edge
@@ -92,88 +89,34 @@
(name (tribes-configuration-database-user tribes)) (name (tribes-configuration-database-user tribes))
(permissions '(createdb login)))))) (permissions '(createdb login))))))
(define (edge-certificate-subjects edge _tribes) (define (edge-certificate-subjects edge tribes)
(let ((subjects (tribes-edge-configuration-certificate-subjects edge))) (let ((subjects (tribes-edge-configuration-certificate-subjects edge)))
(if (null? subjects) (if (null? subjects)
(error "edge certificate requires explicit IP subjects") (list (tribes-configuration-host tribes))
subjects))) subjects)))
(define %edge-acme-state-directory "/var/lib/tribes/acme") (define (edge-certificate-config edge tribes)
(define %edge-acme-key-file
(string-append %edge-acme-state-directory "/edge.key"))
(define %edge-acme-fullchain-file
(string-append %edge-acme-state-directory "/edge.fullchain.pem"))
(define %edge-haproxy-pem-file
(string-append %edge-acme-state-directory "/edge.full.pem"))
(define (subject-is-ip? subject)
(and (not (string-any char-alphabetic? subject))
(string-any (lambda (chr)
(or (char-numeric? chr)
(char=? chr #\.)
(char=? chr #\:)))
subject)))
(define (edge-certificate-subjects-validated edge tribes)
(let* ((subjects (edge-certificate-subjects edge tribes)) (let* ((subjects (edge-certificate-subjects edge tribes))
(email (tribes-edge-configuration-certificate-email edge))
(certificate-profile (certificate-profile
(tribes-edge-configuration-certificate-profile edge)) (tribes-edge-configuration-certificate-profile edge))
(self-signed-only? (string=? certificate-profile "self-signed")) (self-signed-only? (string=? certificate-profile "self-signed")))
(ip-subjects (filter subject-is-ip? subjects)) (unless email
(dns-subjects (filter (lambda (subject) (error "edge certificate email is required"
(not (subject-is-ip? subject))) (tribes-edge-configuration-certificate-name edge)))
subjects))) (lego-certificate-configuration
(when (not (null? dns-subjects)) (name (tribes-edge-configuration-certificate-name edge))
(error "edge certificate subjects must be IP addresses" dns-subjects)) (subjects subjects)
(when (null? ip-subjects) (email email)
(error "edge certificate requires at least one IP subject")) (profile (and (not self-signed-only?) certificate-profile))
(when (and (not self-signed-only?) (listen-http
(not (string=? certificate-profile "shortlived"))) (format #f "~a:~a"
(error "IP address certificates require the shortlived certificate profile")) (tribes-edge-configuration-challenge-address edge)
subjects)) (tribes-edge-configuration-challenge-port edge)))
(acme-enabled? (not self-signed-only?))
(define (edge-acme-enabled? edge) (renew-days (tribes-edge-configuration-renew-days edge))
(not (string=? (tribes-edge-configuration-certificate-profile edge) (requirement '(haproxy))
"self-signed"))) (reload-services '(haproxy)))))
(define (subject->san-entry subject)
(string-append "IP:" subject))
(define (edge-bootstrap-certificate-activation edge tribes)
(let ((subjects (edge-certificate-subjects-validated edge tribes)))
(simple-service
'tribes-edge-bootstrap-certificate
activation-service-type
#~(begin
(use-modules (guix build utils)
(ice-9 textual-ports))
(mkdir-p #$%edge-acme-state-directory)
(chmod #$%edge-acme-state-directory #o700)
(unless (file-exists? #$%edge-acme-key-file)
(system* #$(file-append openssl "/bin/openssl")
"ecparam" "-name" "secp384r1" "-genkey" "-noout"
"-out" #$%edge-acme-key-file)
(chmod #$%edge-acme-key-file #o600))
(unless (file-exists? #$%edge-haproxy-pem-file)
(let ((cert-file (string-append #$%edge-acme-state-directory
"/edge.bootstrap.crt")))
(system* #$(file-append openssl "/bin/openssl")
"req" "-new" "-x509" "-sha384"
"-key" #$%edge-acme-key-file
"-out" cert-file
"-days" "7"
"-subj" "/CN=Tribes bootstrap edge"
"-addext"
#$(string-append
"subjectAltName="
(string-join (map subject->san-entry subjects) ",")))
(call-with-output-file #$%edge-haproxy-pem-file
(lambda (port)
(display (call-with-input-file cert-file get-string-all) port)
(newline port)
(display (call-with-input-file #$%edge-acme-key-file
get-string-all) port)))
(chmod #$%edge-haproxy-pem-file #o600)))))))
(define (edge-cache-vcl-text edge tribes) (define (edge-cache-vcl-text edge tribes)
(string-append (string-append
@@ -220,13 +163,6 @@
" }\n\n" " }\n\n"
" return (pass);\n" " return (pass);\n"
"}\n\n" "}\n\n"
"sub vcl_backend_fetch {\n"
" if (bereq.url ~ \"^/api/admin/\") {\n"
" set bereq.connect_timeout = 1s;\n"
" set bereq.first_byte_timeout = 35s;\n"
" set bereq.between_bytes_timeout = 35s;\n"
" }\n"
"}\n\n"
"sub vcl_backend_response {\n" "sub vcl_backend_response {\n"
" if ((bereq.method == \"GET\" || bereq.method == \"HEAD\") &&\n" " if ((bereq.method == \"GET\" || bereq.method == \"HEAD\") &&\n"
" beresp.status >= 500 && beresp.status <= 599 &&\n" " beresp.status >= 500 && beresp.status <= 599 &&\n"
@@ -269,12 +205,14 @@
(define (edge-services config) (define (edge-services config)
(let* ((tribes (tribes-node-configuration-tribes config)) (let* ((tribes (tribes-node-configuration-tribes config))
(edge (tribes-node-configuration-edge config)) (edge (tribes-node-configuration-edge config))
(_subjects (edge-certificate-subjects-validated edge tribes)) (certificate (edge-certificate-config edge tribes))
(cache-port (tribes-edge-configuration-cache-port edge)) (cache-port (tribes-edge-configuration-cache-port edge))
(http-port (tribes-edge-configuration-http-port edge)) (http-port (tribes-edge-configuration-http-port edge))
(https-port (tribes-edge-configuration-https-port edge))) (https-port (tribes-edge-configuration-https-port edge)))
(list (list
(edge-bootstrap-certificate-activation edge tribes) (service lego-service-type
(lego-configuration
(certificates (list certificate))))
(service vinyl-service-type (service vinyl-service-type
(list (list
(vinyl-configuration (vinyl-configuration
@@ -306,35 +244,9 @@
(format #f "[::]:~a v6only" http-port))) (format #f "[::]:~a v6only" http-port)))
(acme-backend (acme-backend
(format #f "~a:~a" (format #f "~a:~a"
(or (tribes-configuration-listen-address tribes) (tribes-edge-configuration-challenge-address edge)
"127.0.0.1") (tribes-edge-configuration-challenge-port edge)))
(tribes-configuration-listen-port tribes))) (pem-files (list (lego-certificate-full-pem certificate))))))))
(pem-files (list %edge-haproxy-pem-file)))))))
;; Interactive toolkit installed into every node's system profile. These are
;; vanilla upstream packages an operator reaches for over SSH; shipping them in
;; the system closure means they are both present on the node and served by our
;; substitute mirror, instead of forcing a fallback to bordeaux/ci on first use.
(define %tribes-node-operator-tools
(map specification->package
'("ripgrep" "fd" "tmux" "neovim" "btop")))
(define (tribes-with-edge-acme-environment tribes edge)
(tribes-configuration
(inherit tribes)
(extra-environment-variables
(append
(tribes-configuration-extra-environment-variables tribes)
(list
(string-append "TRIBES_ACME_ENABLED="
(if (edge-acme-enabled? edge) "true" "false"))
(string-append "TRIBES_ACME_CERTIFICATE_SUBJECTS="
(string-join
(edge-certificate-subjects-validated edge tribes)
","))
(string-append "TRIBES_ACME_CERTIFICATE_PROFILE="
(tribes-edge-configuration-certificate-profile edge))
(string-append "TRIBES_ACME_STATE_DIR=" %edge-acme-state-directory))))))
(define (tribes-node-bbr-services config) (define (tribes-node-bbr-services config)
(if (tribes-node-configuration-enable-bbr? config) (if (tribes-node-configuration-enable-bbr? config)
@@ -350,11 +262,7 @@
'())) '()))
(define (tribes-node-services config) (define (tribes-node-services config)
(let* ((base-tribes (tribes-node-configuration-tribes config)) (let* ((tribes (tribes-node-configuration-tribes config))
(edge (tribes-node-configuration-edge config))
(tribes (if edge
(tribes-with-edge-acme-environment base-tribes edge)
base-tribes))
(plugins (tribes-configuration-plugins tribes)) (plugins (tribes-configuration-plugins tribes))
(plugin-services (plugin-services
(append-map (append-map
@@ -372,9 +280,6 @@
(simple-service 'tribes-node-network-tools (simple-service 'tribes-node-network-tools
profile-service-type profile-service-type
(list nftables)) (list nftables))
(simple-service 'tribes-node-operator-tools
profile-service-type
%tribes-node-operator-tools)
(service prometheus-node-exporter-service-type (service prometheus-node-exporter-service-type
(prometheus-node-exporter-configuration (prometheus-node-exporter-configuration
(package prometheus-node-exporter) (package prometheus-node-exporter)
@@ -385,8 +290,6 @@
tribes)) tribes))
(tribes-node-bbr-services config) (tribes-node-bbr-services config)
plugin-services plugin-services
(if edge (if (tribes-node-configuration-edge config)
(edge-services (tribes-node-configuration (edge-services config)
(inherit config)
(tribes tribes)))
'())))) '()))))