Skip to content

Commit e54d07c

Browse files
authored
Introduces immutability to OCI image by running everything as non-root user _daemon_ (#36)
1 parent e7bd382 commit e54d07c

5 files changed

Lines changed: 199 additions & 72 deletions

File tree

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,20 @@ To pull the image from the GitHub Container Registry, run the following command:
311311
sudo docker pull ghcr.io/openprinting/ps-printer-app:latest
312312
```
313313

314+
Create a Docker volume:
315+
```sh
316+
sudo docker volume create ps-printer-app
317+
```
318+
314319
To run the container after pulling the image from the GitHub Container Registry, use:
315320
```sh
316321
sudo docker run -d \
317322
--name ps-printer-app \
318323
--network host \
319324
-e PORT=<port> \
325+
-v ps-printer-app:/var/lib/ps-printer-app \
326+
-v /dev/bus/usb:/dev/bus/usb:ro \
327+
--device-cgroup-rule='c 189:* rmw' \
320328
ghcr.io/openprinting/ps-printer-app:latest
321329
```
322330

@@ -326,18 +334,30 @@ Alternatively, you can pull the image from Docker Hub, by running:
326334
sudo docker pull openprinting/ps-printer-app
327335
```
328336

337+
Create a Docker volume:
338+
```sh
339+
sudo docker volume create ps-printer-app
340+
```
341+
329342
To run the container after pulling the image from Docker Hub, use:
330343
```sh
331344
sudo docker run -d \
332345
--name ps-printer-app \
333346
--network host \
334347
-e PORT=<port> \
348+
-v ps-printer-app:/var/lib/ps-printer-app \
349+
-v /dev/bus/usb:/dev/bus/usb:ro \
350+
--device-cgroup-rule='c 189:* rmw' \
335351
openprinting/ps-printer-app:latest
336352
```
337353

338354
- `PORT` is an optional environment variable used to start the printer-app on a specified port. If not provided, it will start on the default port 8000 or, if port 8000 is busy, on 8001 and so on.
339355
- **The container must be started in `--network host` mode** to allow the Printer-Application instance inside the container to access and discover printers available in the local network where the host system is in.
340356
- Alternatively using the internal network of the Docker instance (`-p <port>:8000` instead of `--network host -e PORT=<port>`) only gives access to local printers running on the host system itself.
357+
- `-v ps-printer-app:/var/lib/ps-printer-app` maps a volume for persistent storage.
358+
- The following volume and device settings are crucial for USB printer access:
359+
- `-v /dev/bus/usb:/dev/bus/usb:ro` mounts the host's USB device directory read-only inside the container for USB printer access.
360+
- `--device-cgroup-rule='c 189:* rmw'` allows the container to read, write, and mknod to USB devices.
341361

342362
### Setting up and running a ps-printer-app container locally
343363

@@ -373,18 +393,30 @@ Once the rock is built, you need to compile a docker image from it:
373393
sudo rockcraft.skopeo --insecure-policy copy oci-archive:<rock_image> docker-daemon:ps-printer-app:latest
374394
```
375395

396+
Create a Docker volume:
397+
```sh
398+
sudo docker volume create ps-printer-app
399+
```
400+
376401
**Run the ps-printer-app Docker Container**
377402

378403
```sh
379404
sudo docker run -d \
380405
--name ps-printer-app \
381406
--network host \
382407
-e PORT=<port> \
408+
-v ps-printer-app:/var/lib/ps-printer-app \
409+
-v /dev/bus/usb:/dev/bus/usb:ro \
410+
--device-cgroup-rule='c 189:* rmw' \
383411
ps-printer-app:latest
384412
```
385413
- `PORT` is an optional environment variable used to start the printer-app on a specified port. If not provided, it will start on the default port 8000 or, if port 8000 is busy, on 8001 and so on.
386414
- **The container must be started in `--network host` mode** to allow the Printer-Application instance inside the container to access and discover printers available in the local network where the host system is in.
387415
- Alternatively using the internal network of the Docker instance (`-p <port>:8000` instead of `--network host -e PORT=<port>`) only gives access to local printers running on the host system itself.
416+
- `-v ps-printer-app:/var/lib/ps-printer-app` maps a volume for persistent storage.
417+
- The following volume and device settings are crucial for USB printer access:
418+
- `-v /dev/bus/usb:/dev/bus/usb:ro` mounts the host's USB device directory read-only inside the container for USB printer access.
419+
- `--device-cgroup-rule='c 189:* rmw'` allows the container to read, write, and mknod to USB devices.
388420

389421
#### Setting up
390422

rockcraft.yaml

Lines changed: 140 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ platforms:
2020
# the manufacturer-supplied PostScript PPD files
2121
adopt-info: foomatic-db
2222

23-
# Only build on the architectures supported
23+
run-user: _daemon_
2424

2525
services:
26-
dbus:
27-
command: /scripts/run-dbus.sh
26+
avahi-daemon:
27+
command: /scripts/run-avahi.sh
2828
override: replace
2929
on-failure: restart
3030
startup: enabled
@@ -34,7 +34,7 @@ services:
3434
override: replace
3535
on-failure: shutdown
3636
startup: enabled
37-
after: [dbus]
37+
after: [avahi-daemon]
3838

3939
parts:
4040
pappl:
@@ -696,37 +696,156 @@ parts:
696696
- usr/share/ppd
697697
- -var
698698
- -usr/share/man
699-
after: [pappl-retrofit, pappl, libcupsfilters, libppd, cups-filters, foomatic-db, hplip]
699+
after: [avahi, pappl-retrofit, pappl, libcupsfilters, libppd, cups-filters, foomatic-db, hplip]
700700

701-
avahi-daemon:
702-
plugin: nil
703-
overlay-packages:
704-
- avahi-daemon
701+
avahi:
702+
plugin: autotools
703+
source: https://github.com/avahi/avahi.git
704+
source-type: git
705+
autotools-configure-parameters:
706+
- --prefix=/usr
707+
- --disable-qt3
708+
- --disable-qt4
709+
- --disable-qt5
710+
- --disable-gtk
711+
- --disable-gtk3
712+
- --disable-gdbm
713+
- --disable-python
714+
- --disable-pygtk
715+
- --disable-python-dbus
716+
- --disable-mono
717+
- --disable-monodoc
718+
- --disable-manpages
719+
- --disable-xmltoman
720+
- --with-avahi-user=_daemon_
721+
- --with-avahi-group=_daemon_
722+
# - --with-avahi-priv-access-group=netdev
723+
# - --with-distro=debian
724+
- --disable-gobject
725+
- --datadir=/usr/share
726+
- --libdir=/usr/lib/${CRAFT_ARCH_TRIPLET_BUILD_FOR}
727+
- --with-systemdsystemunitdir=/usr/lib/systemd/system
728+
- --localstatedir=/var
729+
- --sysconfdir=/etc
730+
build-packages:
731+
- g++
732+
- gcc
733+
- gettext
734+
- intltool
735+
- libdaemon-dev
736+
- libdbus-1-dev
737+
- libevent-dev
738+
- libexpat1-dev
739+
- libglib2.0-dev
740+
- libsystemd-dev
741+
- xmltoman
742+
override-build: |
743+
craftctl default
744+
# for reference sort systemd service files
745+
sed -i \
746+
-e 's|\(.*\)avahi-daemon -s.*|\1avahi-daemon -s --no-drop-root|g' \
747+
-e 's|\(.*\)avahi-daemon -r.*|\1avahi-daemon -r --no-drop-root|g' \
748+
${CRAFT_PART_INSTALL}/usr/lib/systemd/system/avahi-daemon.service
749+
mkdir -p \
750+
${CRAFT_PART_INSTALL}/usr/lib/systemd/system/multi-user.target.wants
751+
ln -sf \
752+
../avahi-daemon.service \
753+
${CRAFT_PART_INSTALL}/usr/lib/systemd/system/multi-user.target.wants/avahi-daemon.service
754+
build-environment:
755+
- LD_LIBRARY_PATH: "${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$CRAFT_STAGE/usr/lib"
756+
override-prime: |
757+
set -eux
758+
craftctl default
759+
sed -i 's/use-ipv6=yes/use-ipv6=no/' ${CRAFT_PRIME}/etc/avahi/avahi-daemon.conf
760+
sed -i 's|<user>messagebus</user>|<user>_daemon_</user>|; /<policy user="root">/,/<\/policy>/d' $CRAFT_PRIME/usr/share/dbus-1/system.conf
761+
sed -i 's/<policy group="netdev">/<policy group="_daemon_">/g; s/<policy user="root">/<policy user="_daemon_">/g' $CRAFT_PRIME/usr/share/dbus-1/system.d/avahi-dbus.conf
762+
stage-packages:
763+
- libdaemon0
764+
- libevent-2.1-7
705765
- avahi-utils
706-
- libnss-mdns
707766
- mdns-scan
708-
- dbus
709-
- python3
767+
# - libavahi-client3
768+
# - libavahi-common3
769+
stage:
770+
- etc/avahi
771+
- usr
772+
- -usr/lib/**/libavahi-client.so*
773+
- -usr/lib/**/libavahi-common.so*
774+
- -usr/lib/**/*.acd
775+
- -usr/lib/**/*.la
776+
- -usr/lib/**/avahi
777+
- -usr/lib/**/libavahi-glib*
778+
- -usr/lib/**/libavahi-libevent*
779+
- -usr/lib/**/libevent-*
780+
# - -usr/lib/**/libnss_mdns*
781+
- -usr/lib/**/pkgconfig
782+
- -usr/include
783+
- -usr/share/doc
784+
- -usr/share/man
785+
- -usr/share/locale
786+
after: [pappl-retrofit, pappl, libcupsfilters, libppd, cups-filters, foomatic-db, hplip]
710787

711788
utils:
712789
plugin: nil
713790
overlay-packages:
714791
- python3
792+
- dbus
793+
- libnss-mdns
794+
override-prime: |
795+
set -eux
796+
craftctl default
797+
798+
# Set up Avahi Daemon runtime directory
799+
mkdir -p "$CRAFT_PRIME/var/run/avahi-daemon"
800+
chown 584792:584792 "$CRAFT_PRIME/var/run/avahi-daemon"
801+
chmod 777 "$CRAFT_PRIME/var/run/avahi-daemon"
802+
803+
# Set up D-Bus runtime directory
804+
mkdir -p "$CRAFT_PRIME/var/run/dbus"
805+
chown 584792:584792 "$CRAFT_PRIME/var/run/dbus"
806+
chmod 777 "$CRAFT_PRIME/var/run/dbus"
807+
808+
# Set up the CUPS SSL server root directory
809+
CUPS_SERVERROOT="$CRAFT_PRIME/etc/cups/ssl"
810+
mkdir -p "$CUPS_SERVERROOT"
811+
chown 584792:584792 "$CUPS_SERVERROOT"
812+
chmod 770 "$CUPS_SERVERROOT"
813+
814+
# Set up the state directory and file for the printer app
815+
STATE_DIR="$CRAFT_PRIME/var/lib/ps-printer-app"
816+
mkdir -p "$STATE_DIR"
817+
chown 584792:584792 "$STATE_DIR"
818+
chmod 770 "$STATE_DIR"
819+
820+
# Create a state file inside the state directory
821+
STATE_FILE="$STATE_DIR/ps-printer-app.state"
822+
touch "$STATE_FILE"
823+
chown 584792:584792 "$STATE_FILE"
824+
chmod 644 "$STATE_FILE"
825+
826+
# Ensure the spool directory is owned properly
827+
SPOOL_DIR="$CRAFT_PRIME/var/spool/ps-printer-app"
828+
mkdir -p "$SPOOL_DIR"
829+
chown 584792:584792 "$SPOOL_DIR"
830+
chmod 770 "$SPOOL_DIR"
831+
832+
# Create and set permissions for the application log file
833+
touch $CRAFT_PRIME/ps-printer-app.log
834+
chown 584792:584792 $CRAFT_PRIME/ps-printer-app.log
835+
chmod 644 $CRAFT_PRIME/ps-printer-app.log
836+
837+
# Setting up permissions to USB backend
838+
USB_BACKEND="$CRAFT_PRIME/usr/lib/ps-printer-app/backend/usb"
839+
chmod u+s "$USB_BACKEND"
840+
after: [ps-printer-app, avahi, pappl-retrofit, pappl, libcupsfilters, libppd, cups-filters, foomatic-db, hplip]
715841

716842
scripts:
717843
plugin: dump
718844
source: scripts/
719845
organize:
720-
run-dbus.sh: /scripts/run-dbus.sh
721846
start-server.sh: /scripts/start-server.sh
847+
run-avahi.sh: /scripts/run-avahi.sh
722848
override-prime: |
723849
set -eux
724850
craftctl default
725-
# Ensure the run-dbus.sh script has executable permissions
726-
if [ -f "$CRAFT_PRIME/scripts/run-dbus.sh" ]; then
727-
chmod +x "$CRAFT_PRIME/scripts/run-dbus.sh"
728-
fi
729-
# Ensure the start-server.sh script has executable permissions
730-
if [ -f "$CRAFT_PRIME/scripts/start-server.sh" ]; then
731-
chmod +x "$CRAFT_PRIME/scripts/start-server.sh"
732-
fi
851+
chmod +x $CRAFT_PRIME/scripts/*

scripts/run-avahi.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/sh
2+
set -eux
3+
4+
# Start dbus-daemon in the background
5+
/usr/bin/dbus-daemon --system --nofork &
6+
7+
# Wait for the D-Bus system bus to be ready
8+
while [ ! -e /var/run/dbus/system_bus_socket ]; do
9+
echo "Waiting for dbus-daemon to initialize..."
10+
sleep 1
11+
done
12+
13+
# Start avahi-daemon after dbus-daemon is ready
14+
/usr/sbin/avahi-daemon -f /etc/avahi/avahi-daemon.conf --no-drop-root --debug
15+
16+
# Keep the container running
17+
exec tail -f /dev/null

scripts/run-dbus.sh

Lines changed: 0 additions & 30 deletions
This file was deleted.

scripts/start-server.sh

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,16 @@ if [ -n "${PORT:-}" ]; then
99
fi
1010
fi
1111

12-
# Ensure the /etc/cups/ssl directory exists with proper permissions
13-
CUPS_SERVERROOT="/etc/cups/ssl"
14-
if [ ! -d "$CUPS_SERVERROOT" ]; then
15-
mkdir -p "$CUPS_SERVERROOT"
16-
fi
17-
chmod 755 "$CUPS_SERVERROOT"
18-
19-
# Ensure /var/lib/ps-printer-app directory exists
20-
STATE_DIR="/var/lib/ps-printer-app"
21-
22-
if [ ! -d "$STATE_DIR" ]; then
23-
mkdir -p "$STATE_DIR"
24-
fi
25-
chmod 755 "$STATE_DIR"
12+
# Wait for avahi-daemon to initialize
13+
while true; do
14+
if [ -f "/var/run/avahi-daemon/pid" ] || [ -f "/run/avahi-daemon/pid" ]; then
15+
echo "avahi-daemon is active. Starting ps-printer-app..."
16+
break
17+
fi
2618

27-
# Ensure ps-printer-app.state file exists
28-
STATE_FILE="$STATE_DIR/ps-printer-app.state"
29-
if [ ! -f "$STATE_FILE" ]; then
30-
touch "$STATE_FILE"
31-
fi
32-
chmod 755 "$STATE_FILE"
19+
echo "Waiting for avahi-daemon to initialize..."
20+
sleep 1
21+
done
3322

3423
# Start the ps-printer-app server
35-
ps-printer-app -o log-file=/ps-printer-app.log ${PORT:+-o server-port=$PORT} server
24+
ps-printer-app -o log-file="/ps-printer-app.log" ${PORT:+-o server-port="$PORT"} server

0 commit comments

Comments
 (0)