A vibe coded tangled fork which supports pijul.
1{
2 config,
3 pkgs,
4 lib,
5 ...
6}: let
7 cfg = config.services.tangled.knotmirror;
8in
9 with lib; {
10 options.services.tangled.knotmirror = {
11 enable = mkOption {
12 type = types.bool;
13 default = false;
14 description = "Enable a tangled knot";
15 };
16
17 package = mkOption {
18 type = types.package;
19 description = "Package to use for the knotmirror";
20 };
21
22 tap-package = mkOption {
23 type = types.package;
24 description = "tap package to use for the knotmirror";
25 };
26
27 listenAddr = mkOption {
28 type = types.str;
29 default = "0.0.0.0:7000";
30 description = "Address to listen on";
31 };
32
33 adminListenAddr = mkOption {
34 type = types.str;
35 default = "127.0.0.1:7200";
36 description = "Address to listen on";
37 };
38
39 hostname = mkOption {
40 type = types.str;
41 example = "my.knotmirror.com";
42 description = "Hostname for the server (required)";
43 };
44
45 dbUrl = mkOption {
46 type = types.str;
47 example = "postgresql://...";
48 description = "Database URL. postgresql expected (required)";
49 };
50
51 atpPlcUrl = mkOption {
52 type = types.str;
53 default = "https://plc.directory";
54 description = "atproto PLC directory";
55 };
56
57 atpRelayUrl = mkOption {
58 type = types.str;
59 default = "https://relay1.us-east.bsky.network";
60 description = "atproto relay";
61 };
62
63 fullNetwork = mkOption {
64 type = types.bool;
65 default = false;
66 description = "Whether to automatically mirror from entire network";
67 };
68
69 tap = {
70 port = mkOption {
71 type = types.port;
72 default = 7480;
73 description = "Internal port to run the knotmirror tap";
74 };
75
76 dbUrl = mkOption {
77 type = types.str;
78 default = "sqlite:///var/lib/knotmirror-tap/tap.db";
79 description = "database connection string (sqlite://path or postgres://...)";
80 };
81 };
82 };
83 config = mkIf cfg.enable {
84 environment.systemPackages = [
85 pkgs.git
86 cfg.package
87 ];
88
89 systemd.services.tap-knotmirror = {
90 description = "knotmirror tap service";
91 after = ["network.target"];
92 wantedBy = ["multi-user.target"];
93 serviceConfig = {
94 LogsDirectory = "knotmirror-tap";
95 StateDirectory = "knotmirror-tap";
96 Environment = [
97 "TAP_BIND=:${toString cfg.tap.port}"
98 "TAP_PLC_URL=${cfg.atpPlcUrl}"
99 "TAP_RELAY_URL=${cfg.atpRelayUrl}"
100 "TAP_RESYNC_PARALLELISM=10"
101 "TAP_DATABASE_URL=${cfg.tap.dbUrl}"
102 "TAP_RETRY_TIMEOUT=60s"
103 "TAP_COLLECTION_FILTERS=sh.tangled.repo"
104 (
105 if cfg.fullNetwork
106 then "TAP_SIGNAL_COLLECTION=sh.tangled.repo"
107 else "TAP_FULL_NETWORK=false"
108 )
109 ];
110 ExecStart = "${getExe cfg.tap-package} run";
111 };
112 };
113
114 systemd.services.knotmirror = {
115 description = "knotmirror service";
116 after = ["network.target" "tap-knotmirror.service"];
117 wantedBy = ["multi-user.target"];
118 path = [
119 pkgs.git
120 ];
121 serviceConfig = {
122 LogsDirectory = "knotmirror";
123 StateDirectory = "knotmirror";
124 Environment = [
125 # TODO: add environment variables
126 "MIRROR_LISTEN=${cfg.listenAddr}"
127 "MIRROR_HOSTNAME=${cfg.hostname}"
128 "MIRROR_TAP_URL=http://localhost:${toString cfg.tap.port}"
129 "MIRROR_DB_URL=${cfg.dbUrl}"
130 "MIRROR_GIT_BASEPATH=/var/lib/knotmirror/repos"
131 "MIRROR_KNOT_USE_SSL=true"
132 "MIRROR_KNOT_SSRF=true"
133 "MIRROR_RESYNC_PARALLELISM=12"
134 "MIRROR_METRICS_LISTEN=127.0.0.1:7100"
135 "MIRROR_ADMIN_LISTEN=${cfg.adminListenAddr}"
136 "MIRROR_SLURPER_CONCURRENCY=4"
137 ];
138 ExecStart = "${getExe cfg.package} serve";
139 Restart = "always";
140 };
141 };
142 };
143 }