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:
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:
# ...
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:
[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:
ExecStartstarts the server with a login shell to pick up the environmentRestartensures the service is restarted on failureAftermakes 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:
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:
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:
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-statehook runs before the workshop is refreshed, saving the state of the SDK to$SDK_STATE_DIR.The
restore-statehook 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 refreshesThe 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:
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>:
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:
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.