Craft SDKs with SDKcraft

This is the fourth section of the four-part series; you’ll learn how to create full-featured SDKs that can be published and shared with others using SDKcraft. It relies on the knowledge gained in the Get started with workshops section, where you learned how to create and run workshops, and also builds on the Customize with sketch SDKs section, where you learned how to sketch local SDKs.

Here, you will initialize, define, pack, and publish an SDK: a set of hooks, interfaces, and parts that is bundled into a single package, suitable for use with SDKcraft, the user-oriented CLI utility. The commands you’re about to run cover most of your daily needs with SDKcraft.

Install SDKcraft

Install the snap using the --classic option:

$ sudo snap install --classic sdkcraft

Prerequisites

SDKcraft relies on LXD 6.8+ for low-level operation, using its REST API to craft the SDKs.

If the snap install command reports an issue with LXD, install a recent LXD version with snap.

To install it from scratch:

$ sudo snap install --channel=6/stable lxd

To refresh an existing installation:

$ sudo snap refresh --channel=6/stable lxd

Note

For other ways to install LXD, see the available installation options in LXD documentation. Also, you need to ensure the LXD daemon is enabled and running. Again, refer to LXD documentation and your distribution’s manuals for guidance.

Initialize the SDK

Once you have installed SDKcraft, use it to initialize, define, and pack your first SDK. Here, we’ll build an SDK that installs Ollama for running large language models in the workshop. This demonstrates creating an SDK for a specific application, but SDKs can package any software that aligns with the Workshop way.

First, create a directory named ollama/:

$ mkdir ollama/

It will contain your SDK definition and other source files.

Next, browse to the SDK directory and initialize it:

$ cd ollama/
$ sdkcraft init

This command creates a template definition file named sdkcraft.yaml; although it’s almost empty, it can already be built.

However, let’s take a few extra steps to explore what goes into an SDK.

Update metadata

Update the metadata in sdkcraft.yaml with some domain-specific information to describe the project and build SDKs for several platforms:

sdkcraft.yaml
name: ollama
version: "0.9.6"
summary: Get up and running with large language models
description: |
  Get up and running with Llama 3.3, DeepSeek-R1, Phi-4,
  Gemma 3, Mistral Small 3.1 and other large language models.
license: MIT
platforms:
  ubuntu@22.04:amd64:
  ubuntu@24.04:amd64:

parts:
  my-part:
    plugin: nil

Define parts

SDKcraft leverages the parts mechanism to obtain data from different sources, process it in various ways, and prepare an SDK package for publishing.

In our Ollama SDK, we’ll define two parts: one to download the Ollama binary from its GitHub release page, and another for the systemd service file:

sdkcraft.yaml
# ...
parts:
  ollama:
    plugin: dump
    source: https://github.com/ollama/ollama/releases/download/v${CRAFT_PROJECT_VERSION}/ollama-linux-amd64.tgz
    source-type: tar
  user-service:
    plugin: dump
    source: ollama.service
    source-type: file

The ollama part uses the dump plugin to download and extract the official Ollama binary from GitHub releases.

The user-service part includes a systemd service file that will be used to manage the Ollama daemon.

The first dump downloads the file automatically. However, we need to create the systemd service file that was referenced in the user-service part.

In the ollama/ directory, create a file named ollama.service:

ollama.service
[Unit]
Description=Ollama Service
After=network.target

[Service]
ExecStart=/bin/bash -lc "ollama serve"
Restart=always
RestartSec=3

[Install]
WantedBy=default.target

This defines how the Ollama daemon should run:

  • ExecStart starts the server with a login shell to pick up the environment

  • Restart ensures the service is restarted on failure

  • After makes it depend on network connectivity

Note

The service file is specific to Ollama and how it runs as a daemon. This is just one way to manage a long-running process in an SDK, and other SDKs may use different part layouts depending on their needs.

For in-depth details, refer to the Parts section in Craft Parts documentation.

Add plugs and slots

In SDKcraft, interfaces provide a controllable way of exposing the resources of the host system to the workshops, and you can use them in a variety of ways to extend the functionality of your SDK.

For the Ollama SDK, we need several interfaces: a mount interface to preserve models, a GPU interface for acceleration, and a tunnel interface to expose the API server. The latter is a resource that the SDK itself exposes, so it will be defined as a slot; the former two are plugs because they access external resources.

Open sdkcraft.yaml again and add two plugs and a slot to the appropriate sections:

sdkcraft.yaml
name: ollama
version: "0.9.6"
summary: Get up and running with large language models
description: |
  Get up and running with Llama 3.3, DeepSeek-R1, Phi-4,
  Gemma 3, Mistral Small 3.1 and other large language models.
license: MIT
platforms:
  ubuntu@22.04:amd64:
  ubuntu@24.04:amd64:

plugs:
  gpu:
    interface: gpu
  models:
    interface: mount
    workshop-target: /home/workshop/.ollama/models

slots:
  ollama-server:
    interface: tunnel
    endpoint: 11434

# ...

The models plug preserves downloaded models between workshop refreshes. The gpu plug provides access to GPU acceleration for faster inference, and the ollama-server slot exposes the Ollama API on port 11434.

Note

You can’t explicitly set the host directory for mount plugs here; this restriction prevents SDKs from accessing any arbitrary data on the host filesystem. However, users who add your SDK to their workshops will be able to remount the plug elsewhere at runtime.

Add hooks

To prepare the SDK for use, add the hooks that run at different stages of the workshop’s lifecycle, preparing the SDK for use or preserving its state during updates.

Under ollama/, there is a subdirectory named hooks/. This directory stores all the hooks for an SDK.

Build: setup base, project

Under ollama/hooks/, edit the file named setup-base:

setup-base
cat <<EOF >/etc/profile.d/ollama.sh
export PATH="$SDK/bin:\$PATH"
EOF

It runs when the workshop is launched or refreshed, and is typically used to install system packages and configure the environment.

In the same directory, edit the file named setup-project for Ollama-specific setup:

setup-project
install -D --mode=644 --target-directory ~/.config/systemd/user "$SDK/ollama.service"

systemctl --user daemon-reload
systemctl --user enable --now ollama

It runs after setup-base, once the project directory is mounted and interfaces are connected. This hook installs and starts the Ollama service as a user service, ensuring the AI model server is running and ready to use.

Note

Workshop tweaks this hook’s environment a bit.

First, note the $SDK variable, which points to the root of the SDK installation. This allows you to reference files installed by the SDK.

Also, when invoked from any hooks, apt is configured to exclude recommended or suggested packages and answer “yes” to all confirmation prompts.

Persist: save and restore

Some SDKs need to preserve internal state during workshop refresh operations, such as configuration settings or temporary data that shouldn’t be lost. For these cases, you would create save-state and restore-state hooks.

During a workshop refresh operation:

  • The save-state hook runs before the workshop is refreshed, saving the state of the SDK to $SDK_STATE_DIR.

  • The restore-state hook recovers the state after the workshop has been successfully updated.

However, the Ollama SDK doesn’t need these hooks because:

  • Downloaded models are stored in the mounted models/ directory, which persists across refreshes

  • The systemd service configuration is stateless and recreated on each refresh

  • No custom user configuration needs to be preserved

Warning

The SDK is also refreshed as a part of any workshop refresh operation, so any breaking changes in its save-restore logic will cause an error; make sure to allow for this in your SDK design.

Report: check health

Finally, create a hook named check-health to test whether the installation is functional and report to Workshop accordingly:

check-health
if ! output=$(sudo -u workshop --login ollama list 2>&1); then
  workshopctl set-health error "$output"
  exit
fi
workshopctl set-health okay

It checks whether the Ollama installation is functional by running ollama list. If it succeeds, the health is set to okay using the workshopctl set-health command; otherwise, it reports the error output from the failed command.

In general, the hook should set the health to okay and return a zero code if its health checks succeed. To signal an error, set the health to error or return a nonzero code.

You can also set the health to waiting to signal that the hook should be retried for a few seconds. Unless the hook sets the health to a different value during such a retry, the health is eventually set to error automatically.

Note

The use of sudo -u workshop here is important because only the setup-project hook runs as a normal user by default; other hooks, like check-health, run as root. Running commands as the nonroot user helps preserve the correct environment variables and file ownership, and can be easier than adjusting permissions afterwards.

Try the SDK

When you’re confident the SDK is ready to be built, try it in-place before uploading it to the Store.

Under ollama/, run:

$ sdkcraft try

  Packed ollama_amd64_ubuntu@22.04.sdk
  Packed ollama_amd64_ubuntu@24.04.sdk
  ...

Optionally, you can clean the build cache before trying:

$ sdkcraft clean && sdkcraft try

The command builds and packs the SDK into files such as ollama_amd64_ubuntu@24.04.sdk, which contain the build artifacts along with SDK metadata, hooks, and other components. This is repeated for all supported platforms defined in the sdkcraft.yaml metadata.

In particular, the command builds all SDK parts defined in the sdkcraft.yaml file, e.g., pulling source code, applying patches, configuring and compiling it according to the part definition.

After a successful build, the sdkcraft try command also copies the SDKs to a special try area (usually $XDG_DATA_HOME/workshop/try/). To use them in a workshop, add a prefix: try-<NAME>:

workshop.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: try-ollama

A channel is not needed here; the SDK is installed from the try area when you launch the workshop; the options --verbose and --wait-on-error help debug any issues that may arise during launch or refresh:

$ workshop launch --verbose --wait-on-error

Note

For a detailed explanation of the build process, see the respective Craft Parts documentation section.

Test the SDK

Additionally, you can write and run spread tests against the SDK to ensure its functionality and catch any issues before publishing it. For SDKcraft, spread tests are declared under tests/ in the SDK directory; each test describes a specific executable user workflow.

To run the test suite against the packed SDK:

$ sdkcraft test

At runtime, each test provisions a clean LXD container, installs the packed SDK into a workshop, and runs the declared scenarios end-to-end.

Publish the SDK

When an SDK is ready, built, and tried, publish it to the SDK Store for use with Workshop.

Authenticate, register the SDK name, and upload the artifact:

$ sdkcraft login
$ sdkcraft register ollama
$ sdkcraft upload ./ollama_amd64_ubuntu@24.04.sdk --release latest/beta

This uploads the newly created SDK and releases it under the latest/beta channel in the SDK Store.

For the full publish flow, including how to release already-uploaded revisions to additional channels, see How to publish an SDK.

Use the SDK

The resulting SDK can be used with Workshop as follows:

workshop.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: ollama
    channel: latest/beta

Note that the workshop base must match one of the SDK’s supported platforms.

Summary

This was the last step of the entire tutorial series.

You have learned how to create a workshop, add SDKs to it, and use them in practice. You have also learned how to sketch a local SDK and how to craft and publish a full-featured SDK. You are now familiar with all the basic operations that Workshop and SDKcraft provide and have had an extensive tour of their capabilities.