Monorepo for Tangled tangled.org
9

Configure Feed

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

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.knot 27 self.nixosModules.spindle 28 self.nixosModules.knotmirror 29 ({ 30 lib, 31 config, 32 pkgs, 33 ... 34 }: { 35 virtualisation.vmVariant.virtualisation = { 36 host.pkgs = import nixpkgs {system = hostSystem;}; 37 38 graphics = false; 39 memorySize = 2048; 40 diskSize = 10 * 1024; 41 cores = 2; 42 forwardPorts = [ 43 # ssh 44 { 45 from = "host"; 46 host.port = 2222; 47 guest.port = 22; 48 } 49 # knot 50 { 51 from = "host"; 52 host.port = 6444; 53 guest.port = 6444; 54 } 55 # spindle 56 { 57 from = "host"; 58 host.port = 6555; 59 guest.port = 6555; 60 } 61 # knotmirror 62 { 63 from = "host"; 64 host.port = 7007; # 7000 is deserved in macos for Airplay 65 guest.port = 7000; 66 } 67 # knotmirror-tap 68 { 69 from = "host"; 70 host.port = 7480; 71 guest.port = 7480; 72 } 73 # knotmirror-admin 74 { 75 from = "host"; 76 host.port = 7200; 77 guest.port = 7200; 78 } 79 { 80 from = "host"; 81 host.port = 7100; 82 guest.port = 7100; 83 } 84 { 85 from = "host"; 86 host.port = 6314; 87 guest.port = 6314; 88 } 89 ]; 90 sharedDirectories = { 91 # We can't use the 9p mounts directly for most of these 92 # as SQLite is incompatible with them. So instead we 93 # mount the shared directories to a different location 94 # and copy the contents around on service start/stop. 95 knotData = { 96 source = "$TANGLED_VM_DATA_DIR/knot"; 97 target = "/mnt/knot-data"; 98 }; 99 spindleData = { 100 source = "$TANGLED_VM_DATA_DIR/spindle"; 101 target = "/mnt/spindle-data"; 102 }; 103 spindleLogs = { 104 source = "$TANGLED_VM_DATA_DIR/spindle-logs"; 105 target = "/var/log/spindle"; 106 }; 107 }; 108 }; 109 # 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 110 networking.firewall.enable = false; 111 services.timesyncd.enable = lib.mkForce true; 112 time.timeZone = "Europe/London"; 113 services.getty.autologinUser = "root"; 114 environment.systemPackages = with pkgs; [curl vim git sqlite litecli postgresql_14]; 115 services.tangled.knot = { 116 enable = true; 117 motd = "Welcome to the development knot!\n"; 118 server = { 119 secureMode = false; 120 owner = envVar "TANGLED_VM_KNOT_OWNER"; 121 hostname = envVarOr "TANGLED_VM_KNOT_HOST" "localhost:6444"; 122 plcUrl = plcUrl; 123 jetstreamEndpoint = jetstream; 124 listenAddr = "0.0.0.0:6444"; 125 dev = true; 126 }; 127 knotmirrors = [ 128 "http://localhost:7000" 129 ]; 130 }; 131 services.tangled.spindle = { 132 enable = true; 133 server = { 134 owner = envVar "TANGLED_VM_SPINDLE_OWNER"; 135 hostname = envVarOr "TANGLED_VM_SPINDLE_HOST" "localhost:6555"; 136 plcUrl = plcUrl; 137 jetstreamEndpoint = jetstream; 138 listenAddr = "0.0.0.0:6555"; 139 dev = true; 140 queueSize = 100; 141 maxJobCount = 2; 142 secrets = { 143 provider = "sqlite"; 144 }; 145 }; 146 147 pipelines = { 148 logBucket = envVarOr "SPINDLE_S3_LOG_BUCKET" ""; 149 }; 150 }; 151 services.postgresql = { 152 enable = true; 153 package = pkgs.postgresql_14; 154 ensureDatabases = ["mirror" "tap"]; 155 ensureUsers = [ 156 {name = "tnglr";} 157 ]; 158 authentication = '' 159 local all tnglr trust 160 host all tnglr 127.0.0.1/32 trust 161 ''; 162 }; 163 services.porxie = { 164 enable = true; 165 settings = { 166 PORXIE_SERVER_ADDRESS = "ip:0.0.0.0:6314"; 167 PORXIE_BLOB_ALLOWED_MIMETYPES = ["application/gzip" "image/*" "text/plain"]; 168 PORXIE_IDENTITY_PLC_URL = plcUrl; 169 }; 170 }; 171 services.tangled.knotmirror = { 172 enable = true; 173 knotSSRF = false; 174 listenAddr = "0.0.0.0:7000"; 175 metricsListenAddr = "0.0.0.0:7100"; 176 adminListenAddr = "0.0.0.0:7200"; 177 hostname = "localhost:7000"; 178 dbUrl = "postgresql://tnglr@127.0.0.1:5432/mirror"; 179 fullNetwork = false; 180 tap.dbUrl = "postgresql://tnglr@127.0.0.1:5432/tap"; 181 }; 182 users = { 183 # So we don't have to deal with permission clashing between 184 # blank disk VMs and existing state 185 users.${config.services.tangled.knot.gitUser}.uid = 666; 186 groups.${config.services.tangled.knot.gitUser}.gid = 666; 187 188 # TODO: separate spindle user 189 }; 190 systemd.services = let 191 mkDataSyncScripts = source: target: { 192 enableStrictShellChecks = true; 193 194 preStart = lib.mkBefore '' 195 mkdir -p ${target} 196 ${lib.getExe pkgs.rsync} -a ${source}/ ${target} 197 ''; 198 199 postStop = lib.mkAfter '' 200 ${lib.getExe pkgs.rsync} -a ${target}/ ${source} 201 ''; 202 203 serviceConfig.PermissionsStartOnly = true; 204 }; 205 in { 206 knot = mkDataSyncScripts "/mnt/knot-data" config.services.tangled.knot.stateDir; 207 spindle = mkDataSyncScripts "/mnt/spindle-data" (builtins.dirOf config.services.tangled.spindle.server.dbPath); 208 knotmirror.after = ["postgresql.target"]; 209 tap-knotmirror.after = ["postgresql.target"]; 210 }; 211 }) 212 ]; 213 }