Introduction
Welcome to STACKIT Functions – STACKIT’s premier serverless functions-as-a-service offering!
Why Functions? Serverless functions offer the following benefits for your project:
- Scalable - Automatically scales up or down based on the number of incoming requests, ensuring efficient resource utilization, incl. scale-to-zero.
- Cost Efficient - You only pay for the compute time you use and don’t pay for idle. This can lead to significant cost savings compared to traditional server-based models.
- Serverless - The cloud provider manages the servers, allowing developers to focus solely on writing code. The cloud provider handles maintenance, updates, and security patches.
- Event Driven - Ideal for applications that need to respond to events in real-time, such as IoT devices or webhooks. Useful for data processing, real-time analytics, microservice architectures.
- Language Agnostic - Supports multiple programming languages, making it easy to develop and deploy functions in the language of your choice.
- Rapid Deployment - Enables user to iterate quickly. Great fit for Startups, R&D departements and every use case where results have to be delivered fast.
This documentation will help you create, develop, and deploy your first STACKIT Function using the STACKIT Functions CLI (sfn).
STACKIT Functions Concepts
With STACKIT Functions, you can package and deploy your code as containers, which are automatically scaled in response to incomming HTTP requests.
STACKIT Functions requires a container registry to store container images in. You can bring your own container registry, or, if you don’t have one yet, you can use the STACKIT Container Registry.
STACKIT Functions resources
Within STACKIT Functions, there are three main “resources” you can interact with:
-
A “Function” is the interface for your code. It mainly consists of an unique URL to which it’s deployed, and serves as the “identity” of your code, when communicating with external services.
-
A “Revision” is the implementation of your code. It holds all the configuration related to executing your code, such as what OCI image and environment variables to use. A Function has only one current revision deployed, while the rest of the revisions serve as version history of your application.
-
A “Registry” holds the credentials used for pulling container images. You can share a registry configuration between multiple revisions.
STACKIT Functions CLI
The STACKIT Functions CLI (sfn) is the main way in which you interact with STACKIT Functions.
The CLI works with a “manifest” file, called stackit-functions.yaml, which holds all the information needed to build a new function image and deploy it as a new revision.
You can bootstrap new functions using the official STACKIT Functions templates. This is done using the sfn function create command.
You can build runnable container images from those templates, using the STACKIT Functions builder. This is done using the sfn function build command or the --build flag.
You can then push the image to your container registry and deploy the function to the STACKIT Functions runtime, using the STACKIT Functions CLI. This is done using the sfn function deploy command.
STACKIT Functions runtime
The STACKIT Functions runtime is built on top of Knative, a CNCF project for running serverless functions on top of Kubernetes.
When you deploy a function to STACKIT Functions, our runtime takes care of creating the relevant Knative configurations and making your function accessible at a public URL.
Installing the STACKIT Function CLI
The STACKIT Functions CLI (sfn) is available from the stackitcloud/sfn-cli GitHub Repository.
From there, you can download the latest release as a .tar.gz (Unix systems) or .zip (Windows) file, which includes the sfn (or sfn.exe) binary. Extract that somewhere in your $PATH, and you are good to go!
To automate the process, we have developed an installation script that you can download and run on Linux and Mac:
curl -o ./install-sfn.sh https://raw.githubusercontent.com/stackitcloud/sfn-cli/refs/heads/main/install-sfn.sh
chmod u+x ./install-sfn.sh
./install-sfn.sh
What is in the installation script?
We invite you to preview the contents of the install script. It is written as readable Bash with minimal indirection, to allow you to audit it and potentially customize it to your needs:
#!/bin/sh
set -e
# Check prerequisites:
which curl >/dev/null || (echo "ERROR: curl not found; this script requires curl to run"; exit 1)
# Defaults:
DRY_RUN="${DRY_RUN:-}"
INSTALL_DIR="${INSTALL_DIR:-$HOME/.local/bin}"
INSTALL_VERSION="${INSTALL_VERSION:-latest}"
INSTALL_GOOS="${INSTALL_GOOS:-autodetect}"
INSTALL_GOARCH="${INSTALL_GOARCH:-autodetect}"
# Parse arguments: # https://stackoverflow.com/a/14203146
while [ $# -gt 0 ]; do
case "$1" in
--help)
echo "Usage: $0 [--path \$HOME/.local/bin] [--version latest] [--os autodetect] [--arch autodetect] [--dry-run]"
echo "Install the latest STACKIT Function CLI binary from GitHub releases"
exit 1
;;
--path) INSTALL_DIR="$2"; shift ;;
--version) INSTALL_VERSION="$2"; shift;;
--os) INSTALL_GOOS="$2"; shift;;
--arch) INSTALL_GOARCH="$2"; shift;;
--dry-run) DRY_RUN='1';;
--*) echo "ERROR: Unknown option $1" && exit 2;;
esac
shift || (echo "ERROR: Expected argument"; exit 2)
done
# Resolve OS and architecture:
if [ "$INSTALL_GOOS" = 'autodetect' ]; then
case "$(uname -s)" in
darwin | Darwin) INSTALL_GOOS="darwin";;
linux | Linux) INSTALL_GOOS="linux";;
*) echo "ERROR: Unknown operating system: $(uname -s)" && exit 3;;
esac
fi
if [ "$INSTALL_GOARCH" = 'autodetect' ]; then
case "$(uname -m)" in
x86_64 | amd64) INSTALL_GOARCH="amd64";;
aarch64 | arm64) INSTALL_GOARCH="arm64";;
*) echo "ERROR: Unknown architecture: $(uname -m)" && exit 3;;
esac
fi
# Resolve latest version:
if [ "$INSTALL_VERSION" = 'latest' ]; then
INSTALL_VERSION="$(curl --silent https://api.github.com/repos/stackitcloud/sfn-cli/releases/latest | sed -En 's|.+"tag_name": "v([^"]+)".+|\1|p')"
fi
# Construct download URL:
DOWNLOAD_URL="https://github.com/stackitcloud/sfn-cli/releases/download/v${INSTALL_VERSION}/sfn_${INSTALL_VERSION}_${INSTALL_GOOS}_${INSTALL_GOARCH}.tar.gz"
# Download and install:
echo "INFO: Downloading SFN CLI $INSTALL_VERSION from $DOWNLOAD_URL and installing to $INSTALL_DIR"
if [ -z "$DRY_RUN" ]; then
mkdir -p "$INSTALL_DIR"
curl -L "$DOWNLOAD_URL" | tar -xz -C "$INSTALL_DIR" sfn
echo "INFO: Installed SFN CLI to $INSTALL_DIR/sfn!"
else
echo "INFO: Dry run, skipping installation"
fi
# Check whether PATH contains install dir: # https://unix.stackexchange.com/a/32054
case ":$PATH:" in
*:$INSTALL_DIR:*);;
*)
echo "WARNING: $INSTALL_DIR is not part of your \$PATH"
echo "To use the \`sfn\` command, add export PATH=\"$INSTALL_DIR:\$PATH\" to your ~/.bashrc or ~/.zshrc (or use fish_add_path $INSTALL_DIR)."
echo "Alternatively, call the sfn CLI directly using \`$INSTALL_DIR/sfn\`"
;;
esac
Then, as long as $HOME/.local/bin is in your $PATH, you should be able to run sfn:
$ sfn --version
sfn 1.2.2
Configure access
You need to configure access to the STACKIT project, before you can start using STACKIT Functions. In particular, you need to configure:
- Permissions for your STACKIT account to be able to access STACKIT Functions.
- Registry secrets for STACKIT Functions to be able to access your OCI container image.
Needed permissions
For your user account to be able to deploy functions in a STACKIT project, it needs to have the relevant functions.* permissions, included with the “owner”, “editor”, and “Functions Admin” roles:

You can assign one of these roles using the IAM and management portal, as described in Assign roles to a user or service account.
Logging in
To authorize the STACKIT CLI, use the sfn auth login command:
sfn auth login --project-id <your project ID>
This should open a browser window in which you can give the sfn CLI access to your account.
In addition, the STACKIT CLI will enable the Functions service for your project.
For programmatic access, you can also use service account keys:
sfn auth login --project-id <your project ID> --service-account-key-path <path to service account key.json>
Note: you need to log in at least once with a user account, as the CLI will not attempt enabling the STACKIT Functions service from a service account.
Registry access
To be able to push and pull private function images, the STACKIT Functions CLI and runtime require access to a Docker/OCI registry. If you do not already have an OCI registry for your project, you can use the STACKIT Container Registry.
CLI
The STACKIT Functions CLI uses registry push secrets, that allow it to upload images to the OCI registry. By default, it reads these from your Docker configuration at ~/.docker/config.json.
When using the STACKIT Container Registry, you can follow the instructions at “Create your first Container Registry” in order to authenticate to the Container Registry using the Docker CLI. Other registries will have similar instructions in their documentation.
Runtime
The STACKIT Functions runtime needs registry pull secrets, that allow it to upload images to the OCI registry.
You can configure the registry pull secrets using the STACKIT Functions CLI:
sfn config registry add <address> <username with pull access> <password>
This command will create a new registry credentials configuration in your project, which you can later use when deploying functions.
When using the STACKIT Container Registry, we recommend that you can create a Robot Account for STACKIT Functions access, instead of reusing your personal account, by following these steps:
- Navigate to your project within the Container Registry.
- Go to the Robot Accounts overview page by clicking on the Robot Accounts Tab.
- Click New Robot Account.
- Configure the Basic information for the Robot Account. Name can be any descriptive name, perhaps “stackit-functions”; if you configure an expiration time, do note that your functions may stop working after the expiration time has passed.

- For Permissions, configure only the “Registry” “Pull” permission, as seen in the screenshot.

- In the final screen, copy the generated username and password (note that you won’t be able to access the password again if you close the screen), and use the following command to configure a new registry:
(Note the single quotes in the command above. Without them, your shell will attempt to interpret thesfn config registry add registry.onstackit.cloud 'robot$...' '...'$in the robot account username as the start of a variable substitution)
With this, you are all set up to use a private image registry with your STACKIT Functions project.
Create functions
Initializing a function from template
To create a new function, you can use the sfn function create command. This will pull in the STACKIT Functions templates, and initialize one of them in a folder of your choice.
sfn function create
The command will lead you through a wizard, configuring a name for the function, path to the folder containing generated source code, and the runtime language of your function.
In the end, this command will initialize a new project at {path}/{name}/ with a STACKIT functions manifest in {path}/{name}/stackit-functions.yaml.
Developing functions
You can learn more about the code which the templates generate in the Generated code reference.
See the next section, Build and run functions locally to learn more about debug your functions’ code before deploying.
Build and run functions locally
The STACKIT Function CLI contains commands that simplify the process of building and running a function locally.
Building STACKIT Functions images is handled using Cloud Native Buildpacks, a CNCF project for automatically detecting source code requirements and building images, without requiring complicated configuration.
Note: both building and running functions, require a running Docker installation, accessible over a Unix domain socket in $DOCKER_HOST (or over the default /var/run/docker.sock socket). Full support for alternative OCI runtimes, especially Podman, will come in later releases.
Build a function
To build a function, run the following command in the project directory created by sfn function create:
cd <path-to-functions-project>
sfn function build
When running the build command for the first time, it will error out because you don’t have an image name configured yet. Configure one with the --image flag:
sfn function build --image <your OCI registry>/<repository>/<image name>
Finally, to see the messages printed by the build process, pass the --verbose flag to the sfn function build command:
sfn function build --verbose
Run a function locally
Once you have built a function, you can run it with the run subcommand:
sfn function run
This will start a Docker container with your function, in a simulation of the STACKIT functions environment.
You can access the running function at http://127.0.0.1:8080 by default, unless you override the port the CLI binds to with the --address flag.
Meanwhile, the sfn CLI will forward the log messages from your locally-running function, which you can use for debugging purposes.
Deploy functions
After you have build and tested your function, it’s time to deploy it to STACKIT Functions for real.
To do so, you can follow these steps:
- Get the ID of the Registry credential you want the STACKIT Functions to use, using the STACKIT Functions CLI:
This command will print out a list of registry credentials configured in your project; pick the one matching the image you want to deploy.sfn config registry list - Invoke the
pushsubcommand to upload the image to the OCI registry:
(Note:sfn function pushpushwill pick the right registry from the--imageflag you passed tosfn function buildearlier. If you need to override the image for the deployment process, you can also pass the--imageflag to thedeployandpushsubcommands) - Invoke the
deploysubcommand to create the STACKIT Functions configuration. Make sure to pass the correct--registry-id:
(Note:sfn function deploy --registry-id=<registry credential id>deployalso has options for building and pushing as part of the same step. See thesfn function deployreference for more details.)
Once the deployment process completes, you should get a message similar to the following:
Name: your-function-name
ID: 00000000-0000-0000-0000-000000000000
Created: 1234-05-06T07:08:09.101112Z
Updated: 1234-05-06T07:08:09.101112Z
URL: 00000000-0000-0000-0000-000000000000.functions.onstackit.cloud
Follow the URL displayed by the command to see your function running on the STACKIT Functions runtime!
Note: It might take about a minute for your newly-deployed function revision to become available.
Note: Check out the Troubleshooting guide if your function is not available even after a minute has passed.
Read function logs
(Feature not yet available. Stay tuned!)
Configure variables and secrets
(Feature not yet available, but coming soon to a STACKIT Functions runtime near you! Stay tuned!)
Automate function deployments
Automated deployments are required by programming practices like continuous deployment. This page describes the necessary requirements for integrating STACKIT Functions into your Continuous Deployment pipeline.
Authorize the pipeline
- Create a service account for your deployment pipeline. Give it a descriptive name, such as “functions-deployment-pipeline”
- Assign the “Functions Admin” role to the newly-created service account so it can access the Functions API.
- Create a service account key. Copy it in JSON format.
- Add the service account key to your pipeline as a secret. The exact location for configuring pipeline secrets will differ depending on your Continuous Integration / Continunous Deployment (CI/CD) pipeline provider. For example, in Forgejo (and thus STACKIT Git), you can find repository pipeline secrets under Repository > Settings > Actions > Secrets; in GitHub, secrets can be found in Repository > Settings > Secrets and Variables > Actions; and in Azure DevOps, secrets are specified in Pipelines > Library > Variable Groups or Pipelines > Pipeline > Edit > Variables
- Add registry credentials to your pipeline as a secret. You would need credentials for pushing images to the container registry of your choice; typically, the username and a password of an automated account. As mentioned above, the exact method for configuring pipeline secrets will differ depending on the pipeline provider you use.
Use the STACKIT Functions CLI in your pipeline
The way you configure your pipeline will depend on the exact Continuous Integration / Continunous Deployment (CI/CD) pipeline provider you use.
-
Install the Functions CLI as one of the steps of the pipeline.
With GitHub Actions or Forgejo Actions, you can add the following step inside of
jobs.*.steps:- name: Install the STACKIT Functions CLI run: | curl https://raw.githubusercontent.com/stackitcloud/sfn-cli/refs/heads/main/install-sfn.sh | bash -
Use the
sfn auth logincommand with the service account key, in a later step.With GitHub Actions or Forgejo Actions, you can add the following step inside of
jobs.*.steps:- name: Log in to STACKIT Functions env: PROJECT_ID: "<your project ID here>" run: | $HOME/.local/bin/sfn auth login --service-account=${{ secrets.SERVICE_ACCOUNT }} -
With GitHub Actions or Forgejo Actions, you can add the following step inside of
jobs.*.steps:- name: Deploy to STACKIT Functions env: # Used by the sfn CLI as registry credentials: FUNC_USERNAME: ${{ secrets.REGISTRY_USERNAME }} FUNC_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | $HOME/.local/bin/sfn function deploy
Create custom functions without using the provided templates
You can build your own function container images if the templates built into the STACKIT Functions CLI do not provide the languages/technologies you want to use.
Once you have a built container image with the technology of your choice, you can deploy the image using the sfn function deploy command.
Functions container interface
The KNative-based STACKIT Functions runtime expects a linux/amd64 container. Instead of that container, you should:
- Expose an HTTP 1.1-compatible server on the port defined in the
PORTenvironment variable. - Handle the SIGTERM signal to run any cleanup logic.
Build with Dockerfile
You can build containers using technologies other than Buildpacks, as long as the final built container follows the interface explained eariler in Functions container interface.
For example, using a Dockerfile and the STACKIT Container Registry:
docker build . -t <your-registry.domain/group/image> --platform linux/amd64
Then, you can deploy your function using the STACKIT Functions CLI, passing the --build=false and --push=true flags:
sfn function deploy \
--build=false \
--push=true \
--image <your-registry.domain/group/image>
Using existing images
You can deploy existing images to STACKIT Functions if those images match the required functions container interface. For example, images created by the Knative func CLI are compatible with STACKIT Functions, if they have a matching platform of linux/amd64.
To deploy an existing image already uploaded to a Docker/ICO repository with the STACKIT Functions CLI, pass the --push=false and --build=false flags to sfn function deploy:
sfn function deploy \
--build=false \
--push=false \
--image <your-registry.domain/group/image>
This will deploy a function on STACKIT without building or uploading the image anew.
Create custom templates
You can create custom STACKIT Functions templates, by following the structure of the Official templates.
In particular, a templates repository should contain a separate folder for each template, containing a stackit-functions.yaml file. Repository layout:
https://git-host.example/user/repository-name.git
|-- template-folder
| |-- stackit-functions.yaml
| |-- README.md
| `-- ... source code
`-- ... other templates
The stackit-functions.yaml should contain a function block, defining, at minimum, the name of the template, as well as the runtime and trigger parameters:
function:
name: ts-template
runtime: nodets
trigger: http
The runtime will be used by the STACKIT Function CLI to select the correct entrypoint, as described by the Generated code reference.
Installing custom templates
To install a custom templates repository, use the template install subcommand:
sfn template install --source https://git-host.example/user/repository-name.git
Then, the sfn function create will then be able to use your the custom templates for initializing new function projects.
CLI reference
Auth
Login to STACKIT Functions
Usage: sfn auth login [OPTIONS]
Options:
-v, --verbose
Enable verbose output
--project-id <PROJECT_ID>
the STACKIT project identifier
--service-account-key-path <SERVICE_ACCOUNT_KEY_PATH>
--private-key-path <PRIVATE_KEY_PATH>
RSA private key path. Takes precedence over the key in the service account key, if present
--service-account-key <SERVICE_ACCOUNT_KEY>
-h, --help
Print help
-V, --version
Print version
Logout from STACKIT Functions
Usage: sfn auth logout
Options:
-h, --help Print help
-V, --version Print version
Config
View configuration
Usage: sfn config view
Options:
-h, --help Print help
-V, --version Print version
Update configuration
Usage: sfn config update <KEY> <VALUE>
Arguments:
<KEY> [possible values: project-id, registry]
<VALUE>
Options:
-h, --help Print help
-V, --version Print version
Config Registry
Add a registry
Usage: sfn config registry add [OPTIONS] <ADDRESS> <USERNAME> <PASSWORD>
Arguments:
<ADDRESS>
<USERNAME>
<PASSWORD>
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
-h, --help Print help
-V, --version Print version
Get a single registry
Usage: sfn config registry get [OPTIONS] <ID>
Arguments:
<ID>
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
-h, --help Print help
-V, --version Print version
List registries
Usage: sfn config registry list [OPTIONS]
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
--json Set output to JSON format
-h, --help Print help
-V, --version Print version
Update a registry
Usage: sfn config registry update [OPTIONS] --address <ADDRESS> --username <USERNAME> --password <PASSWORD> <ID>
Arguments:
<ID>
Options:
--address <ADDRESS>
--username <USERNAME>
--password <PASSWORD>
--project-id <PROJECT_ID> the STACKIT project identifier
-h, --help Print help
-V, --version Print version
Delete a registry
Usage: sfn config registry delete [OPTIONS] <ID>
Arguments:
<ID>
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
-h, --help Print help
-V, --version Print version
Environment
Get current environment
Usage: sfn environment [OPTIONS]
Options:
--json Set output to JSON format
-h, --help Print help
-V, --version Print version
Functions
Build a function
Usage: sfn functions build [OPTIONS]
Options:
--build-timestamp <BUILD_TIMESTAMP>
Use the current timestamp as creation time of the OCI image [env: FUNC_BUILD_TIMESTAMP=] [possible values: true, false]
--builder-image <BUILDER_IMAGE>
Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE) [env: FUNC_BUILDER_IMAGE=]
-n, --no-confirm
Prompt to confirm options interactively ($FUNC_CONFIRM) [env: FUNC_NO_CONFIRM=]
-i, --image <IMAGE>
Full image name in the form [registry]/[namespace]/[name]:[tag] (optional). This option takes precedence over --registry ($FUNC_IMAGE) [env: FUNC_IMAGE=]
-p, --path <PATH>
Path to the function. Default is current directory ($FUNC_PATH) [env: FUNC_PATH=]
--platform <PLATFORM>
Optionally specify a target platform, for example "linux/amd64" when using the s2i build strategy [env: FUNC_PLATFORM=]
--push
Attempt to push the function image to the configured registry after being successfully built [env: FUNC_PUSH=]
--username <USERNAME>
Username used to authenticate with remote registry (FUNC_USERNAME) [env: FUNC_USERNAME=]
--password <PASSWORD>
Password used to authenticate with remote registry (FUNC_PASSWORD) [env: FUNC_PASSWORD=]
--token <TOKEN>
Token used to authenticate with remote registry (FUNC_TOKEN) [env: FUNC_TOKEN=]
-r, --registry <REGISTRY>
Registry + namespace (e.g. 'ghcr.io/user'). Function name is derived by name and registry ($FUNC_REGISTRY) [env: FUNC_REGISTRY=]
-v, --verbose
Print verbose logs ($FUNC_VERBOSE) [env: FUNC_VERBOSE=]
-h, --help
Print help
-V, --version
Print version
Create a function
Usage: sfn functions create [OPTIONS] [NAME]
Arguments:
[NAME] Name of the function (which will also be the directory name)
Options:
--no-confirm Disable interactive confirmation ($FUNC_NO_CONFIRM) [env: FUNC_NO_CONFIRM=]
-p, --path <PATH> Path to the function project directory ($FUNC_PATH) [env: FUNC_PATH=]
-r, --runtime <RUNTIME> Function language runtime [env: FUNC_RUNTIME=]
-t, --trigger <TRIGGER> The function trigger ("http" or "cloudevent") [env: FUNC_TRIGGER=]
--source <SOURCE> Template repository installed name (e.g., 'sfn-templates') [env: FUNC_SOURCE=]
--source-name <SOURCE_NAME> The name of the template within the repository (e.g., 'go-template') [env: FUNC_TEMPLATE_NAME=]
--project-id <PROJECT_ID> the STACKIT project identifier
--registry-id <REGISTRY_ID> [env: FUNC_REGISTRY=]
-v, --verbose Print verbose logs ($FUNC_VERBOSE) [env: FUNC_VERBOSE=]
-h, --help Print help
-V, --version Print version
Delete a function
Usage: sfn functions delete [OPTIONS]
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
--function-id <FUNCTION_ID> the STACKIT Functions function identifier
--registry-id <REGISTRY_ID> the STACKIT Functions registry identifier
--path <PATH>
-h, --help Print help
-V, --version Print version
Deploy a function
Usage: sfn functions deploy [OPTIONS]
Options:
--build <BUILD>
Build the function. [auto|true|false]. ($FUNC_BUILD) (default "auto") [env: FUNC_BUILD=] [default: auto]
--build-timestamp <BUILD_TIMESTAMP>
Use the current timestamp as creation time of the OCI image [possible values: true, false]
--builder-image <BUILDER_IMAGE>
Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE) [env: FUNC_BUILDER_IMAGE=]
--env <ENV>
--env-file <ENV_FILE>
[env: ENV_FILE=]
-n, --no-confirm
Prompt to confirm options interactively ($FUNC_CONFIRM) [env: FUNC_NO_CONFIRM=]
-i, --image <IMAGE>
Full image name in the form [registry]/[namespace]/[name]:[tag]@[digest]. This option takes precedence over --registry. Specifying digest is optional, but if it is given, 'build' and 'push' phases are disabled. ($FUNC_IMAGE) [env: FUNC_IMAGE=]
-p, --path <PATH>
Path to the function. Default is current directory ($FUNC_PATH) [env: FUNC_PATH=]
--project-id <PROJECT_ID>
the STACKIT project identifier
--function-id <FUNCTION_ID>
the STACKIT Functions function identifier
--registry-id <REGISTRY_ID>
the STACKIT Functions registry identifier
-u, --push <PUSH>
Push the function image to registry before deploying. ($FUNC_PUSH) (default true) [env: FUNC_PUSH=] [default: true] [possible values: true, false]
-r, --registry <REGISTRY>
Container registry + registry namespace. (ex 'ghcr.io/myuser'). The full image name is automatically determined using this along with function name. ($FUNC_REGISTRY) [env: FUNC_REGISTRY=]
--username <USERNAME>
Username used for registry login [env: FUNC_USERNAME=]
--password <PASSWORD>
password is used to authenticate with the remote registry [env: FUNC_PASSWORD=]
--token <TOKEN>
Token used for registry login [env: FUNC_TOKEN=]
-v, --verbose
Print verbose logs ($FUNC_VERBOSE) [env: FUNC_VERBOSE=]
-h, --help
Print help
-V, --version
Print version
List functions in project
Usage: sfn functions list [OPTIONS]
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
--function-id <FUNCTION_ID> the STACKIT Functions function identifier
--registry-id <REGISTRY_ID> the STACKIT Functions registry identifier
--name <NAME>
--json Set output to JSON format
-h, --help Print help
-V, --version Print version
List function logs
Usage: sfn functions logs [OPTIONS]
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
--function-id <FUNCTION_ID> the STACKIT Functions function identifier
--registry-id <REGISTRY_ID> the STACKIT Functions registry identifier
--max-lines <MAX_LINES>
--since <SINCE>
--path <PATH>
-h, --help Print help
-V, --version Print version
Push a function
Usage: sfn functions push [OPTIONS]
Options:
--build <BUILD>
Build the function. [auto|true|false]. ($FUNC_BUILD) (default "auto") [env: FUNC_BUILD=] [default: auto]
--build-timestamp <BUILD_TIMESTAMP>
Use the current timestamp as creation time of the OCI image [possible values: true, false]
--builder-image <BUILDER_IMAGE>
Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE) [env: FUNC_BUILDER_IMAGE=]
-n, --no-confirm
Disable interactive selection ($FUNC_NO_CONFIRM) [env: FUNC_NO_CONFIRM=]
-e, --env <ENV>
Environment variable to set in the form NAME=VALUE. You may provide this flag multiple times for setting multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-)
-i, --image <IMAGE>
Full image name in the form [registry]/[namespace]/[name]:[tag]@[digest]. This option takes precedence over --registry. Specifying digest is optional, but if it is given, 'build' and 'push' phases are disabled. ($FUNC_IMAGE) [env: FUNC_IMAGE=]
-p, --path <PATH>
Path to the function. Default is current directory ($FUNC_PATH) [env: FUNC_PATH=]
--platform <PLATFORM>
Optionally specify a specific platform to build for (e.g. linux/amd64). ($FUNC_PLATFORM) [env: FUNC_PLATFORM=]
-r, --registry <REGISTRY>
Container registry + registry namespace. (ex 'ghcr.io/myuser'). The full image name is automatically determined using this along with function name. ($FUNC_REGISTRY) [env: FUNC_REGISTRY=]
--username <USERNAME>
Username used for registry login [env: FUNC_USERNAME=]
--password <PASSWORD>
Username used for registry login [env: FUNC_PASSWORD=]
-v, --verbose
Print verbose logs ($FUNC_VERBOSE) [env: FUNC_VERBOSE=]
-h, --help
Print help
-V, --version
Print version
Run a function locally
Usage: sfn functions run [OPTIONS]
Options:
--address <ADDRESS> Interface and port on which to bind and listen. Default is 127.0.0.1:8080. ($FUNC_ADDRESS) [env: FUNC_ADDRESS=] [default: 127.0.0.1:8080]
--build <BUILD> Build the function. [auto|true|false]. ($FUNC_BUILD) (default "auto") [env: FUNC_BUILD=] [default: auto]
--builder-image <BUILDER_IMAGE> Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE) [env: FUNC_BUILDER_IMAGE=]
-n, --no-confirm <NO_CONFIRM> Disable interactive selection ($FUNC_NO_CONFIRM) [env: FUNC_NO_CONFIRM=] [possible values: true, false]
-e, --env <ENV> Environment variable to set in the form NAME=VALUE. You may provide this flag multiple times for setting multiple environment variables [env: FUNC_ENV=]
-i, --image <IMAGE> Full image name in the form [registry]/[namespace]/[name]:[tag]. This option takes precedence over --registry. Specifying tag is optional. ($FUNC_IMAGE) [env: FUNC_IMAGE=]
--json <JSON> Output as JSON. ($FUNC_JSON) [env: FUNC_JSON=] [possible values: true, false]
-p, --path <PATH> Path to the function. Default is current directory ($FUNC_PATH) [env: FUNC_PATH=]
--platform <PLATFORM> Optionally specify a target platform, for example "linux/amd64" [env: FUNC_PLATFORM=]
-r, --registry <REGISTRY> Container registry + registry namespace. (ex 'ghcr.io/myuser'). The full image name is automatically determined using this along with function name. ($FUNC_REGISTRY) [env: FUNC_REGISTRY=]
-v, --verbose Print verbose logs ($FUNC_VERBOSE) [env: FUNC_VERBOSE=]
-h, --help Print help
-V, --version Print version
Get function status information
Usage: sfn functions status [OPTIONS]
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
--function-id <FUNCTION_ID> the STACKIT Functions function identifier
--registry-id <REGISTRY_ID> the STACKIT Functions registry identifier
--path <PATH>
--json Set output to JSON format
-h, --help Print help
-V, --version Print version
Projects
Get an accessible list of projects
Usage: sfn projects [OPTIONS] [PROJECT_NAME]
Arguments:
[PROJECT_NAME]
Options:
--project-id <PROJECT_ID> the STACKIT project identifier
--json Set output to JSON format
-h, --help Print help
-V, --version Print version
Templates
List all installed function templates
Usage: sfn templates list [OPTIONS]
Options:
--source <SOURCE> Filter templates by repository name
--trigger <TRIGGER> Filter trigger by trigger name ("http" or "cloudevent")
--runtime <RUNTIME> Filter by runtime language (e.g., "rust", "go", "python")
--json Set output to JSON format
--verbose Print verbose logs
-h, --help Print help
-V, --version Print version
Install a template
Usage: sfn templates install [OPTIONS]
Options:
--source <SOURCE> The git url of the template repository [default: https://github.com/stackitcloud/sfn-templates.git]
--install-name <INSTALL_NAME> The local name for this template (e.g., my-group/my-template). If not provided, the repository name will be used
-h, --help Print help
-V, --version Print version
Update a template
Usage: sfn templates update [OPTIONS] [SOURCE]
Arguments:
[SOURCE] The name of the repository to update. If not provided and --all is true, all repositories will be updated
Options:
--no-confirm Skip confirmation prompts
--all Update all templates
-h, --help Print help
-V, --version Print version
Remove a template
Usage: sfn templates remove <SOURCE>
Arguments:
<SOURCE> The name of the repository to remove
Options:
-h, --help Print help
-V, --version Print version
stackit-functions.yaml
Generated code
When using the provided templates, the STACKIT Functions builder supplies an entrypoint for your function that takes care of starting an HTTP server and handling health and readiness checks.
This way you can focus on writing only the parts of your function that matter.
Generated code - Go
When using the Go template, place your code in a package called “function”, and exposes a Handler function with the same signature as that expected by ServeMux.HandleFunc:
package function
func Handle(w http.ResponseWriter, r *http.Request) {
// ... Your code goes here
}
Generated code - NodeJS
When using the JavaScript template, place your code in a nodejs package, named "fn", with it’s "main" file exposing either a handler configuation, or a function called new which returns the same.
{ // in package.json
// ..
"name": "fn",
"main": "handler.js"
}
// handler.js
// Option 1: implement the FnInstance interface directly:
module.exports = {
async handle(context, data) {
// ... Your code goes here
}
}
// Option 2: export a new function which returns a FnInstance:
module.exports.new = function() {
return {
async handle(context, data) {
// ... Your code goes here
}
}
}
The handler is expected to fit the following interface:
type FnInstance = {
init?: () => void | Promise<void>;
shutdown?: () => void | Promise<void>;
handle: (context: Context, data: string | object) => Promise<Response>,
};
type Context = {
req: http.IncomingMessage;
res: http.ServerResponse;
method: string;
path: string;
url: string;
headers: Record<string, unknown>;
query: Record<string, string>;
httpVersionMajor: number;
httpVersionMinor: number;
rawBody: Buffer;
body: string | object;
log?: { info: (...a: any[]) => void; error: (...a: any[]) => void };
cloudevent?: CloudEvent;
cloudEventResponse(data): CloudEventBuilder;
};
type Response =
void |
{statusCode?: number, headers?: Record<string, unknown>, body: Body} |
Body;
type Body = CloudEvent | Buffer | object;
Generated code - Python
When using the Python template, place your code in a file called handler.py, which has a function called new() that returns a handler object.
The handle function of the handler is an ASGI application.
def new():
return Function()
class Function:
async def start(self):
return
async def stop(self):
return
def handler(self, scope, receive, send):
# ... Your code goes here, as an ASGI handler
pass
Generated code - Rust
When using the Rust template, create a Rust library package with the following structure:
#![allow(unused)]
fn main() {
pub mod handler {
pub const index: impl actix_web::Handler;
// e.g.: pub async fn index(actix_web::HttpRequest) -> actix_web::HttpResponse;
}
pub mod config {
pub fn configure(cfg: &mut actix_web::web::ServiceConfig);
}
}
You can define the config::configure function to change how the actix_web HTTP server is configured, and define any handler::index function signature that matches the actix_web::Handler trait to handle the incoming HTTP requests.
Generated code - Java Quarkus
The Quarkus template expects a codebase which uses the Quarkus Fungy framework.
Generated code - Java Spring Boot
The Spring Boot template expects a codebase with a main method, which follows the Functions container interface.
Note that we use Spring Boot Native in order to minimize the memory usage of your Spring Boot-based function.
Tooling
Troubleshooting / Known issues
Help! My function isn’t working! All I get is a 404/blank page!
In the very first alpha release of STACKIT Functions, we don’t have support for checking the status of a function or reading logs in the STACKIT Functions CLI / runtime.
Here is a checklist of things that are easy to get wrong, while we are still working on providing better error feedback from the CLI itself.
- Try running the function locally, using
sfn function buildfollowed bysfn function run. If the function runs into errors while starting up, the STACKIT runtime would never be able to forward requests to it. - Make sure you supply valid registry pull credentials. Pass
--registry-idtosfn function deployor have one registry ID configured in yourstackit-functions.yamlmanifest; otherwise, the STACKIT Functions won’t be able to pull your image. You can get the ID of a registry fromsfn config registries list. See also, Registry access.
If you still don’t know why your function is failing to start, please get in touch!
Deploying a function results in a 502 Bad Gateway error
This means that the STACKIT Functions runtime was unable to read your OCI image’s metadata from the OCI Registry.
Ensure you supply the right Registry credentials and use the --registry-id flag when calling sfn function deploy. Otherwise, the runtime won’t be able to access the image.
I get a dependency-related error when building an image
Please report the issue to us–it’s possible that we have missed an issue in the template / build process that needs ironing out for your usecase.
Consider building your images with Dockerfile if the supplied buildpacks fail to work for you.