Skip to main content

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.

Terminal
# 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
  • metadata for identity and labels
  • spec for 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.name is a DNS subdomain: up to 253 characters of lowercase letters, digits, - and .. An AppTarget name 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 in almaforge.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.namespace is not used. Resources are cluster-wide.
  • metadata.ownerReferences and metadata.finalizers are 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.

examples/reference/configuration/kubernetes-target.yaml
# 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.

examples/reference/configuration/database-target.yaml
# 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.

examples/reference/configuration/app-target.yaml
# 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.

examples/reference/configuration/role.yaml
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.

examples/reference/configuration/user.yaml
# 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.

examples/reference/configuration/lock.yaml
# 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.

examples/reference/configuration/certificate-authority.yaml
# 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.

examples/reference/configuration/cluster-name.yaml
# 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.

examples/reference/configuration/auth-config.yaml
# 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.

examples/reference/configuration/network-config.yaml
# 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.

examples/reference/configuration/recording-config.yaml
# 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.nameRoleAllowed drivers
stateThe cluster's one state databasesqlite, 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
recordingsThe cluster's one session-recording destinations3, 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​

examples/reference/configuration/storage-config-state.yaml
# 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).

examples/reference/configuration/storage-config-audit-instances.yaml
# 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​

examples/reference/configuration/storage-config-recordings.yaml
# 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.

examples/reference/configuration/token.yaml
# 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.

examples/reference/configuration/github-connector.yaml
# 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.

examples/reference/configuration/oidc-connector.yaml
# 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.

examples/reference/configuration/jira-connector-env-token.yaml
# 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:

examples/reference/configuration/jira-connector-file-token.yaml
# 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.

examples/reference/configuration/slack-connector.yaml
# 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.

examples/reference/configuration/telegram-connector-env-token.yaml
# 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:

examples/reference/configuration/telegram-connector-file-token.yaml
# 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.

examples/reference/configuration/pagerduty-connector-env-key.yaml
# 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:

examples/reference/configuration/pagerduty-connector-file-key.yaml
# 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.

examples/reference/configuration/auth-server.yaml
# 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.

examples/reference/configuration/app.yaml
# 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.

examples/reference/configuration/database.yaml
# 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.

examples/reference/configuration/database-service.yaml
# 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.

examples/reference/configuration/kubernetes.yaml
# 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.

examples/reference/configuration/cluster-alert.yaml
# 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.

ProviderBest fitNotes
${file:PATH}Mounted secret file, sealed secret materialized on disk, config management outputReads 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 secretKeyRefReads 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:

examples/reference/configuration/file-expansion-deployment.yaml
# 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
examples/reference/configuration/file-expansion-github-connector.yaml
# 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:

systemd
[Service]
EnvironmentFile=/etc/almaforge/github-sso.env
/etc/almaforge/github-sso.env
GITHUB_CLIENT_SECRET=ghp_exampleSecret

Kubernetes environment variable from a Secret:

examples/reference/configuration/env-expansion-secret-ref.yaml
# 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
examples/reference/configuration/env-expansion-github-connector.yaml
# 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.

examples/reference/configuration/escape-rule-github-connector.yaml
# 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.