Configuration

formae is configured using a Pkl configuration file that controls agent behavior, datastore settings, discovery, synchronization, logging, and observability.

Configuration Format

The configuration file uses Pkl syntax and amends the base formae:/Config.pkl schema, which provides validation and defaults for all settings.


Default Configuration

The configuration file is located at $HOME/.config/formae/formae.conf.pkl. If no configuration file exists, formae uses default settings. The config file is not automatically created. Create one if you want to customize settings.

To create a minimal configuration file:

amends "formae:/Config.pkl"

agent {
}

cli {
}

Complete Configuration Reference

Below is a complete configuration showing all available options with their defaults:

amends "formae:/Config.pkl"

agent {
    server {
        nodename = "formae"
        hostname = "localhost"
        port = 49684
        secret = ""
        tlsCert = null
        tlsKey = null
    }

    datastore {
        datastoreType = "sqlite"
        sqlite {
            filePath = "~/.pel/formae/data/formae.db"
        }
        postgres {
            host = "localhost"
            port = 5432
            user = "postgres"
            password = "admin"
            database = ""
            schema = ""
            connectionParams = ""
        }
        auroraDataAPI {
            clusterArn = ""
            secretArn = ""
            database = ""
            region = ""
        }
        mssql {
            host = ""
            port = 1433
            database = ""
            authMode = "sql"
            user = ""
            password = ""
            encrypt = true
            trustServerCertificate = false
            connectionParams = ""
            maxOpenConns = 4
            connMaxLifetime = 1.h
        }
    }

    synchronization {
        enabled = true
        interval = 5.min
    }

    discovery {
        enabled = true
        labelTagKeys = new Listing {
            "Name"
        }
        interval = 10.min
        resourceTypesToDiscover = new Listing { }
    }

    logging {
        filePath = "~/.pel/formae/log/formae.log"
        fileLogLevel = "debug"
        consoleLogLevel = "info"
    }

    oTel {
        enabled = false
        serviceName = "formae-agent"
        otlp {
            enabled = true
            endpoint = "http://localhost:4317"
            protocol = "grpc"
            insecure = true
            temporality = "delta"
        }
        prometheus {
            enabled = true
        }
    }

    retry {
        statusCheckInterval = 10.s
        maxRetries = 9
        retryDelay = 10.s
    }
}

cli {
    api {
        url = "http://localhost"
        port = 49684
    }
}

pluginDir = "~/.pel/formae/plugins"

artifacts {
    repositories {
        new {
            uri = "https://hub.platform.engineering/repos/platform.engineering/pel#stable"
            type = "binary"
        }
        new {
            uri = "https://hub.platform.engineering/repos/platform.engineering/community#stable"
            type = "formae-plugin"
        }
    }
}

Several optional sections are omitted above because they have no defaults: Authentication (agent.auth, cli.auth), Resource plugins (agent.resourcePlugins), and Network (top-level network). See the respective sections below to configure them.


Configuration Reference

Server Settings

Controls the agent's network configuration and cluster identity. Essential for multi-agent deployments.

Property Type Default Description
nodename String "formae" Unique identifier for this agent in the cluster
hostname String "localhost" Network interface where the agent listens for incoming connections
port Number 49684 Port number for the agent API
secret String "" Cluster-wide authentication token for secure agent communication
tlsCert String? null Path to TLS certificate file for secure connections
tlsKey String? null Path to TLS private key file for secure connections

Datastore

Choose between SQLite (default, suitable for single-agent), PostgreSQL (recommended for production with high availability requirements), Aurora Data API (for AWS deployments), or Microsoft SQL Server (for Azure deployments, including Azure SQL Database).

Property Type Default Description
datastoreType String "sqlite" Type of datastore to use: "sqlite", "postgres", "auroradataapi", or "mssql"

SQLite Configuration:

Property Type Default Description
filePath String "~/.pel/formae/data/formae.db" Path to the SQLite database file

PostgreSQL Configuration:

Property Type Default Description
host String "localhost" PostgreSQL server hostname
port Number 5432 PostgreSQL server port
user String "postgres" Database user for authentication
password String "admin" Database password for authentication
database String "" Database name to connect to
schema String "" PostgreSQL schema to use
connectionParams String "" Additional connection parameters

Aurora Data API Configuration:

Use Aurora Data API for data access via AWS RDS Data API.

Property Type Default Description
clusterArn String "" ARN of the Aurora Serverless cluster
secretArn String "" ARN of the Secrets Manager secret containing database credentials
database String "" Database name to connect to
region String "" AWS region where the cluster is located (uses default region if empty)

Microsoft SQL Server Configuration:

Use Microsoft SQL Server for self-hosted SQL Server instances or Azure SQL Database.

Property Type Default Description
host String "" SQL Server hostname (for Azure SQL Database, the fully qualified server name, e.g. myserver.database.windows.net)
port Number 1433 SQL Server port
database String "" Database name to connect to
authMode String "sql" Authentication mode: "sql" (username and password) or "workload-identity" (Azure AD workload identity)
user String "" Database user for SQL authentication
password String "" Database password for SQL authentication
encrypt Boolean true Encrypt the connection with TLS
trustServerCertificate Boolean false Accept the server certificate without validation (use only for development and testing)
connectionParams String "" Additional connection parameters
maxOpenConns Number 4 Maximum number of open connections in the pool
connMaxLifetime Duration 1.h Maximum lifetime of a pooled connection

With authMode = "workload-identity", the agent authenticates using the Azure AD workload identity available in its runtime environment, and the user and password properties are ignored. This is the recommended mode for Azure SQL Database when the agent runs on Azure infrastructure with a managed identity.


Synchronization

Enable synchronization of managed resources. When enabled, formae periodically checks if resources have been modified outside of the tool.

Property Type Default Description
enabled Boolean true Enable synchronization of managed resources
interval Duration 5.min How frequently to check for external changes

Discovery

Automatically finds and catalogs infrastructure resources not yet under formae management. Useful for onboarding existing infrastructure.

Discovery scans targets that have been marked as discoverable = true in your forma files. See the discovery documentation for details on configuring discoverable targets.

Property Type Default Description
enabled Boolean true Enable automatic resource discovery
labelTagKeys List<String> ["Name"] Tag keys to use when building resource labels (concatenated with dashes)
interval Duration 10.min How frequently to run discovery scans
resourceTypesToDiscover List<String> [] Specific resource types to discover (empty list discovers all supported types)

Logging

Configure log output levels and file locations. Keep file log level at debug for troubleshooting support.

Property Type Default Description
filePath String "~/.pel/log/formae.log" Path to the log file
fileLogLevel String "debug" Log level for file output: "debug", "info", "warn", "error"
consoleLogLevel String "info" Log level for console output: "debug", "info", "warn", "error"

OpenTelemetry

Enable telemetry export to your observability platform. When enabled, metrics, logs, and traces are pushed via OTLP.

Property Type Default Description
enabled Boolean false Enable OpenTelemetry integration
serviceName String "formae-agent" Service name for telemetry identification

OTLP Configuration:

Property Type Default Description
enabled Boolean true Whether to enable OTLP push export for traces, metrics, and logs
endpoint String "http://localhost:4317" OTLP collector endpoint URL
protocol String "grpc" Protocol to use: "grpc" or "http"
insecure Boolean true Whether to use insecure connections (disable TLS)
temporality String "delta" Metric temporality: "delta" (OTel-native) or "cumulative" (for Prometheus/Mimir backends without delta support)

Prometheus Configuration:

Property Type Default Description
enabled Boolean true Enable Prometheus /metrics endpoint for pull-based scraping

Retry

Control how formae handles transient failures during resource operations. These values are the agent-wide defaults and can be overridden per plugin in Resource plugins.

Property Type Default Description
statusCheckInterval Duration 10.s How frequently to check the status of a resource operation
maxRetries Number 9 Maximum number of retries for a recoverable failed operation
retryDelay Duration 10.s How long to wait before retrying a failed operation

Resource plugins

agent.resourcePlugins is a list of per-plugin configuration blocks that override defaults published by each plugin. Each installed plugin ships its own typed configuration that you import through the plugins:/ scheme. Any plugin that is not listed uses its built-in defaults.

Available overrides on every resource plugin:

Property Type Description
enabled Boolean Set to false to disable the plugin. When disabled no other fields apply. Default: true.
rateLimit RateLimitConfig? Cap the request rate this plugin issues to its provider. maxRequestsPerSecondForNamespace is the per-target cap.
retry RetryConfig? Override the agent-wide retry settings for this plugin.
resourceTypesToDiscover List<String>? Restrict which resource types this plugin reports during discovery. An empty/absent value means "all supported types".
discoveryFilters List<MatchFilter>? Exclude specific discovered resources by matching on properties (for example, skipping resources that carry a Kubernetes-owner tag).
labelConfig LabelConfig? Customize how human-readable labels are generated for discovered resources. defaultQuery is a JSONPath query; resourceOverrides sets per-resource-type queries that win over the default.

Plugins may also expose plugin-specific fields defined in their own schema/Config.pkl. These appear alongside the fields above on the same configuration block.

Disabling a plugin

Use enabled = false to stop the agent from loading a plugin. No other options apply in this case.

amends "formae:/Config.pkl"

import "plugins:/Azure.pkl" as Azure

agent {
    resourcePlugins {
        new Azure.PluginConfig {
            enabled = false
        }
    }
}

Tuning an installed plugin

This example uses the SFTP plugin because it exposes plugin-specific fields (defaultTimeoutSeconds, defaultFilePermissions) in addition to the common overrides.

amends "formae:/Config.pkl"

import "plugins:/Sftp.pkl" as Sftp

agent {
    resourcePlugins {
        new Sftp.PluginConfig {
            // Common overrides
            rateLimit {
                maxRequestsPerSecondForNamespace = 5
            }
            retry {
                maxRetries = 3
                retryDelay = 30.s
            }

            // Plugin-specific fields defined by the SFTP plugin
            defaultTimeoutSeconds = 60
            defaultFilePermissions = "0600"
        }
    }
}

You can combine multiple plugin blocks under a single resourcePlugins { ... } listing. The type field is automatically set by each plugin's wrapper, so you only need to fill in the overrides you care about.

labelConfig

labelConfig customizes how human-readable labels are generated for resources discovered by this plugin. The query is a JSONPath expression evaluated against the resource's properties. Each plugin ships a sensible default (for example, the AWS plugin uses the Name tag, $.Tags[?(@.Key=='Name')].Value). Override per resource type when the plugin's default doesn't suit your environment, or set defaultQuery to change the rule for every type:

amends "formae:/Config.pkl"

import "plugins:/Aws.pkl" as Aws

agent {
    resourcePlugins {
        new Aws.PluginConfig {
            labelConfig {
                resourceOverrides {
                    ["AWS::EC2::Instance"] = "$.Tags[?(@.Key=='env')].Value"
                }
            }
        }
    }
}

When the query returns nothing, formae falls back to the resource's provider identifier as the label. See Label → Labels for discovered resources for the full resolution order and collision behavior.


CLI

Configure how the CLI connects to the agent API. See Authentication for cli.auth.

Property Type Default Description
api.url String "http://localhost" Base URL for the agent API
api.port Number 49684 Port number for the agent API

Authentication

Authentication is configured separately for the agent and CLI. The agent.auth block controls server-side validation; the cli.auth block provides client-side credentials. Both fields are optional — if unset, the agent serves unauthenticated requests.

Each auth plugin ships its own typed configuration that you import through the plugins:/ scheme, the same pattern used for Resource plugins. The example below uses the auth-basic plugin, which is the default HTTP Basic Authentication option.

amends "formae:/Config.pkl"

import "plugins:/AuthBasic.pkl" as AuthBasic

agent {
    auth = new AuthBasic.AgentConfig {
        authorizedUsers {
            new AuthBasic.AuthorizedUser {
                username = "alice"
                // bcrypt hash — generate with:
                //   htpasswd -bnBC 10 "" yourPassword | tr -d ':'
                password = "$2y$10$ki1wCrM94EViuTv0dRNEVuP3ujj2/uu2Zh8/FyFvExjZyrsdtr1SS"
            }
        }
    }
}

cli {
    auth = new AuthBasic.CliConfig {
        username = "alice"
        password = "mySecretPass"
    }
}

See Security and networking for more detail on the auth-basic setup.


Network

Top-level network configuration. The type field selects the network plugin.

Property Type Default Description
network.type String Network plugin type (e.g. "tailscale")
network.tailscale TailscaleConfig? null Tailscale-specific configuration

See Tailscale for setup instructions.


Plugin directory

Top-level setting for where formae discovers installed plugins.

Property Type Default Description
pluginDir String "~/.pel/formae/plugins" Directory where installed plugins live. Can also be set via the FORMAE_PLUGIN_DIR environment variable.

Artifact repositories

Top-level artifacts block configures the orbital repositories formae consults to install and update its binary, plugins, and tooling. Both the agent and the CLI share this configuration; formae plugin install, formae update, and formae plugin upgrade all resolve packages against the listed repositories.

Property Type Default Description
artifacts.repositories Listing<Repository> pel (binary) and community (formae-plugin) on hub.platform.engineering at the stable channel List of orbital repositories to consult for packages. The defaults cover both binary and plugin distribution; only override when running against a private or custom hub.

Each entry in artifacts.repositories is a Repository with two fields:

Property Type Description
uri String Orbital repository URI; the optional #channel fragment selects the release channel (typically stable or dev).
type "binary" | "formae-plugin" Discriminator. binary repos serve the formae binary and tooling (consulted by formae update); formae-plugin repos serve plugins (consulted by formae plugin install / upgrade).

The default value is equivalent to:

artifacts {
    repositories {
        new {
            uri = "https://hub.platform.engineering/repos/platform.engineering/pel#stable"
            type = "binary"
        }
        new {
            uri = "https://hub.platform.engineering/repos/platform.engineering/community#stable"
            type = "formae-plugin"
        }
    }
}

A typical override that points at a private hub mirroring the same shape:

artifacts {
    repositories {
        new {
            uri = "https://hub.example.com/repos/example.com/pel#stable"
            type = "binary"
        }
        new {
            uri = "https://hub.example.com/repos/example.com/community#stable"
            type = "formae-plugin"
        }
    }
}

Deprecated flat fields

Earlier releases configured a single repository via flat artifacts.url, artifacts.username, and artifacts.password fields. Those fields are still accepted for backwards compatibility but emit deprecation warnings on agent startup, and they cover only the binary repository — plugin installation requires the new repositories listing. Migrate by replacing:

artifacts {
    url = "https://hub.platform.engineering/repos/platform.engineering/pel#stable"
}

with the explicit listing shown above. The username and password fields have no like-for-like replacement in 0.85; per-repository credentials will be reintroduced in a later release.


Deprecated plugins block

Earlier releases configured authentication, network access, and the plugin directory under a single top-level plugins { ... } block. That block is still accepted for backwards compatibility but emits deprecation warnings at startup. Migrate as follows:

Old location New location
plugins.authentication agent.auth + cli.auth
plugins.network top-level network
plugins.pluginDir top-level pluginDir