Source: https://help.spamfoo.com/guides/commands
Last updated: 2026-10-27

***

# Use SpamFoo Client Commands

The `spamfoo-client` program has commands for common admin tasks: making a sign-in link, adding a license key, checking that the service is ready, and changing the proxy secret. This page explains each one.

- Commands work on the files in the data directory, so most of them also work while the service is stopped. Only `status` contacts the running service.
- Running `spamfoo-client` with no command, or with `run`, starts the service instead.
- To see the commands and options on the server, run `spamfoo-client help`.

## Run a Command

How you run a command depends on how you installed SpamFoo Client:

### Docker

Run it inside the running container. It uses `/data` as the data directory. Use the service name from your compose file, or the container name with `docker exec`.

```
docker compose exec spamfoo-client spamfoo-client login-link
docker exec spamfoo-client spamfoo-client login-link
```

### Archive

Run the program from the install folder and pass the data directory. On Linux, run it as root.

```
sudo /opt/spamfoo/spamfoo-client login-link --data-dir=/var/lib/spamfoo
```

When root runs a command on Linux, the files it writes are given to the owner of the folder they're in, so the service can still read them.

### Options for Every Command

Write options as `--name=value` or `--name value`.

| Option | What It Does |
| --- | --- |
| `--data-dir=<path>` | The data directory. Without it, the command uses `/data` in a container, `/var/lib/spamfoo` with the Linux package, and the program's own folder otherwise. |
| `--conf=<path>` | The settings file to read. The command reads the same settings file as the service. See [Settings File](https://help.spamfoo.com/guides/configure#settings-file). |
| `--mode=standalone` | Confirms that the data directory belongs to a SpamFoo Client in standalone mode. See [Commands for Standalone Mode](https://help.spamfoo.com/guides/commands#standalone-only). |
| `--port=<number>` | The port the service listens on, if it isn't 16253. |

## Make a Sign-In Link

```
spamfoo-client login-link [options]
```

Prints a one-time link to the dashboard. Whoever opens the link and clicks **Continue** is signed in with the role in the link. The command makes the link from the proxy secret file, so it works even while the service is stopped.

| Option | What It Does |
| --- | --- |
| `--role=<role>` | `SystemAdmin` (the default), `DomainAdmin`, or `User`. |
| `--domain=<domain>` | The domain a Domain Admin manages. Repeat the option, or separate domains with commas, to give more than one. |
| `--email=<address>` | The mailbox for a User. Required for `User`. Optional for the other roles. |
| `--minutes=<number>` | How long the link can be used, from 1 to 1440 minutes. The default is 15. |
| `--return-path=<path>` | A dashboard page to open after sign-in, starting with `/admin/`. |
| `--url=<address>` | The address the link starts with, such as `http://spamfoo.example.com:16253`. |

Examples:

```
spamfoo-client login-link --role=DomainAdmin --domain=example.com,example.org
spamfoo-client login-link --role=User --email=pat@example.com --minutes=60
```

- The link starts with `--url`. Without it, the link uses [`SPAMFOO_PUBLIC_URL`](https://help.spamfoo.com/guides/configure#public-url) in standalone mode. Otherwise it uses `http://localhost` and the port, and the command prints a note.
- Each link works once. Changing the proxy secret stops every unused link.
- For what each role sees, see [Manage Sign-In and Roles](https://help.spamfoo.com/guides/roles).

> **Warning** Treat a sign-in link like a password until it's used or expires. Anyone who opens it first gets its access.

## Add a License Key

```
spamfoo-client activate --file=/root/spamfoo-key.txt
spamfoo-client activate --stdin < /root/spamfoo-key.txt
```

Saves the license key to `etc/sf.key` in the data directory, readable only by its owner. The key is read from a file or from standard input, never typed after the command, so it stays out of your shell history.

- A running service in standalone mode picks up the key within a few seconds. Check with [`status`](https://help.spamfoo.com/guides/commands#status).
- If `SPAMFOO_LICENSE_KEY` is set, the command warns you, because the environment variable wins over the file.
- In Docker, pass the file with `docker compose exec -T spamfoo-client spamfoo-client activate --stdin < spamfoo-key.txt`.

## Check Readiness

```
spamfoo-client status
```

Shows whether a license key is set up, then asks the running service whether it's ready to classify mail. It prints one of these lines:

- `ready`: SpamFoo Client is ready. The exit code is 0.
- `not ready`, with the reasons: SpamFoo Client is running but can't classify mail yet. The exit code is 1.
- `down`: nothing answered. The exit code is 2.

The exit codes make it easy to use `status` in scripts. It checks the same thing as [`/health/ready`](https://help.spamfoo.com/api/health#ready).

## Change the Proxy Secret

```
spamfoo-client rotate-secret
```

Writes a new random proxy secret to `etc/sf.proxysecret`. In standalone mode, the running service picks it up within a few seconds.

- Everyone signed in to the dashboard is signed out, and unused sign-in links stop working.
- Mail servers can keep using the old secret for 15 minutes. Give them the new one before then.
- If `SPAMFOO_PROXY_SECRET` is set, the command does nothing, because the environment variable wins over the file. Change the variable instead.

See [Change the Secret](https://help.spamfoo.com/guides/roles#change-the-secret).

## Print the Connection String

```
spamfoo-client connection-string [--url=<address>]
```

Prints the server's address and the proxy secret together as one value that starts with `spamfoo+http://` or `spamfoo+https://`. The address follows the same rules as [`login-link`](https://help.spamfoo.com/guides/commands#login-link). The same value is on the **Connection string** card on **System > Status** in standalone mode.

Use it to connect SmarterMail to this SpamFoo Client: paste it into the setup card for SpamFoo in SmarterMail. Use `--url`, or set `SPAMFOO_PUBLIC_URL`, so the address is one SmarterMail can reach. See [Use SpamFoo Client on Another Server](https://help.spamfoo.com/integrations/smartermail/setup#external-client).

> **Warning** The connection string contains the proxy secret. Treat it like a password.

## Commands for Standalone Mode

`activate` and `rotate-secret` only change a SpamFoo Client in standalone mode. They refuse to run unless one of these is true:

- The settings file or the environment sets `SPAMFOO_MODE=standalone`.
- You add `--mode=standalone` to the command.
- The command found the data directory on its own, as it does with the Linux package and Docker.

They never change a SpamFoo Client that SmarterMail runs. SmarterMail manages its license key and secret itself.

## Exit Codes

| Code | Meaning |
| --- | --- |
| `0` | The command worked. |
| `1` | The command failed, or `status` found the service not ready. |
| `2` | `status` got no answer from the service. |
| `64` | The command or an option was wrong. The message says which. |
| `78` | A setting is wrong, or the command can't read the settings file. With the Linux package, run commands as root. |
