Enable classic confinement

When a snap needs system resources beyond what strict confinement and the available interfaces can provide, it needs classic confinement.

This page provides guidance on how to enable classic confinement, as well as example solutions for snaps that have extra plugin-specific configurations to accommodate it.

Set the confinement level

You can enable classic confinment with a single key in the project file:

snapcraft.yaml
confinement: classic

When built, the snap now has unsandboxed access to the system, like a traditional app or package.

Next, check for linting errors to look for low-hanging errors that Snapcraft can detect.

Lastly, you may also need to provide extra configuration for the main part’s plugin.

Request classic confinement on the Snap Store

A classically-confined snap requires approval from the Store team before you can distribute it on the Snap Store.

Submit your snap for review to get approval for classic confinement.

Identify problems with linters

When you first enable classic confinement, you should run an appropriate built-in linter to check for common errors and problems in the snap’s files.

Example project files with classic confinement

The following projects are sample solutions for combining classic confinement with specific plugins. These are only guidelines. Every case is different, so you may need to make other adjustments to your snap’s build to completely confine it.

Autotools plugin

autotools-classic-example is a project with a main part that uses the Autotools plugin.

autotools-classic-example project file
snapcraft.yaml
name: autotools-classic-example
version: "1.0"
summary: An example snap for an autotools project
description: |
  Shows how to create a snap for an application that uses Autotools for
  build and installation.

grade: devel
base: core22
confinement: classic

architectures:
  amd64:

apps:
  # Using the name of the snap as the key name allows the program to be invoked
  # by its name.
  autotools-classic-example:
    command: usr/bin/autotools-classic-example

parts:
  hello:
    plugin: autotools
    source: .
    autotools-configure-parameters:
      - LDFLAGS="
        -Wl,-dynamic-linker=/snap/core22/current/lib64/ld-linux-x86-64.so.2
        -Wl,-rpath=/snap/core22/current/lib/x86_64-linux-gnu"
      - --prefix=/usr

Make plugin

makefile-lib-example is a project with a main part that uses the Make plugin.

makefile-lib-example project file
snapcraft.yaml
name: example-make-lib
base: core22
version: "0.1"
summary: An example snap for a Makefile project using a system library
description: |
  Shows how to create a snap for an application that uses a Makefile for
  build and installation.

grade: devel
confinement: classic

architectures:
  amd64:

lint:
  ignore:
    - library

apps:
  make-example:
    command: bin/example-make-lib

parts:
  make-example-part:
    build-packages:
      - wget2-dev
    plugin: make
    make-parameters:
      - LDFLAGS="-Wl,-dynamic-linker=/snap/core22/current/lib64/ld-linux-x86-64.so.2
        -Wl,-rpath=/snap/core22/current/lib/x86_64-linux-gnu"
    source: .

CMake plugin

cmake-classic-example is a project with a main part that uses the CMake plugin.

cmake-classic-example project file
snapcraft.yaml
name: cmake-classic-example
base: core22
version: "0.1"
summary: An example classic snap for a CMake project
description: |
  Shows how to create a classic confinement snap for an application that
  uses CMake for build and installation.

grade: devel
confinement: classic

apps:
  cmake-classic-example:
    command: usr/bin/cmake-example

parts:
  cmake-example:
    plugin: cmake
    cmake-parameters: [-DCMAKE_INSTALL_PREFIX=/usr]
    build-attributes:
      - enable-patchelf
    source: .

Python plugin

python-ctypes-example is a project with a main part that uses the Python plugin.

python-ctypes-example project file
snapcraft.yaml
name: example-python-ctypes
base: core22
version: "0.1"
summary: An example snap for a Python project using ctypes
description: |
  Shows how to create a snap for a Python application that uses ctypes to
  access a system library.

grade: devel
confinement: classic

apps:
  example-python-ctypes:
    # This refers to the installed location of the program at build-time.
    # When the snap is installed, it will be available as example-python-ctypes.
    command: bin/test-ctypes.py

parts:
  example-part:
    source: .
    plugin: python
    # Override the build to perform a normal build then patch ctypes to fix the
    # run-time library paths.
    override-build: |
      craftctl build
      $CRAFT_PROJECT_DIR/snap/local/patch-ctypes.sh
    # These packages need to be made available so that the build step can patch
    # ctypes.
    stage-packages:
      - python3.10-minimal
      - libpython3.10-minimal
      - libpython3.10-stdlib
    # This resolves warnings reported by the classic linter for Snapcraft 3.7.
    build-attributes:
      - enable-patchelf

Patch Python ctypes to load system libraries

If your app uses ctypes to access system libraries, it must be bundled with patched ctype files. In this sample, both the patch script and the diff are kept in the project as files for processing during build.

To craft this solution:

  1. Copy the patch script into snap/local/ and the diff file into snap/local/patches/.

  2. Stage the system libraries in the main part. The core22 base uses Python 3.10, so the packages are:

    snapcraft.yaml
    stage-packages:
      - python3.10-minimal
      - libpython3.10-minimal
      - libpython3.10-stdlib
    
  3. Override the part’s build to also run a shell script that patches the ctype files:

    snapcraft.yaml
    override-build: |
      craftctl build
      $CRAFT_PROJECT_DIR/snap/local/patch-ctypes.sh
    

    The plugin now builds the part like normal before running the patch script.

  4. Build the snap. During build, the script looks for core Python modules that need to be patched and refer to libraries in the base snap.

Go plugin

golang-classic-example is a project with a main part that uses the Go plugin.

golang-classic-example project file
snapcraft.yaml
# golang-classic-example, a classically-confined project that uses the Go plugin

name: golang-classic-example
base: core22
version: "0.1"
summary: An example snap for a classic confinement golang project
description: |
  Shows how to create a snap for an application written in the Go language
  that uses classic confinement.

grade: devel
confinement: classic

apps:
  golang-classic-example:
    command: bin/main

parts:
  golang-classic-example:
    plugin: go
    source: .
    build-snaps: [go]
    build-packages: [pkg-config, libzstd-dev]
    build-environment:
      - CGO_ENABLED: 1
      - CGO_LDFLAGS_ALLOW: ".*"