Compare commits
11 Commits
9ad7e54527
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 2e228f137b | |||
| 3da73147dc | |||
| fcecc1e5b0 | |||
| bbae941a36 | |||
| 7aa6e4d200 | |||
| 8f3053b5e7 | |||
| 133df762ab | |||
| 031d943979 | |||
| 202f6389bc | |||
| abbc16cdc0 | |||
| b9a1ac623d |
@@ -68,9 +68,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
# 4. Build smoke — every changed package must build. Cache push
|
# 4. Build smoke — every changed package must build.
|
||||||
# is intentionally absent for now (no shared binary cache);
|
|
||||||
# add a step here once cache infra is decided.
|
|
||||||
- name: build smoke
|
- name: build smoke
|
||||||
if: steps.changed.outputs.packages != ''
|
if: steps.changed.outputs.packages != ''
|
||||||
run: |
|
run: |
|
||||||
@@ -79,6 +77,18 @@ jobs:
|
|||||||
.#${pkg} --no-link --print-out-paths
|
.#${pkg} --no-link --print-out-paths
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# 4b. Push the validated outputs to the binary cache. The runner's
|
||||||
|
# config.yaml bind-mounts /srv/cargoxx-cache and the signing
|
||||||
|
# key into every job container.
|
||||||
|
- name: push to binary cache
|
||||||
|
if: steps.changed.outputs.packages != ''
|
||||||
|
run: |
|
||||||
|
for pkg in ${{ steps.changed.outputs.packages }}; do
|
||||||
|
nix copy --extra-experimental-features 'nix-command flakes' \
|
||||||
|
--to "file:///srv/cargoxx-cache/store?secret-key=/srv/cargoxx-cache/keys/cache.sec" \
|
||||||
|
.#${pkg}
|
||||||
|
done
|
||||||
|
|
||||||
# 5. Maintainer check — PR must come from someone listed in
|
# 5. Maintainer check — PR must come from someone listed in
|
||||||
# recipes/<pkg>/maintainers.txt (auto-pass for new packages,
|
# recipes/<pkg>/maintainers.txt (auto-pass for new packages,
|
||||||
# since the PR introduces the file in the same commit).
|
# since the PR introduces the file in the same commit).
|
||||||
|
|||||||
8
flake.lock
generated
8
flake.lock
generated
@@ -31,11 +31,11 @@
|
|||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779128270,
|
"lastModified": 1779130481,
|
||||||
"narHash": "sha256-0ummfZJPptdxdvGvlob9viAdByvW+VFJOVDiNCvQYXE=",
|
"narHash": "sha256-RLeNukl/4X828SipqJib9sNJhSvcSy8Cck4TVZDgIkY=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "3138e78f47bbd865d55aaacda6d2a15c7b14e110",
|
"rev": "f9932a3ad9ecdcdf5ea2906f1d8698b02b8b3e30",
|
||||||
"revCount": 64,
|
"revCount": 65,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.amadey.xyz/mozart/cargoxx"
|
"url": "https://git.amadey.xyz/mozart/cargoxx"
|
||||||
},
|
},
|
||||||
|
|||||||
1
recipes/greeter/maintainers.txt
Normal file
1
recipes/greeter/maintainers.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mozart
|
||||||
17
recipes/greeter/versions/0.1.0.toml
Normal file
17
recipes/greeter/versions/0.1.0.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
schema = 1
|
||||||
|
name = "greeter"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[source]
|
||||||
|
type = "git"
|
||||||
|
url = "https://git.amadey.xyz/mozart/greeter"
|
||||||
|
commit = "7f31f3ea5f01bb03ff83705cf9295b94abb569de"
|
||||||
|
sha256 = "sha256-kOTcunYoqvVnXQOjy0C2lM99Cv4Dve7dI3y/coWaG7o="
|
||||||
|
|
||||||
|
[lock]
|
||||||
|
nixpkgs_rev = "d233902339c02a9c334e7e593de68855ad26c4cb"
|
||||||
|
flake_utils_rev = "11707dc2f618dd54ca8739b309ec4fc024de578b"
|
||||||
|
|
||||||
|
[meta]
|
||||||
|
description = "minimal cargoxx demo library — greets you"
|
||||||
|
license = "MIT"
|
||||||
17
recipes/greeter/versions/0.1.1.toml
Normal file
17
recipes/greeter/versions/0.1.1.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
schema = 1
|
||||||
|
name = "greeter"
|
||||||
|
version = "0.1.1"
|
||||||
|
|
||||||
|
[source]
|
||||||
|
type = "git"
|
||||||
|
url = "https://git.amadey.xyz/mozart/greeter"
|
||||||
|
commit = "d79a99468a158e2b37739404073dcfaab8c12308"
|
||||||
|
sha256 = "sha256-1IV9HrdYoQOFcI3bP280/CYsdmuYvuMFK9hvjdanNto="
|
||||||
|
|
||||||
|
[lock]
|
||||||
|
nixpkgs_rev = "d233902339c02a9c334e7e593de68855ad26c4cb"
|
||||||
|
flake_utils_rev = "11707dc2f618dd54ca8739b309ec4fc024de578b"
|
||||||
|
|
||||||
|
[meta]
|
||||||
|
description = "minimal cargoxx demo library — greets you"
|
||||||
|
license = "MIT"
|
||||||
8
runner/.gitignore
vendored
8
runner/.gitignore
vendored
@@ -1,3 +1,11 @@
|
|||||||
.env
|
.env
|
||||||
data/
|
data/
|
||||||
result
|
result
|
||||||
|
|
||||||
|
# Binary cache state + signing keys. The cache.sec must never be
|
||||||
|
# committed; the public key is regenerated per deployment too
|
||||||
|
# (`nix-store --generate-binary-cache-key`).
|
||||||
|
cache/
|
||||||
|
|
||||||
|
# Caddy state: ACME account + issued certs + on-disk config tree.
|
||||||
|
caddy/
|
||||||
|
|||||||
43
runner/Caddyfile
Normal file
43
runner/Caddyfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Caddy config for the cargoxx binary cache.
|
||||||
|
#
|
||||||
|
# The router does PAT (port forwarding) so the *external* world reaches
|
||||||
|
# us at the standard 80/443 but the *internal* ports are different.
|
||||||
|
# `http_port` and `https_port` below must match the internal ports the
|
||||||
|
# router forwards to. Override via runner/.env:
|
||||||
|
#
|
||||||
|
# CADDY_HTTP_PORT=8080
|
||||||
|
# CADDY_HTTPS_PORT=8443
|
||||||
|
#
|
||||||
|
# (Those env vars are picked up by compose.yml to publish the ports
|
||||||
|
# AND injected into this Caddyfile via the {$VAR:default} substitution
|
||||||
|
# below — Caddy expands env vars natively.)
|
||||||
|
{
|
||||||
|
# Internal ports — must equal whatever the router forwards 80/443 to.
|
||||||
|
http_port {$CADDY_HTTP_PORT:8080}
|
||||||
|
https_port {$CADDY_HTTPS_PORT:8443}
|
||||||
|
# ACME's HTTP-01 challenge probe still arrives at host:80 → router
|
||||||
|
# → :8080; Caddy answers it on the internal port. Auto cert works
|
||||||
|
# as long as the PAT maps 80 → CADDY_HTTP_PORT and 443 → CADDY_HTTPS_PORT.
|
||||||
|
email vorontsov@amadey.xyz
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.cargoxx.amadey.xyz {
|
||||||
|
root * /srv/cache
|
||||||
|
file_server
|
||||||
|
|
||||||
|
# narinfo / nar are immutable per content hash → cache aggressively.
|
||||||
|
@cache_immutable path *.narinfo *.nar.xz *.nar
|
||||||
|
header @cache_immutable Cache-Control "public, immutable, max-age=31536000"
|
||||||
|
|
||||||
|
# Substituter probe; short cache so new entries land quickly.
|
||||||
|
@cache_info path /nix-cache-info
|
||||||
|
header @cache_info Cache-Control "public, max-age=300"
|
||||||
|
|
||||||
|
log {
|
||||||
|
output file /data/access.log {
|
||||||
|
roll_size 50MiB
|
||||||
|
roll_keep 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,45 @@ Self-hosted Gitea Actions runner that validates package PRs.
|
|||||||
GITEA_RUNNER_LABELS=self-hosted
|
GITEA_RUNNER_LABELS=self-hosted
|
||||||
```
|
```
|
||||||
|
|
||||||
4. **Start the runner**:
|
4. **Generate the binary-cache signing key** + cache directory. The
|
||||||
|
workflow's "push to binary cache" step writes here; nginx (or
|
||||||
|
anything you point at it) serves it back over HTTPS to consumers.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir -p cache/store
|
||||||
|
nix-store --generate-binary-cache-key \
|
||||||
|
cache.cargoxx.<your-domain> \
|
||||||
|
cache/cache.sec cache/cache.pub
|
||||||
|
chmod 600 cache/cache.sec
|
||||||
|
```
|
||||||
|
|
||||||
|
The `cache/` directory is gitignored. Both keys live alongside
|
||||||
|
`compose.yml`; the named volume binds use `${PWD}/cache/...`.
|
||||||
|
|
||||||
|
5. **Pick the Caddy ports.** `compose.yml` runs Caddy alongside the
|
||||||
|
runner to HTTPS-front the cache. Because the router does PAT, the
|
||||||
|
*internal* ports Caddy listens on must equal whatever 80/443 are
|
||||||
|
forwarded to. Add to `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
CADDY_HTTP_PORT=8080
|
||||||
|
CADDY_HTTPS_PORT=8443
|
||||||
|
```
|
||||||
|
|
||||||
|
Both compose.yml and the Caddyfile pick those up. The Caddyfile
|
||||||
|
already targets `cache.cargoxx.amadey.xyz` and the e-mail
|
||||||
|
`vorontsov@amadey.xyz`; edit if you're deploying somewhere else.
|
||||||
|
|
||||||
|
ACME provisioning works as long as the router forwards 80 →
|
||||||
|
CADDY_HTTP_PORT and 443 → CADDY_HTTPS_PORT, so Let's Encrypt's
|
||||||
|
HTTP-01 challenge reaches Caddy.
|
||||||
|
|
||||||
|
Consumers' substituter config (`substituters = https://cache.<domain>`,
|
||||||
|
`trusted-public-keys = <cache.pub>`) is baked into cargoxx's own
|
||||||
|
wrapper (`cargoxx/flake.nix:cargoxxNixConfig`), so any installed
|
||||||
|
`cargoxx` binary picks them up — no per-user setup needed.
|
||||||
|
|
||||||
|
6. **Start the runner**:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
# Runs the act_runner that listens to Gitea and spawns one job
|
# Runs two services on the host:
|
||||||
# container per workflow run. The job image (cargoxx-runner-job:latest)
|
# - act_runner — polls Gitea, spawns one job container per workflow
|
||||||
# is built reproducibly from runner/flake.nix — run `nix run .#load-image`
|
# run via the host docker socket. Job image built reproducibly from
|
||||||
# in this directory to load it into the host's Docker daemon before
|
# runner/flake.nix (`nix run .#load-image`).
|
||||||
# starting the runner.
|
# - caddy — HTTPS-fronts the binary cache (./cache/store) so
|
||||||
version: "3.8"
|
# consumers' substituter config can read it. Custom ports because
|
||||||
|
# the router does PAT (port-forwarding 80→CADDY_HTTP_PORT,
|
||||||
|
# 443→CADDY_HTTPS_PORT). Set those in .env.
|
||||||
services:
|
services:
|
||||||
runner:
|
runner:
|
||||||
image: docker.io/gitea/act_runner:nightly
|
image: docker.io/gitea/act_runner:nightly
|
||||||
@@ -18,3 +20,59 @@ services:
|
|||||||
- ./config.yaml:/config.yaml:ro
|
- ./config.yaml:/config.yaml:ro
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# Binary cache — `validate-pr.yml`'s push step writes `$out` NAR
|
||||||
|
# archives here. Named volumes (defined below) make the same
|
||||||
|
# storage reachable from this runner container AND every job
|
||||||
|
# container act_runner spawns AND the caddy frontend below.
|
||||||
|
- cargoxx-cache-store:/srv/cargoxx-cache/store
|
||||||
|
- cargoxx-cache-keys:/srv/cargoxx-cache/keys:ro
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: docker.io/caddy:2
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${CADDY_HTTP_PORT:-8080}:${CADDY_HTTP_PORT:-8080}"
|
||||||
|
- "${CADDY_HTTPS_PORT:-8443}:${CADDY_HTTPS_PORT:-8443}"
|
||||||
|
environment:
|
||||||
|
CADDY_HTTP_PORT: "${CADDY_HTTP_PORT:-8080}"
|
||||||
|
CADDY_HTTPS_PORT: "${CADDY_HTTPS_PORT:-8443}"
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
|
- cargoxx-cache-store:/srv/cache:ro
|
||||||
|
- caddy-data:/data
|
||||||
|
- caddy-config:/config
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
cargoxx-cache-store:
|
||||||
|
# Explicit name disables compose's project-prefix so spawned job
|
||||||
|
# containers (which don't know about compose) can reference the
|
||||||
|
# same volume by the same name.
|
||||||
|
name: cargoxx-cache-store
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: "${PWD}/cache/store"
|
||||||
|
cargoxx-cache-keys:
|
||||||
|
name: cargoxx-cache-keys
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: "${PWD}/cache/keys"
|
||||||
|
caddy-data:
|
||||||
|
# Caddy's own state: ACME account, issued certificates, OCSP
|
||||||
|
# staples. Persist so we don't re-issue certs every restart.
|
||||||
|
name: caddy-data
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: "${PWD}/caddy/data"
|
||||||
|
caddy-config:
|
||||||
|
name: caddy-config
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: "${PWD}/caddy/config"
|
||||||
|
|||||||
@@ -18,9 +18,19 @@ cache:
|
|||||||
container:
|
container:
|
||||||
network: bridge
|
network: bridge
|
||||||
privileged: false
|
privileged: false
|
||||||
options: ""
|
# Bind the binary cache into every job container by referencing the
|
||||||
|
# named volumes defined in compose.yml — those, in turn, are bound
|
||||||
|
# to ./cache/{store,cache.sec} via `${PWD}` so the path is
|
||||||
|
# deployment-relative, not absolute.
|
||||||
|
options: "-v cargoxx-cache-store:/srv/cargoxx-cache/store
|
||||||
|
-v cargoxx-cache-keys:/srv/cargoxx-cache/keys:ro"
|
||||||
workdir_parent: /workspace
|
workdir_parent: /workspace
|
||||||
valid_volumes: []
|
# Whitelist regex of bind specs act_runner forwards to spawned job
|
||||||
|
# containers. The regex matches the full `source:target[:opts]`
|
||||||
|
# string, so a permissive prefix is enough.
|
||||||
|
valid_volumes:
|
||||||
|
- "cargoxx-cache-store"
|
||||||
|
- "cargoxx-cache-keys"
|
||||||
docker_host: "unix:///var/run/docker.sock"
|
docker_host: "unix:///var/run/docker.sock"
|
||||||
force_pull: false
|
force_pull: false
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user