This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1{ 2 config, 3 pkgs, 4 ... 5}: 6# Per-machine Radicle identity and node for day-to-day development 7# (rad clone/push/patch), as opposed to the public seed in ./radicle.lassul.us.nix. 8# 9# One radicle-node = one keypair = one Node ID; a node cannot serve several 10# identities. So every machine gets its own key (generator `rad`) and hence 11# its own DID, and repos that should accept pushes from all machines list each 12# machine's DID as a delegate (`rad id update --delegate did:key:<nid>`). 13# 14# Radicle has no multi-user mode: the `rad` CLI and git-remote-rad write into 15# the profile's storage themselves, signing with the key in keys/radicle. To 16# make one identity usable by several accounts the profile lives outside any 17# home, in /var/lib/rad, group-shared: the node runs as the `rad` system user, 18# everything is setgid `rad` with group rwx, and the CLI/remote-helper wrappers 19# below force umask 002 so files one side creates stay writable for the other. 20# RAD_HOME points there for login shells; membership in `rad` is what grants 21# use of the identity (mainUser is a member, add others per machine). 22# Keys and config.json are symlinks into the clan vars secret dir / nix store, 23# maintained by tmpfiles; storage and the control socket are ordinary state. 24# 25# The node only dials out (no listen address): the laptops sit behind NAT and 26# the public seed neoprism relays for them, so nothing needs a port opened. 27let 28 generator = config.clan.core.vars.generators.rad; 29 radHome = "/var/lib/rad"; 30 31 settings = { 32 publicExplorer = "https://app.radicle.xyz/nodes/$host/$rid$path"; 33 preferredSeeds = [ 34 # our own seed (2configs/radicle.lassul.us.nix on neoprism) 35 "z6MkhTe9WWbqNdRAnWLHxL23gedRQWdhjajRbNAt5fCpae6o@radicle.lassul.us:8776" 36 "z6MkrLMMsiPWUcNPHcRajuMi9mDfYckSoJyPwwnknocNYPm7@seed.radicle.xyz:8776" 37 "z6Mkmqogy2qEM2ummccUthFEaaHvyYmYBYh3dbe9W4ebScxo@iris.radicle.network:8776" 38 ]; 39 cli.hints = true; 40 node = { 41 alias = config.networking.hostName; 42 listen = [ ]; 43 network = "main"; 44 log = "INFO"; 45 relay = "auto"; 46 # Only seed what this machine explicitly initialised, cloned or `rad seed`ed. 47 seedingPolicy.default = "block"; 48 }; 49 }; 50 51 # Validate with `rad config` at build time (same trick as the nixpkgs seed 52 # module) so a typo does not leave every machine's node crash-looping. 53 configFile = 54 pkgs.runCommand "rad-config.json" 55 { 56 nativeBuildInputs = [ pkgs.buildPackages.radicle-node ]; 57 json = builtins.toJSON settings; 58 passAsFile = [ "json" ]; 59 preferLocalBuild = true; 60 } 61 '' 62 install -D -m 644 "$jsonPath" $out 63 ln -s $out config.json 64 install -D -m 644 /dev/stdin keys/radicle.pub <<<"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBgFMhajUng+Rjj/sCFXI9PzG8BQjru2n7JgUVF1Kbv5 snakeoil" 65 RAD_HOME=$PWD rad config >/dev/null 66 ''; 67 68 # `rad` and `git-remote-rad` (what git runs for rad:// remotes) forced to 69 # umask 002; first in the join so they shadow the plain radicle-node ones. 70 wrap = 71 bin: 72 pkgs.writeShellScriptBin bin '' 73 # ${radHome} is shared with the rad-node service via group rad. 74 umask 002 75 exec ${pkgs.radicle-node}/bin/${bin} "$@" 76 ''; 77 radicle-shared = pkgs.symlinkJoin { 78 name = "radicle-shared"; 79 paths = [ 80 (wrap "rad") 81 (wrap "git-remote-rad") 82 pkgs.radicle-node 83 ]; 84 }; 85in 86{ 87 clan.core.vars.generators.rad = { 88 files."radicle.key" = { 89 owner = "rad"; 90 group = "rad"; 91 mode = "0440"; 92 }; 93 files."radicle.pub".secret = false; 94 runtimeInputs = [ pkgs.openssh ]; 95 script = '' 96 ssh-keygen -t ed25519 -N "" -C "radicle ${config.networking.hostName}" -f "$out/radicle.key" 97 mv "$out/radicle.key.pub" "$out/radicle.pub" 98 ''; 99 }; 100 101 users.users.rad = { 102 isSystemUser = true; 103 group = "rad"; 104 home = radHome; 105 }; 106 users.groups.rad = { }; 107 users.users.mainUser.extraGroups = [ "rad" ]; 108 109 environment.systemPackages = [ radicle-shared ]; 110 environment.variables.RAD_HOME = radHome; 111 112 systemd.tmpfiles.rules = [ 113 "d ${radHome} 2770 rad rad -" 114 "d ${radHome}/cobs 2770 rad rad -" 115 "d ${radHome}/keys 2770 rad rad -" 116 "d ${radHome}/node 2770 rad rad -" 117 "d ${radHome}/storage 2770 rad rad -" 118 "L+ ${radHome}/keys/radicle - - - - ${generator.files."radicle.key".path}" 119 "L+ ${radHome}/keys/radicle.pub - - - - ${generator.files."radicle.pub".path}" 120 "L+ ${radHome}/config.json - - - - ${configFile}" 121 # SQLite creates databases 0644 regardless of umask, which would lock the 122 # second party out ("attempt to write a readonly database"). Pre-create 123 # them empty and group-writable (an empty file is a valid empty database; 124 # -wal/-shm copy the main file's mode). Adjusts mode on every boot too. 125 "f ${radHome}/cobs/cache.db 0664 rad rad -" 126 "f ${radHome}/node/node.db 0664 rad rad -" 127 "f ${radHome}/node/notifications.db 0664 rad rad -" 128 "f ${radHome}/node/policies.db 0664 rad rad -" 129 ]; 130 131 systemd.services.rad-node = { 132 description = "Radicle node (machine identity, ${radHome})"; 133 documentation = [ "man:radicle-node(1)" ]; 134 wantedBy = [ "multi-user.target" ]; 135 wants = [ "network-online.target" ]; 136 after = [ "network-online.target" ]; 137 environment = { 138 # rad stats $HOME/.gitconfig 139 HOME = radHome; 140 RAD_HOME = radHome; 141 }; 142 path = [ pkgs.gitMinimal ]; 143 serviceConfig = { 144 User = "rad"; 145 Group = "rad"; 146 UMask = "0002"; 147 # --force: reclaim a control socket left behind by an unclean shutdown. 148 ExecStart = "${pkgs.radicle-node}/bin/radicle-node --force"; 149 Restart = "on-failure"; 150 RestartSec = 5; 151 }; 152 }; 153}