Getting the daemon working on NixOS

I recently decided to try out the new atuin daemon since I have been having some trouble with timeouts on zfs.

atuin daemon works fine when launched from the console, however, I’ve been struggling to get it to work as a systemd service. I’ve never set one up before so there’s a good chance I’m getting a few things wrong.

I set up the service with the following NixOS configuration:

systemd.services.atuin = {
  enable = true;

  environment = {
    HOME = "/home/ethan";
    ATUIN_LOG = "info";
  };
  serviceConfig = {
    ExecStart = "${pkgs.atuin}/bin/atuin daemon";
  };
  wantedBy = [ "multi-user.target" ];
  wants = [ "network.target" ];
};

And this atuin/config.toml:

[daemon]
enabled = true
socket_path = "/home/ethan/.local/share/atuin/atuin.sock"

The service starts successfully:

● atuin.service
     Loaded: loaded (/etc/systemd/system/atuin.service; enabled; preset: enabled)
     Active: active (running) since Thu 2024-05-23 22:10:17 BST; 13min ago
   Main PID: 343103 (atuin)
         IP: 19.1K in, 4.0K out
         IO: 0B read, 0B written
      Tasks: 4 (limit: 38415)
     Memory: 8.2M (peak: 8.9M)
        CPU: 89ms
     CGroup: /system.slice/atuin.service
             └─343103 /nix/store/h29ks5ll84qrc8pr56adk4k6xhb96mi7-atuin/bin/atuin daemon

May 23 22:10:17 nixos-desktop systemd[1]: Started atuin.service.
May 23 22:10:17 nixos-desktop atuin[343103]: 2024-05-23T21:10:17.038017Z  INFO atuin_daemon::server: listening on unix socket "/home/ethan/.local/share/atuin/atuin.sock"
May 23 22:10:17 nixos-desktop atuin[343103]: 2024-05-23T21:10:17.038084Z  INFO atuin_daemon::server::sync: booting sync worker
May 23 22:10:17 nixos-desktop atuin[343103]: 2024-05-23T21:10:17.039188Z  INFO atuin_daemon::server::sync: sync worker tick
May 23 22:10:17 nixos-desktop atuin[343103]: 2024-05-23T21:10:17.191047Z  INFO atuin_daemon::server::sync: sync complete uploaded=0 downloaded=[]

However I’m still getting errors after every command:

Error: failed to connect to local atuin daemon. Is it running?

Location:
    /build/source/crates/atuin-daemon/src/client.rs:31:26

Is there something I’m configuring incorrectly?

You’re starting the daemon as a system service; you want it as a user service under your userid. The client failure will be file permissions on the socket.

Oh I see. Thanks that helped.

One other thing I was missing was that I needed to run systemctl status with --user.

In case anyone finds this post with the same struggle, here’s the working configuration I ended up with.

systemd.user.services.atuind = {
  enable = true;

  environment = {
    ATUIN_LOG = "info";
  };
  serviceConfig = {
    ExecStart = "${pkgs.atuin}/bin/atuin daemon";
  };
  after = [ "network.target" ];
  wantedBy = [ "default.target" ];
};

Is it possible to add this service in your home-manager config? I saw an option for home-manager to add a user service, but if I use this option to create this service the daemon won’t start.

This is what I use with h-m:


  systemd.user =
    let
      atuinSockDir = "${config.home.homeDirectory}/.local/share/atuin";
      atuinSock = "${atuinSockDir}/atuin.sock";
      unitConfig = {
        Description = "Atuin Magical Shell History Daemon";
        ConditionPathIsDirectory = atuinSockDir;
        ConditionPathExists = "${config.home.homeDirectory}/.config/atuin/config.toml";
      };
    in
    {
      sockets.atuin-daemon = {
        Unit = unitConfig;
        Install.WantedBy = [ "default.target" ];
        Socket = {
          ListenStream = atuinSock;
          Accept = false;
          SocketMode = "0600";
        };
      };
      services.atuin-daemon = {
        Unit = unitConfig;
        Service.ExecStart = "${pkgs.atuin}/bin/atuin daemon";
      };
    };

Along with the following as part of atuin setup, to use socket activation:


    programs.atuin = {
      enable = true;
      settings = {
        # …
        daemon.enabled = true;
        daemon.systemd_socket = true;
       };
    };

This looks great. I will have to give it a try. Maybe we could even package it for h-m for Atuin, I think. That would make it easier to enable the daemon for everyone.

Yeah I was going to add it to hm once the feature moves out of the “experimental” status; last I knew it was still not intended to be widely used, mostly in case some incompatible change needs to be made. If it has been stabilised since, I missed it.

I think it’s been used by enough people now that we can trust it to be stable. I’ll look at moving it to be better supported in the next release

Sounds great. We could even add the hm option already with a note saying that the daemon support is experimental or something similar. Personally, I do not think there would be a problem with that.

For future reference:
Atuin 18.4.0 introduced a change to the default location of a socket for the daemon.
It uses the socket /run/user/1000/atuin.sock, if XDG_RUNTIME_DIR is set. Relevant PR:

Without home-manager

Use the above-shown manual service and socket configuration. Ideally, set the socket directory to what Atuin should default to:

-      atuinSockDir = "${config.home.homeDirectory}/.local/share/atuin";
+      atuinSockDir = "%t";

See section Context for additional explanation. If you have problems with the daemon timing out, set timeout times in the Atuin config, e.g. as in section With home-manager,

With home-manager

The daemon on NixOS with Atuin 18.4.0 from the nixpkgs with the home-manager module for Atuin and its daemon works correctly now.

The configuration of the home-manager module for Atuin for the daemon is as follows. (Only, I have a strange issue with connectivity where it takes around 8–15 seconds to connect to the server, which by default times out on a timeout of 5 seconds, so I had to modify the Atuin config accordingly (either as a Nix expression, or an imported TOML value) in the module attribute settings.

# Might not be necessary for you.
network_connect_timeout = 60
network_timeout = 60

[daemon]
enabled = true
systemd_socket = true

Notice that we do not define systemd_path, allowing the home-manager to use the new default of ${XDG_RUNTIME_DIR}/atuin.sock if it is set.

With the h-m configuration:

  programs.atuin = {
    enable = true;
    enableBashIntegration = true;
    enableFishIntegration = true;
    enableZshIntegration = true;
    daemon = {
      enable = true;
    };
    settings = lib.importTOML atuin_config_file.toml;
  };

Context

The previous default location (~/.local/share/atuin/atuin.sock) will not work with h-m as it hardcodes the path for Atuin version 18.4.0+ to %t/atuin.sock which is defined as follows:

The %t specifier in systemd service files represents the runtime directory. It is either /run for the root user or the value of the XDG_RUNTIME_DIR variable for unprivileged users.

Yes, I opened https://github.com/atuinsh/atuin/issues/2525 two days ago… :sweat_smile: (sorry, I’m not allowed to post the link)

@Adda @uep Any plans to upstream this config as a simple setting into home-manager?

It’s getting out of hand to track the necessary config across multiple forum posts.

It’s in h-m now, and i switched to just using that.

    atuin = {
      enable = true;
      flags = [ "--disable-up-arrow" ];
      daemon.enable = true;
      settings = {
        dialect = "uk";
        # …
      };
    };