Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

Screenshot of the STACKIT Portal permissions interface, highlighting the “Functions Admin” permission and showing the “Functions Reader” permission.

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:

  1. Navigate to your project within the Container Registry.
  2. Go to the Robot Accounts overview page by clicking on the Robot Accounts Tab.
  3. Click New Robot Account.
  4. 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. Basic Information screen of the Robot Account interface, with the name set to “stackit-functions”, description set to “STACKIT Functions Access”, and expiration time set to “Never” / -1
  5. For Permissions, configure only the “Registry” “Pull” permission, as seen in the screenshot. Permissions screen of the Robot Account interface, with the Registry Pull permission checked
  6. 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:
    sfn config registry add registry.onstackit.cloud 'robot$...' '...'
    
    (Note the single quotes in the command above. Without them, your shell will attempt to interpret the $ 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:

  1. Get the ID of the Registry credential you want the STACKIT Functions to use, using the STACKIT Functions CLI:
    sfn config registry list
    
    This command will print out a list of registry credentials configured in your project; pick the one matching the image you want to deploy.
  2. Invoke the push subcommand to upload the image to the OCI registry:
    sfn function push
    
    (Note: push will pick the right registry from the --image flag you passed to sfn function build earlier. If you need to override the image for the deployment process, you can also pass the --image flag to the deploy and push subcommands)
  3. Invoke the deploy subcommand to create the STACKIT Functions configuration. Make sure to pass the correct --registry-id:
    sfn function deploy --registry-id=<registry credential id>
    
    (Note: deploy also has options for building and pushing as part of the same step. See the sfn function deploy reference 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

  1. Create a service account for your deployment pipeline. Give it a descriptive name, such as “functions-deployment-pipeline”
  2. Assign the “Functions Admin” role to the newly-created service account so it can access the Functions API.
  3. Create a service account key. Copy it in JSON format.
  4. 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
  5. 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.

  1. 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
    
  2. Use the sfn auth login command 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 }}
    
  3. Use the Deploy command.

    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 PORT environment 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 build followed by sfn 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-id to sfn function deploy or have one registry ID configured in your stackit-functions.yaml manifest; otherwise, the STACKIT Functions won’t be able to pull your image. You can get the ID of a registry from sfn 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.

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.