+1
.envrc
+1
.envrc
···
1
+
use flake
+98
flake.lock
+98
flake.lock
···
1
+
{
2
+
"nodes": {
3
+
"crane": {
4
+
"locked": {
5
+
"lastModified": 1757183466,
6
+
"narHash": "sha256-kTdCCMuRE+/HNHES5JYsbRHmgtr+l9mOtf5dpcMppVc=",
7
+
"owner": "ipetkov",
8
+
"repo": "crane",
9
+
"rev": "d599ae4847e7f87603e7082d73ca673aa93c916d",
10
+
"type": "github"
11
+
},
12
+
"original": {
13
+
"owner": "ipetkov",
14
+
"repo": "crane",
15
+
"type": "github"
16
+
}
17
+
},
18
+
"flake-utils": {
19
+
"inputs": {
20
+
"systems": "systems"
21
+
},
22
+
"locked": {
23
+
"lastModified": 1731533236,
24
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
25
+
"owner": "numtide",
26
+
"repo": "flake-utils",
27
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
28
+
"type": "github"
29
+
},
30
+
"original": {
31
+
"owner": "numtide",
32
+
"repo": "flake-utils",
33
+
"type": "github"
34
+
}
35
+
},
36
+
"nixpkgs": {
37
+
"locked": {
38
+
"lastModified": 1758029226,
39
+
"narHash": "sha256-TjqVmbpoCqWywY9xIZLTf6ANFvDCXdctCjoYuYPYdMI=",
40
+
"owner": "NixOS",
41
+
"repo": "nixpkgs",
42
+
"rev": "08b8f92ac6354983f5382124fef6006cade4a1c1",
43
+
"type": "github"
44
+
},
45
+
"original": {
46
+
"owner": "NixOS",
47
+
"ref": "nixpkgs-unstable",
48
+
"repo": "nixpkgs",
49
+
"type": "github"
50
+
}
51
+
},
52
+
"root": {
53
+
"inputs": {
54
+
"crane": "crane",
55
+
"flake-utils": "flake-utils",
56
+
"nixpkgs": "nixpkgs",
57
+
"rust-overlay": "rust-overlay"
58
+
}
59
+
},
60
+
"rust-overlay": {
61
+
"inputs": {
62
+
"nixpkgs": [
63
+
"nixpkgs"
64
+
]
65
+
},
66
+
"locked": {
67
+
"lastModified": 1758162771,
68
+
"narHash": "sha256-hdZpMep6Z1gbgg9piUZ0BNusI6ZJaptBw6PHSN/3GD0=",
69
+
"owner": "oxalica",
70
+
"repo": "rust-overlay",
71
+
"rev": "d0cabb6ae8f5b38dffaff9f4e6db57c0ae21d729",
72
+
"type": "github"
73
+
},
74
+
"original": {
75
+
"owner": "oxalica",
76
+
"repo": "rust-overlay",
77
+
"type": "github"
78
+
}
79
+
},
80
+
"systems": {
81
+
"locked": {
82
+
"lastModified": 1681028828,
83
+
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
84
+
"owner": "nix-systems",
85
+
"repo": "default",
86
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
87
+
"type": "github"
88
+
},
89
+
"original": {
90
+
"owner": "nix-systems",
91
+
"repo": "default",
92
+
"type": "github"
93
+
}
94
+
}
95
+
},
96
+
"root": "root",
97
+
"version": 7
98
+
}
+464
flake.nix
+464
flake.nix
···
1
+
{
2
+
description = "Parakeet is a Rust-based Bluesky AppView";
3
+
inputs = {
4
+
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
5
+
crane.url = "github:ipetkov/crane";
6
+
flake-utils.url = "github:numtide/flake-utils";
7
+
rust-overlay = {
8
+
url = "github:oxalica/rust-overlay";
9
+
inputs.nixpkgs.follows = "nixpkgs";
10
+
};
11
+
};
12
+
outputs =
13
+
{
14
+
self,
15
+
nixpkgs,
16
+
crane,
17
+
flake-utils,
18
+
rust-overlay,
19
+
...
20
+
}:
21
+
flake-utils.lib.eachDefaultSystem (
22
+
system:
23
+
let
24
+
pkgs = import nixpkgs {
25
+
inherit system;
26
+
overlays = [ (import rust-overlay) ];
27
+
};
28
+
craneLib = (crane.mkLib pkgs).overrideToolchain (
29
+
p:
30
+
p.rust-bin.selectLatestNightlyWith (
31
+
toolchain:
32
+
toolchain.default.override {
33
+
extensions = [
34
+
"rust-src"
35
+
"rust-analyzer"
36
+
];
37
+
}
38
+
)
39
+
);
40
+
41
+
inherit (pkgs) lib;
42
+
unfilteredRoot = ./.; # The original, unfiltered source
43
+
src = lib.fileset.toSource {
44
+
root = unfilteredRoot;
45
+
fileset = lib.fileset.unions [
46
+
# Default files from crane (Rust and cargo files)
47
+
(craneLib.fileset.commonCargoSources unfilteredRoot)
48
+
];
49
+
};
50
+
# Common arguments can be set here to avoid repeating them later
51
+
commonArgs = {
52
+
inherit src;
53
+
strictDeps = true;
54
+
nativeBuildInputs = with pkgs; [
55
+
pkg-config
56
+
];
57
+
buildInputs = [
58
+
# Add additional build inputs here
59
+
pkgs.openssl
60
+
pkgs.postgresql
61
+
pkgs.libpq
62
+
pkgs.clang
63
+
pkgs.libclang
64
+
pkgs.lld
65
+
pkgs.protobuf
66
+
]
67
+
++ lib.optionals pkgs.stdenv.isDarwin [
68
+
# Additional darwin specific inputs can be set here
69
+
pkgs.libiconv
70
+
pkgs.darwin.apple_sdk.frameworks.Security
71
+
];
72
+
LIBCLANG_PATH = "${pkgs.llvmPackages_18.libclang.lib}/lib";
73
+
CLANG_PATH = "${pkgs.llvmPackages_18.clang}/bin/clang";
74
+
PROTOC_INCLUDE = "${pkgs.protobuf}/include";
75
+
PROTOC = "${pkgs.protobuf}/bin/protoc";
76
+
77
+
# Additional environment variables can be set directly
78
+
# MY_CUSTOM_VAR = "some value";
79
+
};
80
+
81
+
# Build *just* the cargo dependencies, so we can reuse
82
+
# all of that work (e.g. via cachix) when running in CI
83
+
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
84
+
85
+
individualCrateArgs = commonArgs // {
86
+
inherit cargoArtifacts;
87
+
inherit (craneLib.crateNameFromCargoToml { inherit src; }) version;
88
+
# NB: we disable tests since we'll run them all via cargo-nextest
89
+
doCheck = false;
90
+
};
91
+
fileSetForCrate =
92
+
crate:
93
+
lib.fileset.toSource {
94
+
root = ./.;
95
+
fileset = lib.fileset.unions [
96
+
./Cargo.toml
97
+
./Cargo.lock
98
+
./migrations
99
+
(craneLib.fileset.commonCargoSources ./consumer)
100
+
./consumer/src/db/sql
101
+
(craneLib.fileset.commonCargoSources ./dataloader-rs)
102
+
(craneLib.fileset.commonCargoSources ./did-resolver)
103
+
(craneLib.fileset.commonCargoSources ./lexica)
104
+
(craneLib.fileset.commonCargoSources ./parakeet)
105
+
./parakeet/src/sql
106
+
(craneLib.fileset.commonCargoSources ./parakeet-db)
107
+
(craneLib.fileset.commonCargoSources ./parakeet-index)
108
+
./parakeet-index/proto
109
+
(craneLib.fileset.commonCargoSources ./parakeet-lexgen)
110
+
(craneLib.fileset.commonCargoSources crate)
111
+
];
112
+
};
113
+
114
+
# Build the actual crate itself, reusing the dependency
115
+
# artifacts from above.
116
+
consumer = craneLib.buildPackage (
117
+
individualCrateArgs
118
+
// {
119
+
pname = "consumer";
120
+
cargoExtraArgs = "-p consumer";
121
+
src = fileSetForCrate ./consumer;
122
+
postInstall = ''
123
+
mkdir -p $out/{bin,lib/consumer}
124
+
'';
125
+
}
126
+
);
127
+
dataloader = craneLib.buildPackage (
128
+
individualCrateArgs
129
+
// {
130
+
pname = "dataloader";
131
+
cargoExtraArgs = "-p dataloader --features default";
132
+
src = fileSetForCrate ./dataloader-rs;
133
+
}
134
+
);
135
+
did-resolver = craneLib.buildPackage (
136
+
individualCrateArgs
137
+
// {
138
+
pname = "did-resolver";
139
+
cargoExtraArgs = "-p did-resolver";
140
+
src = fileSetForCrate ./did-resolver;
141
+
}
142
+
);
143
+
lexica = craneLib.buildPackage (
144
+
individualCrateArgs
145
+
// {
146
+
pname = "lexica";
147
+
cargoExtraArgs = "-p lexica";
148
+
src = fileSetForCrate ./lexica;
149
+
}
150
+
);
151
+
parakeet = craneLib.buildPackage (
152
+
individualCrateArgs
153
+
// {
154
+
pname = "parakeet";
155
+
cargoExtraArgs = "-p parakeet";
156
+
src = fileSetForCrate ./parakeet;
157
+
}
158
+
);
159
+
parakeet-db = craneLib.buildPackage (
160
+
individualCrateArgs
161
+
// {
162
+
pname = "parakeet-db";
163
+
cargoExtraArgs = "-p parakeet-db --features default";
164
+
src = fileSetForCrate ./parakeet-db;
165
+
}
166
+
);
167
+
parakeet-index = craneLib.buildPackage (
168
+
individualCrateArgs
169
+
// {
170
+
pname = "parakeet-index";
171
+
cargoExtraArgs = "-p parakeet-index --features server";
172
+
src = fileSetForCrate ./parakeet-index;
173
+
}
174
+
);
175
+
parakeet-lexgen = craneLib.buildPackage (
176
+
individualCrateArgs
177
+
// {
178
+
pname = "parakeet-lexgen";
179
+
cargoExtraArgs = "-p parakeet-lexgen";
180
+
src = fileSetForCrate ./parakeet-lexgen;
181
+
}
182
+
);
183
+
in
184
+
{
185
+
checks = {
186
+
# Build the crate as part of `nix flake check` for convenience
187
+
inherit
188
+
consumer
189
+
dataloader
190
+
did-resolver
191
+
lexica
192
+
parakeet
193
+
parakeet-db
194
+
parakeet-index
195
+
parakeet-lexgen
196
+
;
197
+
};
198
+
199
+
packages = {
200
+
default = parakeet;
201
+
inherit
202
+
consumer
203
+
dataloader
204
+
did-resolver
205
+
lexica
206
+
parakeet
207
+
parakeet-db
208
+
parakeet-index
209
+
parakeet-lexgen
210
+
;
211
+
};
212
+
213
+
devShells.default = craneLib.devShell {
214
+
# Inherit inputs from checks.
215
+
checks = self.checks.${system};
216
+
217
+
# Additional dev-shell environment variables can be set directly
218
+
RUST_BACKTRACE = 1;
219
+
NIXOS_OZONE_WL = 1;
220
+
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
221
+
222
+
# Extra inputs can be added here; cargo and rustc are provided by default.
223
+
packages = with pkgs; [
224
+
openssl
225
+
bacon
226
+
postgresql
227
+
rust-analyzer
228
+
rustfmt
229
+
clippy
230
+
git
231
+
nixd
232
+
direnv
233
+
libpq
234
+
clang
235
+
libclang
236
+
];
237
+
};
238
+
}
239
+
)
240
+
// flake-utils.lib.eachDefaultSystemPassThrough (system: {
241
+
nixosModules = {
242
+
default =
243
+
{
244
+
pkgs,
245
+
lib,
246
+
config,
247
+
...
248
+
}:
249
+
with lib;
250
+
let
251
+
cfg = config.services.parakeet;
252
+
253
+
inherit (lib)
254
+
mkEnableOption
255
+
mkIf
256
+
mkOption
257
+
types
258
+
;
259
+
in
260
+
{
261
+
options.services.parakeet = {
262
+
enable = mkEnableOption "parakeet";
263
+
264
+
package = mkOption {
265
+
type = types.package;
266
+
default = self.packages.${pkgs.system}.default;
267
+
description = "The path to the parakeet package.";
268
+
};
269
+
270
+
environmentFiles = mkOption {
271
+
type = types.listOf types.path;
272
+
default = [ "/var/lib/parakeet/config.env" ];
273
+
description = ''
274
+
File to load environment variables from. Loaded variables override
275
+
values set in {option}`environment`.
276
+
'';
277
+
};
278
+
};
279
+
config = mkIf cfg.enable {
280
+
environment.systemPackages = [
281
+
self.packages.${pkgs.system}.consumer
282
+
];
283
+
systemd.services.consumer = {
284
+
description = "consumer";
285
+
after = [ "network-online.target" ];
286
+
wants = [ "network-online.target" ];
287
+
wantedBy = [ "multi-user.target" ];
288
+
serviceConfig = {
289
+
ExecStart = "${self.packages.${pkgs.system}.consumer}/bin/consumer --indexer";
290
+
Type = "exec";
291
+
292
+
EnvironmentFile = cfg.environmentFiles;
293
+
User = "parakeet";
294
+
Group = "parakeet";
295
+
StateDirectory = "parakeet";
296
+
StateDirectoryMode = "0755";
297
+
Restart = "always";
298
+
299
+
# Hardening
300
+
RemoveIPC = true;
301
+
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
302
+
NoNewPrivileges = true;
303
+
PrivateDevices = true;
304
+
ProtectClock = true;
305
+
ProtectKernelLogs = true;
306
+
ProtectControlGroups = true;
307
+
ProtectKernelModules = true;
308
+
PrivateMounts = true;
309
+
SystemCallArchitectures = [ "native" ];
310
+
MemoryDenyWriteExecute = false; # required by V8 JIT
311
+
RestrictNamespaces = true;
312
+
RestrictSUIDSGID = true;
313
+
ProtectHostname = true;
314
+
LockPersonality = true;
315
+
ProtectKernelTunables = true;
316
+
RestrictAddressFamilies = [
317
+
"AF_UNIX"
318
+
"AF_INET"
319
+
"AF_INET6"
320
+
];
321
+
RestrictRealtime = true;
322
+
DeviceAllow = [ "" ];
323
+
ProtectSystem = "full";
324
+
ProtectProc = "invisible";
325
+
ProcSubset = "pid";
326
+
ProtectHome = true;
327
+
PrivateUsers = true;
328
+
PrivateTmp = true;
329
+
UMask = "0077";
330
+
};
331
+
};
332
+
systemd.services.parakeet = {
333
+
description = "parakeet";
334
+
after = [ "network-online.target" ];
335
+
wants = [ "network-online.target" ];
336
+
wantedBy = [ "multi-user.target" ];
337
+
serviceConfig = {
338
+
ExecStart = "${cfg.package}/bin/parakeet";
339
+
Type = "exec";
340
+
341
+
EnvironmentFile = cfg.environmentFiles;
342
+
User = "parakeet";
343
+
Group = "parakeet";
344
+
StateDirectory = "parakeet";
345
+
StateDirectoryMode = "0755";
346
+
Restart = "always";
347
+
348
+
# Hardening
349
+
RemoveIPC = true;
350
+
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
351
+
NoNewPrivileges = true;
352
+
PrivateDevices = true;
353
+
ProtectClock = true;
354
+
ProtectKernelLogs = true;
355
+
ProtectControlGroups = true;
356
+
ProtectKernelModules = true;
357
+
PrivateMounts = true;
358
+
SystemCallArchitectures = [ "native" ];
359
+
MemoryDenyWriteExecute = false; # required by V8 JIT
360
+
RestrictNamespaces = true;
361
+
RestrictSUIDSGID = true;
362
+
ProtectHostname = true;
363
+
LockPersonality = true;
364
+
ProtectKernelTunables = true;
365
+
RestrictAddressFamilies = [
366
+
"AF_UNIX"
367
+
"AF_INET"
368
+
"AF_INET6"
369
+
];
370
+
RestrictRealtime = true;
371
+
DeviceAllow = [ "" ];
372
+
ProtectSystem = "full";
373
+
ProtectProc = "invisible";
374
+
ProcSubset = "pid";
375
+
ProtectHome = true;
376
+
PrivateUsers = true;
377
+
PrivateTmp = true;
378
+
UMask = "0077";
379
+
};
380
+
};
381
+
systemd.services.parakeet-index = {
382
+
description = "parakeet-index";
383
+
after = [ "network-online.target" ];
384
+
wants = [ "network-online.target" ];
385
+
wantedBy = [ "multi-user.target" ];
386
+
serviceConfig = {
387
+
ExecStart = "${self.packages.${pkgs.system}.parakeet-index}/bin/parakeet-index";
388
+
Type = "exec";
389
+
390
+
EnvironmentFile = cfg.environmentFiles;
391
+
User = "parakeet";
392
+
Group = "parakeet";
393
+
StateDirectory = "parakeet";
394
+
StateDirectoryMode = "0755";
395
+
Restart = "always";
396
+
397
+
# Hardening
398
+
RemoveIPC = true;
399
+
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
400
+
NoNewPrivileges = true;
401
+
PrivateDevices = true;
402
+
ProtectClock = true;
403
+
ProtectKernelLogs = true;
404
+
ProtectControlGroups = true;
405
+
ProtectKernelModules = true;
406
+
PrivateMounts = true;
407
+
SystemCallArchitectures = [ "native" ];
408
+
MemoryDenyWriteExecute = false; # required by V8 JIT
409
+
RestrictNamespaces = true;
410
+
RestrictSUIDSGID = true;
411
+
ProtectHostname = true;
412
+
LockPersonality = true;
413
+
ProtectKernelTunables = true;
414
+
RestrictAddressFamilies = [
415
+
"AF_UNIX"
416
+
"AF_INET"
417
+
"AF_INET6"
418
+
];
419
+
RestrictRealtime = true;
420
+
DeviceAllow = [ "" ];
421
+
ProtectSystem = "full";
422
+
ProtectProc = "invisible";
423
+
ProcSubset = "pid";
424
+
ProtectHome = true;
425
+
PrivateUsers = true;
426
+
PrivateTmp = true;
427
+
UMask = "0077";
428
+
};
429
+
};
430
+
users = {
431
+
users.parakeet = {
432
+
group = "parakeet";
433
+
isSystemUser = true;
434
+
};
435
+
groups.parakeet = { };
436
+
};
437
+
services.postgresql = {
438
+
enable = true;
439
+
ensureUsers = [
440
+
{
441
+
name = "parakeet";
442
+
ensureDBOwnership = true;
443
+
}
444
+
];
445
+
ensureDatabases = [ "parakeet" ];
446
+
authentication = pkgs.lib.mkOverride 10 ''
447
+
#type database DBuser auth-method
448
+
local all all trust
449
+
host all all 127.0.0.1/32 trust
450
+
host all all ::1/128 trust
451
+
'';
452
+
package = mkForce pkgs.postgresql_16;
453
+
};
454
+
services.redis.servers.parakeet = {
455
+
enable = true;
456
+
# port = 0;
457
+
unixSocket = "/run/redis-parakeet/redis.sock";
458
+
user = "parakeet";
459
+
};
460
+
};
461
+
};
462
+
};
463
+
});
464
+
}
+4
-1
parakeet-index/build.rs
+4
-1
parakeet-index/build.rs
···
1
1
fn main() -> Result<(), Box<dyn std::error::Error>> {
2
-
tonic_build::configure().compile_protos(&["proto/parakeet.proto"], &[""])?;
2
+
tonic_build::configure().compile_protos(
3
+
&[std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("proto/parakeet.proto")],
4
+
&[std::path::Path::new(env!("CARGO_MANIFEST_DIR"))],
5
+
)?;
3
6
4
7
Ok(())
5
8
}