Skip to main content

snap

The top-level snapcraft key is the recommended way to configure Snap builds. It requires an explicit base field and separates per-core options cleanly.

The legacy snap key is deprecated — it is still supported for core22 and older but will not receive new features. See Migrating from snap to snapcraft if you are on the old key.


Beta — core24 support is new. Please report any issues.

core24 targets Ubuntu 24.04 Noble and requires Electron 25.0.0+ (28.0.0+ recommended). It uses snapcraft v8 (craft-application framework) and brings first-class Wayland, the GNOME extension, and Launchpad remote builds for multi-arch CI.

{
"snapcraft": {
"base": "core24",
"core24": {
"confinement": "strict"
}
}
}

Building Snap packages requires a Linux environment (or Docker).

Build Environments

Choose one build environment. They are mutually exclusive.

OptionPlatformRecommended for
useLXD: trueLinuxLinux CI where nested virtualisation is unavailable
useMultipass: truemacOS / Windows / LinuxLocal development
useDestructiveMode: trueLinux onlyDocker CI containers without any virtualisation
remoteBuild.enabled: trueAnyMulti-arch CI (amd64, arm64, armhf) via Launchpad

If none is set and you are on Linux, snapcraft's own default (Multipass) is used. On non-Linux platforms you must choose useMultipass or remoteBuild.

LXD

Container-based isolation. Preferred on most Linux CI systems because it does not require nested virtualisation (unlike Multipass).

{
"snapcraft": {
"base": "core24",
"core24": {
"useLXD": true
}
}
}

LXD must be installed and the build user must be in the lxd group:

sudo snap install lxd
sudo usermod -aG lxd $USER
lxd init --minimal

Multipass

VM-based isolation. The default choice for local development on macOS and Windows.

{
"snapcraft": {
"base": "core24",
"core24": {
"useMultipass": true
}
}
}

Destructive Mode

Builds directly on the host without any VM or container (snapcraft --destructive-mode).

!!! warning Not recommended for production builds. Destructive mode pollutes the host environment — any library present on the host at build time can end up in the snap, making builds difficult to reproduce. Prefer useLXD or useMultipass for clean builds.

Valid reason(s) to use this mode:

  • CI test suites where the environment is already fully controlled.

The gnome extension is incompatible with destructive mode. electron-builder automatically clears extensions when useDestructiveMode is set; explicitly including "gnome" alongside it will throw an error.

{
"snapcraft": {
"base": "core24",
"core24": {
"useDestructiveMode": true,
"extensions": []
}
}
}

Remote Build on Launchpad

Builds on Canonical's Launchpad infrastructure. Works from any platform and supports building for multiple architectures simultaneously (amd64, arm64, armhf).

{
"snapcraft": {
"base": "core24",
"core24": {
"remoteBuild": {
"enabled": true,
"buildFor": ["amd64", "arm64"],
"acceptPublicUpload": true
}
}
}
}

!!! note Unless privateProject is set, your source code is uploaded to a public Launchpad repository. Set acceptPublicUpload: true to suppress the interactive consent prompt in CI.

Authentication

Remote builds require Snapcraft Store credentials. electron-builder resolves them in this order:

  1. remoteBuild.cscLink — base64-encoded credentials or a file path in the build config.
  2. SNAP_CSC_LINK — environment variable, same format (CI-recommended).
  3. SNAPCRAFT_STORE_CREDENTIALS — plain-text macaroon, read directly by snapcraft.
  4. An active interactive snapcraft login session.

Credentials are injected only into the spawned snapcraft subprocess environment and are never exposed through process.env.

This follows the same pattern as WIN_CSC_LINK / CSC_LINK for code signing.

CI Setup

Generate credentials once and store as a CI secret:

# Run locally — output is your CI secret value
snapcraft export-login - | base64 -w0

Then set SNAP_CSC_LINK in your CI environment:

# GitHub Actions
- name: Build and publish snap
env:
SNAP_CSC_LINK: ${{ secrets.SNAP_CSC_LINK }}
run: npx electron-builder --linux snap
Classic Confinement

Snap Store requires manual review and approval for classic confinement. Electron apps typically use strict with appropriate interface plugs.

To reference credentials file directly via the config (useful for monorepos where the credential is managed per-project):

{
"snapcraft": {
"base": "core24",
"core24": {
"remoteBuild": {
"enabled": true,
"cscLink": "file://..."
}
}
}
}

GNOME Extension

By default, core24 builds apply the gnome extension, which:

  • Pulls in the gnome-46-2404 platform content snap (GTK3, GLib, etc.)
  • Adds gtk-3-themes, icon-themes, sound-themes content snaps
  • Adds the gpu-2404 GPU support content snap
  • Injects layout, environment variables, and plugs required by Electron on Ubuntu 24.04

You normally do not need to configure extensions at all. To opt out:

{
"snapcraft": {
"base": "core24",
"core24": {
"extensions": []
}
}
}

When extensions is empty, electron-builder falls back to the standard Electron plug set and you are responsible for layout and content snap declarations.

Minimal Plugs

Start with only the plugs you actually need. Unnecessary plugs may slow Snap Store review. At minimum, browser-support, network, desktop, and desktop-legacy are needed for most Electron apps.


Wayland

core24 always allows native Wayland. The snap runs with --ozone-platform=wayland on compositors that support it and falls back to XWayland otherwise.

To force X11-only mode, set forceX11: true:

{
"snapcraft": {
"base": "core24",
"core24": {
"forceX11": true
}
}
}

Stage Packages

The default stage packages are ["libnspr4", "libnss3", "libxss1", "libappindicator3-1", "libsecret-1-0"].

Use the "default" keyword to extend the defaults rather than replace them:

{
"snapcraft": {
"base": "core24",
"core24": {
"stagePackages": ["default", "libv4l-0"]
}
}
}

Core 22

core22 targets Ubuntu 22.04 Jammy. It is the most recent stable (non-beta) base and is supported via the legacy SnapCoreLegacy implementation.

{
"snapcraft": {
"base": "core22",
"core22": {
"summary": "My Electron app",
"confinement": "strict",
"stagePackages": ["default"]
}
}
}

Key differences from core24:

  • allowNativeWayland defaults to false — Wayland is disabled by default for older Electron compatibility. Set to true to enable. (The legacy interface uses allowNativeWayland; core24 uses forceX11.)
  • No extensions — no GNOME extension support; uses the desktop-gtk2 part instead.
  • useTemplateApp — when stagePackages is not customised, electron-builder uses a pre-built Electron snap template for faster assembly (x64 and armv7l only).
  • Build is handled by the app-builder-bin binary, not by a direct snapcraft invocation.

Core 20

core20 targets Ubuntu 20.04 Focal.

{
"snapcraft": {
"base": "core20",
"core20": {
"summary": "My Electron app",
"confinement": "strict"
}
}
}

Behaviour is identical to core22 above. Use core22 unless the Snap Store requires core20.


Core 18

core18 targets Ubuntu 18.04 Bionic. Use only if your store listing requires it.

{
"snapcraft": {
"base": "core18",
"core18": {
"summary": "My Electron app",
"confinement": "strict"
}
}
}

Custom Pass-Through

Set base: "custom" to pass a snapcraft.yaml file (or an inline object) through to snapcraft verbatim. electron-builder performs no injection — no plugs, extensions, organize mappings, or desktop entries are added.

{
"snapcraft": {
"base": "custom",
"custom": {
"yaml": "build/snapcraft.yaml"
}
}
}

The yaml path is resolved relative to the build resources directory (build/ by default). You can also supply the YAML content inline as an object in the config.


Migrating from snap to snapcraft

The legacy snap key is equivalent to using snapcraft with a per-core options object. The base field moves to the top level of snapcraft, and all other fields move inside the corresponding core key.

// Before — deprecated snap key
{
"snap": {
"base": "core22",
"summary": "My app",
"confinement": "strict",
"stagePackages": ["default", "libfoo"]
}
}

// After — snapcraft key (recommended)
{
"snapcraft": {
"base": "core22",
"core22": {
"summary": "My app",
"confinement": "strict",
"stagePackages": ["default", "libfoo"]
}
}
}

The snap key continues to work for core22 and older. Omit base from the inner object — it lives at snapcraft.base now.

The appPartStage option controls which files are included from the main app part:

snap:
appPartStage:
- -usr/share/doc
- -usr/share/man

Publishing to the Snap Store

  1. Create an account at snapcraft.io, register your snap name, and install the snapcraft CLI — see Publishing to the Snap Store
  2. Configure publishing in your electron-builder config:
publish:
provider: snapStore
repo: myapp # your registered snap name
channels:
- stable
  1. Build and publish: electron-builder --linux snap --publish always

Channel Strategy

ChannelPurpose
edgeLatest development builds (auto-published from CI)
betaBeta testing builds
candidateRelease candidates
stableProduction releases

Local Testing

Install a locally built snap without the Snap Store:

sudo snap install --dangerous dist/myapp_1.0.0_amd64.snap

Run and check logs:

myapp
journalctl --user -xe | grep myapp

To uninstall: sudo snap remove myapp

Debugging

Enable verbose electron-builder output:

DEBUG=electron-builder electron-builder --linux snap

For snap runtime issues, check confinement denials:

snap run --shell myapp
# Inside the snap shell, test what's accessible

Configuration

snapcraft (new)

Interface: SnapcraftOptions

New-style snap configuration. Use this via the snapcraft key in your build config. Selects the snapcraft core version and its per-core options.

Extends

Properties

artifactName?

readonly optional artifactName?: string | null

The artifact file name template.

Inherited from

TargetSpecificOptions.artifactName


base

readonly base: "custom" | "core18" | "core20" | "core22" | "core24"

The snap base to use as the execution environment. Determines which set of per-core options (core18, core20, core22, core24, custom) is active.

Only one core may be selected per build target.


core18?

readonly optional core18?: SnapOptionsLegacy | null

Configuration for a core18 build. Only active when base is "core18".


core20?

readonly optional core20?: SnapOptionsLegacy | null

Configuration for a core20 build. Only active when base is "core20".


core22?

readonly optional core22?: SnapOptionsLegacy | null

Configuration for a core22 build. Only active when base is "core22".


core24?

readonly optional core24?: SnapOptions24 | null

Beta

[Beta] Options for building a core24 snap. Uses the snapcraft CLI directly. Inherits desktop-entry fields from CommonLinuxOptions and publish config from TargetSpecificOptions.


readonly optional cscLink?: string

Snapcraft Store credentials — base64-encoded credentials string or file path. Accepts the same formats as WIN_CSC_LINK / CSC_LINK: base64 data, absolute/relative/~/ file paths, and file:// URIs. Relative paths are resolved against the build resources directory.

Injected as SNAPCRAFT_STORE_CREDENTIALS into every snapcraft subprocess (core18/core20/core22/core24 builds and snapcraft upload). Not applied for base: "custom" — inject credentials manually via environment variables.

The SNAP_CSC_LINK environment variable is the CI-friendly alternative. Generate with: snapcraft export-login - | base64 -w0


custom?

readonly optional custom?: SnapOptionsCustom | null

Beta

[Beta] Pass-through custom snap configuration. electron-builder will read the snapcraft.yaml at yamlPath and use it verbatim — no plugs, extensions, organize mappings, or desktop files are injected.


publish?

optional publish?: Publish

Inherited from

TargetSpecificOptions.publish

SnapOptions24 (core24)

{!./app-builder-lib.Interface.SnapOptions24.md!}

RemoteBuildOptions

{!./app-builder-lib.Interface.RemoteBuildOptions.md!}

SnapOptionsCustom

{!./app-builder-lib.Interface.SnapOptionsCustom.md!}

snap (legacy, deprecated)

~~Interface: SnapOptions~~

Flat snap options. Used via the snap key in your build config.

Deprecated

Prefer the snapcraft key with an explicit base field (e.g. { "snapcraft": { "base": "core24", "core24": { ... } } }). The flat snap interface is maintained for backward compatibility and targets core22 and older snap bases only.

Fields inherited from CommonLinuxOptions (e.g. description, category, mimeTypes, executableArgs) are automatically populated from linux.* configuration and do not need to be repeated here. Per-core values take precedence when both are set.

Extends

Properties

~~after?~~

readonly optional after?: string[] | null

Names of snapcraft parts that must be built before the app part. Defaults to ["desktop-gtk2"].

Use "default" to keep the default and add extras: ["default", "my-helper-part"].


~~allowNativeWayland?~~

readonly optional allowNativeWayland?: boolean | null

Allow the snap to run with native Wayland support (--ozone-platform=wayland). Defaults to false for Electron < 38 (legacy behaviour); true for Electron ≥ 38. Set explicitly to override the version-based default.


~~appPartStage?~~

readonly optional appPartStage?: string[] | null

Filesets controlling which files from the app part are staged into the snap. Supports individual files, directories, globs, globstars, and exclusions (prefix !). See Snapcraft filesets. When not set, the snap template's default stage list is used for legacy bases (core18/core20/core22).


~~artifactName?~~

readonly optional artifactName?: string | null

The artifact file name template.

Inherited from

TargetSpecificOptions.artifactName


~~assumes?~~

readonly optional assumes?: string | string[] | null

Snapd features that must be present on the host before the snap can be installed.


~~autoStart?~~

readonly optional autoStart?: boolean

Whether the snap should automatically start on login.

Default

false

~~base?~~

readonly optional base?: string | null

The snap base to use as the execution environment. Examples: core18, core20, core22.

For new projects, use the snapcraft key with base: "core24" instead of this legacy interface.


~~buildPackages?~~

readonly optional buildPackages?: string[] | null

Debian packages required at build time (installed inside the build environment).


~~category?~~

readonly optional category?: string | null

The application category.

Inherited from

CommonLinuxOptions.category


~~compression?~~

readonly optional compression?: "xz" | "lzo" | null

Compression algorithm for the snap SquashFS image.

  • xz — smaller file, slower decompression (good for distribution).
  • lzo — larger file, faster decompression (good for development iteration). Omit to use snapcraft's default (xz).

When not set, linux.compression is mapped automatically: "store""lzo", "maximum""xz", "normal" → snapcraft default. Explicitly setting this field always overrides the mapped value.


~~confinement?~~

readonly optional confinement?: "devmode" | "strict" | "classic" | null

The type of snap confinement.

  • strict — recommended; the snap runs in a fully isolated sandbox.
  • devmode — sandbox violations are logged but not enforced; for development only.
  • classic — no confinement; equivalent to a traditionally packaged application. Requires Snap Store approval before publishing.

Default

strict

~~description?~~

readonly optional description?: string | null

As description from application package.json, but allows you to specify different for Linux.

Inherited from

CommonLinuxOptions.description


~~desktop?~~

readonly optional desktop?: LinuxDesktopFile | null

The Desktop file

Inherited from

CommonLinuxOptions.desktop


~~environment?~~

readonly optional environment?: {[key: string]: string; } | null

Environment variables injected into the snap's runtime environment. Merged with the electron-builder default { TMPDIR: "$XDG_RUNTIME_DIR" }. User-supplied values take precedence.


~~executableArgs?~~

readonly optional executableArgs?: string[] | null

The executable parameters. Pass to executableName

Inherited from

CommonLinuxOptions.executableArgs


~~grade?~~

readonly optional grade?: "devel" | "stable" | null

The quality grade of the snap.

  • stable — suitable for all channels, including stable and candidate.
  • devel — development snapshot; cannot be promoted to stable or candidate.

Default

stable

~~hooks?~~

readonly optional hooks?: string | null

Directory containing snap hooks, relative to the build resources directory (build/).

Default

build/snap-hooks

~~layout?~~

readonly optional layout?: {[key: string]: object; } | null

Snap layouts — bind-mount or symlink host paths into the snap's namespace, making libraries or config at /usr, /var, /etc, etc. accessible inside the confined environment.


~~mimeTypes?~~

readonly optional mimeTypes?: string[] | null

The mime types in addition to specified in the file associations. Use it if you don't want to register a new mime type, but reuse existing.

Inherited from

CommonLinuxOptions.mimeTypes


~~plugs?~~

readonly optional plugs?: PlugDescriptor | (string | PlugDescriptor)[] | null

Plugs (consumed interfaces) to declare for the app entry point. Defaults to ["desktop", "desktop-legacy", "home", "x11", "wayland", "unity7", "browser-support", "network", "gsettings", "audio-playback", "pulseaudio", "opengl"].

Use "default" in the list to keep the defaults and append extras: ["default", "camera"] adds camera to the standard set.

To configure plug attributes (e.g. allow-sandbox for Chromium's internal sandbox), use a descriptor object:

[
{ "browser-sandbox": { "interface": "browser-support", "allow-sandbox": true } },
"another-simple-plug-name"
]

~~publish?~~

optional publish?: Publish

Inherited from

TargetSpecificOptions.publish


~~slots?~~

readonly optional slots?: SlotDescriptor | (string | SlotDescriptor)[] | null

Slots (provided interfaces) to declare for the app.

To expose an MPRIS player under the Chromium bus name (required for strict confinement):

[{ "mpris": { "name": "chromium" } }]

Chromium hard-codes the bus name chromium, so the slot name must match for snapd to allow it.


~~stagePackages?~~

readonly optional stagePackages?: string[] | null

Ubuntu packages to stage alongside the app (equivalent to depends for deb). Defaults to ["libnspr4", "libnss3", "libxss1", "libappindicator3-1", "libsecret-1-0"].

Use the "default" keyword to extend the default list: ["default", "my-extra-lib"] appends my-extra-lib to the defaults.


~~summary?~~

readonly optional summary?: string | null

A short summary of the snap (max 78 characters). Defaults to productName.


~~synopsis?~~

readonly optional synopsis?: string | null

The short description.

Inherited from

CommonLinuxOptions.synopsis


~~title?~~

readonly optional title?: string | null

Display title for the snap (may contain uppercase letters and spaces). Defaults to productName. See snap format.


~~useTemplateApp?~~

readonly optional useTemplateApp?: boolean

Whether to use the pre-built Electron snap template for faster builds. When true, electron-builder delegates snap assembly to the upstream Electron snap template rather than running a full snapcraft build, significantly reducing build time. Defaults to true when stagePackages is not customised. Only applicable to x64 and armv7l builds.