Description
Experiment with and implement a server (openSUSE Kubic, SUSE CaaSP) with connected thin clients (Raspberry Pi) that executes GUI applications from docker containers running on the server.
- Github repository: gh/jupiter-system
- OBS repository: OBS/gedit.jupiter
- docker image registry: roo/jupiter-system/gedit
- Presentation: ~slindomansilla/HW17-jupiter-system-presentation.pdf
- Demo: ~slindomansilla/HW17-jupiter-system.ogv
1. First experiment succeeded
Executing Firefox installed on a MicroOS host with X11 from a client (Leap 42.3)
Required packages on MicroOS to run Firefox (packages not installed on the default MicroOS installation)
- xauth
- iso-codes
- libcanberra-gtk3-module
- cantarell-fonts
- dejavu-fonts
- fontconfig
- fonts-config
- google-opensans-fonts
- libfont-specimen0
- libfontenc1
- mkfontdir
- mkfontscale
- yast2-fonts
You can install those packages on MicroOS with the following commands
transactional-update pkg install xauth iso-codes libcanberra-gtk3-module cantarell-fonts dejavu-fonts fontconfig fonts-config google-opensans-fonts libfont-specimen0 libfontenc1 mkfontdir mkfontscale yast2-fonts
And then
reboot
to use the new snapshot
Further details
On a MicroOS installation, the file /etc/ssh/sshd_config already have the setting X11Forwarding yes. Which is needed for X11 forwarding.
2. Second experiment succeeded
Executing Firefox on a docker container on a MicroOS host with X11 from a client (Leap 42.3)
To be able to run firefox, a lot of extra work has to be done to dockerize it. So I opted for an easier application, gedit, since the important part is the X forwarding to a docker container.
2.1 Preparing the docker image opensuse/tumbleweed:gedit (to run gedit, not firefox)
#!BuildTag: jupiter-system/gedit:1.0.2-3.20.2-3.24
FROM opensuse:42.3
LABEL MAINTAINER="sergiolindo.empresa@gmail.com"
LABEL VERSION="1.0.2"
LABEL DESCRIPTION="gedit to be executed on a MicroOS server with X forwarding from a remote X-client"
LABEL GITHUB="https://github.com/SergioAtSUSE/jupiter-system"
RUN usermod --append --groups nogroup nobody
RUN zypper --gpg-auto-import-keys ref
# OBS applicances requirements
RUN zypper --non-interactive install --force-resolution libsystemd0
RUN zypper --non-interactive install --force-resolution libudev1
# X forwarding auth requirement
RUN zypper --non-interactive install --force-resolution xauth
# App and dependencies
RUN zypper --non-interactive install --force-resolution gedit=3.20.2-3.24
RUN zypper --non-interactive install --force-resolution iso-codes
RUN zypper --non-interactive install --force-resolution libcanberra-gtk3-module
RUN zypper --non-interactive install --force-resolution cantarell-fonts
# For recently open files feature
VOLUME [ "/home/nobody/.local/share" ]
# For saving documents
RUN mkdir "/permanent-data"
RUN chown nobody:nogroup "/permanent-data"
RUN chmod ug+rwxs "/permanent-data"
VOLUME [ "/permanent-data" ]
USER nobody:nogroup
WORKDIR /permanent-data
ENTRYPOINT [ "/usr/bin/gedit" ]
xauth is needed to let the docker container authenticate to the X server.
iso-codes, gtk3-modules and cantarell-fonts are dependencies needed to run gedit, that usually are already on a normal installed system.
The volume /home/nobody/.local/share is needed for the recently open files feature to work properly.
The volume /permanent-data is the dedicated volume to save files that remains even if the container is removed.
Find more info about this dockerfile on section 3.2.
2.2 Preparing the docker container
2.2.1 First connect through ssh
sergio@leap42.3:~$ ssh -X sergio@microos
2.2.2 X11UseLocalhost no
The less dangerous, but still not secure, approach to allow docker containers to access the forwarded X port is using the value FamilyWild(65535 or 0xFFFF) on the cookie-based credential for xauth inside the container.
For that to work, it is necessary to allow X forwarding to X-clients from non-localhost hostnames in /etc/ssh/sshd_config:
X11UseLocalhost no
remember to restart the sshd service
sergio@microos:~$ sudo systemctl restart sshd.service
You need now to close the ssh session and connect again with -X. To check that the non-localhost forwarding is working, check the display used
sergio@microos:~$ exit
sergio@leap42.3:~$ ssh -O exit microos # if you use ControlPersist or ControlMaster
sergio@leap42.3:~$ ssh -X sergio@microos
sergio@microos:~$ echo $DISPLAY
microos:10.0
If instead the hostname of the machine (in this case microos) localhost is shown, make sure you did all the previous steps from this section (section 2.2).
2.2.3 xauth credential FamilyWild
The less dangerous, but still not secure, approach to allow docker containers to access the forwarded X port is using the value FamilyWild(65535 or 0xFFFF) on the cookie-based credential for xauth inside the container.
To create the credentials execute
sergio@microos:~$ touch .docker.xauth
sergio@microos:~$ xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f .docker.xauth nmerge -
Notice the '-' at the end, to tell the xauth command that it should take the input from STDIN (also from the piped command) and not from the yet empty .docker.xauth file.
This will write a cookie-based credential into the file .docker.xauth. This file is on the MicroOS host. The credential will have the FamilyWild value and the existing cookie for the forwarded X display.
xauth -f .docker.xauth nmerge - will set the right permissions 600. This is important, any user with access to that file can read the cookie and so access the forwarded display (because we allowed to forward X to non-localhosts X-clients).
Since this file is not used as the Xauthority on the MicroOS host, there is no danger of X-clients outside localhost trying to access that display, unless they get the cookie.
Finally start the docker container
sergio@microos:~$ sudo docker container run --rm --name ${USER}_gedit -e DISPLAY=$DISPLAY -e XAUTHORITY=/home/sergio/.Xauthority -v ~/.docker.xauth:/home/sergio/.Xauthority --user ${UID}:nogroup jupiter-system/gedit:1.0.2-3.20.2-3.24
The container needs to have the same DISPLAY set as the ssh server (microos host), which is the forwarded one.
It also needs the XAUTHORITY set with the credential file (even if we use the standard path, the environment variable is not automatically set on docker containers by default)
The credential file is bind-mounted as the XAUTHORITY file. For security, the container is not run as the default user root, but as a regular user on the MicroOS host (sergio(1000)). The user needs to have read access to the credential file, and it is more secure to use the local user on the MicroOS host than giving rights to the nobody user inside the container or even permissions to groups or others.
WARNING: Since the Xauthority file inside the container uses the value FamilyWild, any X-client that can access the container have access to the forwarded X. The security of the docker container has to be carefully reviewed.
3 Building the docker image with OBS
3.1 Getting the build context from github
In order to get the build context from github, the obs-service-download_url is needed. This is how the _service file looks like
<services>
<service name="download_url">
<param name="protocol">https</param>
<param name="host">raw.githubusercontent.com</param>
<param name="path">/software-for-life/jupiter-system/v1.0.2-3.20.2-3.24/docker-build-contexts/gedit.jupiter/Dockerfile</param>
<param name="filename">Dockerfile</param>
</service>
</services>
3.2 Dockerfile requirements in OBS
3.2.1 Image tag
The dockerfile needs to specify the image tag as the first line (see dockerfile on section 2.1)
#!BuildTag: jupiter-system/gedit:1.0.0-3.20.2-3.24
The version format I used is: [dockerfile-version]-[obs-package-version]-[obs-package-release-version]
3.2.2 Isolated build environment
OBS has a restriction for the base image. You can use any image from registry.opensuse.org (actually is taking the images available locally, it doesn't use any registry). And since it runs in an offline environment, you are not able to access files from outside. There is an exception, the virtual machine running the build is using Leap 42.3 as guest. Using the base image opensuse:42.3, you can access to the repositories to install packages from zypper.
3.2.3 systemd vs. systemd-mini
OBS would try to get systemd-mini variant packages by default, but this does not work for appliances. In order to force OBS to pick systemd varian packages, it is necessary to explicitly install libsystemd0 and libudev1.
3.2.4 osc build
for docker image
At the moment, July 12th 2018, osc is not able to build an image that relies on a dockerfile fetched by an OBS service. It will expect and take the Dockerfile at the root directory of the OBS package.
After checking in the changes, OBS is able to build the Dockerfile fetched by the service.
3.2.5 zypper install package-x.y.z
To specify a version of a package, it is necesary to use the zypper operator =
.
- Find out more here gh/open-build-service/issues/5359
This project is part of:
Hack Week 17
Activity
Comments
-
over 6 years ago by SLindoMansilla | Reply
It is my own invention. I always search for names ideas on internet to be sure that my project will not be confused by an existing one. I didn't find anything related with that name in google, so here I go.
Similar Projects
This project is one of its kind!