A self-contained rust app is an app that can be built from source with a single cargo build
command. This also means that the snapcraft rust plugin defaults are likely to work, and the final snapcraft.yaml
is likely to be minimal.
Starting point
Let’s take gitui
for example. If you follow the rust snap tutorial, you will end up with a snapcraft.yaml
similar to this one:
name: gitui
version: '0.24.0'
summary: Terminal UI for git
description: |
Blazing 💥 fast terminal-ui for git written in rust 🦀
license: MIT
website: https://github.com/extrawurst/gitui
confinement: devmode
base: core22
parts:
gitui:
plugin: rust
source: https://github.com/extrawurst/gitui.git
source-tag: 'v0.24.0'
source-depth: 1
apps:
gitui:
command: bin/gitui
- The name should ideally match the project’s name, but note that it is unique within the ecosystem.
- For this example we can just copy the summary and description as-is from the project page.
- The version field should match the app’s version being built. The resulting snap will be named
gitui_0.24.0_amd64.snap
, and when installed, thesnap info gitui
will show that version number. It should match the version displayed when runninggitui --version
. One way to achieve this is to rely on the maintainer’s tagging practice and always make sure that the.version
field matches the.parts.gitui.source-tag
field.
Test the snap
Build the snap by simply running snapcraft
in the same folder. This will create a file called gitui_0.24.0_amd64.snap
. Install it:
sudo snap install --devmode *.snap
Now, gitui
is ready to use
$ which gitui
/snap/bin/gitui
$ gitui --version
gitui 0.24.0
Choose the right confinement
Having confinement: devmode
is fine for testing and debugging, but for a snap to be public it must either be classically or strictly confined.
Arguably, in gitui
's case, the benefit of having a strictly confined snap outweighs potential usability disadvantages.
For comparison:
- Text editor snaps, e.g. nvim and helix, are classically confined. This makes sense because one would want one’s text editor to be able to display any file on the system.
- Gaming apps such as 0ad and dosbox-x are strictly confined, because they don’t really need access to the entire system.
- Other git UIs such as gitkraken and lazygit have classic and strict confinement, respectively.
Let’s take a look at the list of interfaces we would need to plug into the snap for it to work well in strict confinement:
Interface | Description | Rationale |
---|---|---|
home | access non-hidden files in the home directory | Most repos are likely to reside somewhere under $HOME |
personal-files | read or write files in the user’s home directory | Read .gitconfig etc. |
network | enables network access | Pull, push, etc. |
removable-media | read/write files on removable storage devices | Some users may want to interact with repos on removable devices |
If you’re not too familiar with the app, you can use strace
to try to figure out what interfaces the app may need. For example:
strace -e trace=openat,newfstatat git fetch
Build a strictly confined snap
To confine the app, we need to:
- Specify
confinement: strict
. - Declare some plugs (interfaces), such as
personal-files
, at the root level. - List all plugs per app under the
apps
section.
name: gitui
version: '0.24.0'
summary: Terminal UI for git
description: |
Blazing 💥 fast terminal-ui for git written in rust 🦀
license: MIT
website: https://github.com/extrawurst/gitui
confinement: strict
base: core22
parts:
gitui:
plugin: rust
source: https://github.com/extrawurst/gitui.git
source-tag: 'v0.24.0'
source-depth: 1
plugs:
gitfiles:
interface: personal-files
read:
- $HOME/.git-credentials
- $HOME/.gitconfig
apps:
gitui:
command: bin/gitui
plugs:
- home
- gitfiles
- removable-media
- network
The snap is not signed (yet), so needs to be installed with --dangerous
(previously, --devmode
implied --dangerous
):
sudo snap install --dangerous *.snap