Skip to content

Configuration

  1. Start the login wizard:

    Terminal window
    redmine auth login
  2. Provide your Redmine server URL and authentication method (API key or username/password).

  3. Optionally set a default project — it is prepopulated in project-scoped commands.

  4. The wizard writes a profile to ~/.redmine-cli.yaml. You are ready to go.

You can authenticate against as many Redmine instances as you like. Each redmine auth login creates a named profile.

Terminal window
redmine auth login # second instance
redmine auth login --name work # with an explicit name
  • Directory~/
    • .redmine-cli.yaml active profile + all profile data
    • Directory.local/bin/
      • redmine binary (install script target)
~/.redmine-cli.yaml
active_profile: work
profiles:
work:
server: https://redmine.work.com
auth_method: apikey
api_key: your-api-key
default_project: myproject
output_format: table
personal:
server: https://redmine.personal.com
auth_method: apikey
api_key: another-key
output_format: json

The CLI writes the config file atomically with mode 0600: a new file is written next to it and renamed into place, so an interrupted write never leaves a truncated config. A missing config directory is created with mode 0700. If the config path is a symlink (for example into a dotfiles checkout), the file it points to is updated and the link is kept. A config file you made read-only is never overwritten. A file that cannot be replaced by a rename (for example a config bind-mounted into a container, or one in a directory you cannot write to) is overwritten in place instead.

You can keep the API key (or password) out of the config file and in your operating system keyring instead. It is fully opt-in and backward compatible: existing plaintext profiles keep working unchanged.

  1. Opt in during login. The wizard asks whether to use the keyring when a usable backend is detected on a TTY. For scripted logins use the flag:

    Terminal window
    redmine auth login --keyring
  2. The profile records credential_store: keyring and the secret is written to the keyring, not the file. On the next run the secret is read back from the keyring automatically.

Logging in again for a profile that already uses the keyring keeps the keyring by default; it never silently falls back to the plaintext file. Pass --keyring=false to explicitly switch a profile back to plaintext storage.

The MCP server’s bearer token (mcp.auth_token, see AI agents) is kept in the keyring too. A keyring profile that still has a plaintext mcp.auth_token keeps working: the value in the file is used, and it is moved into the keyring and removed from the file the next time the CLI saves the config (for example on redmine auth login or redmine auth switch). If the keyring is unavailable at that point, the token stays in the file and the save still succeeds. To rotate the token, write the new value into mcp.auth_token; REDMINE_MCP_AUTH_TOKEN and --auth-token still take precedence. Switching the profile back to plaintext moves the token back into the file, and redmine auth logout removes it from the keyring.

Resolution order is CLI flag, then environment variable, then keyring, then the plaintext file field. Environment variables and flags are resolved before the keyring is consulted, so an explicit API key or password means that secret is not read from the keyring.

The MCP token is a separate lookup: on a keyring profile, redmine mcp serve --http reads it from the keyring whenever --auth-token-file, --auth-token, REDMINE_MCP_AUTH_TOKEN and mcp.auth_token all leave it unset, even if the API key came from a flag or environment variable. If that read fails (for example a locked keychain over SSH), or REDMINE_NO_KEYRING=1 disables it, the server refuses to start rather than serve without a token that may exist.

CI friendly

Every setting can be overridden with a REDMINE_-prefixed variable:

Terminal window
export REDMINE_SERVER=https://redmine.example.com
export REDMINE_API_KEY=your-api-key
export REDMINE_AUTH_METHOD=apikey
# opt out of the startup update check
export REDMINE_NO_UPDATE_CHECK=1
# refuse all requests that modify data (read-only mode)
export REDMINE_READ_ONLY=1
# hard-disable the optional system keyring
export REDMINE_NO_KEYRING=1
# wait at most 5 minutes for the server to start responding (default 0: no limit)
export REDMINE_HTTP_TIMEOUT=5m
# hide the environment from --jq expressions (env / $ENV evaluate to {})
export REDMINE_JQ_NO_ENV=1

See Self-Update for details on the update check.

Flags take precedence over config values and environment variables.

Flag Description
-s, --server Redmine server URL
-k, --api-key API key for authentication (visible in process listings; see below)
--api-key-file Read the API key from a file, or from stdin with -
--profile Use a specific auth profile
--config Config file path (default ~/.redmine-cli.yaml)
-o, --output Output format: table, json (see Output formats)
-q, --jq Filter JSON output with a jq expression; implies -o json (see Filtering with –jq)
--no-color Disable colored output
--read-only Refuse all requests that modify data on the server
--header Extra HTTP header as "Name: value" (repeatable)
-v, --verbose Enable debug logging

A key given with --api-key shows up in process listings (ps), shell history, and CI logs. Prefer one of these instead:

Terminal window
redmine --api-key-file ~/.config/redmine/key issues list # read from a file
pass show redmine | redmine --api-key-file - issues list # read from stdin
export REDMINE_API_KEY=your-api-key # environment variable
redmine auth login --keyring # system keyring

--api-key-file trims surrounding whitespace, including the trailing newline, and cannot be combined with --api-key. With -, stdin is consumed by the key, so it cannot also feed a command that reads stdin.

A profile’s stored secret (in the config file or the system keyring) belongs to the server the profile was saved with. If --server or REDMINE_SERVER points the profile at a different origin (scheme, host, or port), the CLI still sends that secret, but prints a warning first:

warning: sending the stored credentials of profile "work" (for https://redmine.work.com) to https://other.example.com; pass --api-key-file or REDMINE_API_KEY explicitly to silence this

Supply the key for the other server explicitly (--api-key-file, REDMINE_API_KEY, or REDMINE_PASSWORD for basic auth) to silence the warning.

A profile’s custom headers can carry tokens for the same server, so they get the same check. The warning names the headers, never their values:

warning: sending the configured headers of profile "work" (for https://redmine.work.com) to https://other.example.com: X-Proxy-Token; pass the headers meant for that server with --header to silence this

A header given with --header on the same command is not checked, since it replaces the profile header of that name.

Point the CLI at a production Redmine without any risk of changing data. When enabled, every request that would modify the server is refused before it is sent; all listing, viewing, and searching commands keep working.

Enable it in any of three ways (precedence: flag > environment variable > config):

Terminal window
redmine --read-only issues list # single invocation
export REDMINE_READ_ONLY=1 # whole shell session
~/.redmine-cli.yaml
profiles:
prod:
server: https://redmine.example.com
auth_method: apikey
api_key: your-api-key
read_only: true

Pass --read-only=false to override the environment variable or a read_only: true profile for a single invocation.

Some servers sit behind a firewall or reverse proxy that expects extra request headers, for example a browser-like User-Agent or an access token. Add them per profile under headers:

~/.redmine-cli.yaml
profiles:
work:
server: https://redmine.work.com
auth_method: apikey
api_key: your-api-key
headers:
User-Agent: Mozilla/5.0
X-Proxy-Token: your-proxy-token

For a single invocation, pass --header (repeatable). It overrides a profile header with the same name:

Terminal window
redmine --header "User-Agent: Mozilla/5.0" issues list

Passed to redmine auth login, the headers are used for the connection test and saved to the profile, so a server that requires them works from the first login:

Terminal window
redmine auth login --header "User-Agent: Mozilla/5.0"

Logging in again keeps a profile’s headers as long as the server’s host stays the same. If you point the profile at a different server, its headers are dropped, since they may be secrets meant for the old one. To remove a header, delete it from the config file.

Headers are only sent to the configured server, never to hosts it redirects to. Authentication headers always take precedence. Headers the HTTP client manages itself (Host, Content-Type, Content-Length, Transfer-Encoding, Connection, Accept-Encoding) cannot be configured, and empty values are rejected. Without a configured User-Agent, the CLI identifies itself as redmine-cli/<version>.

Use an https:// server URL where you can. Plain http:// is supported, for example for an internal instance, but the API key or password then crosses the network unencrypted. redmine auth login points this out once when you enter a plain http:// URL for a host other than loopback (localhost and names under it such as dev.localhost, 127.0.0.0/8, ::1); other commands connect without a warning.

Redirects are followed up to 10 hops. A redirect from https:// to http:// is always refused, so a connection that starts encrypted is never downgraded. Credentials and custom headers are only sent when both the scheme and the host (including the port) match the configured server; the one exception is an http:// server redirecting to https:// on the same host. A redirect away from the configured server is refused when it leads to a loopback, private or otherwise non-public address, for API requests (including redmine api) and attachment downloads alike; see attachments download for the full rules.

Connecting to the server times out after 30 seconds and the TLS handshake after 15 seconds. By default there is no limit on how long the server may take to start responding, so slow queries on a busy Redmine still complete, and no limit on total request time, so large attachment downloads keep streaming as long as data arrives. To give up on a server that stops answering, set REDMINE_HTTP_TIMEOUT to a Go duration such as 90s or 5m; it bounds the wait for the response to start (0, the default, means no limit).

API responses are capped at 256 MiB, and at most 1 MiB of an error response is read. Attachment downloads are not size-limited, since they are streamed to disk.

Terminal window
redmine config

Prints the active profile, server, auth method, default project, output format, read-only state, and the names of configured headers (values are hidden).