Up to now we have installed snapped applications on standard Ubuntu. If they plug the cups-control
interface, they get access to the socket of the installed Debian packages of CUPS, /run/cups/cups.sock
and to the D-Bus notification facility of the same Debian packages of CUPS.
Now we get 2 new scenarios where these applications should also work. The first is Ubuntu 23.10, where we will switch from the Debian packages of CUPS to the CUPS Snap, meaning that such applications would need to access the snapped CUPS daemon instead of a classically installed one. The other scenario is Ubuntu Core, which does not contain a CUPS printing stack in its immutable image and the user is supposed to install the CUPS Snap to get printing functionality. Dabian packages cannot get installed here.
The original scenario using the Debian packages of CUPS on classic Ubuntu is well established and works.
The other scenarios can get made to work by manually connecting the cups-control
plug to CUPS Snap’s cups:cups-control
slot, but they fail if the user grabs an application from the Snap Store for which cups-control
auto-connection got granted and the application fails to access CUPS due to the auto-connection being done to the wrong slot or not at all. Also manual connection not supplying the slot on the command line (expecting auto-selection) fails.
This thread is about to find a fix for this. An application which plugs cups-control
and has auto-connection for it granted by the Snap Store team should always auto-connect to the correct xxx:cups-control
slot so that it get full administrative access to the CUPS daemon in use, independent whether this daemon is provided by classic packages or the CUPS Snap, and independent whether we are running a classic distro or Ubuntu Core.
Tests show success and failure in the different scenarios:
1. Classic Ubuntu with CUPS from Debian packages (SUCCESS)
This is the well-tested “standard” case for which the :cups-control
slot of of snapd got originally designed and this just works. Auto-connection or manual connection without specifiying the slot
$ sudo snap connect client-snap:cups-control
connects to snapd’s :cups-control
slot and this just works using the CUPS installed via Debian packages and taking commands through the standard socket /run/cups/cups.sock
.
2. Classic Ubuntu with CUPS from CUPS Snap (FAIL)
Now I have tested the scenario which we want to have in Ubuntu 23.10, the CUPS Snap being the print environment of the system, no Debian packages of CUPS installed.
For that I have stopped and disabled the Debian CUPS via systemctl
, installed the CUPS Snap and set its no-proxy
flag so that it runs in its standalone mode, see my call for testing for detailed instructions.
When I install a Snap which auto-connects cups-control
or manually connect cups-control
without specifying the slot
$ sudo snap connect client-snap:cups-control
the Snap’s cups-control
plug gets always connected to snapd’s :cups-control
slot, independent whether the slot is backed by a CUPS daemon or not. The slot which would be needed here is the CUPS Snap’s cups:cups-control
slot.
Now, when you try it out, simply by printing from Firefox (Firefox uses the cups-control
plug and not cups
as an app which prints should use) you will not see any failure as printing just works in this case, but if you try with a Snap which actually does administrative operations on CUPS (like modifying queues) these operations will fail. The non-administrative operations work due to the fact that the connection to :cups-control
gives access to /run/cups/cups.sock
and when the CUPS Snap is in standalone mode (no classically installed CUPS in the way) it also listens via /run/cups/cups.sock
. The administrative operations do not work (you get a Forbidden
) due to the snapped CUPS daemon’s Snap mediation. It allows administrative operations from external client Snaps only if they plug the CUPS Snap’s cups:cups-control
slot, plugging any cups-control
slot somewhere around is not good enough!
3. Ubuntu Core (FAIL)
This scenario I did not test by myself, but a user who has created a Snap of an application doing administrative actions on CUPS and wants to use this Snap on Ubuntu Core has done so and I have helped them making it work. See this thread, especially start reading from this post on.
In Ubuntu Core we do not even have a :cups-control
slot, so snapd seems to identify on startup that it is under Ubuntu Core where a classically installed CUPS does not exist and so does not open the slot. Manually connecting cups-control
without specifying the slot (or auto-connection) fails as follows:
$ sudo snap connect client-snap:cups-control
error: snap "snapd" has no "cups-control" interface slots
And, as with the CUIPS Snap being used on a classic distro, manually connecting explicitly to the CUPS Snap’s slot works:
$ sudo snap connect client-snap:cups-control cups:cups-control
Do you want to test it?
See my call for testing upstream to get scenarios 2 and 3.
Use the CUPS Snap from the --edge
channel:
$ sudo snap refresh --edge cups
Install Snaps which plug cups-control
from the Snap Store (like Firefox).
Check connections of application snaps:
$ snap connections client-snap
with client-snap
replaced by the name of the actual Snap you are trying out.
and of CUPS:
$ snap connections cups
Here always both plugs and slots are shown. Slots without Snap name (starting with :
) are from snapd.
Connect cups-control
manually, without specifting a slot, it always connects to :cups-control
(of snpad):
$ sudo snap connect client-snap:cups-control
Connect to the cups-control
slot of the CUPS Snap:
$ sudo snap connect client-snap:cups-control cups:cups-control
I am not aware of a printer setup tool in the Snap Store which we could use as an example for testing here. So do the following if you want to test: Copy the lines below into an editor and save the file as snapcraft.yaml
:
name: cups-admin-test
base: core22 # The base snap is the execution environment for this snap
version: 0.1.0
summary: CUPS admin and non-admin tasks out of a Snap
description: Testing interfaces for the CUPS Snap
grade: stable
confinement: strict
apps:
lpinfo:
command: usr/sbin/lpinfo
plugs: [network, cups-control]
lpadmin:
command: usr/sbin/lpadmin
plugs: [network, avahi-observe, home, cups-control]
lpstat:
command: usr/bin/lpstat
plugs: [network, avahi-observe, cups-control]
lpoptions:
command: usr/bin/lpoptions
plugs: [network, home, cups-control]
lp:
command: usr/bin/lp
plugs: [network, home, cups-control]
cancel:
command: usr/bin/cancel
plugs: [network, cups-control]
lpmove:
command: usr/sbin/lpmove
plugs: [network, cups-control]
cupsenable:
command: usr/sbin/cupsenable
plugs: [network, cups-control]
cupsdisable:
command: usr/sbin/cupsdisable
plugs: [network, cups-control]
cupsaccept:
command: usr/sbin/cupsaccept
plugs: [network, cups-control]
cupsreject:
command: usr/sbin/cupsreject
plugs: [network, cups-control]
accept:
command: usr/sbin/cupsaccept
plugs: [network, cups-control]
reject:
command: usr/sbin/cupsreject
plugs: [network, cups-control]
cupsctl:
command: usr/sbin/cupsctl
plugs: [network, cups-control]
parts:
cups-client:
plugin: dump
source: .
stage-packages:
- cups-client
- libcups2
prime:
- usr/bin/*
- usr/sbin/*
- usr/lib/*
Then run the command
snapcraft pack
and when this has finished, run
sudo snap install --dangerous cups-admin-test_0.1.0_amd64.snap
and use the commands shown above with cups-admin-test
as client Snap.
A non-invasive administrative operation for testing is lpinfo -v
. So run
cups-admin-test.lpinfo -v
to see whether the test Snap has admin permissions on CUPS.
Summary of the problem
Automatic connecting of the cups-control
plug of a Snap, regardless whether by installing a Snap with appropriate permissions or by manually connecting without specifying the slot, always connects to snapd’s :cups-control
slot, independently whether this actually works or whether the slot even exists.
As an awkward workaround one can manually connect to the CUPS Snap’s cups:cups-control
by explicitly specifying the slot and then everything works as expected.
This is an inconsistent behavior for users. They cannot install a Snap from the Snap Store which has auto-connection permission for cups-control
and it just works. It only just works on a classic distro wioth classic CUPS installation. It will fail and require manual connection on Ubuntu 23.10 (which uses CUPS Snap) or Ubuntu Core (also uses CUPS Snap).
Request for a fix
The fix is needed to be implemented in snapd. snapd provides the :cups-control
slot to make it easy to snap printer setup tools or generally software which does administrative tasks on CUPS. As Snap is all about distribution-independent packaging, it must be possible to snap such applications without needint to care about the destination system, neither in the upstream code, the snapping, or the documentation for the Snap. Therefore an app plugging cups-control
must always be able to admin the CUPS which the destination system provides for its users to be able to print.
So snapd needs to always handle the request to plug cups-control
of a client Snap to the correct slot, without needing any manual action of the user and without requiring from the user to know about the 3 mentioned scenarios.
snapd would somehow need to check whether the socket file /run/cups/cups.sock
is backed by an unsnapped CUPS daemon (cupsd
). There are probably tools to determine the executable name with its path for what backs a socket file. If the path does not contain /snap/
one could assume that the cupsd
is unsnapped. In this case, and only in this case, snapd should behave as before. If /run/cups/cups.sock
does not exist (for example as it could not get created by the CUPS Snap running under the immutable Ubuntu Core) or the cupsd
backing it is snapped, it should connect the plug to cups:cups-control
or somehow mirror cups:cups-control
into :cups-control
but in a way that the Snap mediation of cupsd
does not fail (I would modify/extend it if needed).
snapd should not simply check for the presence of the CUPS Snap here, as it could run in parallel to a classic CUPS installation (“proxy” mode and “parallel” mode of the CUPS Snap).
Discussion and further thoughts
I have discussed this with both @jamesh and @mvo. Especially there were the follwing thoughts:
- snapd developers say that snapd does not need to care of special cases like printing: This is wrong, as snapd provides the
:cups-control
slot. This slot must always work and snappers of applications rely (and users) on it. - The CUPS Snap should get replaced by a an actual CUPS Snap and a CUPS Proxy Snap. This does not eliminate this problem. It only eases plug and slot naming a bit, and simplifies the startup scripts of the CUPS Snap somewhat, but it makes migration from classic CUPS to the CUPS Snap unnecessarily complex.
- Applications which only print but do not manage CUPS (like Firefox) should use the
cups
plug and not thecups-control
plug, but this also does not eliminate our problem here.
I hope we can solve this before Ubuntu 23.10 to create a smooth user experience.