Add Docker and Nix packaging for the node
server/docker/: multi-stage image (rust:1-slim build, trixie runtime) with all four binaries plus the pinned yggdrasil 0.5.14 .deb (sha256-verified, fetched from the official release), a compose example per household (host network, NET_ADMIN, /dev/net/tun, init: true), a German-commented node.toml.example (safe default: leech mode) and a README covering privileges, two-household wiring, leech mode and the kill switch. Image build and smoke tests verified locally with docker 29.8.1. flake.nix: builds the workspace as one spidernet package via rustPlatform.buildRustPackage (cargoLock against the committed Cargo.lock) plus an experimental NixOS module; written without a local Nix and marked accordingly.
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
# SpiderNet Nix flake — builds the Rust workspace in server/ and exposes
|
||||
# one `spidernet` package containing all four binaries (sn-node, sn-exit,
|
||||
# sn-fetch, sn-fair) in $out/bin, plus an experimental NixOS module.
|
||||
#
|
||||
# NO WARRANTY — SpiderNet is provided "as is" without warranty of any kind
|
||||
# (AGPL-3.0, sections 15/16). Use is entirely at the operator's own
|
||||
# responsibility.
|
||||
#
|
||||
# !!! NOT VERIFIED ON THIS MACHINE !!!
|
||||
# Nix is not installed in the environment where this flake was written.
|
||||
# `nix flake check` and `nix build` have NOT been run — treat everything
|
||||
# below as best-effort and report build failures as issues.
|
||||
#
|
||||
# Usage (once Nix >= 2.19 is installed):
|
||||
# nix build . # -> result/bin/{sn-node,sn-exit,...}
|
||||
# nix shell .# -c sn-fair --capacity 100 --participant 1=contributing
|
||||
#
|
||||
# The nixpkgs input is pinned to the current stable NixOS release branch
|
||||
# (nixos-26.05, released 2026-05-30; nixos-25.11 is already deprecated).
|
||||
|
||||
{
|
||||
description =
|
||||
"SpiderNet: pooled-bandwidth neighborhood network node software";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ self, nixpkgs }:
|
||||
let
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
forAllSystems = nixpkgs.lib.genAttrs systems;
|
||||
in
|
||||
{
|
||||
packages = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (pkgs) lib;
|
||||
|
||||
# Only the files cargo needs; keeps target/, docs and any other
|
||||
# clutter out of the Nix store hash.
|
||||
src = lib.cleanSourceWith {
|
||||
src = lib.cleanSource ./server;
|
||||
filter =
|
||||
path: type:
|
||||
# Prune cargo build dirs entirely.
|
||||
!(type == "directory" && lib.hasSuffix "/target" path)
|
||||
&& (
|
||||
type == "directory"
|
||||
|| lib.hasSuffix ".rs" path
|
||||
|| lib.hasSuffix ".toml" path
|
||||
|| lib.hasSuffix ".lock" path
|
||||
);
|
||||
};
|
||||
|
||||
spidernet = pkgs.rustPlatform.buildRustPackage {
|
||||
pname = "spidernet";
|
||||
version = "0.1.0";
|
||||
|
||||
inherit src;
|
||||
cargoLock.lockFile = ./server/Cargo.lock;
|
||||
|
||||
# Integration tests talk to real servers; skip them when
|
||||
# packaging. Run `cargo test` inside server/ for development.
|
||||
doCheck = false;
|
||||
|
||||
meta = {
|
||||
description =
|
||||
"SpiderNet node software (sn-node, sn-exit, sn-fetch, sn-fair)";
|
||||
longDescription = ''
|
||||
SpiderNet pools the bandwidth of household internet
|
||||
connections over a neighborhood mesh (Yggdrasil overlay).
|
||||
NO WARRANTY — AGPL-3.0, sections 15/16.
|
||||
'';
|
||||
license = lib.licenses.agpl3Only;
|
||||
mainProgram = "sn-node";
|
||||
platforms = lib.platforms.unix;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit spidernet;
|
||||
default = spidernet;
|
||||
}
|
||||
);
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# EXPERIMENTAL NixOS module — never built or activated anywhere.
|
||||
# Runs `sn-node daemon` (which manages the yggdrasil sidecar) as a
|
||||
# hardened systemd service.
|
||||
#
|
||||
# Usage example (in a NixOS configuration that imports this flake):
|
||||
#
|
||||
# imports = [ spidernet.nixosModules.default ];
|
||||
#
|
||||
# services.spidernet = {
|
||||
# enable = true;
|
||||
# configFile = "/etc/spidernet/node.toml";
|
||||
# # stateDir defaults to "spidernet" -> /var/lib/spidernet,
|
||||
# # which the example config uses as state_dir.
|
||||
# };
|
||||
#
|
||||
# The config file must set state_dir = "/var/lib/spidernet" (or
|
||||
# leave the default and rely on WorkingDirectory below).
|
||||
# ------------------------------------------------------------------
|
||||
nixosModules.default =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.spidernet;
|
||||
in
|
||||
{
|
||||
options.services.spidernet = {
|
||||
enable = lib.mkEnableOption "SpiderNet node daemon (sn-node)";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
# The flake package of the evaluating system; can be
|
||||
# overridden with any build of spidernet.
|
||||
default = self.packages.${pkgs.system}.default;
|
||||
defaultText = lib.literalExpression "spidernet.packages.\${pkgs.system}.default";
|
||||
description = "SpiderNet package to run (contains sn-node etc.).";
|
||||
};
|
||||
|
||||
configFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
Path to the node.toml config file read by
|
||||
`sn-node daemon --config`.
|
||||
'';
|
||||
};
|
||||
|
||||
stateDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "spidernet";
|
||||
description = ''
|
||||
State directory (systemd StateDirectory), holding node.key
|
||||
and the generated yggdrasil.conf. Created as
|
||||
/var/lib/<stateDir>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.spidernet = {
|
||||
description = "SpiderNet node (Yggdrasil overlay, optional exit)";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
|
||||
# The daemon spawns yggdrasil (manage = true by default).
|
||||
path = [ pkgs.yggdrasil ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
"${lib.getExe cfg.package} daemon --config ${cfg.configFile}";
|
||||
StateDirectory = cfg.stateDir;
|
||||
WorkingDirectory = "/var/lib/${cfg.stateDir}";
|
||||
|
||||
# TUN setup requires CAP_NET_ADMIN; nothing more.
|
||||
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
||||
DeviceAllow = [
|
||||
"/dev/net/tun rw"
|
||||
# Yggdrasil TUN devices are created at runtime.
|
||||
"char-tun rwm"
|
||||
];
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
# State dir must stay writable.
|
||||
ReadWritePaths = [ "/var/lib/${cfg.stateDir}" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user