feat(nix): swarm-controller systemd unit, service user and socket
services.hyperhive.swarm.controller.{enable,package,socketPath} plus the
unprivileged swarm-controller user, its runtime and state directories,
and the unit itself.
enable is deliberately not derived from services.hyperhive.enable, unlike
c0re: a swarm has one controller, so turning it on is a statement about
swarm topology rather than about whether hyperhive is installed.
The socket gets its own RuntimeDirectory. nginx reaches a unix upstream
by having the socket's directory bind-mounted into the gateway
container, and the socket is 0666 because connect needs write -- so the
directory is the only access control there is. Sharing one with the host
admin socket would hand that socket to the gateway too. The constraint
is stated at both ends, in the option description and beside the bind,
because it is invisible from either site alone; a test pins the path so
a tidying edit fails rather than reviews cleanly.
RuntimeDirectoryPreserve and the daemon's stale-socket unlink are a
pair: preserving the directory without the unlink means bind fails with
EADDRINUSE after a restart.
This commit is contained in:
parent
f10f8a6bc6
commit
435dfbfb33
4 changed files with 149 additions and 0 deletions
|
|
@ -87,3 +87,31 @@ async fn main() -> Result<()> {
|
|||
.await
|
||||
.context("serving swarm-controller")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::DEFAULT_SOCKET;
|
||||
use std::path::Path;
|
||||
|
||||
/// The socket must not share a directory with anything else, because
|
||||
/// the socket is `0666` and the directory is therefore the only access
|
||||
/// control it has. `/run/hyperhive` in particular holds hive-c0re's
|
||||
/// **admin** socket, and nginx reaches a unix upstream by mounting the
|
||||
/// socket's whole directory into the gateway container.
|
||||
///
|
||||
/// A test rather than a comment: the failure this guards against is a
|
||||
/// one-word edit that looks tidier and reads fine in review.
|
||||
#[test]
|
||||
fn socket_lives_in_its_own_runtime_dir() {
|
||||
let parent = Path::new(DEFAULT_SOCKET)
|
||||
.parent()
|
||||
.expect("socket path has a parent directory");
|
||||
assert_eq!(
|
||||
parent,
|
||||
Path::new("/run/swarm-controller"),
|
||||
"the socket's directory is its access control — moving it under a shared \
|
||||
directory (notably /run/hyperhive, which holds the host admin socket) \
|
||||
exposes everything else in that directory to the gateway container"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue