Defining Workflows with ops.yml Configurations
ops.yml file is the primary configuration file defining Commands, Pipelines, and Services workflows on the CTO.ai platform. Alongside a
Dockerfile that defines the runtime environment for executing your workflow’s custom code, your
ops.yml configuration controls how workflows are run on our platform.
ops.yml config file may be used to define one or more CTO.ai workflows.
This page is intended to give you an understanding of how an
ops.yml file is used to configure workflows on the CTO.ai platform, as well as the relationship between various elements within an
ops.yml file and the workflow container image that is built as a result.
If you wish to jump right in to configuring your workflows, our ops.yml Reference page explains the structure of an
ops.yml file and the meaning of the elements within.
At the simplest level, each workflow defined in an
ops.yml file executes its
run command in the container built from the workflows’ common
Dockerfile defines the common containerized runtime environment that is built to execute the workflows in a given
ops.yml file. Each
ops.yml file that defines one or more Commands or Services workflow (or an individual workflows in the
.ops/jobs/ directory of a Pipelines workflow) may correspond with exactly one
Dockerfile. Thus, a single
ops.yml file that defines several Commands workflows will use the single
Dockerfile included in that directory to build a common container image for running those workflows.
A minimal functional container image—as shown above in the default
Dockerfile generated for Bash-based Commands workflows—pulls one of our base images, imports your application code (
ADD --chown=ops:9999 . .), and… that’s it. For all workflows, the entrypoint for your workflow container is defined in your
ops.yml file (described below), rather than being directly defined as part of the final container image.
The files in the following box are the basic
ops.yml configurations that are generated when initializing new Commands or Services workflows that use our Bash runtime environment.
In both of the examples above, the basic file contains some basic metadata (
description) and a shell command to
run in the workflow’s container. When you build a workflow using the
ops build CLI command, the resulting container image will be tagged with the
name value and act as the runtime environment for the command specified under the
In the Services workflow example, the
domain values are additional configuration settings that control the execution of the workflow’s container image on the CTO.ai platform.
ops.yml file for a Pipeline, our third type of workflow, is shown in the box below. Unlike Commands and Services workflows, the application logic for Pipelines resides in one or more
jobs defined by the workflow. The
steps key for each Job defines an array of strings to be passed to the workflow container; when a Pipeline workflow is built, these steps are added to the final image as lines in a shell script to be run within the resulting container.
For any given
ops.yml file defining one or more Pipeline Jobs, you can run
ops init . -j in the directory containing that
ops.yml file to generate scaffolding code for each Job. Separate template directories for each Job are created as subdirectories of
.ops/jobs/, with each Pipeline Job functioning as a self-contained Commands workflow.
For a deeper explanation of the
ops init subcommand and the scaffolding generated by our CLI, our Workflows Overview document has you covered.
In line with the best practices laid out for Twelve-Factor Applications, workflows on the CTO.ai platform provide multiple methods to make your application’s configuration available in its execution environment.
The simplest way to pass application configuration to your workflow’s runtime environment is through
static environment variables. The
static key within the
env mapping accepts an array of strings defining environment variables in
KEY=val format. For example, the
ops.yml excerpt below shows how the environment variable
DOCKER_REGISTRY can be set to the value
ghcr.io in the Pipeline workflow’s execution environment:
static env variables must be set on a per-workflow basis, and if the value of the variable must be changed in multiple workflows, you’d have to manually change the value in the
ops.yml file of each workflow. To make it easier for you to manage your application configurations, we offer Configs and Secrets Stores, where you can centrally set these values for all workflows published to your CTO.ai team.
Before a workflow can use a value from either your Secrets Store or Configs Store, you’ll need to make that value accessible as an environment variable by specifying its key in the
configs array under the workflow’s
env mapping. Unlike
static variables, however, you only need to specify the keys of the respective values to make available in the workflow’s runtime environment.
In the example above, all three types of environment variables are set under the
secrets. However, each value comes from a different place:
DOCKER_REGISTRYis set as
ghcr.iodirectly in the
BASE_API_URLretrieves the value of that key from the Configs Store of the Team that owns the workflow.
GITHUB_TOKENretrieves the value of that key from the Secrets Store of the Team that owns the workflow.
You can define
secrets values for your CTO.ai Team from our Dashboard or via our CLI.
In addition to the features described above which allow you to pass Configs and Secrets to your workflow as environment variables, it’s possible to access your Secrets and Configs from your application code without needing to specify their keys in your
ops.yml file. This can be done using methods such as
sdk.getConfig()—two examples from our Node SDK.
Keeping in line with standard security practices, workflow containers are run as a non-privileged user to minimize the damage that could be caused if a malicious process were to gain access to your Commands, Pipelines, or Services workflows.
Workflow containers are run with both their
user:group set to
ops:9999. Because of this runtime restriction, if your application code requires elevated privileges, you will need to ensure the necessary permissions are configured in your
To write files within a running container, the
/tmp directories are writeable by default.
If your workflow requires write access in a directory beyond the default writeable directories, you should set the ownership of that location to the
ops:9999 user. This is accomplished by adding the
--chown flag to an
COPY instruction in the
Dockerfile, or by using a
RUN instruction to
chmod the files or directories that you wish to be writeable: