Configuration

Configuration

SSH-Frontière uses a TOML file to declare domains, actions, access levels, arguments, and authentication tokens.

Location

Default path: /etc/ssh-frontiere/config.toml

Override (by priority order):

  1. --config <path> in the command= line of authorized_keys
  2. Environment variable SSH_FRONTIERE_CONFIG
  3. Default path

Recommended permissions: root:forge-runner 640 (adjust the group to your service account).

File structure

[global]                              # General settings
[domains.<id>]                        # Functional domains
  [domains.<id>.actions.<id>]         # Authorized actions
    [domains.<id>.actions.<id>.args]  # Named arguments (optional)
[auth]                                # RBAC authentication (optional)
  [auth.tokens.<id>]                  # Tokens with secret, level, and tags

[global] section

KeyTypeDefaultDescription
log_filestringrequiredPath to JSON log file
default_timeoutinteger300Default timeout in seconds
max_stdout_charsinteger65536Stdout limit (64 KB)
max_stderr_charsinteger16384Stderr limit (16 KB)
max_output_charsinteger131072Global hard limit (128 KB)
max_stream_bytesinteger10485760Streaming volume limit (10 MB)
timeout_sessioninteger3600Session keepalive timeout
max_auth_failuresinteger3Auth attempts before lockout
ban_commandstring""IP ban command (placeholder {ip})
log_commentsboolfalseLog client # lines
expose_session_idboolfalseDisplay session UUID in banner

The keys log_level, default_level, and mask_sensitive are accepted by the parser for backward compatibility with older configurations, but are no longer used.

[domains] section

A domain is a functional scope (e.g., forgejo, infra, notify). Each domain contains authorized actions.

[domains.forgejo]
description = "Git forge infrastructure"

[domains.forgejo.actions.backup-config]
description = "Backup the configuration"
level = "ops"
timeout = 600
execute = "sudo /usr/local/bin/backup-config.sh {domain}"
max_body_size = 65536       # Body limit (64 KB, optional)

Each action accepts the following keys: description (required), level (required), execute (required), timeout (optional, overrides global), tags (optional), max_body_size (optional, default 65536 bytes — limited for the +body protocol).

Trust levels

Strict hierarchy: read < ops < admin

LevelUsage
readRead-only: healthcheck, status, list
opsRoutine operations: backup, deploy, restart
adminAll actions + administration

Arguments

Arguments are declared as a TOML dictionary:

[domains.forgejo.actions.deploy.args]
tag = { type = "enum", values = ["latest", "stable", "canary"], default = "latest" }
FieldTypeDescription
typestring"enum" or "string"
valueslistAllowed values (for enum)
defaultstringDefault value (makes the argument optional)
sensitiveboolIf true, masked in logs
freeboolIf true, accepts any value without constraint

Placeholders in execute

PlaceholderDescription
{domain}Domain name (always available)
{arg_name}Value of the corresponding argument

Visibility tags

Tags filter access to actions horizontally. An action without tags is accessible to everyone. An action with tags is only accessible to identities whose tags share at least one tag in common.

[domains.forgejo.actions.deploy]
# ...
tags = ["forgejo", "deploy"]

[auth] section (optional)

RBAC authentication enables privilege escalation via challenge-response:

[auth]
challenge_nonce = false              # true = anti-replay nonce mode

[auth.tokens.runner-ci]
secret = "b64:c2VjcmV0LXJ1bm5lci1jaQ=="   # Base64-encoded secret
level = "ops"                               # Granted level
tags = ["forgejo"]                          # Visibility tags

The secret must be prefixed with b64: and base64-encoded. To generate a secret:

echo -n "my-random-secret" | base64
# bXktcmFuZG9tLXNlY3JldA==

Load-time validation

Configuration is fully validated at each load (fail-fast). On error, the program exits with code 129. Validations:

Complete example

[global]
log_file = "/var/log/ssh-frontiere/commands.json"
default_timeout = 300
max_stdout_chars = 65536
max_stderr_chars = 16384
max_output_chars = 131072
timeout_session = 3600
max_auth_failures = 3

[domains.forgejo]
description = "Git forge infrastructure"

[domains.forgejo.actions.backup-config]
description = "Backup the Forgejo configuration"
level = "ops"
timeout = 600
execute = "sudo /usr/local/bin/backup-config.sh {domain}"

[domains.forgejo.actions.deploy]
description = "Deployment with version tag"
level = "ops"
timeout = 300
execute = "sudo /usr/local/bin/deploy.sh {domain} {tag}"

[domains.forgejo.actions.deploy.args]
tag = { type = "enum", values = ["latest", "stable", "canary"], default = "latest" }

[domains.infra]
description = "Server infrastructure"

[domains.infra.actions.healthcheck]
description = "Service health check"
level = "read"
timeout = 30
execute = "/usr/local/bin/healthcheck.sh"

[auth]
challenge_nonce = false

[auth.tokens.runner-ci]
secret = "b64:c2VjcmV0LXJ1bm5lci1jaQ=="
level = "ops"
tags = ["forgejo"]

For a detailed guide with all use cases, see the complete configuration guide in the repository.


Next: Deployment — put into production.