Compare commits
4 changed files with 6 additions and 173 deletions
|
|
@ -213,31 +213,13 @@ transient.
|
||||||
|
|
||||||
The hive-c0re-owned repo at `/var/lib/hyperhive/meta/`
|
The hive-c0re-owned repo at `/var/lib/hyperhive/meta/`
|
||||||
declares one flake input per agent (`agent-<n>.url =
|
declares one flake input per agent (`agent-<n>.url =
|
||||||
"git+http://<forge>/agent-configs/<n>.git"`) and one
|
"git+file:///var/lib/hyperhive/applied/<n>"`) and one
|
||||||
`nixosConfigurations.<n>` output per agent. Each output wraps
|
`nixosConfigurations.<n>` output per agent. Each output wraps
|
||||||
`inputs.agent-<n>.nixosModules.default` with the identity +
|
`inputs.agent-<n>.nixosModules.default` with the identity +
|
||||||
`HIVE_PORT` / `HIVE_LABEL` / `HIVE_DASHBOARD_PORT` injection
|
`HIVE_PORT` / `HIVE_LABEL` / `HIVE_DASHBOARD_PORT` injection
|
||||||
module that `setup_applied` used to generate inline.
|
module that `setup_applied` used to generate inline.
|
||||||
Containers run against `--flake /var/lib/hyperhive/meta#<n>`.
|
Containers run against `--flake /var/lib/hyperhive/meta#<n>`.
|
||||||
|
|
||||||
The declared input url is the agent's **forge config repo** (the
|
|
||||||
same `agent-configs/<n>` the config-PR flow lands approved changes
|
|
||||||
on), so the meta flake references a reviewable, reproducible source
|
|
||||||
rather than a local checkout. hive-c0re authenticates that
|
|
||||||
`git+http` fetch via a git credential helper that reads the live
|
|
||||||
forge-core token — no token in the url or the lock. The deploy and
|
|
||||||
manual-rebuild paths, however, do **not** re-lock from the forge:
|
|
||||||
they `--override-input agent-<n>
|
|
||||||
git+file:///var/lib/hyperhive/applied/<n>`, locking the exact config
|
|
||||||
that `verify_commit` gated and `applied/<n>/main` was
|
|
||||||
fast-forwarded to. That keeps a deploy/rebuild reproducible and
|
|
||||||
independent of forge reachability — rebuilds fire on crash-restart
|
|
||||||
and meta bumps, not just config PRs — while the declared url stays
|
|
||||||
the forge. `sync_agents` re-renders + re-locks the persistent input;
|
|
||||||
a plain `nix flake lock` leaves an existing applied override in
|
|
||||||
place (it only re-locks when the declared url itself changes), so
|
|
||||||
the forge-declared / applied-deployed split is stable.
|
|
||||||
|
|
||||||
Per-deploy lock flow (two-phase, owned by
|
Per-deploy lock flow (two-phase, owned by
|
||||||
`actions::run_merge_config_pr` → `deploy_applied_target` →
|
`actions::run_merge_config_pr` → `deploy_applied_target` →
|
||||||
`meta::{prepare,finalize,abort}_deploy`):
|
`meta::{prepare,finalize,abort}_deploy`):
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,6 @@ Two things live in the `agent-configs` Forgejo organization:
|
||||||
approved history, the `failed/<id>` tag records the divergence).
|
approved history, the `failed/<id>` tag records the divergence).
|
||||||
Repos stay private, so an agent can't read another
|
Repos stay private, so an agent can't read another
|
||||||
agent's config. (Agents remain read-only collaborators on `core/meta`.)
|
agent's config. (Agents remain read-only collaborators on `core/meta`.)
|
||||||
hive-c0re also references this repo as the agent's **persistent meta
|
|
||||||
flake input** (`agent-<n>.url = git+http://<forge>/agent-configs/<n>.git`;
|
|
||||||
see [approvals.md § Meta flake](approvals.md)), fetching it as the `core`
|
|
||||||
user via a git credential helper that reads the live forge-core token —
|
|
||||||
so the config lives on the forge, not a hand-synced local checkout.
|
|
||||||
- The dashboard links each container's "config" anchor to this
|
- The dashboard links each container's "config" anchor to this
|
||||||
config repo, so operators can click straight from the SW4RM tab into
|
config repo, so operators can click straight from the SW4RM tab into
|
||||||
the rendered repo without an extra `git` step.
|
the rendered repo without an extra `git` step.
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ pub async fn sync_agents(hive: &HiveEnv, agents: &[AgentSpec]) -> Result<()> {
|
||||||
&hive.operator_pronouns,
|
&hive.operator_pronouns,
|
||||||
&hive.context_window_tokens,
|
&hive.context_window_tokens,
|
||||||
agents,
|
agents,
|
||||||
crate::forge::forge_http_base(),
|
|
||||||
);
|
);
|
||||||
let flake_path = dir.join("flake.nix");
|
let flake_path = dir.join("flake.nix");
|
||||||
let on_disk = std::fs::read_to_string(&flake_path).unwrap_or_default();
|
let on_disk = std::fs::read_to_string(&flake_path).unwrap_or_default();
|
||||||
|
|
@ -239,29 +238,7 @@ pub async fn prepare_deploy(name: &str) -> Result<()> {
|
||||||
let _guard = META_LOCK.lock().await;
|
let _guard = META_LOCK.lock().await;
|
||||||
let dir = crate::paths::meta_root();
|
let dir = crate::paths::meta_root();
|
||||||
let input = format!("agent-{name}");
|
let input = format!("agent-{name}");
|
||||||
// Re-lock the agent input against the LOCAL applied mirror, not the
|
nix_logged(&dir, &["flake", "update", &input], name, "prepare-deploy").await?;
|
||||||
// persistent forge URL declared in the meta flake (see the `## Meta flake`
|
|
||||||
// note in docs/approvals.md): the deploy must build the exact reviewed
|
|
||||||
// config that `verify_commit` gated and `applied/<n>/main` was
|
|
||||||
// fast-forwarded to, and it must keep working when the forge is
|
|
||||||
// unreachable (rebuilds fire on crash-restart / meta bumps too, not just
|
|
||||||
// config PRs). `--override-input` writes the applied rev into the lock;
|
|
||||||
// the forge URL stays the declared, reviewable source of truth.
|
|
||||||
let applied = applied_override_url(&crate::paths::applied_dir(name));
|
|
||||||
nix_logged(
|
|
||||||
&dir,
|
|
||||||
&[
|
|
||||||
"flake",
|
|
||||||
"update",
|
|
||||||
&input,
|
|
||||||
"--override-input",
|
|
||||||
&input,
|
|
||||||
&applied,
|
|
||||||
],
|
|
||||||
name,
|
|
||||||
"prepare-deploy",
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
// Stage the new lock — git+file://'s dirty-tree fetcher reads
|
// Stage the new lock — git+file://'s dirty-tree fetcher reads
|
||||||
// index entries, so the upcoming nixos-container update sees the
|
// index entries, so the upcoming nixos-container update sees the
|
||||||
// bumped rev without a commit yet.
|
// bumped rev without a commit yet.
|
||||||
|
|
@ -304,22 +281,7 @@ pub async fn lock_update_for_rebuild(name: &str) -> Result<()> {
|
||||||
let _guard = META_LOCK.lock().await;
|
let _guard = META_LOCK.lock().await;
|
||||||
let dir = crate::paths::meta_root();
|
let dir = crate::paths::meta_root();
|
||||||
let input = format!("agent-{name}");
|
let input = format!("agent-{name}");
|
||||||
// Re-lock from the local applied mirror, not the persistent forge URL —
|
nix(&dir, &["flake", "update", &input]).await?;
|
||||||
// same rationale as `prepare_deploy`: build exactly `applied/<n>/main` and
|
|
||||||
// stay reproducible when the forge is unreachable.
|
|
||||||
let applied = applied_override_url(&crate::paths::applied_dir(name));
|
|
||||||
nix(
|
|
||||||
&dir,
|
|
||||||
&[
|
|
||||||
"flake",
|
|
||||||
"update",
|
|
||||||
&input,
|
|
||||||
"--override-input",
|
|
||||||
&input,
|
|
||||||
&applied,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
if !paths_dirty(&dir, &["flake.lock"]).await? {
|
if !paths_dirty(&dir, &["flake.lock"]).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
@ -339,17 +301,6 @@ fn agent_input_override(applied_dir: &Path, sha: &str) -> String {
|
||||||
format!("git+file://{}?rev={sha}", applied_dir.display())
|
format!("git+file://{}?rev={sha}", applied_dir.display())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `--override-input` URL re-locking an agent's config input against its
|
|
||||||
/// LOCAL applied mirror (`git+file://<applied_dir>`, current `main` head)
|
|
||||||
/// instead of the persistent forge URL declared in the meta flake. The
|
|
||||||
/// deploy + rebuild paths re-lock from here: the applied tree was already
|
|
||||||
/// fast-forwarded to the reviewed head, so this builds exactly that config
|
|
||||||
/// and stays reproducible when the forge is unreachable. No `?rev` — `main`
|
|
||||||
/// head is the reviewed head at deploy time. Pure so it's unit-testable.
|
|
||||||
fn applied_override_url(applied_dir: &Path) -> String {
|
|
||||||
format!("git+file://{}", applied_dir.display())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Non-mutating "would this commit apply?" verify for the PR-based config
|
/// Non-mutating "would this commit apply?" verify for the PR-based config
|
||||||
/// flow. Evaluates the agent's nixos configuration with its meta
|
/// flow. Evaluates the agent's nixos configuration with its meta
|
||||||
/// input overridden to the exact `sha`, WITHOUT moving `applied/main` or
|
/// input overridden to the exact `sha`, WITHOUT moving `applied/main` or
|
||||||
|
|
@ -635,11 +586,6 @@ pub async fn bulk_commit_topology(
|
||||||
Ok(changed)
|
Ok(changed)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(
|
|
||||||
clippy::too_many_arguments,
|
|
||||||
reason = "many genuine flake inputs (source flakes, port, pronouns, tokens, \
|
|
||||||
agents, forge base); a params struct would just move the same fields"
|
|
||||||
)]
|
|
||||||
fn render_flake(
|
fn render_flake(
|
||||||
hyperhive_flake: &str,
|
hyperhive_flake: &str,
|
||||||
docs_flake: &str,
|
docs_flake: &str,
|
||||||
|
|
@ -648,7 +594,6 @@ fn render_flake(
|
||||||
operator_pronouns: &str,
|
operator_pronouns: &str,
|
||||||
context_window_tokens: &std::collections::HashMap<String, u64>,
|
context_window_tokens: &std::collections::HashMap<String, u64>,
|
||||||
agents: &[AgentSpec],
|
agents: &[AgentSpec],
|
||||||
forge_base: &str,
|
|
||||||
) -> String {
|
) -> String {
|
||||||
render_flake_with_lookup(
|
render_flake_with_lookup(
|
||||||
hyperhive_flake,
|
hyperhive_flake,
|
||||||
|
|
@ -658,7 +603,6 @@ fn render_flake(
|
||||||
operator_pronouns,
|
operator_pronouns,
|
||||||
context_window_tokens,
|
context_window_tokens,
|
||||||
agents,
|
agents,
|
||||||
forge_base,
|
|
||||||
agent_canonical_inputs,
|
agent_canonical_inputs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -935,7 +879,6 @@ fn render_flake_with_lookup<F>(
|
||||||
operator_pronouns: &str,
|
operator_pronouns: &str,
|
||||||
context_window_tokens: &std::collections::HashMap<String, u64>,
|
context_window_tokens: &std::collections::HashMap<String, u64>,
|
||||||
agents: &[AgentSpec],
|
agents: &[AgentSpec],
|
||||||
forge_base: &str,
|
|
||||||
lookup: F,
|
lookup: F,
|
||||||
) -> String
|
) -> String
|
||||||
where
|
where
|
||||||
|
|
@ -980,19 +923,12 @@ where
|
||||||
let _ = writeln!(out, " hyperhive-docs.url = \"{docs_flake}\";");
|
let _ = writeln!(out, " hyperhive-docs.url = \"{docs_flake}\";");
|
||||||
out.push_str(" hyperhive-docs.flake = false;\n");
|
out.push_str(" hyperhive-docs.flake = false;\n");
|
||||||
}
|
}
|
||||||
// Each agent's *persistent* config input is its canonical repo on the
|
|
||||||
// forge (`git+{forge_base}/agent-configs/<name>.git`, `forge_base` supplied
|
|
||||||
// by the caller from `HIVE_FORGE_URL`), authenticated by hive-core's git
|
|
||||||
// credential helper (which reads the live `forge-core-token` — no token in
|
|
||||||
// the URL or lock). The deploy re-lock + `verify_commit` eval keep pinning
|
|
||||||
// the local `applied/<name>` override (`agent_input_override`), so a deploy
|
|
||||||
// never does a network fetch — only the persistent input tracks the forge.
|
|
||||||
for spec in agents {
|
for spec in agents {
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
out,
|
out,
|
||||||
" agent-{name}.url = \"git+{forge_base}/{org}/{name}.git\";",
|
" agent-{}.url = \"git+file://{}\";",
|
||||||
name = spec.name,
|
spec.name,
|
||||||
org = crate::forge::CONFIG_ORG,
|
crate::paths::applied_dir(&spec.name).display(),
|
||||||
);
|
);
|
||||||
// For each canonical input the agent declares in its own
|
// For each canonical input the agent declares in its own
|
||||||
// `flake.nix` (detected by reading its applied `flake.lock`),
|
// `flake.nix` (detected by reading its applied `flake.lock`),
|
||||||
|
|
@ -1514,20 +1450,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn applied_override_url_targets_local_mirror_main_head() {
|
|
||||||
// Deploy + rebuild re-lock against the local applied mirror's `main`
|
|
||||||
// head (no `?rev`), never the persistent forge URL — so a rebuild
|
|
||||||
// survives forge unreachability and builds the fast-forwarded config.
|
|
||||||
let p = Path::new("/var/lib/hyperhive/agents/iris/applied");
|
|
||||||
let url = applied_override_url(p);
|
|
||||||
assert_eq!(url, "git+file:///var/lib/hyperhive/agents/iris/applied");
|
|
||||||
assert!(
|
|
||||||
!url.contains("?rev="),
|
|
||||||
"must lock main head, not a pinned rev: {url}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn render_flake_uses_explicit_nixpkgs_url_when_provided() {
|
fn render_flake_uses_explicit_nixpkgs_url_when_provided() {
|
||||||
let out = render_flake(
|
let out = render_flake(
|
||||||
|
|
@ -1538,7 +1460,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
);
|
);
|
||||||
// nixpkgs is a top-level input with an explicit URL; hyperhive
|
// nixpkgs is a top-level input with an explicit URL; hyperhive
|
||||||
// follows it.
|
// follows it.
|
||||||
|
|
@ -1582,7 +1503,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!out.contains("hyperhive-docs"),
|
!out.contains("hyperhive-docs"),
|
||||||
|
|
@ -1602,7 +1522,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
out.contains("nixpkgs.follows = \"hyperhive/nixpkgs\""),
|
out.contains("nixpkgs.follows = \"hyperhive/nixpkgs\""),
|
||||||
|
|
@ -1636,7 +1555,6 @@ mod tests {
|
||||||
sample_spec("bitburner", false, 9002),
|
sample_spec("bitburner", false, 9002),
|
||||||
sample_spec("dmatrix", false, 9003),
|
sample_spec("dmatrix", false, 9003),
|
||||||
],
|
],
|
||||||
"http://forge.test",
|
|
||||||
lookup,
|
lookup,
|
||||||
);
|
);
|
||||||
// bitburner declares nixpkgs → follows emitted.
|
// bitburner declares nixpkgs → follows emitted.
|
||||||
|
|
@ -1665,7 +1583,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
|_| Vec::new(),
|
|_| Vec::new(),
|
||||||
);
|
);
|
||||||
// No agent-side follows when the lookup reports nothing
|
// No agent-side follows when the lookup reports nothing
|
||||||
|
|
@ -1700,7 +1617,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
);
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
std::env::remove_var("HIVE_FORGE_URL");
|
std::env::remove_var("HIVE_FORGE_URL");
|
||||||
|
|
@ -1723,36 +1639,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_flake_agent_input_points_at_forge_config_repo() {
|
|
||||||
// The persistent agent config input must reference the canonical
|
|
||||||
// repo on the forge (git+http, org `agent-configs`), NOT the local
|
|
||||||
// `applied/<n>` checkout — that's what lets the config live on the
|
|
||||||
// forge instead of a hand-synced local copy. Auth is out-of-band via
|
|
||||||
// hive-core's git credential helper, so no creds appear in the URL.
|
|
||||||
// `forge_base` is an explicit param now, so no env mutation is needed.
|
|
||||||
let out = render_flake(
|
|
||||||
"github:example/hyperhive",
|
|
||||||
"path:/nix/store/bbbb-hyperhive-docs-source",
|
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
|
||||||
8000,
|
|
||||||
"she/her",
|
|
||||||
&std::collections::HashMap::new(),
|
|
||||||
&[sample_spec("alice", false, 9001)],
|
|
||||||
"http://forge.example.test",
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
out.contains(
|
|
||||||
"agent-alice.url = \"git+http://forge.example.test/agent-configs/alice.git\""
|
|
||||||
),
|
|
||||||
"expected the agent input to point at the forge config repo:\n{out}"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
!out.contains("agent-alice.url = \"git+file://"),
|
|
||||||
"the local applied/<n> path must no longer be the persistent input:\n{out}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn render_flake_embeds_hive_ca_when_signalled() {
|
fn render_flake_embeds_hive_ca_when_signalled() {
|
||||||
// When hive-tls.nix signals a self-signed hive CA via
|
// When hive-tls.nix signals a self-signed hive CA via
|
||||||
|
|
@ -1779,7 +1665,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1862,7 +1747,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -1947,7 +1831,6 @@ mod tests {
|
||||||
"she/her",
|
"she/her",
|
||||||
&std::collections::HashMap::new(),
|
&std::collections::HashMap::new(),
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", false, 9001)],
|
||||||
"http://forge.test",
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
||||||
|
|
@ -21,33 +21,9 @@ let
|
||||||
# only satisfies the ownership guard. libgit2 honours the literal `*`
|
# only satisfies the ownership guard. libgit2 honours the literal `*`
|
||||||
# (mid-path globs aren't supported, so per-agent repos can't be listed);
|
# (mid-path globs aren't supported, so per-agent repos can't be listed);
|
||||||
# in practice these processes only ever touch hyperhive's own repos.
|
# in practice these processes only ever touch hyperhive's own repos.
|
||||||
#
|
|
||||||
# The agent config inputs now live on the forge
|
|
||||||
# (`git+http://${forge.domain}/agent-configs/<n>.git`, see meta.rs render),
|
|
||||||
# so hive-core's `nix flake update` of those inputs is an authenticated
|
|
||||||
# `git+http` fetch. The `[credential]` stanza points git at the `hive-forge`
|
|
||||||
# helper below (scoped to the forge host) so the fetch authenticates as the
|
|
||||||
# forge `core` user with no token in any URL or lock.
|
|
||||||
safeDirGitconfig = pkgs.writeText "hyperhive-safe-gitconfig" ''
|
safeDirGitconfig = pkgs.writeText "hyperhive-safe-gitconfig" ''
|
||||||
[safe]
|
[safe]
|
||||||
directory = *
|
directory = *
|
||||||
[credential "http://${config.services.hyperhive.forge.domain}"]
|
|
||||||
helper = hive-forge
|
|
||||||
username = core
|
|
||||||
'';
|
|
||||||
|
|
||||||
# git credential helper for hive-core's authenticated fetches of the
|
|
||||||
# agent-config repos on the forge. Reads the live forge-core admin token
|
|
||||||
# (`/var/lib/hyperhive/forge-core-token` — paths.rs `FORGE_CORE_TOKEN`) on
|
|
||||||
# every invocation, so it never holds a stale copy and survives token
|
|
||||||
# rotation. Scoped to the forge host by the `[credential]` stanza above;
|
|
||||||
# implements the git credential-helper protocol (only `get` answers).
|
|
||||||
forgeCredHelper = pkgs.writeShellScriptBin "git-credential-hive-forge" ''
|
|
||||||
[ "''${1:-}" = "get" ] || exit 0
|
|
||||||
if [ -r /var/lib/hyperhive/forge-core-token ]; then
|
|
||||||
printf 'username=core\n'
|
|
||||||
printf 'password=%s\n' "$(cat /var/lib/hyperhive/forge-core-token)"
|
|
||||||
fi
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# The `hive-c0re serve` config JSON. Keys are snake_case to match the
|
# The `hive-c0re serve` config JSON. Keys are snake_case to match the
|
||||||
|
|
@ -140,9 +116,6 @@ in
|
||||||
after = [ "hive-c0re.socket" ];
|
after = [ "hive-c0re.socket" ];
|
||||||
path = [
|
path = [
|
||||||
pkgs.git
|
pkgs.git
|
||||||
# `git-credential-hive-forge` on PATH so git finds it when nix fetches
|
|
||||||
# the forge-hosted agent-config inputs (helper = hive-forge).
|
|
||||||
forgeCredHelper
|
|
||||||
"/run/current-system/sw"
|
"/run/current-system/sw"
|
||||||
];
|
];
|
||||||
environment = import ./environment.nix { inherit lib config pkgs; };
|
environment = import ./environment.nix { inherit lib config pkgs; };
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue