Skip to main content
Version: Weekly Build

Creating Service Providers

Codesphere allows you to publish existing Codesphere landscapes as Managed Service Providers. This enables other developers to discover and deploy your custom solutions.

Landscape-based Service Providers

A landscape-based service provider enables others to instantiate your Codesphere landscape as a pre-configured managed service that they can deploy and manage through the service catalog.

info

Publishing providers requires cluster admin permissions. Team admins can request providers to be scoped to specific teams.

Prerequisites

Before creating a landscape-based service provider, you need:

  1. A Git repository containing a valid Codesphere landscape with a ci.yml file.
  2. A provider definition, either as a provider.yml file at the repository root or provided directly in the API request.
  3. Git access to the landscape repository. Codesphere pulls the repository through your Git connection, so the account you use to create the provider must have permission to access it. You can manage your Git connections in your user settings.

Git access is tied to a user

The Git connection of the user who created (or last updated) a provider is used for pulling the landscape repository. If that user loses access to the repository, deployments of the provider will fail. To transfer the provider to another user's Git connection, that user sends a PUT or PATCH request for the provider — their connection is then used for pulling. For long-lived providers, consider publishing with a technical user.

Provider Definition

The provider.yml file defines all metadata and configuration schemas for your service provider.

name: mattermost
schemaVersion: v1
author: Your Team
displayName: Mattermost
iconUrl: https://example.com/mattermost-icon.png
category: collaboration
description: |
Open-source team messaging and collaboration platform.
Supports channels, direct messaging, and file sharing.

backend:
landscape:
gitUrl: https://github.com/your-org/mattermost-landscape

configSchema:
type: object
properties:
SITE_NAME:
type: string
description: Display name for your Mattermost instance
default: mattermost
readOnly: false
MAX_USERS:
type: integer
description: Maximum number of users allowed
x-update-constraint: increase-only
required: ['MAX_USERS']

secretsSchema:
type: object
properties:
ADMIN_PASSWORD:
type: string
format: password

detailsSchema:
type: object
properties:
hostname:
type: string
port:
type: integer

plans:
# The plan has no influence on the resource usage, so you should only define one.
# You can also set plans to an empty array to disable the plan selection UI.
- id: 0
name: Default Plan
description: Resource usage depends on the ci-profile of the landscape.
parameters: {}

versions:
0.0.1:
ciProfile: debug
# gitRef can be a commit-hash, branch or tag
gitRef: 1a410efbd13591db07496601ebc7a059dd55cfe9
description: Initial release
1.0.0-rc:
appVersion: Nextcloud v33
ciProfile: prod
gitRef: release-branches/1-0-0-rc
description: |
Release Candidate.
Changelog:
- Feature X
- Feature Y
- Fix Z
1.0.0:
appVersion: Nextcloud v33
ciProfile: prod
gitRef: release-tags/1-0-0
description: Long Term Support Release
scope:
type: team
teamIds: [4008]

Provider Fields

FieldDescription
nameUnique identifier for the provider. Must match ^[-a-z0-9_]+$.
versionVersion string in the format v[0-9]+ (e.g., v1, v2).
displayNameHuman-readable name shown in the Marketplace UI.
iconUrlURL to the provider icon (absolute or relative path).
categoryGrouping category (e.g., databases, messaging, monitoring).
authorOrganization or individual responsible for the provider.
descriptionMarkdown-formatted description of the service.
backend.landscape.gitUrlGit repository URL containing the landscape configuration.
configSchemaJSON Schema defining user-configurable options. These values are passed to the landscape as environment variables.
secretsSchemaJSON Schema defining secret values (e.g., passwords). These values are set in the landscape's secrets vault.
detailsSchemaJSON Schema defining runtime details exposed after provisioning.
versionsVersions of the service that users can deploy. At least one version is required. See Provider Versions.
scopeVisibility of the provider: global makes it available to everyone, team restricts it to the listed teamIds. See Provider Scopes.

The configSchema, secretsSchema, and detailsSchema serve different purposes but share the same format: each must be a valid OpenAPI schema object, which is how Codesphere parses them. As in OpenAPI, properties can be marked as required or given sensible default values.

Below you can see where each schema type appears in the Codesphere UI:

The configSchema defines the configuration properties the user sets when creating a service — for example, the PostgreSQL version to deploy. Once the service is created, the configuration can be inspected in the service settings. Properties that are not marked as readOnly can be updated later (see Update Constraints).

Config Schema in Service Settings

caution

Updating configuration parameters may cause a short downtime of the service.

Provider Versions

Every provider must define at least one entry in versions. Each version pins the exact state of the landscape that gets deployed:

  • gitRef: A commit hash, branch, or tag of the landscape repository.
  • ciProfile: The CI profile from the landscape's ci.yml to use for deployment.
  • appVersion (optional): A human-readable label for the deployed application version.
  • description (optional): Markdown-formatted release notes shown to the user.

When creating a service, users choose which version to deploy.

Deprecated fields

backend.landscape.ciProfile and backend.landscape.gitRef used to define these values once for the whole provider. They are deprecated — ciProfile and gitRef are now defined per version — but remain available for backward compatibility.

Publishing and Updating a Landscape-based Provider

The recommended way to publish and update a provider is the idempotent upsert endpoint of the Codesphere Public API. Send a PUT request to /managed-services/providers:

  • If no provider with the same name and schemaVersion exists yet, it is created.
  • If one already exists, all mutable fields are updated in place.

This means you can use the same request to create a provider and to roll out later changes — you don't need to track whether the provider already exists. This is useful in CI/CD pipelines, for example.

You can either provide a Git URL that includes the provider.yml file or the full provider specification in the payload.

tip

Dedicated create (POST) and update (PATCH) endpoints still exist for partial updates and more explicit workflows, but for most cases the upsert endpoint is the simplest choice.

Versions are append-only

You can add new entries to versions, but existing version records cannot be modified or removed through an upsert. All other provider fields are updated in place.

The simplest approach is to provide the Git repository URL. Codesphere will fetch and validate the provider.yml file from your repository automatically.

note

If you omit gitRef, the default branch of the repository is used to fetch the provider.yml file.

curl -X PUT "https://<your-codesphere-url>/api/managed-services/providers" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"gitUrl": "https://github.com/your-org/mattermost-landscape",
"gitRef": "my-branch",
"scope": {
"type": "global"
}
}'

Provider Scopes

When creating a provider, you can define its visibility scope:

Scope TypeDescription
globalAvailable to all teams in the Codesphere instance. Requires cluster admin permissions.
teamAvailable only to specified teams. Provide an array of teamIds.

Passing Configuration to Landscapes

When a service is created from a landscape-based provider, the user's input is passed down to the landscape: properties from the configSchema are set as environment variables, and secrets from the secretsSchema are injected into the landscape's vault. Both can be referenced in the landscape's ci.yml:

schemaVersion: v0.2
run:
my-service:
steps:
- command: ./start.sh
env:
APP_VERSION: ${{ workspace.env['APP_VERSION'] }}
ADMIN_PASSWORD: ${{ vault.ADMIN_PASSWORD }}

In this example, APP_VERSION is a property of the provider's configSchema and ADMIN_PASSWORD is a property of the provider's secretsSchema.

Update Constraints with x-update-constraint

The configSchema supports a custom extension x-update-constraint that lets you restrict how individual properties can be changed after a service has been created. This is useful for enforcing operational rules — for example, preventing storage from being decreased or locking down a database engine version after initial setup.

Add the x-update-constraint keyword to any property in your configSchema:

configSchema:
type: object
properties:
storage:
type: integer
description: Storage allocation in GB
x-update-constraint: increase-only
version:
type: string,
description: Version of the Postgres DB.
enum: ['17.6', '16.10', '15.14', '14.19', '13.22']
x-update-constraint: immutable,

Available Constraints

ConstraintBehavior
increase-onlyThe new value must be greater than or equal to the current value. Only applies to numeric fields.
immutableThe property cannot be changed once it has been set.

info

Update constraints are only enforced when updating an existing service. During initial creation, all values are accepted as long as they pass the standard schema validation.

Supported Formats

Provider schemas use JSON Schema validation. The following format values are supported in schema properties:

int32, int64, float, double, byte, binary, date, date-time, password, uri, hostname

Dynamic Details with x-endpoint

The detailsSchema supports a custom OpenAPI extension x-endpoint that allows you to fetch runtime details dynamically from your service. This is useful for retrieving live status information, metrics, or other data that changes after provisioning.

When x-endpoint is set on a property, Codesphere will fetch the value from the specified endpoint. The endpoint URL supports interpolation using other details fields.

detailsSchema:
type: object
properties:
hostname:
type: string
port:
type: integer
status:
type: object
properties:
state:
type: string
uptime:
type: number
x-endpoint: "https://{{hostname}}:{{port}}/status"

In this example, the status property is fetched dynamically from the service's /status endpoint using the hostname and port values.

info

Only GET requests are supported for x-endpoint. The endpoint must return JSON matching the property's schema definition.

Custom REST Backends

Codesphere's Managed Services architecture is designed to be extensible. If landscape-based providers don't meet your specific requirements you can implement your own custom REST backend.

tip

For a complete guide on implementing the Managed Service Adapter API specification, see Create a Custom REST Backend.