@jaspermayone.com's dotfiles
1# modules/atuin-server/default.nix
2# NixOS module for self-hosted Atuin sync server
3{
4 lib,
5 config,
6 pkgs,
7 ...
8}:
9let
10 cfg = config.atelier.services.atuin-server;
11in
12{
13 options.atelier.services.atuin-server = {
14 enable = lib.mkEnableOption "Atuin sync server";
15
16 hostname = lib.mkOption {
17 type = lib.types.str;
18 example = "atuin.example.com";
19 description = "Hostname for the Atuin server.";
20 };
21
22 port = lib.mkOption {
23 type = lib.types.int;
24 default = 8888;
25 description = "Internal port for the Atuin server.";
26 };
27
28 openRegistration = lib.mkOption {
29 type = lib.types.bool;
30 default = true;
31 description = "Whether to allow new user registrations.";
32 };
33
34 dataDir = lib.mkOption {
35 type = lib.types.path;
36 default = "/var/lib/atuin-server";
37 description = "Directory for Atuin server data (SQLite database).";
38 };
39
40 cloudflareCredentialsFile = lib.mkOption {
41 type = lib.types.path;
42 description = "Path to Cloudflare API credentials file for ACME.";
43 };
44 };
45
46 config = lib.mkIf cfg.enable {
47 # Systemd service for Atuin server
48 systemd.services.atuin-server = {
49 description = "Atuin Sync Server";
50 after = [ "network.target" ];
51 wantedBy = [ "multi-user.target" ];
52
53 environment = {
54 ATUIN_HOST = "127.0.0.1";
55 ATUIN_PORT = toString cfg.port;
56 ATUIN_OPEN_REGISTRATION = lib.boolToString cfg.openRegistration;
57 ATUIN_DB_URI = "sqlite://${cfg.dataDir}/atuin.db";
58 };
59
60 serviceConfig = {
61 Type = "simple";
62 ExecStart = "${pkgs.atuin}/bin/atuin server start";
63 Restart = "on-failure";
64 User = "atuin";
65 Group = "atuin";
66 WorkingDirectory = cfg.dataDir;
67
68 # Hardening
69 CapabilityBoundingSet = "";
70 NoNewPrivileges = true;
71 ProtectSystem = "strict";
72 ProtectHome = true;
73 PrivateTmp = true;
74 PrivateDevices = true;
75 ProtectKernelTunables = true;
76 ProtectKernelModules = true;
77 ProtectControlGroups = true;
78 LockPersonality = true;
79 ReadWritePaths = [ cfg.dataDir ];
80 };
81 };
82
83 # System user for Atuin
84 users.users.atuin = {
85 isSystemUser = true;
86 group = "atuin";
87 home = cfg.dataDir;
88 createHome = true;
89 };
90 users.groups.atuin = { };
91
92 # Caddy reverse proxy
93 services.caddy.virtualHosts.${cfg.hostname} = {
94 extraConfig = ''
95 tls {
96 dns cloudflare {env.CLOUDFLARE_API_TOKEN}
97 }
98 reverse_proxy localhost:${toString cfg.port}
99 '';
100 };
101 };
102}