Declarative Configuration Reference
AlmaForge resources are declarative documents you can apply, inspect, and delete with alma.
If you are familiar with kubectl, the workflow is intentionally similar: write YAML, apply it, read it back, and treat the manifest as the source of truth.
The CLI, resource files, and direct API clients use the same resource format. The Terraform provider exposes supported kinds as typed HCL resources. See Infrastructure as Code for supported workflows.
# Apply a manifestalma apply -f role.yaml
# Read it back in canonical formalma get role/<role-name> -o yaml
# Delete by namealma delete role/<role-name>The examples below use the canonical AlmaForge document shape:
apiVersion: almaforge.com/v1- PascalCase
kind metadatafor identity and labelsspecfor the user-managed configuration
The examples focus on fields users commonly set. Runtime-only and computed fields are not shown.
Use alma get <kind>/<name> -o yaml to inspect a live resource.
The examples below show the fields operators commonly configure.
Names and labels
metadata uses Kubernetes-style naming and label rules. Apply these
resources with alma, not directly to a Kubernetes API server.
metadata.nameis a DNS subdomain: up to 253 characters of lowercase letters, digits,-and.. AnAppTargetname is stricter, up to 63 characters and no dot, because an app is reached at<name>.<proxy host>.- A label key is up to 63 characters of letters, digits,
-,_and., optionally prefixed with a domain, as inalmaforge.com/origin. A nonempty label value uses the same characters and length, and starts and ends with a letter or a digit. An empty label value is allowed. metadata.namespaceis not used. Resources are cluster-wide.metadata.ownerReferencesandmetadata.finalizersare not accepted.
Usernames are the exception. Your identity provider chooses them, so a
User name may be anything without a /, an email address included.
Common Configuration Resources
These resources describe the things operators most often manage by
manifest. Runtime records such as App, Database, and Kubernetes
exist too, but operators normally create the corresponding target
resources instead.
Server
Registers an SSH-accessible host. Installed SSH services create
Server records when they join the cluster. Agentless OpenSSH hosts
are also represented as Server resources.
KubernetesTarget
Registers a Kubernetes API server for proxied access.
# Kubernetes API server target served by an AlmaForge Kubernetes agent.
# An empty spec tells the agent to use its configured kubeconfig.
apiVersion: almaforge.com/v1
kind: KubernetesTarget
metadata:
name: prod-eks
labels:
env: prod
region: us-east-1
spec: {}
DatabaseTarget
Registers a database endpoint that AlmaForge can broker access to.
# Self-hosted PostgreSQL target served by an AlmaForge Database agent.
# The URI only needs to be reachable from the agent host.
apiVersion: almaforge.com/v1
kind: DatabaseTarget
metadata:
name: orders-postgres
labels:
env: prod
team: payments
spec:
protocol: postgres
uri: orders-prod.internal:5432
tls:
serverName: orders-prod.internal
adminUser:
name: alma_admin
defaultDatabase: postgres
AppTarget
Registers an HTTP or TCP application behind AlmaForge. See the applications guide for DNS requirements and workflow details.
# HTTP application target served by an AlmaForge App agent. Users open
# the application at the public address routed to the Proxy.
apiVersion: almaforge.com/v1
kind: AppTarget
metadata:
name: grafana
labels:
env: prod
team: sre
spec:
uri: https://grafana.internal:3000
fqdn: grafana.almaforge.example.com
insecureSkipVerify: false
Access & Identity
These resources define who can log in, what they can do, and how long the grant should last.
Role
Defines what a user or workload can access and which session constraints apply. See the RBAC Reference for the full field-by-field breakdown, built-in roles, and example role definitions.
apiVersion: almaforge.com/v1
kind: Role
metadata:
name: editor
labels:
environment: prod # Optional labels for search and inventory.
spec:
options:
maxSessionTTL: 8h # Maximum lifetime of certificates issued under this role.
forwardAgent: false # Disable SSH agent forwarding by default.
portForwarding: true # Allow port forwarding when explicitly needed.
clientIdleTimeout: 15m # Disconnect idle sessions after 15 minutes.
disconnectExpiredCert: true # Drop sessions once the client certificate expires.
sshFileCopy: true # Allow SCP and SFTP operations.
allow:
serverLogins:
- ubuntu # Linux accounts users may assume on servers.
- root
kubernetesGroups:
- ops-admins # Kubernetes groups to impersonate.
databaseNames:
- app # Database names users may access.
- analytics
databaseUsers:
- readonly # Database users users may become.
- reporting
appLabels:
environment: prod # Match applications by labels.
databaseLabels:
environment: prod # Match databases by labels.
kubernetesLabels:
environment: prod # Match Kubernetes clusters by labels.
serverLabels:
environment: prod # Match servers by labels.
rules:
- resources: ['role', 'user'] # API resources this role may manage.
verbs: ['list', 'read']
deny:
serverLogins:
- postgres # Explicit denies override allow rules.
User
Read-only runtime record of an SSO-mapped identity. AlmaForge
has no local user accounts. Every user lands through an
SSO connector and the corresponding User is materialized on
first login. Operators inspect User records with
alma get user/<name> and lock them through the
Lock resource. Do not apply User manifests.
# User example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: User
metadata:
name: jane
spec:
roles:
- editor # Roles granted to the user.
- auditor
traits:
logins:
- jane # Trait values can be referenced from role templates.
- ubuntu
team:
- sre
expiresAt: '2026-12-31T23:59:59Z' # Optional account expiry.
Lock
Temporarily blocks access for a user, role, login, access request, or server identity.
# Lock example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: Lock
metadata:
name: emergency-jane-lock
spec:
target:
user: jane # Lock this user.
login: ubuntu # Also block a specific local UNIX login.
message: 'Access disabled during the incident response window.'
expiresAt: '2026-04-01T12:00:00Z' # Remove the lock automatically at this time.
createdBy: roman@almaforge.com # Recorded author of the lock.
Cluster Configuration
These resources define cluster identity, authentication defaults, recording defaults, storage backends, and how new services join.
CertificateAuthority
Defines a certificate authority bundle used to verify and, when private keys are present, sign host or user certificates. Auth servers normally manage the local cluster CAs. Operators usually inspect these resources for audit and backup workflows rather than editing them by hand.
# CertificateAuthority example for the declarative configuration reference.
# Auth servers manage local cluster CAs. This shape is what `alma get`
# exports, and what you write when importing another cluster's public keys.
#
# publicKey and cert are byte fields, so their authorized-key and PEM text
# travels base64-encoded on one line. Folding it across lines would insert
# spaces and break the decode. Private keys are omitted: they stay on the
# auth server, and a document carrying only public material still validates.
apiVersion: almaforge.com/v1
kind: CertificateAuthority
metadata:
name: root.almaforge.example.com # The cluster this CA serves.
spec:
type: host # Values include host, user, db, jwt, and oidc_idp.
signingAlg: 3 # Signing algorithm: 1 RSA-SHA1, 2 RSA-SHA2-256, 3 RSA-SHA2-512.
activeKeys: # Keys this CA currently signs and verifies with.
ssh:
- publicKey: c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUoxZjE1MTNTMlJMbVdPMGFrYmZqUTVkbGhkbWtUcWVvRitlbEZxOTJEbXAgcm9vdC5hbG1hZm9yZ2UuZXhhbXBsZS5jb20K
tls:
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJyekNDQVZXZ0F3SUJBZ0lVUklHZmFXR0pFU0hKUHVjekxPWGc1ZWM3TG1zd0NnWUlLb1pJemowRUF3SXcKTFRFck1Da0dBMVVFQXd3aWNtOXZkQzVoYkcxaFptOXlaMlV1WlhoaGJYQnNaUzVqYjIwZ2FHOXpkQ0JEUVRBZQpGdzB5TmpBNU1EUXhNelV4TkRkYUZ3MHpOakE1TURFeE16VXhORGRhTUMweEt6QXBCZ05WQkFNTUluSnZiM1F1CllXeHRZV1p2Y21kbExtVjRZVzF3YkdVdVkyOXRJR2h2YzNRZ1EwRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJzQjV5Y0hvc3VKeTYwNEUyZEF1andWSFlkL1k4Q0tPWjV1TVUvYkl4N1JEVHl5LzBZZ0JPcgpBTmhrckdYbW1hUVBOQ1RYRHEyZW1rVmdtT2pDVEFjN28xTXdVVEFkQmdOVkhRNEVGZ1FVckNpaDZnTTFmdnJ1Ci9DQWE0SzE2SU1yYWlkY3dId1lEVlIwakJCZ3dGb0FVckNpaDZnTTFmdnJ1L0NBYTRLMTZJTXJhaWRjd0R3WUQKVlIwVEFRSC9CQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQkVrYmkxTDFnS2RwMWNoZnpLZ2FSQgorTDFuQkVLOURGM3lEQlFCak9CK09nSWhBSk5odHBjRGhIVmt3bGdmQ2FTRS9WUGpCMndvNTFud0FGQ0RoZTlsCnl6U1UKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
additionalTrustedKeys: # Extra public keys accepted for verification only.
tls:
- cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJyekNDQVZXZ0F3SUJBZ0lVRTRCdG4rUlZLYU1zSWM2Y1FWY0crM2lSYXVvd0NnWUlLb1pJemowRUF3SXcKTFRFck1Da0dBMVVFQXd3aWJHVmhaaTVoYkcxaFptOXlaMlV1WlhoaGJYQnNaUzVqYjIwZ2FHOXpkQ0JEUVRBZQpGdzB5TmpBNU1EUXhNelV4TkRkYUZ3MHpOakE1TURFeE16VXhORGRhTUMweEt6QXBCZ05WQkFNTUlteGxZV1l1CllXeHRZV1p2Y21kbExtVjRZVzF3YkdVdVkyOXRJR2h2YzNRZ1EwRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJWUmhKR0UyeW9RWjVPZEIrclNFbkVXUFJBRDNUTFIyTVlXMmlRaS9JVDJRVGpERlhrZ01iOQp1djdXSWY0N3ZROVEwSlJ6K0dSbGpESWJIZUthNVpsN28xTXdVVEFkQmdOVkhRNEVGZ1FVYlNMMnd4ODRGK3RvCkdxZGk2TmtvOWdFbHVuWXdId1lEVlIwakJCZ3dGb0FVYlNMMnd4ODRGK3RvR3FkaTZOa285Z0VsdW5Zd0R3WUQKVlIwVEFRSC9CQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQUlhRHhOOUF2RWxMWGRnVFo2T1B4ZAp5WlUzbHdLWnZXdVQxN1ZKS2tLMU9nSWhBTER5SGpkc0hSUDBEL2M1a2FKcEhjdVZtWWdSaGFzRWNJbXlJcXNMCk5oNEcKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
ClusterName
Sets the immutable cluster identity used across certificates, URLs, and trust relationships.
# ClusterName example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: ClusterName
metadata:
name: cluster-name
spec:
clusterName: almaforge.example.com # Human-facing cluster name.
clusterID: 6f62e8e2-7d9d-4b7a-a8a6-faf2df8b66ae # Stable cluster UUID.
AuthConfig
Controls how users authenticate into the cluster.
# AuthConfig example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: AuthConfig
metadata:
name: cluster
spec:
# Disconnect sessions immediately after client certificate expiry.
disconnectExpiredCert: true
# Message shown to users after login.
messageOfTheDay: 'Production access is audited.'
# Default certificate TTL when a user does not request one explicitly.
defaultSessionTTL: 8h
NetworkConfig
Defines cluster-wide defaults for connection timeouts and routing behavior.
# NetworkConfig example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: NetworkConfig
metadata:
name: cluster
spec:
# Disconnect idle SSH and database sessions after 15 minutes.
clientIdleTimeout: 15m
# Show this message when the idle timeout closes a session.
idleTimeoutMessage: 'Session closed after 15 minutes of inactivity.'
# Send keep-alives every five minutes and disconnect after three misses.
keepAliveInterval: 5m
keepAliveCountMax: 3
# Give nodes up to two minutes without auth connectivity before controlled
# sessions start getting terminated.
sessionControlTimeout: 2m
# Web UI idle timeout.
webIdleTimeout: 1h
# Prefer the most recently heartbeating backend when multiple targets match.
# Values: unambiguous_match, most_recent.
routingStrategy: most_recent
# Reverse tunnel strategy. `agentMesh: {}` is the full value here. There
# are no nested settings under `agentMesh`. Use `proxyPeering` with an
# `agentConnectionCount` instead when operating with proxy peering.
tunnelStrategy:
agentMesh: {}
# Ping wrapped TLS-routing connections every 15 seconds.
proxyPingInterval: 15s
# Keep hostname matching strict unless you specifically need case-insensitive routing.
caseInsensitiveRouting: false
RecordingConfig
Controls whether sessions are recorded at the node, at the proxy, or not at all.
# RecordingConfig example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: RecordingConfig
metadata:
name: cluster
spec:
# Choose where sessions are recorded.
# `node` records on the target node and is the usual default.
# `proxy` records at the proxy, which can simplify collection in some topologies.
# `off` disables session recording entirely.
# `node-sync` keeps recording on the node with synchronous upload semantics.
mode: node
# Control whether the proxy verifies host keys when proxy-side recording is used.
# Keep this enabled unless you have a specific compatibility reason not to.
# Omitting the field enables it.
proxyChecksHostKeys: true
StorageConfig
Selects the storage backend driver and its connection settings. StorageConfig is bootstrap-only: it is loaded from the auth server's bootstrap file at startup and is read-only at runtime. Operators change storage by editing the bootstrap file and restarting the auth server, never via the API.
The spec block uses the Kubernetes PersistentVolume pattern.
Exactly one driver field must be set. Whichever field is set selects
the backend. alma get storageconfig returns the live
configuration the auth server is currently using.
The cluster carries one or more StorageConfig instances. The
metadata.name selects the role:
metadata.name | Role | Allowed drivers |
|---|---|---|
state | The cluster's one state database | sqlite, dynamo, etcd, postgres, firestore |
audit or audit-<suffix> | Audit event sink. One or more can exist for fan-out. audit is the default local-file sink AlmaForge materializes when nothing is configured. Override it or add audit-<suffix> instances for fan-out. | dynamo, postgres, firestore, athena, file, stdout |
recordings | The cluster's one session-recording destination | s3, gcs, azure, file |
Each audit-* instance is an independent sink. Events are written
to every audit instance the auth server has loaded.
Set auditRetentionPeriod on the dynamo, postgres, or firestore
driver block to configure audit retention. Omit it for athena and file,
which reject the field. Manage Athena retention through S3 lifecycle rules
and local file retention through your log rotation policy.
State instance
# StorageConfig example for cluster state storage.
# The state instance stores auth service state.
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
name: state
spec:
# Choose one driver. Pick the block that matches the backend
# you want. Leave the others out.
# Sqlite backend. Default for single-node and small deployments.
sqlite:
# Filesystem path to the sqlite database directory. Defaults
# to $ALMA_DATA_DIR/backend when empty.
path: /var/lib/almaforge/backend
# Optional tunables below. Leave empty to accept the built-in defaults.
# bufferSize: 1024
# pollStreamPeriod: 1s
# sync: FULL
# busyTimeout: 10000
# journal: delete
# DynamoDB backend. Use for multi-region HA deployments on AWS.
# dynamo:
# region: us-east-1
# tableName: almaforge-state
# readCapacityUnits: 10
# writeCapacityUnits: 10
# billingMode: pay_per_request
# # endpoint: https://dynamodb.us-east-1.amazonaws.com # for tests / non-AWS
# etcd backend. Use for multi-node clusters backed by an existing etcd.
# etcd:
# peers:
# - https://etcd-1.example.com:2379
# - https://etcd-2.example.com:2379
# - https://etcd-3.example.com:2379
# prefix: /almaforge
# tlsKeyFile: /etc/almaforge/etcd-client-key.pem
# tlsCertFile: /etc/almaforge/etcd-client-cert.pem
# tlsCAFile: /etc/almaforge/etcd-ca.pem
# dialTimeout: 30s
# PostgreSQL backend. Use for SQL-managed clusters.
# postgres:
# connString: postgres://almaforge:secret@db.example.com:5432/almaforge?sslmode=verify-full
# authMode: "" # "", "azure", or "aws"
# changeFeedPollInterval: 1s
# Firestore backend. Use for GCP-native deployments.
# firestore:
# projectID: my-gcp-project
# collectionName: almaforge-state
# credentialsPath: /etc/almaforge/gcp-sa.json
Audit instances
Audit storage is fan-out: every audit-<suffix> instance receives
every event. Use one instance per sink (DynamoDB + a local file
mirror, for example).
# StorageConfig examples for audit event sinks.
# Each audit or audit-* instance is an independent sink.
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
# Any name with the audit- prefix. Suffix is operator-chosen.
name: audit-dynamo
spec:
dynamo:
region: us-east-1
tableName: almaforge-events
# Per-driver retention. DynamoDB stamps a TTL on every write.
auditRetentionPeriod: 8760h
# Optional capacity tuning for provisioned mode.
# readCapacityUnits: 10
# writeCapacityUnits: 10
# billingMode: pay_per_request
# continuousBackups: true
# autoScaling: true
---
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
name: audit-postgres
spec:
postgres:
connString: postgres://almaforge:secret@db.example.com/audit?sslmode=verify-full
# Background sweeper deletes rows older than retention.
auditRetentionPeriod: 720h
# Optional cleanup tuning.
# disableExpiry: false
# expiryInterval: 1h
---
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
name: audit-firestore
spec:
firestore:
projectID: my-gcp-project
collectionName: almaforge-events
credentialsPath: /etc/almaforge/gcp-sa.json
# Background purge deletes documents older than retention.
auditRetentionPeriod: 168h
---
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
name: audit-athena
spec:
# Athena does not enforce retention from AlmaForge. Configure
# a lifecycle policy on the underlying S3 bucket instead.
athena:
region: us-east-1
database: almaforge
tableName: events
workgroup: primary
topicARN: arn:aws:sns:us-east-1:123456789012:alma-audit
largeEventsS3: s3://alma-audit-large/
locationS3: s3://alma-audit/events/
queueURL: https://sqs.us-east-1.amazonaws.com/123456789012/alma-audit
---
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
name: audit-file
spec:
# File audit logs rotate but never delete. Set up logrotate or
# similar if disk pressure matters.
file:
path: /var/log/almaforge/audit
Recordings instance
# StorageConfig example for session recording storage.
# The recordings instance accepts object-store and local file drivers.
apiVersion: almaforge.com/v1
kind: StorageConfig
metadata:
name: recordings
spec:
# Choose one driver. Recordings have no retention field.
# configure lifecycle on the bucket itself.
# AWS S3 (or any S3-compatible object store).
s3:
bucket: almaforge-recordings
region: us-east-1
# path: optional/key/prefix
# endpoint: https://s3-compatible.example.com
# acl: private
# sseKmsKey: arn:aws:kms:::key/abc
# insecure: false
# disableServerSideEncryption: false
# Google Cloud Storage.
# gcs:
# bucket: almaforge-recordings
# projectID: my-gcp-project
# credentialsPath: /etc/almaforge/gcp-sa.json
# # path: optional/object/prefix
# # kmsKeyName: projects/my-gcp-project/locations/us/keyRings/r/cryptoKeys/k
# Azure Blob Storage.
# azure:
# serviceURL: https://account.blob.core.windows.net/
# sessionContainerName: sessions
# inprogressContainerName: sessions-inprogress
# Local disk. Single-node deployments only.
# file:
# path: /var/lib/almaforge/recordings
Token
Grants agents, bots, or workloads permission to join the cluster. See the Workload Identity guide for the conceptual model, the per-method allow-rule fields, and end-to-end examples.
For static joins, spec.static.secret stores
sha256(client_secret) encoded as 64 lowercase hex characters. The
joining process presents the plaintext client_secret through
ALMA_CLIENT_SECRET. Do not put the plaintext in the Token manifest.
# Token example for the declarative configuration reference.
# Adjust metadata.name and spec values for your cluster before applying.
apiVersion: almaforge.com/v1
kind: Token
metadata:
name: node-bootstrap
spec:
# System roles granted to the joining service after a successful join.
roles:
- system:ssh
# The join method is selected by which sub-message is set.
# Set one of: static, ec2, aws, github, gitlab, circleCI,
# spacelift, kubernetes, azure, gcp. This token uses the EC2
# instance-identity-document method via spec.ec2.
ec2:
# Allow rules restrict where the token may be used from.
allow:
- awsAccount: '123456789012'
awsRegions:
- us-east-1
awsRole: telemetry-node
# Suggested labels that newly enrolled resources should set on themselves.
# Each value is a list, so one key can suggest several values.
suggestedLabels:
environment: [prod]
region: [us-east-1]
Connectors & Integrations
These resources connect the cluster to external identity providers and optional approval integrations.
GithubConnector
Maps GitHub organization and team membership to AlmaForge roles.
For spec.clientID and spec.clientSecret, see
Resource value expansion.
# GithubConnector example for the declarative configuration reference.
# Keep the OAuth client secret out of the manifest when possible.
apiVersion: almaforge.com/v1
kind: GithubConnector
metadata:
name: github
spec:
clientID: Iv23li3AExample
clientSecret: ${env:GITHUB_CLIENT_SECRET}
display: GitHub
endpointURL: https://github.com
apiEndpointURL: https://api.github.com
teamsToRoles:
- organization: almaforge
team: platform
roles:
- editor
- auditor
OIDCConnector
Configures an OpenID Connect identity provider.
For spec.clientID, spec.clientSecret, and
spec.googleServiceAccount, see
Resource value expansion.
# OIDCConnector example for the declarative configuration reference.
# Keep OAuth client secrets and service account JSON out of the manifest.
apiVersion: almaforge.com/v1
kind: OIDCConnector
metadata:
name: google
spec:
issuerURL: https://accounts.google.com
clientID: 1234567890-abcdef.apps.googleusercontent.com
clientSecret: ${env:OIDC_CLIENT_SECRET}
googleServiceAccount: ${env:GOOGLE_SERVICE_ACCOUNT_JSON}
googleAdminEmail: admin@almaforge.example.com # Required whenever googleServiceAccount is set.
display: Google Workspace
scope:
- openid
- email
- profile
prompt: select_account
usernameClaim: email
claimsToRoles:
- claim: hd
value: almaforge.example.com
roles:
- editor
- auditor
allowUnverifiedEmail: false
pkceMode: auto
JiraConnector
Configures the built-in Jira access request integration. The Jira
plugin runs inside almad on every auth service process.
There is no separate binary and no file-level jira_service config
section. Applying a JiraConnector resource starts the plugin
automatically. Deleting it stops the plugin. No restart is required for either
transition. The plugin polls the resource once a minute, so changes
take effect within ~60 seconds of alma apply.
For spec.username and spec.apiToken, see
Resource value expansion.
# JiraConnector example that reads the API token from an environment variable.
# Use this when the auth service process manager injects the secret.
apiVersion: almaforge.com/v1
kind: JiraConnector
metadata:
# The name `jira` is the well-known singleton. Additional
# connectors are ignored by the single-instance guard.
name: jira
spec:
url: https://example.atlassian.net
username: bot@company.com
# Literal value, or ${env:NAME} / ${file:PATH} reference.
apiToken: '${env:JIRA_API_TOKEN}'
project: OPS
issueType: Task
To keep the API token out of the resource itself, use a ${file:...}
or ${env:...} reference:
# JiraConnector example that reads the API token from a file.
# Use this when secret management writes the token on each auth host.
apiVersion: almaforge.com/v1
kind: JiraConnector
metadata:
name: jira
spec:
url: https://example.atlassian.net
username: bot@company.com
apiToken: '${file:/etc/almaforge/jira-token}'
project: OPS
issueType: Task
SlackConnector
Configures the built-in Slack access request integration.
For spec.botToken, see Resource value expansion.
# Slack access-request integration. Keep the bot token out of
# the resource by using value expansion when possible.
apiVersion: almaforge.com/v1
kind: SlackConnector
metadata:
name: slack
spec:
botToken: ${env:SLACK_BOT_TOKEN}
# The "*" key is the required default recipient list.
roleToRecipients:
'*':
values:
- C0123456789
TelegramConnector
Configures the built-in Telegram access-request integration. One-way
push only: messages flow from AlmaForge to Telegram, never the
reverse.
For spec.botToken, see Resource value expansion.
# TelegramConnector example that reads the bot token from an environment variable.
# Use this when the auth service process manager injects the secret.
apiVersion: almaforge.com/v1
kind: TelegramConnector
metadata:
# The name `telegram` is the well-known singleton. Additional
# connectors are ignored by the single-instance guard.
name: telegram
spec:
# Literal value, or ${env:NAME} / ${file:PATH} reference.
botToken: '${env:TELEGRAM_BOT_TOKEN}'
# Optional. Defaults to https://api.telegram.org. Override only
# when running a self-hosted Bot API server for airgapped clusters.
apiURL: https://api.telegram.org
roleToRecipients:
# "*" is the required default recipient list. Values are Telegram
# chat identifiers: numeric chat_id or @channelusername. AlmaForge
# cannot resolve Telegram users by login, email, or handle.
'*':
values:
- '-1001234567890'
dba:
values:
- '-1009876543210'
- '@dba-approvals'
To keep the bot token out of the resource itself, use a ${file:...}
or ${env:...} reference:
# TelegramConnector example that reads the bot token from a file.
# Use this when secret management writes the token on each auth host.
apiVersion: almaforge.com/v1
kind: TelegramConnector
metadata:
name: telegram
spec:
botToken: '${file:/etc/almaforge/telegram-token}'
roleToRecipients:
'*':
values:
- '-1001234567890'
See the Telegram integration guide for the full step-by-step setup and how to find a chat ID.
PagerdutyConnector
Configures the built-in PagerDuty access-request integration. The
PagerDuty plugin runs inside almad on every auth service
process. There is no separate binary and no file-level
pagerduty_service config section. Applying a PagerdutyConnector
resource starts the plugin automatically. Deleting it stops the
plugin. No restart is required for either transition. The plugin
polls the resource once a minute, so changes take effect within
~60 seconds of alma apply.
For spec.apiKey, see Resource value expansion.
# PagerdutyConnector example that reads the API key from an environment variable.
# Use this when the auth service process manager injects the secret.
apiVersion: almaforge.com/v1
kind: PagerdutyConnector
metadata:
# The name `pagerduty` is the well-known singleton. Additional
# connectors are ignored by the single-instance guard.
name: pagerduty
spec:
userEmail: almaforge-bot@example.com
# Literal value, or ${env:NAME} / ${file:PATH} reference.
apiKey: '${env:PAGERDUTY_API_KEY}'
To keep the API key out of the resource itself, use a ${file:...}
or ${env:...} reference:
# PagerdutyConnector example that reads the API key from a file.
# Use this when secret management writes the key on each auth host.
apiVersion: almaforge.com/v1
kind: PagerdutyConnector
metadata:
name: pagerduty
spec:
userEmail: almaforge-bot@example.com
apiKey: '${file:/etc/almaforge/pagerduty-key}'
# Optional. Defaults to https://api.pagerduty.com. Override for
# the EU region (https://api.eu.pagerduty.com) or testing.
apiURL: https://api.pagerduty.com
# Optional. Off by default. Opt in to auto-approve access
# requests when the requester is currently on call for one of
# the configured Pagerduty services. When false (or omitted),
# the plugin still creates the Pagerduty incident but leaves
# the access request for human review.
approveOnCall: true
See the PagerDuty integration guide for the full step-by-step setup, annotation model, and on-call auto-approval semantics.
Advanced Runtime Resources
These resources cover runtime services, discovery helpers, and lower-level system objects. Most are created by services or internal workflows rather than edited directly.
ProxyServer
Represents a proxy service instance and the addresses it exposes.
AuthServer
Represents an auth service instance in the control plane.
# Auth service presence record. AlmaForge services normally create
# this runtime resource automatically.
apiVersion: almaforge.com/v1
kind: AuthServer
metadata:
name: auth-1
spec:
version: 1.0.0
hostname: auth-1
App
Records an application service instance and the AppTarget it is
currently proxying. Application services normally create and refresh
these runtime records. Operators usually manage AppTarget resources
instead.
# Application service runtime record. App services normally create this
# resource to report which AppTarget they proxy. Manage AppTarget resources
# for operator-owned application configuration.
apiVersion: almaforge.com/v1
kind: App
metadata:
name: grafana-app-service
spec:
version: 1.0.0 # AlmaForge version running on the application service.
hostname: app-agent-1 # Hostname reported by the application service.
hostID: 00000000-0000-0000-0000-000000000001 # Stable UUID for this service instance.
app: # AppTarget currently proxied by this service instance.
apiVersion: almaforge.com/v1
kind: AppTarget
metadata:
name: grafana
spec:
uri: https://grafana.internal:3000 # Backend URL reached by the app service.
fqdn: grafana.almaforge.example.com # Public DNS name users open through AlmaForge.
Database
Records a database service instance and the DatabaseTarget it is
currently serving. Database services normally create and refresh these
runtime records. Operators usually manage DatabaseTarget resources
instead.
# Database service runtime record. Database services normally create this
# resource to report which DatabaseTarget they serve. Manage DatabaseTarget
# resources for operator-owned database configuration.
apiVersion: almaforge.com/v1
kind: Database
metadata:
name: orders-postgres-service
spec:
version: 1.0.0 # AlmaForge version running on the database service.
hostname: db-agent-1 # Hostname reported by the database service.
hostID: 00000000-0000-0000-0000-000000000002 # Stable UUID for this service instance.
database: # DatabaseTarget currently served by this service instance.
apiVersion: almaforge.com/v1
kind: DatabaseTarget
metadata:
name: orders-postgres
spec:
protocol: postgres # Database protocol handled by the service.
uri: orders-prod.internal:5432 # Database address reachable from the database service.
DatabaseService
Records a database agent and the registered Database resources it
matches. Database agents create and refresh this runtime record.
# Database agent runtime record. Database agents create and refresh this
# resource to report the registered Database resources they match.
apiVersion: almaforge.com/v1
kind: DatabaseService
metadata:
name: prod-database-agent
spec:
resources:
- labels:
environment:
- prod
Kubernetes
Records a Kubernetes service instance and the KubernetesTarget it is
currently serving. Kubernetes services normally create and refresh
these runtime records. Operators usually manage KubernetesTarget
resources instead.
# Kubernetes service runtime record. Kubernetes services normally create this
# resource to report which KubernetesTarget they serve. Manage KubernetesTarget
# resources for operator-owned cluster configuration.
apiVersion: almaforge.com/v1
kind: Kubernetes
metadata:
name: prod-eks-service
spec:
version: 1.0.0 # AlmaForge version running on the Kubernetes service.
hostname: kube-agent-1 # Hostname reported by the Kubernetes service.
hostID: 00000000-0000-0000-0000-000000000003 # Stable UUID for this service instance.
cluster: # KubernetesTarget currently served by this service instance.
apiVersion: almaforge.com/v1
kind: KubernetesTarget
metadata:
name: prod-eks
spec: {} # Empty spec means the service uses its local current kubeconfig context.
ClusterAlert
Displays a short-lived cluster-level message in alma status, the web
UI, and login flows. Auth services usually issue alerts when they need
to surface an operational condition to users.
# ClusterAlert example for the declarative configuration reference.
# Auth services usually create these short-lived messages to surface
# operational conditions in status, web UI, and login flows.
apiVersion: almaforge.com/v1
kind: ClusterAlert
metadata:
name: maintenance-window
spec:
severity: medium # Values are low, medium, or high.
message: Scheduled maintenance starts at 22:00 UTC.
createdAt: '2026-05-16T20:00:00Z' # RFC3339 timestamp when the alert was generated.
Instance
Records a unique server identity and the services running under it.
Session
Tracks an active session.
Resource value expansion
Selected connector string fields can hold either an inline literal
or a ${scheme:body} reference. Use an inline literal for a quick
lab setup or a short-lived test. Use ${file:...} when the value
already lands on disk on the auth server. Use ${env:...} when
your process manager or container runtime injects the value into
the auth server environment.
Most operators reach for expansion to keep OAuth client secrets,
API tokens, and service account credentials out of the resource
YAML. Identity fields like clientID and Jira username also
support expansion for per-environment templating.
Set the field to a literal such as sk-literal-value, an environment
reference such as ${env:GITHUB_CLIENT_SECRET}, or a file reference
such as ${file:/etc/almaforge/github-client-secret}.
Both providers resolve against the auth server, not the machine that
runs alma apply.
| Provider | Best fit | Notes |
|---|---|---|
${file:PATH} | Mounted secret file, sealed secret materialized on disk, config management output | Reads PATH from the Auth server filesystem. Trailing spaces, tabs, carriage returns, and newlines are stripped. Leading whitespace is preserved. |
${env:NAME} | systemd environment, container env, Kubernetes secretKeyRef | Reads environment variable NAME from the Auth server process environment. Leading and trailing whitespace is stripped. |
Reading a value from a file
Reach for ${file:PATH} when you already have a file on disk and
want the connector to read it at use time.
Kubernetes Secret mounted into the auth pod:
# Kubernetes Deployment fragment showing a Secret mounted as a file.
# The connector resource can read the mounted file with ${file:...}.
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
volumes:
- name: github-secret
secret:
secretName: github-sso
containers:
- name: almad
volumeMounts:
- name: github-secret
mountPath: /etc/almaforge/secrets
readOnly: true
# GithubConnector example that reads the OAuth secret from a file.
# Use this when secret management writes the final value on each auth host.
kind: GithubConnector
spec:
clientSecret: '${file:/etc/almaforge/secrets/client-secret}'
The same pattern works when a sealed-secret flow or another secret
management step writes the final plaintext file on disk before
almad starts.
Reading a value from an environment variable
Reach for ${env:NAME} when the secret is already injected into
the process environment.
systemd drop-in:
[Service]
EnvironmentFile=/etc/almaforge/github-sso.env
GITHUB_CLIENT_SECRET=ghp_exampleSecret
Kubernetes environment variable from a Secret:
# Kubernetes Secret environment-variable example for resource value expansion.
# Mount this into the auth service pod or adapt it to your deployment tool.
env:
- name: GITHUB_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: github-sso
key: client-secret
# GithubConnector example that reads the OAuth secret from an environment variable.
# Use this when the auth service process manager injects the secret.
kind: GithubConnector
spec:
clientSecret: '${env:GITHUB_CLIENT_SECRET}'
Escape rule
Use $${...} in a resource field when you need a literal ${...}
string instead of an expansion. This is the resource field's escape
syntax, not shell quoting.
# GithubConnector example showing how to store a literal expansion string.
# Use $${...} when the stored value must not be expanded.
kind: GithubConnector
spec:
clientSecret: '$${env:GITHUB_CLIENT_SECRET}'
The stored value becomes ${env:GITHUB_CLIENT_SECRET}. It is not
expanded again. Expansion is non-recursive.
Rotation and errors
Resolution is lazy. The raw ${...} string is stored in the backend.
The secret is fetched only when the consumer needs it.
Login-time fields pick up a rotated value on the next login or OAuth
exchange. This applies to GitHub clientID and clientSecret,
and to OIDC clientID, clientSecret, and
googleServiceAccount.
Plugin-startup fields are read when the plugin starts, not on every
poll. After rotating a referenced file, re-apply the connector. To
change the daemon's environment, restart it with the new value.
Each built-in plugin polls its own connector
once a minute and restarts when the resource version changes, so the
new value is picked up within about 60 seconds with no
almad restart. This applies to PagerDuty apiKey, Jira
username and apiToken, Slack botToken, and Telegram
botToken.
Values are capped at 64 KiB. Oversized files and oversized environment variables are rejected at dereference time.
Apply-time validation is syntactic only. Unknown schemes, malformed
${...} syntax, empty paths, and invalid environment variable names
fail at apply time. Missing files and unset environment variables fail
when the field is actually dereferenced.