internal/rosa: mirror service via external cache
Test / Create distribution (push) Successful in 51s
Test / Sandbox (push) Successful in 2m43s
Test / ShareFS (push) Successful in 3m58s
Test / Hakurei (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 5m29s
Test / Hakurei (race detector) (push) Successful in 6m43s
Test / Flake checks (push) Successful in 1m18s

This provides an authenticated implementation of the external cache.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-06-07 17:15:27 +09:00
parent 22e508fe17
commit e8bb5a622d
3 changed files with 461 additions and 1 deletions
+18 -1
View File
@@ -2,6 +2,7 @@ package main
import (
"context"
"net/http"
"os"
"path/filepath"
"testing"
@@ -9,6 +10,7 @@ import (
"hakurei.app/check"
"hakurei.app/container"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
"hakurei.app/message"
)
@@ -30,7 +32,7 @@ type cache struct {
// Loaded artifact of [rosa.QEMU].
qemu pkg.Artifact
base string
base, mirror string
}
// open opens the underlying [pkg.Cache].
@@ -86,6 +88,21 @@ func (cache *cache) open() (err error) {
}
done <- struct{}{}
if cache.mirror != "" {
var pub []byte
pub, err = os.ReadFile(base.Append("ed25519.pub").String())
if err != nil {
cache.c.Close()
return
}
var r rosa.Remote
if r, err = rosa.NewRemote(cache.mirror, pub, http.DefaultClient); err != nil {
cache.c.Close()
return err
}
cache.c.SetExternal(r)
}
if cache.qemu != nil {
var pathname *check.Absolute
pathname, _, err = cache.c.Cure(cache.qemu)
+82
View File
@@ -14,6 +14,7 @@ package main
import (
"context"
"crypto/ed25519"
"crypto/sha512"
"errors"
"fmt"
@@ -47,6 +48,19 @@ import (
"hakurei.app/cmd/mbf/internal/pkgserver/ui"
)
// writeFileExcl is like [os.WriteFile], but sets [os.O_EXCL] instead.
func writeFileExcl(name string, data []byte, perm os.FileMode) error {
f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
if err != nil {
return err
}
_, err = f.Write(data)
if err1 := f.Close(); err1 != nil && err == nil {
err = err1
}
return err
}
func main() {
container.TryArgv0(nil)
@@ -186,6 +200,10 @@ func main() {
&cm.base,
"d", command.StringFlag("$MBF_CACHE_DIR"),
"Directory to store cured artifacts",
).Flag(
&cm.mirror,
"r", command.StringFlag("$MBF_REMOTE"),
"URL of mirror service",
).Flag(
&cm.idle,
"sched-idle", command.BoolFlag(false),
@@ -462,6 +480,70 @@ func main() {
},
)
c.NewCommand(
"keygen",
"Create keypair for local cache",
func([]string) error {
pub, priv, err := ed25519.GenerateKey(nil)
if err != nil {
return err
}
return errors.Join(writeFileExcl(filepath.Join(
cm.base,
"ed25519.pub",
), pub, 0444), writeFileExcl(filepath.Join(
cm.base,
"ed25519",
), priv, 0400))
},
)
c.NewCommand(
"serve",
"Export local cache as mirror",
func(args []string) error {
const shutdownTimeout = 15 * time.Second
if len(args) != 1 {
return errors.New("serve requires 1 argument")
}
var key ed25519.PrivateKey
if p, err := os.ReadFile(filepath.Join(cm.base, "ed25519")); err != nil {
return err
} else if len(p) != ed25519.PrivateKeySize {
return errors.New("invalid private key")
} else {
key = p
}
var h http.Handler
if base, err := os.OpenRoot(cm.base); err != nil {
return err
} else {
h = rosa.NewMirror(msg, base, key)
}
server := http.Server{Addr: args[0], Handler: h}
go func() {
<-ctx.Done()
cc, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
defer cancel()
if err := server.Shutdown(cc); err != nil {
log.Fatal(err)
}
}()
msg.Verbosef("listening on %q", args[0])
err := server.ListenAndServe()
if errors.Is(err, http.ErrServerClosed) {
err = nil
}
return err
},
)
{
var (
flagGentoo string