Securing the LINSTOR REST API with Token Authentication

LINSTOR® 1.34 introduces bearer token authentication, a straightforward way to restrict access to its REST API. Before this release, securing the API required setting up LDAP integration or mutual TLS client certificates, both of which add operational complexity. Token authentication gives you the same access control with far less setup. A single command enables it, and tokens are easy to create, distribute, and revoke.

This article walks through enabling token authentication on a LINSTOR® cluster, explains how token distribution works for satellite nodes, and demonstrates what happens when a request arrives without a valid token.

❗ IMPORTANT: Token authentication is available from LINSTOR® 1.34 onward. If you are running an older release, upgrade before proceeding.

How token authentication works

When token authentication is enabled, every request to the LINSTOR controller REST API must include a valid bearer token in the Authorization HTTP header. Tokens are randomly generated 32-character strings. Only the SHA-256 hash of each token is stored on the controller. The raw value is displayed once at creation time and never again.

There are two categories of token:

User tokens (UserToken: Yes)
Used by administrators, automation, and any system that needs to manage the cluster through the linstor CLI or the REST API directly. These are created and distributed manually.
Satellite tokens (UserToken: No)
Used by the linstor-satellite service on each satellite node to authenticate its connection back to the controller. These are created and distributed automatically when running the init command.

The init command handles setup for both in one step.

Initializing token authentication

Before running init, create the LINSTOR client configuration directory if it does not already exist, so that the initial token can be saved automatically:

mkdir -p ~/.config/linstor

Then run the initialization command on the controller node:

linstor controller auth init 'admin-initial'

The output will look similar to the following example, confirming the token was saved and displaying its raw value:

Token saved to config file: /home/vagrant/.config/linstor/linstor-client.conf
SUCCESS:
    Token authentication initialized successfully. Init token ZbifiKRFVjiSlXh8dfECBDkeEL7hsCCU

This single command does several things:

  • Enables token authentication on the LINSTOR controller node
  • Automatically enables HTTPS on the REST API and generates a self-signed certificate
  • Creates the first user token with the given description and saves it to ~/.config/linstor/linstor-client.conf
  • Creates individual satellite tokens and distributes them to every connected satellite node, saving each to /var/lib/linstor.d/auth.json on that satellite node

❗ IMPORTANT: The raw token string is only shown once. If you lose it, you will need to create a new one with linstor controller auth create.

The init command accepts a few options worth knowing about:

--no-https
Skip automatic HTTPS setup. Use this if you have already configured HTTPS manually.
--only-satellites
Only regenerate and redistribute satellite tokens. Useful if you need to re-initialize satellite tokens without affecting existing user tokens.
--do-not-save-token
Do not write the new token to the client configuration file.

Verifying the setup

After initialization, the linstor CLI on the controller node will authenticate automatically using the saved token. Next, confirm the cluster is still accessible.

linstor node list

The output will look similar to the following example, with all nodes showing as Online:

+--------------------------------------------------------------------------+
| Node      | Platform | NodeType   | Addresses                   | State  |
|==========================================================================|
| linstor-0 |          | CONTROLLER | 192.168.223.10:3370 (PLAIN) | Online |
| linstor-1 | LINUX    | SATELLITE  | 192.168.223.11:3366 (PLAIN) | Online |
| linstor-2 | LINUX    | SATELLITE  | 192.168.223.12:3366 (PLAIN) | Online |
| linstor-3 | LINUX    | SATELLITE  | 192.168.223.13:3366 (PLAIN) | Online |
+--------------------------------------------------------------------------+

List all active tokens, including the automatically created satellite tokens, with the --all flag:

linstor controller auth list --all

The output will look similar to the following example, showing both the user token and the individual satellite tokens with their IP address filters:

+------------------------------------------------------------------------------------------------+
| ID | Description         | Created             | Active | UserToken | IpFilter       | Expires |
|================================================================================================|
| 11 | admin-initial       | 2026-06-02 14:25:39 | Yes    | Yes       | -              | -       |
| 12 | satellite:linstor-1 | 2026-06-02 14:25:39 | Yes    | No        | 192.168.223.11 | -       |
| 13 | satellite:linstor-2 | 2026-06-02 14:25:39 | Yes    | No        | 192.168.223.12 | -       |
| 17 | satellite:linstor-3 | 2026-06-02 14:32:11 | Yes    | No        | 192.168.223.13 | -       |
+------------------------------------------------------------------------------------------------+

Notice that each satellite token has an IP address filter automatically applied. Token ID 12 is only accepted from 192.168.223.11, and so on. This means a satellite token cannot be used from any other address, even if the raw value were somehow obtained. Satellite tokens are also rotated automatically each time a satellite reconnects to the controller.

Distributing tokens to other nodes

The linstor CLI on any node other than the controller needs a user token to reach the API. On each node that should have administrative access, create the client configuration directory and write the token.

mkdir -p ~/.config/linstor
cat > ~/.config/linstor/linstor-client.conf << EOF
[global]
controllers = 192.168.223.10
auth-token = ZbifiKRFVjiSlXh8dfECBDkeEL7hsCCU
EOF

📝 NOTE: Satellite nodes that have been connected to the controller since initialization already have a token in /var/lib/linstor.d/auth.json. The linstor CLI on a satellite node will automatically fall back to this file if no auth-token is set in the client configuration. This means satellite nodes have implicit CLI access unless the auth.json file is explicitly removed, which will also disconnect the satellite service from the controller. For this reason, restricting CLI access on satellite nodes is best done at the network or operating system level rather than by using token management alone.

Managing tokens

After initialization, you can create additional tokens for other systems or users, list existing tokens, temporarily disable them, or revoke them entirely.

Creating additional tokens

To create a token for an additional system, such as a monitoring agent that needs read access, use controller auth create:

linstor controller auth create 'monitoring-system' --expires-at 2026-12-31

The output will look similar to the following example, displaying the raw token value that must be copied before moving on:

SUCCESS:
    Auth token created successfully: wNW4iqX2HJHXEOCVHhyZKDVfDr7rmlYw

Unlike init, the create command does not save the token to the client configuration by default. Copy the printed token value before moving on. It will not be shown again. Use --save-token to overwrite the current entry in ~/.config/linstor/linstor-client.conf if needed.

Available options for controller auth create:

--ip-filter <filter>
Restrict the token to requests from a specific IP address or range.
--expires-at <date>
Set an expiry date in ISO 8601 format (for example, 2026-12-31). After this date the token is rejected.
--save-token
Save the token to the client configuration file.

Listing tokens

linstor controller auth list

The output will look similar to the following example, listing only user tokens by default:

+-------------------------------------------------------------------------------------------+
| ID | Description       | Created             | Active | UserToken | IpFilter | Expires    |
|===========================================================================================|
| 11 | admin-initial     | 2026-06-02 14:25:39 | Yes    | Yes       | -        | -          |
| 20 | monitoring-system | 2026-06-02 14:47:23 | Yes    | Yes       | -        | 2026-12-31 |
+-------------------------------------------------------------------------------------------+

Without --all, only user tokens are shown. Add --all to include satellite tokens.

Modifying a token

To temporarily disable a token without revoking it, use controller auth modify and specify the token ID:

linstor controller auth modify 20 --active false

The output will look similar to the following example:

SUCCESS:
    Auth token modified successfully

Set --active true to re-enable it. You can also update --description or --ip-filter (pass an empty string '' to remove an existing IP filter).

Revoking a token

linstor controller auth delete 20

The output will look similar to the following example:

SUCCESS:
    Auth token revoked successfully

Revoked tokens are permanently invalidated and cannot be re-enabled.

Using a token

There are three ways to present a token to the API.

Client configuration file

The recommended approach is to save the token in ~/.config/linstor/linstor-client.conf:

[global]
controllers = 192.168.223.10
auth-token = ZbifiKRFVjiSlXh8dfECBDkeEL7hsCCU

The linstor CLI reads this file on every invocation, so no additional flags are needed.

Command-line argument

Pass the token directly for a one-off command without modifying the configuration file:

linstor --auth-token ZbifiKRFVjiSlXh8dfECBDkeEL7hsCCU node list

REST API header

When calling the LINSTOR REST API directly, include the token as a bearer token in the Authorization header:

curl -sk \
  -H 'Authorization: Bearer ZbifiKRFVjiSlXh8dfECBDkeEL7hsCCU' \
  https://192.168.223.10:3371/v1/nodes

Access control in practice

With token authentication enabled, any request that arrives without a valid token is rejected with HTTP 401:

curl -sk -o /dev/null -w '%{http_code}\n' \
  https://192.168.223.10:3371/v1/nodes

The output will show that the request was rejected:

401

A request carrying a valid bearer token succeeds:

curl -sk -o /dev/null -w '%{http_code}\n' \
  -H 'Authorization: Bearer ZbifiKRFVjiSlXh8dfECBDkeEL7hsCCU' \
  https://192.168.223.10:3371/v1/nodes

The output will confirm that the LINSTOR controller accepted the request:

200

Recovering from a lockout

If all user tokens are lost or revoked and you can no longer reach the API, the linstor-config tool can remove the token authentication setting directly from the database. Stop the controller service before running it.

systemctl stop linstor-controller
/usr/share/linstor-server/bin/linstor-config disable-token-auth
systemctl start linstor-controller

The output will confirm that token authentication was disabled:

Loading configuration file "/etc/linstor/linstor.toml"
Token authentication disabled.
Please restart the linstor-controller for this to take effect.

After restarting, the REST API is accessible without authentication. You can then enter a linstor controller auth init command again to re-enable it and generate fresh tokens.

📝 NOTE: Revoking or expiring every user token will lock you out of the API. Besides the linstor-config disable-token-auth procedure above, you can recover without controller downtime by using a satellite node’s existing token in /var/lib/linstor.d/auth.json to create a new user token.

Conclusion

Token authentication in LINSTOR® 1.34 closes a gap that previously required either leaving the REST API open on trusted networks or using more complex LDAP or mutual TLS setups. A single linstor controller auth init command enables HTTPS, secures the REST API, and distributes credentials to all satellite nodes, making it practical to lock down a cluster in minutes rather than hours.

You can scope tokens with IP address filters and expiration dates, which makes it straightforward to issue short-lived credentials to automation systems without granting permanent access.

LINSTOR is open source software that you can install by compiling it from source code or by using public package repositories available from some Linux distributions such as Ubuntu, Debian, and Proxmox VE. If you are new to LINSTOR® and want to try it out by using the convenience of official LINBIT customer packages and deployment tools, reach out to the LINBIT® team to request evaluation access to the LINBIT® container registry and customer repositories.

Picture of Matt Kereczman

Matt Kereczman

Matt Kereczman is a Solutions Architect at LINBIT with a long history of Linux System Administration and Linux System Engineering. Matt is a cornerstone in LINBIT's technical team, and plays an important role in making LINBIT and LINBIT's customer's solutions great. Matt was President of the GNU/Linux Club at Northampton Area Community College prior to graduating with Honors from Pennsylvania College of Technology with a BS in Information Security. Open Source Software and Hardware are at the core of most of Matt's hobbies.

Talk to us

LINBIT is committed to protecting and respecting your privacy, and we’ll only use your personal information to administer your account and to provide the products and services you requested from us. From time to time, we would like to contact you about our products and services, as well as other content that may be of interest to you. If you consent to us contacting you for this purpose, please tick above to say how you would like us to contact you.

You can unsubscribe from these communications at any time. For more information on how to unsubscribe, our privacy practices, and how we are committed to protecting and respecting your privacy, please review our Privacy Policy.

By clicking submit below, you consent to allow LINBIT to store and process the personal information submitted above to provide you the content requested.

Talk to us

LINBIT is committed to protecting and respecting your privacy, and we’ll only use your personal information to administer your account and to provide the products and services you requested from us. From time to time, we would like to contact you about our products and services, as well as other content that may be of interest to you. If you consent to us contacting you for this purpose, please tick above to say how you would like us to contact you.

You can unsubscribe from these communications at any time. For more information on how to unsubscribe, our privacy practices, and how we are committed to protecting and respecting your privacy, please review our Privacy Policy.

By clicking submit below, you consent to allow LINBIT to store and process the personal information submitted above to provide you the content requested.