Deploy your first service
Goal
For feature teams. In this guide you deploy a small Java service to a test environment. Then you add a database to it. You use the Joomiz CLI.
You finish with a service that is registered, planned and applied.
Before you start
You need three things from your platform team:
- The address of the control plane.
- A way to sign in. This is a token, or the settings for
joomiz login. - The ID and the name of your team. The example uses
finance-teamandFinance Team. Use your own.
You also need the Joomiz CLI.
You use the Joomiz CLI to run these commands. There is no download for the CLI yet. Your platform team provides it.
Tell the CLI where the control plane is. Replace the address with the address from your platform team.
export JOOMIZ_SERVER_URL=https://joomiz.example.com
Then sign in. If your platform team gave you the settings for joomiz login, run joomiz login. The command joomiz login --help lists what it needs.
If your platform team gave you a token, read it into your shell without showing it:
read -rs JOOMIZ_TOKEN
export JOOMIZ_TOKEN
Paste the token and press Enter. The token does not show on the screen or in your shell history. Do not write the token in joomiz.yaml or in another file of your project.
The output in this guide comes from a practice platform. Your output differs in three ways:
- The address of the control plane is yours. This guide shows
https://joomiz.example.com. - The IDs and the times are yours.
- The messages of the provisioners use other words. The practice platform ends some lines with
Nothing real was changed — this is a stub.A real platform does not print this text.
Steps
Create the file
Make a folder for the service. Run joomiz init inside it. The command writes a file named joomiz.yaml. It does not contact the control plane.
mkdir quick-start-shop
cd quick-start-shop
joomiz init --name=quick-start-shop \
--description="A small shop service for the quick start." \
--repository=https://github.com/example/quick-start-shop \
--golden-path=java-web-application \
--owner-id=finance-team \
--owner-name="Finance Team"
The golden-path is a supported way to build a service. Your platform team decides which names exist.
You see:
Wrote joomiz.yaml
id: f86f491d-2073-42d1-8166-17ab5d0eb093
name: quick-start-shop
description: A small shop service for the quick start.
repository: https://github.com/example/quick-start-shop
golden-path: java-web-application
owner.id: finance-team
owner.name: Finance Team
init generates an id for the application. Copy your id from the output.
The file that init wrote holds the key version and the application block. Replace the whole file with the complete file below. In the new file, replace the value of id with your own id. If your team is not finance-team, also write your own team in owner.
version: 1
application:
id: f86f491d-2073-42d1-8166-17ab5d0eb093
name: quick-start-shop
description: A small shop service for the quick start.
repository: https://github.com/example/quick-start-shop
golden-path: java-web-application
owner:
id: finance-team
name: Finance Team
# What your build produces.
artifacts:
- id: shop-jar
type: jar
spec:
path: target/shop.jar
environments:
test:
# Where the service runs.
targets:
- id: test-foundation
type: cloud-foundry-space
spec:
api-endpoint: https://api.cf.test.internal
org: example-org
space: quick-start-shop-test
# What runs there: the jar, on that target.
deployments:
- id: shop-test-deployment
type: cloud-foundry-app
artifact: shop-jar
target: test-foundation
spec:
instances: 1
memory: 1G
disk-quota: 1G
buildpack: java_buildpack
The file has these parts:
versionsays which shape of the file you use.initwritesversion: 1.applicationsays who owns the service.artifactssays what your build produces. Here it is onejarnamedshop-jar.environmentssays where the service runs. The environmenttesthas a target and a deployment.
A target is the place where a service runs, here a Cloud Foundry space. A deployment puts an artifact on a target. The spec of the target (api-endpoint, org and space) describes your own Cloud Foundry. Ask your platform team for the right values.
Register the application
Register the application once. Registration stores the identity of your application and its owner, and the lists artifacts and tooling.
joomiz register
You see:
Registered quick-start-shop with https://joomiz.example.com/applications
id: f86f491d-2073-42d1-8166-17ab5d0eb093
name: quick-start-shop
description: A small shop service for the quick start.
repository: https://github.com/example/quick-start-shop
golden-path: java-web-application
owner.id: finance-team
owner.name: Finance Team
location: /applications/f86f491d-2073-42d1-8166-17ab5d0eb093
Check the file
Check the whole file. The command changes nothing.
joomiz validate
You see:
joomiz.yaml is valid (checked by https://joomiz.example.com/validate)
application: no problems
tooling: no problems
environments: no problems in 1 environment (1 target, 1 deployment, 0 managed-resources, 0 consumed-resources)
If the report lists problems, each line names the part of the file with the problem. Fix the file and run the command again.
Preview the change
Run plan to see what apply would do. A plan changes nothing.
joomiz plan --environment test
You see:
plan for joomiz.yaml in environment test (computed by https://joomiz.example.com/plan?environment=test)
target/cloud-foundry-space: succeeded — Planned 1 change for target/cloud-foundry-space.
test-foundation (created): succeeded — Would create 'test-foundation' (target/cloud-foundry-space) in environment 'test'. Nothing was changed.
deployment/cloud-foundry-app: succeeded — Planned 1 change for deployment/cloud-foundry-app.
shop-test-deployment (created): succeeded — Would create 'shop-test-deployment' (deployment/cloud-foundry-app) in environment 'test'. Nothing was changed.
2 resource types, 2 resources
plan succeeded (revision 00420a5d-9800-44ca-b807-55b49683ce4d, plan efa320ac-a5ff-4f44-ab37-863c1f05f2b6)
Read the output from the top:
- Each block starts with a category and a type, for example
target/cloud-foundry-space. (created)means that the resource does not exist yet.- A plan changes nothing. It only describes the change.
- The last line gives the
revisionof your file. A revision is one exact file that was submitted for an application, identified by a hash. How Joomiz works explains it.
Apply the change
Run apply with the same file. Do not edit the file between plan and apply.
joomiz apply --environment test
You see:
applied joomiz.yaml to environment test (via https://joomiz.example.com/apply?environment=test)
target/cloud-foundry-space: succeeded — Applied 1 change for target/cloud-foundry-space.
test-foundation (created): succeeded — Created 'test-foundation' (target/cloud-foundry-space) in environment 'test'. Nothing real was changed — this is a stub.
deployment/cloud-foundry-app: succeeded — Applied 1 change for deployment/cloud-foundry-app.
shop-test-deployment (created): succeeded — Created 'shop-test-deployment' (deployment/cloud-foundry-app) in environment 'test'. Nothing real was changed — this is a stub.
2 resource types, 2 resources
apply succeeded (plan efa320ac-a5ff-4f44-ab37-863c1f05f2b6, apply 4253081c-9199-4b86-999a-a1785ff29956)
The last line says apply succeeded. The service is deployed in the environment test.
Read the result
Every plan and every apply is saved as a run. List your runs:
joomiz runs
You see:
ID KIND APPLICATION ENVIRONMENT STATUS STARTED
9a0706f0-e71d-480b-b1e1-704016b85579 apply quick-start-shop (f86f491d) test succeeded 2026-10-28T12:52:39.421Z
77dcee0c-4394-41ff-b52a-0774c2b7f4a9 plan quick-start-shop (f86f491d) test succeeded 2026-10-28T12:52:38.705Z
The KIND column shows the action of the run: plan or apply. The newest run is first.
Add a database
Add a PostgreSQL database. Replace the content of joomiz.yaml with the next file. Keep your own id in it.
version: 1
application:
id: f86f491d-2073-42d1-8166-17ab5d0eb093
name: quick-start-shop
description: A small shop service for the quick start.
repository: https://github.com/example/quick-start-shop
golden-path: java-web-application
owner:
id: finance-team
name: Finance Team
# What your build produces.
artifacts:
- id: shop-jar
type: jar
spec:
path: target/shop.jar
environments:
test:
# Where the service runs.
targets:
- id: test-foundation
type: cloud-foundry-space
spec:
api-endpoint: https://api.cf.test.internal
org: example-org
space: quick-start-shop-test
# What runs there: the jar, on that target.
deployments:
- id: shop-test-deployment
type: cloud-foundry-app
artifact: shop-jar
target: test-foundation
spec:
instances: 1
memory: 1G
disk-quota: 1G
buildpack: java_buildpack
env:
# A reference, not a password. The value is known after the database exists.
DB_PASSWORD: "${{managed-resources.shop-db.outputs.password}}"
# A database that Joomiz creates and owns for this service.
managed-resources:
- id: shop-db
type: postgres
spec:
flavor: cf-plan-small
version: "16"
storage-gb: 20
multi-az: false
The file has two additions:
- A managed resource named
shop-db, of typepostgres. A managed resource is a resource that Joomiz creates and owns for your service. - An
enventry on the deployment.DB_PASSWORDis a reference:${{managed-resources.shop-db.outputs.password}}.
The password is not in the file. The database reports its password as the address of a secret in a vault. A reference points at that output.
Check the new file:
joomiz validate
You see:
joomiz.yaml is valid (checked by https://joomiz.example.com/validate)
application: no problems
tooling: no problems
environments: no problems in 1 environment (1 target, 1 deployment, 1 managed-resource, 0 consumed-resources)
Preview the change:
joomiz plan --environment test
You see:
plan for joomiz.yaml in environment test (computed by https://joomiz.example.com/plan?environment=test)
managed-resource/postgres: succeeded — Planned 1 change for managed-resource/postgres.
shop-db (created): succeeded — Would create 'shop-db' (managed-resource/postgres) in environment 'test'. Nothing was changed.
outputs.password: https://vault.example.com/secrets/quick-start-shop-db-password
deployment/cloud-foundry-app: succeeded — Planned 1 change for deployment/cloud-foundry-app.
shop-test-deployment (updated): succeeded — Would update 'shop-test-deployment' (deployment/cloud-foundry-app) in environment 'test'. Nothing was changed. 1 spec value is not known until apply.
env.DB_PASSWORD: (known after apply)
2 resource types, 2 resources
plan succeeded (revision 6620a87d-65de-4d75-b348-43793d9b4834, plan 791d8513-b464-4540-b559-f8d4c4fb6a4d)
Read the output:
- The database is planned before the deployment, because the deployment uses it.
- The deployment reads
(updated), because it exists from the first apply. outputs.passwordis the address of a secret in a vault. It is not the password.env.DB_PASSWORD: (known after apply)means that the value does not exist until the database exists.
Apply the change:
joomiz apply --environment test
You see:
applied joomiz.yaml to environment test (via https://joomiz.example.com/apply?environment=test)
managed-resource/postgres: succeeded — Applied 1 change for managed-resource/postgres.
shop-db (created): succeeded — Created 'shop-db' (managed-resource/postgres) in environment 'test'. Nothing real was changed — this is a stub.
outputs.password: https://vault.example.com/secrets/quick-start-shop-db-password
deployment/cloud-foundry-app: succeeded — Applied 1 change for deployment/cloud-foundry-app.
shop-test-deployment (updated): succeeded — Updated 'shop-test-deployment' (deployment/cloud-foundry-app) in environment 'test'. Nothing real was changed — this is a stub.
2 resource types, 2 resources
apply succeeded (plan 791d8513-b464-4540-b559-f8d4c4fb6a4d, apply 5970e5ee-841a-494a-bc6e-b8bf6d9fe992)
Check
Run plan again with the same file. Nothing is left to change.
joomiz plan --environment test
You see:
plan for joomiz.yaml in environment test (computed by https://joomiz.example.com/plan?environment=test)
0 resource types, 0 resources
plan succeeded (revision 6620a87d-65de-4d75-b348-43793d9b4834, plan 4d9b0bf1-6f31-4e0e-84f8-bdc7daba8a5f)
The plan lists no resources, because the applied state already matches the file. The revision is the same as in the plan before, because the file is the same.
Troubleshooting
Every failed command prints a line that starts with error: and exits with a code other than 0.
| Symptom | Cause | Fix |
|---|---|---|
no credential is available | The CLI has no token and no saved sign-in. | Set JOOMIZ_TOKEN, or run joomiz login. |
HTTP 401 and Unauthorized | The token is not valid, or it has expired. | Get a new token from your platform team. |
HTTP 409 and Application already registered | You registered this id before. | Skip register. Go on with validate. |
HTTP 400 and Invalid owner | Your token cannot act for the owner.id in the file. | Write the ID of your own team in owner.id. |
no artifact with id ... is declared | A deployment names an artifact that the file does not declare. | Make artifact in the deployment equal to an id in artifacts. |
this file declares no environment named ... | The --environment value is not in the file. | Use a name from environments, here test. |
No appliable plan and this file has never been planned | You changed the file after plan, or you did not run plan. | Run plan with the file you want to apply. Then run apply with the same file. |
Next
Learn the parts of your file in The shape of a joomiz.yaml file.