this repo has no description
1{ 2 nixpkgs, 3 system, 4 hostSystem, 5 self, 6}: let 7 envVar = name: let 8 var = builtins.getEnv name; 9 in 10 if var == "" 11 then throw "\$${name} must be defined, see https://docs.tangled.org/hacking-on-tangled.html#hacking-on-tangled for more details" 12 else var; 13 envVarOr = name: default: let 14 var = builtins.getEnv name; 15 in 16 if var != "" 17 then var 18 else default; 19 20 plcUrl = envVarOr "TANGLED_VM_PLC_URL" "https://plc.directory"; 21 jetstream = envVarOr "TANGLED_VM_JETSTREAM_ENDPOINT" "wss://jetstream1.us-west.bsky.network/subscribe"; 22in 23 nixpkgs.lib.nixosSystem { 24 inherit system; 25 modules = [ 26 self.nixosModules.did-method-plc 27 self.nixosModules.bluesky-jetstream 28 self.nixosModules.bluesky-relay 29 self.nixosModules.knot 30 self.nixosModules.spindle 31 ({ 32 lib, 33 config, 34 pkgs, 35 ... 36 }: { 37 virtualisation.vmVariant.virtualisation = { 38 host.pkgs = import nixpkgs {system = hostSystem;}; 39 40 graphics = false; 41 memorySize = 2048; 42 diskSize = 10 * 1024; 43 cores = 2; 44 forwardPorts = [ 45 # caddy 46 { 47 from = "host"; 48 host.port = 80; 49 guest.port = 80; 50 } 51 { 52 from = "host"; 53 host.port = 443; 54 guest.port = 443; 55 } 56 { 57 from = "host"; 58 proto = "udp"; 59 host.port = 443; 60 guest.port = 443; 61 } 62 # ssh 63 { 64 from = "host"; 65 host.port = 2222; 66 guest.port = 22; 67 } 68 # knot 69 { 70 from = "host"; 71 host.port = 6444; 72 guest.port = 6444; 73 } 74 # spindle 75 { 76 from = "host"; 77 host.port = 6555; 78 guest.port = 6555; 79 } 80 ]; 81 sharedDirectories = { 82 # We can't use the 9p mounts directly for most of these 83 # as SQLite is incompatible with them. So instead we 84 # mount the shared directories to a different location 85 # and copy the contents around on service start/stop. 86 caddyData = { 87 source = "$TANGLED_VM_DATA_DIR/caddy"; 88 target = config.services.caddy.dataDir; 89 }; 90 knotData = { 91 source = "$TANGLED_VM_DATA_DIR/knot"; 92 target = "/mnt/knot-data"; 93 }; 94 spindleData = { 95 source = "$TANGLED_VM_DATA_DIR/spindle"; 96 target = "/mnt/spindle-data"; 97 }; 98 spindleLogs = { 99 source = "$TANGLED_VM_DATA_DIR/spindle-logs"; 100 target = "/var/log/spindle"; 101 }; 102 }; 103 }; 104 # This is fine because any and all ports that are forwarded to host are explicitly marked above, we don't need a separate guest firewall 105 networking.firewall.enable = false; 106 # resolve `*.tngl.boltless.dev` to host 107 services.dnsmasq.enable = true; 108 services.dnsmasq.settings.address = "/tngl.boltless.dev/10.0.2.2"; 109 security.pki.certificates = [ 110 (builtins.readFile ../contrib/certs/root.crt) 111 ]; 112 time.timeZone = "Europe/London"; 113 services.timesyncd.enable = lib.mkVMOverride true; 114 services.getty.autologinUser = "root"; 115 environment.systemPackages = with pkgs; [curl vim git sqlite litecli]; 116 virtualisation.docker.extraOptions = '' 117 --dns 172.17.0.1 118 ''; 119 services.tangled.knot = { 120 enable = true; 121 motd = "Welcome to the development knot!\n"; 122 server = { 123 owner = envVar "TANGLED_VM_KNOT_OWNER"; 124 hostname = envVarOr "TANGLED_VM_KNOT_HOST" "localhost:6444"; 125 plcUrl = plcUrl; 126 jetstreamEndpoint = jetstream; 127 listenAddr = "0.0.0.0:6444"; 128 }; 129 }; 130 services.tangled.spindle = { 131 enable = true; 132 server = { 133 owner = envVar "TANGLED_VM_SPINDLE_OWNER"; 134 hostname = envVarOr "TANGLED_VM_SPINDLE_HOST" "localhost:6555"; 135 plcUrl = plcUrl; 136 jetstreamEndpoint = jetstream; 137 listenAddr = "0.0.0.0:6555"; 138 dev = true; 139 queueSize = 100; 140 maxJobCount = 2; 141 secrets = { 142 provider = "sqlite"; 143 }; 144 }; 145 }; 146 services.did-method-plc.enable = true; 147 services.bluesky-pds = { 148 enable = true; 149 # overriding package version to support emails 150 package = pkgs.bluesky-pds.overrideAttrs (old: rec { 151 version = "0.4.188"; 152 src = pkgs.fetchFromGitHub { 153 owner = "bluesky-social"; 154 repo = "pds"; 155 tag = "v${version}"; 156 hash = "sha256-t8KdyEygXdbj/5Rhj8W40e1o8mXprELpjsKddHExmo0="; 157 }; 158 pnpmDeps = pkgs.fetchPnpmDeps { 159 inherit version src; 160 pname = old.pname; 161 sourceRoot = old.sourceRoot; 162 fetcherVersion = 2; 163 hash = "sha256-lQie7f8JbWKSpoavnMjHegBzH3GB9teXsn+S2SLJHHU="; 164 }; 165 }); 166 settings = { 167 LOG_ENABLED = "true"; 168 169 PDS_JWT_SECRET = "8cae8bffcc73d9932819650791e4e89a"; 170 PDS_ADMIN_PASSWORD = "d6a902588cd93bee1af83f924f60cfd3"; 171 PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX = "2e92e336a50a618458e1097d94a1db86ec3fd8829d7735020cbae80625c761d7"; 172 173 PDS_EMAIL_SMTP_URL = envVarOr "TANGLED_VM_PDS_EMAIL_SMTP_URL" null; 174 PDS_EMAIL_FROM_ADDRESS = envVarOr "TANGLED_VM_PDS_EMAIL_FROM_ADDRESS" null; 175 176 PDS_DID_PLC_URL = "http://localhost:8080"; 177 PDS_CRAWLERS = "https://relay.tngl.boltless.dev"; 178 PDS_HOSTNAME = "pds.tngl.boltless.dev"; 179 PDS_PORT = 3000; 180 }; 181 }; 182 services.bluesky-relay = { 183 enable = true; 184 }; 185 services.bluesky-jetstream = { 186 enable = true; 187 livenessTtl = 300; 188 websocketUrl = "ws://localhost:3000/xrpc/com.atproto.sync.subscribeRepos"; 189 }; 190 services.caddy = { 191 enable = true; 192 configFile = pkgs.writeText "Caddyfile" '' 193 { 194 debug 195 cert_lifetime 3601d 196 pki { 197 ca local { 198 intermediate_lifetime 3599d 199 } 200 } 201 } 202 203 plc.tngl.boltless.dev { 204 tls internal 205 reverse_proxy http://localhost:8080 206 } 207 208 *.pds.tngl.boltless.dev, pds.tngl.boltless.dev { 209 tls internal 210 reverse_proxy http://localhost:3000 211 } 212 213 jetstream.tngl.boltless.dev { 214 tls internal 215 reverse_proxy http://localhost:6008 216 } 217 218 relay.tngl.boltless.dev { 219 tls internal 220 reverse_proxy http://localhost:2470 221 } 222 223 knot.tngl.boltless.dev { 224 tls internal 225 reverse_proxy http://localhost:6444 226 } 227 228 spindle.tngl.boltless.dev { 229 tls internal 230 reverse_proxy http://localhost:6555 231 } 232 ''; 233 }; 234 users = { 235 # So we don't have to deal with permission clashing between 236 # blank disk VMs and existing state 237 users.${config.services.tangled.knot.gitUser}.uid = 666; 238 groups.${config.services.tangled.knot.gitUser}.gid = 666; 239 240 # TODO: separate spindle user 241 }; 242 systemd.services = let 243 mkDataSyncScripts = source: target: { 244 enableStrictShellChecks = true; 245 246 preStart = lib.mkBefore '' 247 mkdir -p ${target} 248 ${lib.getExe pkgs.rsync} -a ${source}/ ${target} 249 ''; 250 251 postStop = lib.mkAfter '' 252 ${lib.getExe pkgs.rsync} -a ${target}/ ${source} 253 ''; 254 255 serviceConfig.PermissionsStartOnly = true; 256 }; 257 in { 258 knot = mkDataSyncScripts "/mnt/knot-data" config.services.tangled.knot.stateDir; 259 spindle = mkDataSyncScripts "/mnt/spindle-data" (builtins.dirOf config.services.tangled.spindle.server.dbPath); 260 }; 261 }) 262 ]; 263 }