This repository has no description
0

Configure Feed

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

configs.services.git: own knotmirror

+165 -15
+1
configs/dns/lassul.us.zone
··· 73 73 _acme-challenge.pds IN NS ns1 74 74 git IN CNAME neoprism 75 75 knot IN CNAME neoprism 76 + mirror IN CNAME neoprism 76 77 when IN CNAME neoprism 77 78 paperless IN CNAME neoprism 78 79
+9 -15
configs/services/git/appview.nix
··· 1 1 { 2 2 self, 3 3 config, 4 - lib, 5 4 pkgs, 6 5 ... 7 6 }: ··· 14 13 { 15 14 # Tangled appview: the web UI for repos on knot.lassul.us (knot.nix) and 16 15 # other knots. Users log in with their atproto account via OAuth to their 17 - # PDS. Records come from Bluesky's jetstream and repo contents from the 18 - # public knotmirror (mirror.tangled.network), both upstream defaults. 19 - # Follows tangled's nix/modules/appview.nix, without its flake (the module 20 - # files are in a fetched source, importing them would be IFD). 16 + # PDS. Records come from Bluesky's jetstream (upstream default) and repo 17 + # contents from our knotmirror (knotmirror.nix). Follows tangled's 18 + # nix/modules/appview.nix, without its flake (the module files are in a 19 + # fetched source, importing them would be IFD). 21 20 22 21 clan.core.vars.generators.tangled-appview = { 23 22 files."appview.env" = { }; ··· 97 96 TANGLED_AVATAR_HOST = "https://avatar.tangled.sh"; 98 97 TANGLED_PLC_URL = "https://plc.directory"; 99 98 TANGLED_PDS_HOST = "https://tngl.sh"; 100 - TANGLED_LABEL_DEFAULTS = 101 - lib.concatMapStringsSep "," 102 - (l: "at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/${l}") 103 - [ 104 - "wontfix" 105 - "good-first-issue" 106 - "duplicate" 107 - "documentation" 108 - "assignee" 109 - ]; 99 + # records of tangled's account, fetched from its PDS at startup; repos 100 + # start without labels 101 + TANGLED_LABEL_DEFAULTS = ""; 110 102 TANGLED_LABEL_GFI = "at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/good-first-issue"; 111 103 # probed at every login, upstream's is knot1.tangled.sh 112 104 TANGLED_KNOT_DEFAULT = "knot.lassul.us"; 113 105 # OG images of repos, issues and pulls, rendered by tangled 114 106 TANGLED_OGRE_HOST = "http://127.0.0.1:9"; 107 + # browsers get raw blob links to it, so not localhost 108 + TANGLED_KNOTMIRROR_URL = "https://mirror.lassul.us"; 115 109 }; 116 110 }; 117 111
+1
configs/services/git/default.nix
··· 2 2 imports = [ 3 3 ./appview.nix 4 4 ./knot.nix 5 + ./knotmirror.nix 5 6 ./pds.nix 6 7 ]; 7 8 }
+21
configs/services/git/knot.nix
··· 157 157 158 158 networking.firewall.allowedTCPPorts = [ sshPort ]; 159 159 160 + # knot 2 doesn't request crawls (no KNOT_MIRRORS), so subscribe our 161 + # mirror (knotmirror.nix) to the knot's event stream whenever either 162 + # starts; the mirror marks a knot offline after it was unreachable for a 163 + # while 164 + systemd.services.knotmirror-request-crawl = { 165 + wantedBy = [ 166 + "knot-rs.service" 167 + "knotmirror.service" 168 + ]; 169 + after = [ 170 + "knot-rs.service" 171 + "knotmirror.service" 172 + ]; 173 + serviceConfig.Type = "oneshot"; 174 + script = '' 175 + ${pkgs.curl}/bin/curl -fsS --retry 10 --retry-connrefused \ 176 + -H 'Content-Type: application/json' -d '{"hostname":"${domain}"}' \ 177 + http://127.0.0.1:7000/xrpc/sh.tangled.sync.requestCrawl 178 + ''; 179 + }; 180 + 160 181 # repos (with the ACL data), sealed keys and ssh host key; the master key 161 182 # is in vars 162 183 lass.backup.state.tangled-knot.folders = [ stateDir ];
+133
configs/services/git/knotmirror.nix
··· 1 + { 2 + self, 3 + lib, 4 + pkgs, 5 + ... 6 + }: 7 + let 8 + domain = "mirror.lassul.us"; 9 + listenAddr = "127.0.0.1:7000"; 10 + tapPort = 7480; 11 + redisPort = 6377; 12 + package = self.packages.${pkgs.stdenv.hostPlatform.system}.tangled.knotmirror; 13 + in 14 + { 15 + # Tangled knotmirror: the appview reads repo contents from here instead of 16 + # mirror.tangled.network. It mirrors a repo the first time the appview asks 17 + # for it (resolving the knot from the repo's DID) and follows the event 18 + # streams of knots that requested a crawl (ours, see knot.nix). Public, 19 + # since the appview links browsers to raw blobs and images on it. Follows 20 + # tangled's nix/modules/knotmirror.nix, without its flake (the module files 21 + # are in a fetched source, importing them would be IFD); tap is nixpkgs'. 22 + 23 + environment.systemPackages = [ 24 + pkgs.git 25 + package 26 + ]; 27 + 28 + services.redis.servers.knotmirror = { 29 + enable = true; 30 + port = redisPort; 31 + }; 32 + 33 + systemd.services.tap-knotmirror = { 34 + description = "knotmirror tap service"; 35 + after = [ "network.target" ]; 36 + wantedBy = [ "multi-user.target" ]; 37 + # outbox only: no firehose subscription to the bsky relay for nothing 38 + environment.TAP_OUTBOX_ONLY = "true"; 39 + serviceConfig = { 40 + # upstream runs it as root 41 + DynamicUser = true; 42 + LogsDirectory = "knotmirror-tap"; 43 + StateDirectory = "knotmirror-tap"; 44 + Environment = [ 45 + "TAP_BIND=:${toString tapPort}" 46 + "TAP_PLC_URL=https://plc.directory" 47 + "TAP_RELAY_URL=https://relay1.us-east.bsky.network" 48 + "TAP_RESYNC_PARALLELISM=10" 49 + "TAP_DATABASE_URL=sqlite:///var/lib/knotmirror-tap/tap.db" 50 + "TAP_RETRY_TIMEOUT=60s" 51 + "TAP_COLLECTION_FILTERS=sh.tangled.repo" 52 + # nothing calls tap's /repos/add without the full network, so it 53 + # tracks no repos 54 + "TAP_FULL_NETWORK=false" 55 + ]; 56 + ExecStart = "${lib.getExe pkgs.tap} run"; 57 + }; 58 + }; 59 + 60 + systemd.services.knotmirror = { 61 + description = "knotmirror service"; 62 + after = [ 63 + "postgresql.target" 64 + "redis-knotmirror.service" 65 + "network.target" 66 + "tap-knotmirror.service" 67 + ]; 68 + requires = [ 69 + "postgresql.target" 70 + "redis-knotmirror.service" 71 + ]; 72 + wantedBy = [ "multi-user.target" ]; 73 + path = [ pkgs.git ]; 74 + # pinged after indexing languages, upstream's is tangled.org 75 + environment.MIRROR_APPVIEW_URL = "https://git.lassul.us"; 76 + serviceConfig = { 77 + # upstream runs it as root; the name matches the postgres role for peer 78 + # auth 79 + DynamicUser = true; 80 + User = "knotmirror"; 81 + LogsDirectory = "knotmirror"; 82 + StateDirectory = "knotmirror"; 83 + Environment = [ 84 + "MIRROR_LISTEN=${listenAddr}" 85 + "MIRROR_HOSTNAME=${domain}" 86 + "MIRROR_TAP_URL=http://localhost:${toString tapPort}" 87 + "MIRROR_DB_URL=postgres:///knotmirror?host=/run/postgresql&user=knotmirror" 88 + "MIRROR_REDIS_ADDR=localhost:${toString redisPort}" 89 + "MIRROR_GIT_BASEPATH=/var/lib/knotmirror/repos" 90 + "MIRROR_KNOT_USE_SSL=true" 91 + "MIRROR_KNOT_SSRF=true" 92 + "MIRROR_RESYNC_PARALLELISM=12" 93 + "MIRROR_METRICS_LISTEN=127.0.0.1:7100" 94 + "MIRROR_ADMIN_LISTEN=127.0.0.1:7200" 95 + "MIRROR_SLURPER_CONCURRENCY=4" 96 + "MIRROR_SEARCH_ZOEKT_URL=" 97 + ]; 98 + ExecStart = "${lib.getExe package} serve"; 99 + Restart = "always"; 100 + }; 101 + }; 102 + 103 + services.postgresql = { 104 + enable = true; 105 + ensureDatabases = [ "knotmirror" ]; 106 + ensureUsers = [ 107 + { 108 + name = "knotmirror"; 109 + ensureDBOwnership = true; 110 + } 111 + ]; 112 + }; 113 + 114 + # no backup: postgres, redis, tap and the repos only cache what the knots 115 + # serve, and the mirror refetches it 116 + 117 + services.nginx.virtualHosts.${domain} = { 118 + enableACME = true; 119 + forceSSL = true; 120 + locations."/" = { 121 + proxyPass = "http://${listenAddr}"; 122 + recommendedProxySettings = true; 123 + # reads only: sh.tangled.sync.requestCrawl (POST) would let anyone 124 + # subscribe us to any knot, ours requests it via localhost 125 + extraConfig = '' 126 + limit_except GET { 127 + deny all; 128 + } 129 + proxy_read_timeout 10m; 130 + ''; 131 + }; 132 + }; 133 + }