Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 180 additions & 1 deletion platform/smallstep-agent.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
updated_at: June 9, 2026
updated_at: July 27, 2026
title: Install the Smallstep Agent
html_title: Install the Smallstep Agent on macOS, Windows, and Linux
description: Install, configure, and deploy the Smallstep Agent on macOS, Windows, and Linux endpoints. Includes manual install, MDM integration, system requirements, and network endpoints.
Expand Down Expand Up @@ -47,6 +47,7 @@ Running into trouble? See the [Smallstep Agent troubleshooting guide](./troubles
- Ubuntu (Current Stable and LTS)
- Debian (Current Releases)
- Fedora (Current Releases)
- NixOS
- `systemd`-based service manager
- A TPM 2.0 module is required. Smallstep depends on TPMs to create a high-assurance device inventory.
- `p11-kit`, `tpm-tss2`
Expand Down Expand Up @@ -284,6 +285,177 @@ curl -fsSL https://packages.smallstep.com/scripts/smallstep-agent-install.sh | s
```


### NixOS

The [`step-agent`](https://search.nixos.org/packages?query=step-agent) package is in nixpkgs, on the `nixos-unstable` channel.
NixOS has no `services.step-agent` module yet,
so the system user, systemd service, and PKCS#11 wiring that the Debian and RPM packages install are declared in your own configuration instead.

<Alert severity="info">
<div>
The agent requires a hardware TPM 2.0 on NixOS.
The Debian and RPM packages fall back to a software TPM on hosts without one,
but the helper scripts that set that up are not part of the nixpkgs package,
so a host with no <code>/dev/tpmrm0</code> cannot enroll yet.
</div>
</Alert>

1. If you track a stable NixOS channel, add an overlay so that `pkgs.step-agent` resolves.
Skip this step on `nixos-unstable`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But nixos-unstable is currently the only channel it's available on?


```nix
nixpkgs.overlays = [
(final: prev: {
inherit
(import (builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz") {
system = prev.stdenv.hostPlatform.system;
config.allowUnfreePredicate = pkg: prev.lib.getName pkg == "step-agent";
})
step-agent
;
})
];
```

2. Save the following as `step-agent.nix` alongside your `configuration.nix`,
and add `./step-agent.nix` to its `imports` list:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is just a static file, let's throw it into S3 and have them download it.


```nix
{ config, lib, pkgs, ... }:

{
# The step-agent package is unfree.
nixpkgs.config.allowUnfreePredicate = pkg: lib.getName pkg == "step-agent";

environment.systemPackages = [ pkgs.step-agent ];

# The agent talks to the TPM from user space, so it needs read/write access
# to the TPM resource manager. This creates the tss group and the udev rules
# that grant that group /dev/tpmrm0.
security.tpm2.enable = true;

users.groups.step-agent = { };
users.users.step-agent = {
isSystemUser = true;
group = "step-agent";
home = "/var/lib/step-agent";
extraGroups = [ "tss" ];
};

# /run/step-agent holds the PKCS#11 and SSH sockets that other users connect
# to. Create it with tmpfiles rather than systemd's RuntimeDirectory=, which
# deletes the directory every time the service stops.
systemd.tmpfiles.rules = [
"d /run/step-agent 0755 step-agent step-agent - -"
];

systemd.services.step-agent = {
description = "Smallstep Agent";
documentation = [ "https://u.step.sm/docs/agent" ];
after = [ "network-online.target" ];
requires = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];

# The agent starts once the device is registered and agent.yaml exists.
unitConfig.ConditionPathIsReadWrite = "/etc/step-agent/agent.yaml";

environment = {
HOME = "/var/lib/step-agent";
RUNTIME_DIRECTORY = "/run/step-agent";
};

serviceConfig = {
Type = "notify";
WatchdogSec = "60s";
ExecStart = "${lib.getExe pkgs.step-agent} start";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
User = "step-agent";
Group = "step-agent";
ConfigurationDirectory = "step-agent";
StateDirectory = "step-agent";
Restart = "always";
RestartSec = 10;

ProtectSystem = true;
ProtectHome = "read-only";
PrivateTmp = true;
SecureBits = "keep-caps";
AmbientCapabilities = [ "CAP_IPC_LOCK" "CAP_CHOWN" "CAP_DAC_OVERRIDE" "CAP_FOWNER" ];
CapabilityBoundingSet = [ "CAP_SYSLOG" "CAP_IPC_LOCK" "CAP_CHOWN" "CAP_DAC_OVERRIDE" "CAP_FOWNER" ];
DeviceAllow = [ "/dev/tpmrm0 rw" ];
ReadWritePaths = [ "-/dev/tpmrm0" ];

LimitNOFILE = 65536;
LimitMEMLOCK = "infinity";
};
};

# Restart the agent when its configuration changes, such as after registering.
systemd.paths.step-agent-restart = {
wantedBy = [ "multi-user.target" ];
pathConfig.PathChanged = "/etc/step-agent/agent.yaml";
};

systemd.services.step-agent-restart.serviceConfig = {
Type = "oneshot";
ExecStart = "${config.systemd.package}/bin/systemctl restart step-agent.service";
};

# Let the agent restart units and manage NetworkManager connections.
security.polkit.enable = true;
security.polkit.extraConfig = ''
polkit.addRule(function(action, subject) {
if (subject.user == "step-agent") {
if (action.id == "org.freedesktop.systemd1.manage-units") {
return polkit.Result.YES;
}
if (action.id.indexOf("org.freedesktop.NetworkManager.") == 0) {
return polkit.Result.YES;
}
}
});
'';

# Publish the agent's PKCS#11 server to p11-kit clients. The module path has
# to be explicit: the agent searches FHS locations that do not exist on NixOS.
environment.etc."pkcs11/modules/step-agent.module".text = ''
module: ${pkgs.p11-kit}/lib/pkcs11/p11-kit-client.so
server-address: unix:path=/run/step-agent/step-agent-pkcs11.sock
'';
}
```

3. Rebuild your system:

```bash
sudo nixos-rebuild switch
```

4. Register the device with your team:

```bash
sudo step-agent register [team name]
```

Registration writes `agent.yaml` into `/etc/step-agent`,
which systemd creates and keeps writable through `ConfigurationDirectory=`.
Do not manage `agent.yaml` with `environment.etc`:
that produces a read-only symlink into the Nix store, and the service refuses to start.

5. Check that it was installed correctly:

```bash
step-agent version
```

Output:

```bash
step-agent/0.67.3 (linux/amd64)
Release Date: 2026-05-19 15:50 UTC
```


## Registering and approving endpoints

### Self-registration
Expand Down Expand Up @@ -327,6 +499,8 @@ sudo systemctl enable --now step-agent
sudo systemctl enable --now step-agent-restart.path
```

On NixOS, `nixos-rebuild switch` enables and starts both units, so skip this step.

If you get any errors, check the agent’s status:

```bash
Expand Down Expand Up @@ -360,6 +534,9 @@ modutil -dbdir ~/.pki/nssdb -add step-agent \
Export `P11_KIT_SERVER_ADDRESS` and point it at the running agent's socket **before** you run `modutil`. `modutil` loads and initializes the module as it adds it, so running it first fails with a load error and can leave a broken module registered in the NSS database. If you hit this, see [Recovering from a failed `modutil` add](./troubleshooting-agent.mdx#recovering-from-a-failed-modutil-add).
</Alert>

On NixOS, `p11-kit-client.so` lives in the Nix store rather than under `/usr/lib`.
Point `modutil` at it with `-libfile $(nix eval --raw nixpkgs#p11-kit)/lib/pkcs11/p11-kit-client.so`.

Next, start Chrome from the command line.

In Chrome, you should now have access to certificates managed by Smallstep.
Expand All @@ -384,6 +561,8 @@ To uninstall the Smallstep Agent from a Linux system:
sudo apt-get remove step-agent
```

**For NixOS:** remove `./step-agent.nix` from your `imports` list, then run `sudo nixos-rebuild switch`.

2. Optionally, remove configuration and certificate files:

```bash
Expand Down
7 changes: 6 additions & 1 deletion platform/troubleshooting-agent.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
updated_at: February 03, 2026
updated_at: July 27, 2026
title: Troubleshooting Guide
html_title: Smallstep Troubleshooting Guide
description: Troubleshoot Smallstep Device Identity issues. Diagnose platform, MDM, and endpoint problems with step-by-step guidance.
Expand Down Expand Up @@ -593,6 +593,11 @@ Quick reference for platform-specific commands and file locations.
| Collect logs | `step-agent logs collect --log-dir /var/lib/step-agent/logs` |
| Agent configuration | `/etc/step-agent/agent.yaml` |

On NixOS these paths are the same, with two differences.
There is no `/usr/bin/step-agent`: the binary is a Nix store path on your `PATH`.
And `step-agent doctor` reports p11-kit as missing unless the client module is registered by its store path,
as shown in [the NixOS install instructions](./smallstep-agent.mdx#nixos).

<Alert severity="info">
If the agent won't start, check for this message in the logs:
```
Expand Down
2 changes: 1 addition & 1 deletion step-cli/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Big shout out to the maintainers of these packages! We appreciate you.

#### NixOS

Install the [`step-cli`](https://search.nixos.org/packages?channel=20.09&show=step-cli&from=0&size=50&sort=relevance&query=step-cli) package on NixOS.
Install the [`step-cli`](https://search.nixos.org/packages?show=step-cli&from=0&size=50&sort=relevance&query=step-cli) package on NixOS.

#### FreeBSD

Expand Down
Loading