26 October 2026
Slimming your snaps
- 5 min read
- Likes 9

When the first Ubuntu release was published in 2004, there was a hard limit on how big the installation image could be. That’s because the typical way to install Warty Warthog was to burn it to a CD, and 700 megabytes is all a single CD could hold.
In those days, the size of individual software packages was a metric worth optimizing. Beyond the hard limit of what could fit on the installation medium, Internet speeds were slow, and disk capacity was limited. Many users would gladly put up with complex dependency management and limited portability if it meant fewer bytes sent over the network and stored on disk for each package.
Fast forward about a decade, and the snap format emerged, in a different environment. Network and disk weren’t as scarce, so sending and storing a few redundant libraries wasn’t as much of a downside. It was worth it if it meant that a single package artifact could work across past and future versions of multiple Linux distributions.
That said, package size is still important, and if you’re not paying attention as a package maintainer, snap sizes can get out of hand. This is especially true in an AI era, where applications may need to bundle multi-gigabyte machine learning models alongside executable code.
Fortunately, there are a few techniques for package maintainers to reduce the size of a snap, some old and some new. We’ll take a look at two general approaches. First, we’ll remove unnecessary files through explicit path filtering and package slices. Then we’ll consider splitting dependencies into separate shared content snaps and optional snap components.
Listen to the linter
The library linter is your first line of defense against unwieldy snaps. It is built into Snapcraft and is enabled by default. Using dependency information encoded inside executables, it can flag files that can be safely omitted from the final package.
Suppose you’re trying to package the ffmpeg video encoder. You might want to include some support for input/output devices from the libavdevice58 library. Your snapcraft.yaml file would look something like this:
apps:
ffmpeg:
command: usr/bin/ffmpeg
parts:
ffmpeg-part:
plugin: nil
stage-packages:
- ffmpeg
- libavdevice58
When you pack your snap, you’ll see a warning like this:
- library: libicuio.so.70: unused library 'usr/lib/x86_64-linux-gnu/libicuio.so.70.1'. (https://documentation.ubuntu.com/snapcraft/stable/how-to/debugging/use-the-library-linter)
Conveniently, that warning message links to documentation that tells you exactly what to do: use the minus-sign-prefix syntax to omit the specific unused library file from being included in the final package. You can go one step further and replace the version- and architecture-specific components with wildcards, so this library is handled properly on every platform where you build your snap.
parts:
ffmpeg-part:
# ...
stage:
# ...
- -usr/lib/${CRAFT_ARCH_TRIPLET_BUILD_FOR}/libicuio.so*
Slicing through
Selectively removing libraries from dependencies is a process often done for rocks, our OCI container images, to reduce file size and potential attack surface. This technique works just as well for snaps, too. Using the Chisel utility, Snapcraft can select subsets of files within Ubuntu packages, called slices. The real advantage comes not just from removing unnecessary files but entire other packages that are no longer dependencies once those files are removed.
You can list package slices in the stage-slices sections of your project file, simply by using an underscore between the package name and the slice name.
parts:
ffmpeg-part:
plugin: nil
stage-slices:
- ffmpeg_bins
- libavdevice58_libs
Feeling content with content snaps
Of course, removing libraries isn’t always the solution. Sometimes you really do need them, even a lot of them. For example, modern desktop environments like GNOME and KDE have a huge number of runtime dependencies. Requiring every application to bundle a full desktop runtime would be massively inefficient, both in terms of disk space and runtime memory footprint.
One way to handle this is by using content snaps. By bundling a set of shared dependencies as an entirely separate snap, content snaps can keep each individual application’s snap file size small. Moreover, a single content snap can provide libraries to multiple running snaps, which reduces total system memory usage.
The GNOME content snap is one of the most popular. It contains over 600 megabytes of libraries, interpreters, and data that other snap packages can safely leave out. Moreover, whenever there are security patches or bugfixes to those libraries, Canonical publishes those updates to the GNOME content snap. When that happens, every snap that uses it will benefit from up-to-date dependencies without the individual package maintainers needing to take any action.
When creating a snap, using a content snap is as simple as defining a plug in your project file
plugs:
gnome-46-2404:
interface: content
target: $SNAP/gnome-platform
default-provider: gnome-46-2404
In practice, you generally wouldn’t write this explicitly. You would use the GNOME extension instead, which takes care of connecting content snaps and many other conveniences as well. Some newer extensions, like the gpu and desktop extensions in core26, go a step further, applying the earlier strategy of file path filtering to remove redundancy between the package and its content snaps.
Components
Sometimes a snap is large not because of shared dependencies, but due to a large collection of app-specific assets. Think of kernel modules or large language models. Ideally, a user could download and install just the features they need. That’s the idea behind snap components, introduced just recently with Ubuntu 26.04 and available for snaps using core22 and newer.
For example, suppose you’re packaging the Piper text-to-speech engine as a snap. It has large data bundles for each voice and language. With components, each voice can be packaged as its own component. You can tell Snapcraft to put the voice data into a component via the organize key..
components:
voices-en-gb-alan-medium:
type: standard
summary: en-GB alan voice for Piper
description: en-GB alan voice for Piper
version: '0.1'
parts:
voices-en-gb-alan-medium:
plugin: dump
source: https://huggingface.co/rhasspy/piper-voices/
source-type: git
source-subdir: en/en_GB/alan/medium
organize:
en_GB-alan-medium.onnx: (component/voices-en-gb-alan-medium)/en_GB-alan-medium.onnx
en_GB-alan-medium.onnx.json: (component/voices-en-gb-alan-medium)/en_GB-alan-medium.onnx.json
When you pack your snap, you’ll get both a .snap package without voice data, and a .comp file that contains only the voice data. The snap and all of its components are published together, but users can selectively install whatever subset of components they like.
Next steps
If you’ve packaged a snap and it’s larger than you’d like, you have options. I’ve described a few techniques for filtering files and splitting packages; the ones that are right for you depend on what you’re building and how users will interact with your software. If you’d like advice on which strategies are best for you, come post on the snapcraft.io forums or in our Matrix room.