loomplane.yaml

Every field of the loomplane.yaml manifest, with its type, limits and meaning.

This is the complete field reference. For how to think about a manifest, read The manifest first. The JSON schema at pkg/manifest/schema.json ($id https://loomplane.dev/schemas/loomplane.json) is the machine-readable version, and it's also the MCP resource loomplane://schema/loomplane.yaml. Loomplane rejects unknown fields and unsupported versions. A manifest can be up to 256 KiB.

Top level

FieldTypeMeaning
version1 or 2Required. 1 for all existing workflows. 2 adds the optional federation section
defaultsobjectprovider, region and cloud_tags for everything that doesn't set its own
servicesmap, up to 100What the application runs, by name
resourcesmap, up to 100Backing services, by name. A resource can't share a service's name
gatewaysmap, up to 10Public entry points that route by path
linksmap, up to 5Private network links between Google Cloud and AWS
ignoreobjectresources: kinds analysis found that you don't use
heldobjectsame_address: block (default) or warn
federationobjectVersion 2 only. See below

Names (of services, resources, gateways, links and environments in overrides) match ^[a-z][a-z0-9-]{0,39}$: lower case letters, digits and hyphens, starting with a letter, 40 characters at most.

defaults

FieldMeaning
providerProvider for every service, resource and gateway that sets none
regionRegion for the same. It only applies together with the default provider: a service that names another provider doesn't take the default region
cloud_tagsUp to 8 tags used to pick a Cloud target for every service with no placement of its own. Can't be combined with provider

services

FieldTypeMeaning
sourcestringRequired. Where the service's code is, as analysis found it: a Go main package's directory, a Rust binary's source file, a Node package's, Python project's or JVM module's directory, or a Dockerfile. A Python Procfile process other than web is shop/Procfile/worker. When two ecosystems have a service at one path, prefix the ecosystem: go:, rust:, node:, python:, jvm: or container:
repostringThe alias of the repository the service is in. A project with one repository can leave it out
kindenumCorrects what analysis decided: http-service, web-app, static-site or worker
buildobjectSee build
providerstringWhere it runs, by the provider's name
regionstringThe provider's region
targetconn_...The checked server or Kubernetes connection to run on
cloud_targetstringA named target in the environment's assigned Cloud. Can't be set with cloud_tags
cloud_tagsarrayUp to 8 tags. Selects the one target that carries every tag. Can't be set with cloud_target
endpointobjectSee endpoint
health_pathstringA readiness path, such as /_/health. Starts with /
port1 to 65535The port it listens on. Without it, the one its Dockerfile exposes, or 8080 with a warning
publicbooleanWhether it gets an address on the internet. Yes for anything that serves HTTP, no for a worker, unless you say
scale{min, max}Instances. min is 0 or more, max is 1 to 100. On targets that let you choose
size{cpu, memory}cpu is virtual CPUs above 0 and up to 8 (such as 0.5 or 2). memory is MiB, 128 to 32768
needsarray of namesResources and services it talks to. Each gets it an address in a variable, and it deploys after them
need_optionsmapOptions passed to a need, by need and then by option name
enabledbooleanfalse leaves it out
environmentsmapOverrides by environment name. Takes every field above except source, repo, kind, build, needs and need_options

provider, cloud_target and cloud_tags can't be mixed at the same level. An effective direct provider or target also conflicts with Cloud placement, including one inherited from defaults.

build

FieldMeaning
contextThe directory its Dockerfile builds from, from the repository root. . is the root. Without it, the context a Compose file gives the Dockerfile, or the Dockerfile's own directory
builderFor Kubernetes source builds: the conn_... of the SSH/Docker builder
registryThe conn_... of the OCI registry
imageAn existing image pinned as registry/repository@sha256:..., instead of building

Loomplane passes the Dockerfile to the build by its path from the context, so it can sit anywhere. A service without a Dockerfile is built from its source, and build on it is ignored with a warning.

endpoint

Settings for a service on your own server or cluster.

FieldMeaning
host_portThe published host port, 1 to 65535
hostnameThe public hostname
ingress_classThe Kubernetes ingress class
tls_secretThe name of an existing Kubernetes TLS secret

need_options

Options a service hands to something it needs, by need name and then option name:

services:
  api:
    source: services/api
    needs: [fabriq]
    need_options:
      fabriq:
        tenant: acme

The need has to be in needs. Option names are lower case letters, digits and underscores, start with a letter and run to 32 characters. A value is up to 200 characters with no newline or other control character. Which options a kind accepts is checked when you plan.

The dashboard and POST /projects/:id/manifest/edits can change these in place without touching your comments. link adds a need to a service (with options if you give them, replacing old ones as a whole; with none, they stay). unlink removes the need and its options, and fails if the service doesn't need it. set_use sets one dependency on a catalog resource and leaves the rest of its uses alone. Send one of the three per edit.

resources

FieldMeaning
kindRequired. postgres, mysql, mariadb, redis, valkey, mongodb, kafka, rabbitmq, nats, object-storage, search, memcached, clickhouse and so on: the names analysis uses, or a catalog kind
provider, regionWhere it's provisioned
versionThe engine's version, such as "17". Without it, the provider's newest
targetThe conn_... of the checked server or Kubernetes connection a catalog resource runs on
usesWhere a catalog resource gets each dependency
environmentsprovider, region or enabled by environment name

uses

A catalog resource can depend on other things, such as a Postgres for its data or a Redis for its cache. By default Loomplane provisions a new one of each and wires it in. uses chooses something else, one dependency at a time, keyed by the dependency's name as the catalog lists it.

FieldMeaning
resourceUse another resource in this manifest. It must exist and can't be the resource itself
externalConnect to an endpoint you added to the catalog, by its ID (endpoint_ and 26 characters)
enabledTurn an optional dependency on or off. false can't go with resource or external

Set resource or external, not both. Set nothing and you get a new one.

resources:
  db:
    kind: postgres
  gateway:
    kind: sample
    target: conn_your_server
    uses:
      postgres:
        resource: db
      redis:
        external: endpoint_01jbz7q5mx8vh3k2r9t4w6y0ae
      falkordb:
        enabled: true

sample stands in for a catalog kind with those three dependencies, and conn_your_server for one of your checked connections. The manifest checks what it can see on its own: that db is in it and isn't gateway itself, and that the endpoint ID has the right form. The rest waits until you plan, when Loomplane finds out whether the kind has a dependency called postgres, whether db is a kind it accepts, and whether the endpoint answers from the target.

gateways

FieldMeaning
provider, regionWhere it runs: cloud-run or ecs-fargate
routesRequired. 1 to 50 routes
environmentsprovider, region or enabled by environment name

A route is {path, to, strip_prefix}. path is a prefix such as /api that matches /api and anything under /api/. to is the service name. strip_prefix removes the prefix first, so /api/users arrives as /users. The longest matching path wins.

FieldMeaning
betweenRequired. The two clouds it joins: gcp and aws
regionWhere the Google Cloud side runs. Put it where the Cloud Run services that use it run
environmentsregion or enabled by environment name

A link needs more than a connection check asks for. The Google Cloud key needs Compute Network Admin (roles/compute.networkAdmin). The AWS key needs ec2:CreateVpnGateway, ec2:AttachVpnGateway, ec2:DetachVpnGateway, ec2:DeleteVpnGateway, ec2:DescribeVpnGateways, ec2:CreateCustomerGateway, ec2:DeleteCustomerGateway, ec2:CreateVpnConnection, ec2:DeleteVpnConnection, ec2:DescribeVpnConnections, ec2:DescribeRouteTables, ec2:EnableVgwRoutePropagation and ec2:CreateTags. See Gateways and networking for what a link builds and bills.

ignore

ignore.resources lists resource kinds analysis found that the application doesn't use, so plans stop asking about them.

held

held.same_address decides what a scoped plan does when a held service uses a service that was deleted outside Loomplane and that the plan creates again. The held service isn't redeployed, so it keeps the old address.

With block (the default) that's a problem until you add the held repository to the scope. With warn it's a warning, but only when the planner can tell the address won't change: a Cloud Run service created again with the name, region and connection it had, which gets the same URL. Anything else, including a replacement, is still a problem.

held:
  same_address: warn

Variables Loomplane adds

NeedsVariable
Postgres, MySQL, MariaDBDATABASE_URL
Redis, ValkeyREDIS_URL
MemcachedMEMCACHED_SERVERS
MongoDBMONGODB_URI
AMQP brokersAMQP_URL
KafkaKAFKA_BROKERS
NATSNATS_URL
Object storageSTORAGE_URL
SearchSEARCH_URL
ClickHouseCLICKHOUSE_URL
Another serviceIts name in capitals plus _URL (API_URL)

Provider names

vercel, cloud-run, cloud-sql, memorystore, cloud-storage, ecs-fargate, rds, elasticache, s3, cross-cloud-vpn, render, digitalocean, azure-container-apps, azure-database, azure-managed-redis, server, kubernetes, plus any provider plugin. The Clouds overview says what each runs and provisions.

Federation (version 2)

Federation is still being built. Version 2 records federation proposals, and its plans stay blocked until destination agents, network drivers and policy enforcement pass qualification. Don't use it to try to get private traffic between clouds.

To convert a file, review its destinations and public exposure, change version explicitly, add the federation section and review the resulting blocked plan. Keep the original for rollback. The editor never upgrades it for you.

MapContents
destinationsName to {id: dest_..., environments: {env: dest_...}}. IDs must resolve in the organization, project and environment
network_links{from, to, transport} where transport is imported or ipsec
service_exports{service, destination, exposure: private, port, protocol, identity}. protocol is http, grpc or tcp, and identity is workload or gateway
access_grants{source_service, source_destination, export, methods, paths, grpc_methods, expires_at}
placements{service, destination}

Each map allows 100 entries. A grant allows 16 HTTP methods, 32 paths of up to 1024 bytes, or 32 gRPC methods of up to 256 bytes (gRPC selectors look like /package.Service/Method). expires_at is RFC 3339, and an expired grant is rejected at execution even if the manifest still parses. Exports need public: false and an explicit service port that matches. Every export and source grant needs a matching placement. needs still controls configuration and startup order and grants no access.

Connections supply credentials through Vault, so manifests contain no tokens, kubeconfigs or certificate keys. Management is off by default and turned on with federation.enabled. See Configuration.

On this page