Skip to content

1ctl marketplace

1ctl marketplace lets you deploy production-ready applications from a curated catalog with a single command. Each entry in the catalog is a template that encodes a container image, default resource requirements, required environment variables, ports, and volume configuration. You provide a name and optional overrides; the platform handles the Kubernetes plumbing.

you → 1ctl marketplace deploy <id> --name my-db → POST /v1/cli/marketplace/{id}/deploy → Deployment + Service + HTTPRoute

Aliases. 1ctl market and 1ctl apps are equivalent to 1ctl marketplace. All subcommands work the same under any alias.


Marketplace templates are stored in the marketplace_apps table. Each template defines:

  • The container image and tag
  • Default CPU and memory requests
  • Required and optional environment variables (some injected automatically via Infisical for default credentials)
  • Exposed ports and readiness probe configuration
  • Volume mount paths and storage requirements

When you run 1ctl marketplace deploy, the template defaults are merged with any flags you supply — your flags always win. The result is a deployment-backed workload that is then managed through the normal deployment lifecycle.

The intended product boundary is:

ConcernLong-term homeWhy
Browse curated applications1ctl marketplaceMarketplace is a catalog and discovery surface.
Inspect template defaults and required inputs1ctl marketplace getUsers need to understand what they are about to instantiate.
Create a workload from a curated template1ctl marketplace deploy today; likely also 1ctl deploy --template ... laterTemplate selection is an input to deployment creation, not a separate runtime species.
Operate the running workload after creation1ctl deploy, 1ctl logs, 1ctl domains, 1ctl secretsOnce created, a marketplace workload should behave like every other deployment.

In other words:

marketplace = catalog / template discovery / install intent
deploy = canonical runtime lifecycle

This is the direction to preserve over time. Marketplace should remain a first-class noun for discovery, but Satusky should avoid growing a second forever-diverging deployment system beside 1ctl deploy.

Current implementation versus intended model

Section titled “Current implementation versus intended model”

Today, the backend already treats marketplace workloads as deployments underneath, but it still reaches that result through a separate marketplace deployment path:

MarketplaceApp template
POST /marketplaces/deploy/create/:namespace/:marketplaceId
MarketplaceDeploymentService
Deployment + Service + Ingress records
Kubernetes resources

The marketplace backend also contains app-specific orchestration branches for workloads such as CNPG Postgres and NATS. That is useful: some templates are richer than “one image plus one Service.” But it does not require marketplace workloads to become a separate lifecycle. A good template system may produce one deployment, several resources, or operator-managed infrastructure while still handing the resulting workload back to the ordinary deployment control plane.

The long-term target is:

MarketplaceApp template
↓ resolve defaults + validate inputs
DeploymentSpec / workload spec
shared deployment pipeline
normal deployment lifecycle

This keeps one place for rollout behavior, machine placement, domains, secrets, status, metrics, restart, rollback, and destroy semantics.

Why not fully merge marketplace into deploy?

Section titled “Why not fully merge marketplace into deploy?”

Because the nouns answer different user questions:

User questionBest command
“What curated apps can I install?”1ctl marketplace list
“What does this PostgreSQL template require?”1ctl marketplace get postgres-16
“Create a workload from this curated template.”1ctl marketplace deploy postgres-16 ... or future 1ctl deploy --template postgres-16 ...
“What is running, is it healthy, and how do I operate it?”1ctl deploy ...

The best long-term shape is therefore separate catalog, unified lifecycle — not two completely separate products, and not one giant command group that hides the existence of curated templates.

Keeping marketplace as a catalog while converging runtime management onto deployments gives Satusky several durable advantages:

  • one placement model for both custom and template-backed workloads
  • one domains model
  • one monitoring and status model
  • one restart / rollback / destroy model
  • fewer duplicate flags and fewer chances for behavior drift
  • freedom for templates to become richer later without forcing users to learn a second operational language

This also pairs cleanly with the planned machine-label strategy: a template-backed workload should eventually accept the same machine selectors as any other deployment, instead of inventing marketplace-only placement rules.

Other platforms generally separate template discovery from runtime ownership:

PlatformObserved patternLesson for Satusky
Fly.iofly launch helps create/configure an app, while fly deploy is the durable deploy/redeploy lifecycle.Creation sugar can exist without creating a second runtime model.
DigitalOcean Marketplace1-Click Apps are curated inputs used to create underlying Droplets or Kubernetes apps.Marketplace entries can remain catalog artifacts rather than permanent workload types.
RailwayTemplates are discoverable as their own concept, but the CLI exposes railway deploy --template <code>.A template can be first-class for discovery while still entering through the deployment path.

Relevant references:

If Satusky later supports products that are genuinely higher-order than a deployment — for example, a multi-service WordPress stack with a database, cache, worker, scheduled jobs, and lifecycle coupling — the right new primitive may be app or stack. Even then, marketplace should still remain the catalog that instantiates the object; it should not become the permanent runtime home for everything installed from a template.


1ctl marketplace list [--limit <n>] [--offset <n>] [--sort <field>]

Browse the catalog of available applications.

FlagDefaultDescription
--limit20Maximum number of results to return.
--offset0Pagination offset.
--sortnameSort field. Accepts name or downloads.

Backend: GET /v1/cli/marketplace

Example output:

ID NAME CATEGORY CPU MEMORY DESCRIPTION
postgres-16 PostgreSQL 16 Database 0.5 512Mi Relational database
mysql-8 MySQL 8 Database 0.5 512Mi Relational database
redis-7 Redis 7 Cache 0.25 256Mi In-memory data store
rabbitmq-3 RabbitMQ 3 Messaging 0.5 512Mi Message broker
grafana-10 Grafana 10 Monitoring 0.5 512Mi Observability dashboard
prometheus Prometheus Monitoring 1.0 1Gi Metrics collection
wordpress-6 WordPress 6 CMS 0.5 512Mi Content management system

1ctl marketplace get <marketplace-id>

Returns the full details of a template: description, all available configuration options, default resource requirements, and any environment variables the template exposes.

Backend: GET /v1/cli/marketplace/{id}

Terminal window
1ctl marketplace get postgres-16

Example output:

ID: postgres-16
Name: PostgreSQL 16
Category: Database
Description: Production-ready PostgreSQL 16 with persistent storage.
Default resources:
CPU: 0.5 cores
Memory: 512Mi
Storage: 10Gi
Environment variables:
POSTGRES_DB (auto-generated)
POSTGRES_USER (auto-generated)
POSTGRES_PASSWORD (auto-generated via Infisical)
Ports:
5432/tcp (PostgreSQL)
Storage:
Mount: /var/lib/postgresql/data
Class: default

1ctl marketplace deploy <marketplace-id> --name <name> [options]

Deploy a marketplace application. Template defaults are applied for any flag you do not supply.

FlagDefaultDescription
--namerequiredName for your deployment. Must be unique within your namespace.
--hostnameauto-generatedSubdomain under .satusky.app to assign to this deployment.
--cputemplate defaultCPU cores to allocate. Overrides the template default.
--memorytemplate defaultMemory limit. Overrides the template default.
--domainnoneAttach a custom domain.
--storage-sizetemplate defaultPersistent volume size, e.g. "10Gi".
--storage-classdefaultKubernetes StorageClass for the persistent volume.
--multiclusterfalseDeploy across multiple clusters.
--multicluster-modeactive-passiveTraffic distribution: active-active or active-passive.

Backend: POST /v1/cli/marketplace/{id}/deploy

The backend merges your flags with the template spec, then creates a Kubernetes Deployment, Service, HTTPRoute, and PersistentVolumeClaim (if the template requires storage). An Issuer is created if a domain is attached.

Current status. This command is the marketplace-specific creation path implemented today. It is useful and should remain user-friendly, but it should not be allowed to drift into a separate deployment lifecycle from 1ctl deploy.


Terminal window
# Browse the catalog
1ctl marketplace list
# Sort by most-deployed apps
1ctl marketplace list --sort downloads
# Inspect the PostgreSQL template before deploying
1ctl marketplace get postgres-16
# Deploy PostgreSQL with a larger disk and more memory
1ctl marketplace deploy postgres-16 \
--name my-db \
--storage-size 20Gi \
--cpu 1 \
--memory 1Gi
# Deploy Redis with the minimum resources needed
1ctl marketplace deploy redis-7 \
--name my-cache \
--memory 256Mi
# Deploy WordPress with a custom domain
1ctl marketplace deploy wordpress-6 \
--name company-blog \
--domain blog.acme.com \
--storage-size 5Gi
# Deploy RabbitMQ across two clusters in active-active mode
1ctl marketplace deploy rabbitmq-3 \
--name message-broker \
--multicluster \
--multicluster-mode active-active

After a successful deploy, the CLI prints the deployment ID, assigned hostname, and initial pod status:

==> Deploying postgres-16 as my-db
==> Created resources
Deployment: my-db
Service: my-db
HTTPRoute: my-db.org-acme-prod.satusky.app
Volume: my-db-pvc (20Gi)
==> Deployment created
ID: dep_01jbx9p3q4
URL: https://my-db.org-acme-prod.satusky.app
Port: 5432
Monitor status: 1ctl deploy status --deployment-id dep_01jbx9p3q4

Marketplace deployments are first-class Satusky deployments. Once created, manage them with the standard 1ctl deploy subcommands:

Terminal window
# Check pod health
1ctl deploy status --deployment-id dep_01jbx9p3q4
# Stream logs
1ctl logs --deployment-id dep_01jbx9p3q4
# Restart pods (e.g. after changing secrets)
1ctl deploy restart --deployment-id dep_01jbx9p3q4
# Destroy the deployment and its volume
1ctl deploy destroy --deployment-id dep_01jbx9p3q4

The current CLI is sensible for discovery:

Terminal window
1ctl marketplace list
1ctl marketplace get postgres-16
1ctl marketplace deploy postgres-16 --name my-db

A strong future addition would be a canonical deploy entrypoint that makes the shared lifecycle explicit:

Terminal window
# Planned direction, not implemented today
1ctl deploy --template postgres-16 --name my-db

If added, 1ctl marketplace deploy can remain as an ergonomic alias for users who think “install Redis” before they think “create a deployment.” The important part is that both commands should compile into the same workload/deployment spec and pass through the same backend pipeline.

Capabilities that should stay shared with normal deploys

Section titled “Capabilities that should stay shared with normal deploys”
CapabilityMarketplace-specific today?Desired long-term rule
CPU and memory overridesPartly duplicatedReuse the standard deploy model.
DomainsPartly duplicatedReuse the standard domains model.
Machine targetingMarketplace has --hostname; deploy has --machine / --machine-tagConverge on the deployment placement model.
Future machine selectorsNot availableUse the same future --machine-selector primitive.
Status, logs, restart, rollback, destroyAlready handled by deploy/logsKeep fully shared.
Deployment strategies, HPA, VPA, PDBNot exposed in marketplacePrefer shared deployment capabilities unless a template explicitly forbids them.

Current gaps to resolve before the model is complete

Section titled “Current gaps to resolve before the model is complete”
GapWhy it matters
Separate marketplace deployment orchestration exists in the backend.It can drift from ordinary deploy behavior over time.
Marketplace deploy flags are not fully aligned with 1ctl deploy.Users may learn two subtly different ways to express the same intent.
Marketplace uses --hostname while deploy uses machine-oriented placement flags.The BYOA placement model should become one language everywhere.
Rich templates can create more than a plain deployment, but the durable runtime contract is not yet documented as a shared workload spec.Without a written contract, special cases can accrete into a second product.
No canonical 1ctl deploy --template ... path exists yet.The shared lifecycle is true conceptually, but not visible enough in the CLI.

Template resolution. marketplace_apps rows contain a full container spec: image, default CPU/memory, required env vars, port definitions, volume mount paths, and readiness probe configuration. When you deploy, the API reads this row and merges it with your request body — your supplied values replace the template defaults field-by-field.

Secret injection. Some templates (particularly databases) generate default credentials (usernames, passwords) automatically. These are provisioned via the Infisical integration and injected as Kubernetes Secrets, not ConfigMaps. Default credentials are displayed once in the deploy output; retrieve them later with 1ctl secret list.

Kubernetes resources created. Every marketplace deploy produces the same set of resources as 1ctl deploy:

ResourcePurpose
DeploymentRuns the container
ServiceClusterIP or LoadBalancer endpoint
HTTPRouteHTTP(S) routing and TLS termination
PersistentVolumeClaimDurable storage (if --storage-size is set or the template requires it)
IssuerTLS certificate provisioning (if a custom domain is attached)

All resources are created in your organization’s namespace and isolated from other organizations.

Current implementation references in satusky-core_backend:

  • routes/marketplace_route.go exposes marketplace catalog endpoints and a dedicated deploy endpoint.
  • controllers/marketplace_controller.go handles marketplace deployment requests.
  • services/marketplace_deployment_service.go validates requests, creates deployment/service/ingress records, marks DeploymentSource: "marketplace", and dispatches app-specific orchestration.

The backend is already close to the desired conceptual model because marketplace deployments become ordinary deployment records. The remaining architectural work is to move from “separate marketplace pipeline that eventually creates deployments” toward “template resolution feeding the shared deployment pipeline.”