1{ config, lib, pkgs, ... }:
2
3with lib;
4let
5
6 cfg = config.services.qdrant;
7
8 settingsFormat = pkgs.formats.yaml { };
9 configFile = settingsFormat.generate "config.yaml" cfg.settings;
10in {
11
12 options = {
13 services.qdrant = {
14 enable = mkEnableOption (lib.mdDoc "Vector Search Engine for the next generation of AI applications");
15
16 settings = mkOption {
17 description = lib.mdDoc ''
18 Configuration for Qdrant
19 Refer to <https://github.com/qdrant/qdrant/blob/master/config/config.yaml> for details on supported values.
20 '';
21
22 type = settingsFormat.type;
23
24 example = {
25 storage = {
26 storage_path = "/var/lib/qdrant/storage";
27 snapshots_path = "/var/lib/qdrant/snapshots";
28 };
29 hsnw_index = {
30 on_disk = true;
31 };
32 service = {
33 host = "127.0.0.1";
34 http_port = 6333;
35 grpc_port = 6334;
36 };
37 telemetry_disabled = true;
38 };
39
40 defaultText = literalExpression ''
41 {
42 storage = {
43 storage_path = "/var/lib/qdrant/storage";
44 snapshots_path = "/var/lib/qdrant/snapshots";
45 };
46 hsnw_index = {
47 on_disk = true;
48 };
49 service = {
50 host = "127.0.0.1";
51 http_port = 6333;
52 grpc_port = 6334;
53 };
54 telemetry_disabled = true;
55 }
56 '';
57 };
58 };
59 };
60
61 config = mkIf cfg.enable {
62 services.qdrant.settings = {
63 storage.storage_path = mkDefault "/var/lib/qdrant/storage";
64 storage.snapshots_path = mkDefault "/var/lib/qdrant/snapshots";
65 # The following default values are the same as in the default config,
66 # they are just written here for convenience.
67 storage.on_disk_payload = mkDefault true;
68 storage.wal.wal_capacity_mb = mkDefault 32;
69 storage.wal.wal_segments_ahead = mkDefault 0;
70 storage.performance.max_search_threads = mkDefault 0;
71 storage.performance.max_optimization_threads = mkDefault 1;
72 storage.optimizers.deleted_threshold = mkDefault 0.2;
73 storage.optimizers.vacuum_min_vector_number = mkDefault 1000;
74 storage.optimizers.default_segment_number = mkDefault 0;
75 storage.optimizers.max_segment_size_kb = mkDefault null;
76 storage.optimizers.memmap_threshold_kb = mkDefault null;
77 storage.optimizers.indexing_threshold_kb = mkDefault 20000;
78 storage.optimizers.flush_interval_sec = mkDefault 5;
79 storage.optimizers.max_optimization_threads = mkDefault 1;
80 storage.hnsw_index.m = mkDefault 16;
81 storage.hnsw_index.ef_construct = mkDefault 100;
82 storage.hnsw_index.full_scan_threshold_kb = mkDefault 10000;
83 storage.hnsw_index.max_indexing_threads = mkDefault 0;
84 storage.hnsw_index.on_disk = mkDefault false;
85 storage.hnsw_index.payload_m = mkDefault null;
86 service.max_request_size_mb = mkDefault 32;
87 service.max_workers = mkDefault 0;
88 service.http_port = mkDefault 6333;
89 service.grpc_port = mkDefault 6334;
90 service.enable_cors = mkDefault true;
91 cluster.enabled = mkDefault false;
92 # the following have been altered for security
93 service.host = mkDefault "127.0.0.1";
94 telemetry_disabled = mkDefault true;
95 };
96
97 systemd.services.qdrant = {
98 description = "Vector Search Engine for the next generation of AI applications";
99 wantedBy = [ "multi-user.target" ];
100 after = [ "network.target" ];
101
102 serviceConfig = {
103 LimitNOFILE=65536;
104 ExecStart = "${pkgs.qdrant}/bin/qdrant --config-path ${configFile}";
105 DynamicUser = true;
106 Restart = "on-failure";
107 StateDirectory = "qdrant";
108 CapabilityBoundingSet = "";
109 NoNewPrivileges = true;
110 PrivateTmp = true;
111 ProtectHome = true;
112 ProtectClock = true;
113 ProtectProc = "noaccess";
114 ProcSubset = "pid";
115 ProtectKernelLogs = true;
116 ProtectKernelModules = true;
117 ProtectKernelTunables = true;
118 ProtectControlGroups = true;
119 ProtectHostname = true;
120 RestrictSUIDSGID = true;
121 RestrictRealtime = true;
122 RestrictNamespaces = true;
123 LockPersonality = true;
124 RemoveIPC = true;
125 SystemCallFilter = [ "@system-service" "~@privileged" ];
126 };
127 };
128 };
129}