Ephemeral, secure 5250 console with Docker on ppc64 Linux
This is a personal project about ppc64 Linux, Docker, and Access Client Solutions, I'd like to share with you.
Special greetings
Although I've been working on this project in my spare time, I'd like to say a special thank you to nice people at Blue for providing me with the development resources!
Brief description
The aim of this project is to provide an IBM i 5250 console for customers:
- ephemeral: nothing is left behind, unless granted
- secure: only the authorized 5250 console can be accessed, using client-less encrypted communication with optional 2FA and recording
- easy to use: just an HTM5 browser, the familiar ACS being launched automatically after login
- full ppc64 Open-Source software: why not?
Components
- of course, a ppc64 Linux partition
- Docker
- Guacamole (as Docker containers)
- x11docker (with custom images)
- ACS (in a x11docker image)
Skills needed
- Power administration, including partitioning and HMC
- basic Linux administration knowledge
- (obviously) IBM i and ACS
- basic Git and Docker
- basic networking
1. Linux operating system
When it comes to deciding on a ppc64 distro, I've defined several criteria to narrow down the choice:
- free, without subscription or commercial license
- actively supported (by the community)
- RMC compatible: I want the partition to be able to move using LPM, and dynamically add/remove resources
- of course, able to run Docker with the images I need
I found that CentOS was the best choice, meeting all my requirements.
So here it is: the distro will be CentOS 9. Why 9? 10 already exists! Because of:
- IBM only officially supports up to CentOS 8 for ppc64 Linux extension software, 9 is the closest “in-support” version
- as we'll see later, an obsolete image is required for booting; I'm not sure whether such an image is available for CentOS 10 ... (I haven't checked, though)
1.1 Linux installation
Disclaimer : I assume you're familiar with Power partitioning and RHEL/CentOS installation, I won't go into details here.
Quick overview of the partition I use:
- one Power 9 vCPU, 0.2 CPU shared/uncapped
- 8GB RAM, up to 16GB
- one 128GB SAN disk (vSCSI mode)
- one network interface providing unlimited Internet access
There's a well-known problem with the latest ppc64 distros, something related to unnecessary drivers in the initrd, leading to “out of memory” messages on boot. I've identified the following distros as being affected: RHEL/CentOS/Fedora, Suse/OpenSuse. So we have to use an obsolete boot image, with a lightweight initrd.
I've found a CentOS mirror that has obsolete images for version 9 (not all have them...): https://mirror.in2p3.fr/pub/linux/centos-stream/9-stream/BaseOS/ppc64le/iso/ (download the oldest boot image).
In Anaconda, configure the network connection and use an online source URL, for example: https://mirror.in2p3.fr/pub/linux/centos-stream/9-stream/BaseOS/ppc64le/os/.
I chose “Minimal Install” in Software Selection, then added:
- Console Internet Tools
- Containers Management
- System Tools
Also, a "Server" install will work just fine.
After a couple of minutes, I got a Budget exhausted after napi rescheduled
message. I fixed it using sysctl -w net.core.netdev_budget=500
.
1.2 IBM tools
Next step is to install IBM's service and productivity tools from https://www.ibm.com/support/pages/service-and-productivity-tools.
As we use CentOS 9, the /opt/ibm/lop/configure
script has to be modified. Just modify lines 356-357 as following:
if [ "$release" = "8" ]; then
mk_centos_repos "${centos8_repos[@]}"
to
if [ "$release" = "9" ]; then
mk_centos_repos "${centos8_repos[@]}"
Then dnf install ibm-power-managed-rhel8.ppc64le
is your friend.
If your partition and the HMC have correct communication, you should see the RMC status going Active, as well as "hot-add" buttons going blue.
1.3 Some addons
This project is based on Docker, so you may want to install it: https://docs.docker.com/engine/install/centos/.
This ends the Linux OS installation!
2. Dockerized Guacamole
I won't go into details about Guacamole, just know that it's about providing a RDP or VNC remote desktop, as well as a SSH terminal, in a HTML5 browser. More information is available at their web site: https://guacamole.apache.org/.
For easy maintenance, I choose to use Docker containers. And, like almost systems engineers, I'm lazy. So I found an excellent ready-to-use GitHub project: https://github.com/boschkundendienst/guacamole-docker-compose.
2.1 ppc64 vs amd64
The GitHub project we want to use, as many others, just use straight images from Docker Hub, that's okay. But, in our case, the Guacamole Docker images are only available for amd64! : https://hub.docker.com/r/guacamole/guacamole/tags. To be honest, there's only a few ppc64-ready Docker images out there...
So, let's go with creating our own!
If you want to step over, the ready-to-use project is here: https://github.com/smanceau44/guacamole-docker-compose.
2.2 Cloning, building, pushing, ... 1o1
So, we have to make ppc64 Guacamole Docker images available. They can remain local, or be published to Docker Hub to share them with the community.
If you want to take the easy and fast path, they are available here: https://hub.docker.com/repository/docker/smanceau44/guacamole/general and https://hub.docker.com/repository/docker/smanceau44/guacd/general (no PostgreSQL or nginx images, they're already available for ppc64 :) ).
Let's start with cloning the guacamole-docker-compose GitHub project, then take a look to the Docker Compose file, especially the image:
instructions. From them, we can find what needs rebuilding for ppc64.
Most of the times, there is a Git project somewhere with the Docker build file. Here is the one for Guacamole Server (guacd): https://github.com/apache/guacamole-server/blob/main/Dockerfile.
In this file, we need the FROM
instructions to check if a ppc64 Docker image is available. Luckily enough, the Alpine Linux Guacamole is relying onto, has one.
A note about Apache Guacamole GitHub repositories: Apache devs usually commit their changes directly onto the "main" branch, although a "next" branch is available. You may want to clone the repo to your GitHub account, then add a tag with the date! That's what I'm using here...
After a quick look to https://docs.docker.com/get-started/introduction/build-and-push-first-image/, the list of command we'll need will be quite straightforward, example for Guacamole Server:
- clone the GitHub repo to the local server with
git clone --depth 1 --branch 1.5.5_20250220 https://github.com/smanceau44/guacamole-server.git && cd guacamole-server
- build the Docker image with
docker build -t smanceau44/guacd:1.5.5_20250220 .
- (optionally) push Docker image into Hub with
docker push smanceau44/guacd:1.5.5_20250220
Then, your image will be available for local use, and maybe for others. Repeat the process with guacamole-client as "guacamole" Docker image.
Then, we can change the images in the guacamole-docker-compose project, clone it to our local server, run the preparation script, and finally launch it:
cd /srv && git clone --depth 1
--branch ppc64le_1.5.5_20250220
https://github.com/smanceau44/guacamole-docker-compose.git && cd
guacamole-docker-compose
./prepare.sh
docker compose up -d
2.3 Using it
Guacamole should be listening in HTTPS using port 8443 on the server IP address.
Default password for user guacadmin
is ... guacadmin
😉 .
You can try it by creating a SSH connection to the server. Free tip: to pop-up the Guacamole menu, use left Shift
+ Ctrl
+ Alt
keys together!
Please do not use the 127.0.0.1 IP address, but the Linux server LAN IP address. Loopback will go to the Guacamole Docker container, and is useless for us!
3. Dockerized desktop with x11docker
At this point, you may have noticed that Guacamole can provide access to a graphical environment using VNC or RDP. You may even have tried it on your server (provided you've installed the necessary packages).
That's okay-ish, but not exactly what we want: our mission is to provide an isolated and ephemeral graphical environment!
That's where an excellent project comes very handy: https://github.com/mviereck/x11docker. In a nutshell, it provides an X11 graphical environment (including full desktop) from a disposable container.
If you want to step over the building steps, you can go directly to the "Install ..." chapter below.
3.1 Build images for a basic desktop
As you may have noticed, x11docker is just a Bash script. But the Docker images for x11server
and xfce
it relies onto, are not available for ppc64! So we have to build them.
If you want to take the fast lane, they're already available at Docker Hub, author smanceau44
.
Nothing fancy here, just a simple rebuild using ppc64 source images (FROM
clauses), as we've already done for Guacamole.
Docker is smart enough to pull images with the corresponding processor architecture, all that has to be done is to publish our own to Docker Hub, with the same name ;) Example for xserver
:
3.2 Install x11docker & dependencies
Of course, install x11docker: https://github.com/mviereck/x11docker#tldr and its dependencies: https://github.com/mviereck/x11docker/wiki/dependencies#recommended-base (I ran dnf -y install nxagent xorg-x11-xinit xorg-x11-xauth xclip xorg-x11-server-utils xorg-x11-utils catatonit jq
here).
Our server has to be RDP-enabled, so let's install it with dnf -y install xrdp
. As usual, enable and start the systemd service.
3.3 Test the basic xfce desktop!
We still have a long way to go, but we can finally see something concrete!
First, create a new connection in Guacamole, using:
- Protocol: RDP
- Hostname: the LAN IP address for your server
- Username, Password: can be fixed, leave it empty to be prompted. Please read note below
- Initial Program:
x11docker --desktop --fullscreen smanceau44/xfce
- Keyboard: you may need to set it
- Color depth: I recommend "Low color (16-bit)"
- Disable audio: we don't have any
Note about user: I strongly advise to test your configuration as root
. You may find that a bad practice, but remember: we're using a Docker container, so there is no harm!
You can do anything you want, including deleting all files! And please remember: to pop-up the Guacamole menu, use left Shift
+ Ctrl
+ Alt
keys together.
While running this dockerized xfce, a docker ps -l
will show the smanceau44/xfce
container. If things goes south, you can kill this container then launch a new one from Guacamole.
4. Carry on with ACS
The next step will be to produce a Docker image containing ACS. Sounds cool, doesn't it?
Note : IBM won't allow any re-distribution of ACS, you'll have to download the installation package from MRS. Anyway, if you want to include it in your GitHub project, please :
Sorry, no fast-path here, because of copyright enforcement! You'll have to build your own Docker image. Anyway, GitHub project is here: https://github.com/smanceau44/dockerfile-x11docker-acs_ppc64le.
4.1 Dockerfile
This time, we can't rely on something already existing, we'll have to produce our own Dockerfile.
Not that hard, here it is:
# This Dockerfile is intended to add IBM's ACS to a ppc64le xfce x11docker image
FROM smanceau44/xfce
# Warn builder about mandatory dependencies
RUN echo "/!\ Please provide IBM's ACS IBMiAccess_v1r1.zip in build directory" && \
echo "/!\ Or press Ctrl-C now to exit (waiting 60s)" && \
sleep 60
# Install some packages
RUN echo "deb http://debian.mirrors.ovh.net/debian bullseye main" > /etc/apt/sources.list && \
echo "deb http://debian.mirrors.ovh.net/debian-security bullseye-security main" >> /etc/apt/sources.list && \
echo "deb http://debian.mirrors.ovh.net/debian bullseye-updates main" >> /etc/apt/sources.list && \
echo "deb-src http://debian.mirrors.ovh.net/debian bullseye main" >> /etc/apt/sources.list && \
apt-get update && \
env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
default-jdk \
firefox-esr \
dialog
# Copy and unpack ACS source into our working environment
COPY IBMiAccess_v1r1.zip /tmp/
RUN mkdir /tmp/acs && cd /tmp/acs && jar -xf /tmp/IBMiAccess_v1r1.zip && rm /tmp/IBMiAccess_v1r1.zip
# Customization steps
RUN cd /tmp/acs/ && \
cp AcsConfig.properties AcsConfig_org.properties && \
echo "com.ibm.iaccess.InstallType=preset" >> /tmp/acs/AcsConfig.properties && \
echo "com.ibm.iaccess.IncludeComps=console,vcp,hmc," >> /tmp/acs/AcsConfig.properties && \
echo "com.ibm.iaccess.autoimport={HOME}/x11docker_share/acs_bak.zip" >> /tmp/acs/AcsConfig.properties && \
echo "com.ibm.iaccess.autoimport.version=*" >> /tmp/acs/AcsConfig.properties && \
echo "com.ibm.iaccess.splf.FilterRestricted=true" >> /tmp/acs/AcsConfig.properties && \
echo "com.ibm.iaccess.desktopshortcuts=yes" >> /tmp/acs/AcsConfig.properties && \
echo "com.ibm.iaccess.InstallType=preset" >> /tmp/acs/AcsConfig.properties
# Run the setup programm
RUN cd /tmp/acs/Linux_Application && chmod +x ./install_acs_xx && ./install_acs_xx /Q
# Cleanup our room
RUN cd && rm -rf /tmp/acs/
Some details:
- FROM: we are using the ppc64le X environment we've build before
- echos: builder must provide the IBM's ACS image
- apt-get commands: we need a jdk to run ACS, and "dialog" is required. Firefox can be of use 😎
- copy/unpack: this will copy the zip file from your building host, then unpack it
- customization: this is the interesting part!
- we only want to provide 5250 console & Virtual Control Panel
- a configuration file will be imported automatically
- some configuration to restrict access...
- setup: installing our customized ACS in the Docker image
Just put the IBM's "IBMiAccess_v1r1.zip" file aside the Dockerfile, then run docker build -t smanceau44/acs .
(replacing "smanceau44" with whatever you want).
4.2 Evolve the host environment
We need a file gateway between the Docker container and the host, to upload and automatically download ACS's configuration files (please see the autoimport
directive we've added before).
As I designed this project, every user, including root, should have a x11docker_share
directory available in it's home.
Also, you may want to add your Linux partition a network interface, to communicate privately with your HMC or LAN Console (please, please, don't put a gateway on it, unless you need it and understand what you're doing!).
4.3 Create a Guacamole connection, test it
To create the Guacamole connection definition, the easiest way is to clone the xfce we've used before for testing, changing:
- obviously, the name (I used "ACS_noauto_root")
- the command: mine is
x11docker --desktop --network --fullscreen --clipboard --share=/root/x11docker_share smanceau44/acs
=> this time, allowing network access and sharing the clipboard (why not?) plus a host directory
If no gremlin was involved, you may find a shared directory, also ACS and Firefox available:
We can also check that ACS is restricted, as requested:
Please keep this Guacamole connection, we'll use it later!
5. Users
Before we go ahead with configuration, we have to identify our clients.
They are differents "levels" of authentication here, please note that they are not related and can be mixed (i.e. a Guacamole user can have several sessions available, using different HMC users).
5.1 Linux users & more
For each different ACS configuration, we'll need a Linux user.
To enhance security, we'll use a group and a sudoers file:
groupadd DockerACS
echo "%DockerACS ALL = (root) NOPASSWD:SETENV: /usr/local/bin/x11docker" > /etc/sudoers.d/DockerACS
we must run x11docker as root
user
Then:
adduser DockACS_lin_1 --create-home --groups DockerACS
passwd DockACS_lin_1
Create a x11docker_share
in user's home directory (don't forget to change owner):
mkdir x11docker_share
chown DockACS_lin_1:DockACS_lin_1 x11docker_share/
5.2 Guacamole user
Gacamole has it's own users database, so we'll need to create a user profile here, as well.
If you activated Guacamole's MFA, there will be additional steps.
5.3 HMC user
Of course, if you use a HMC as 5250 Console proxy, there will be another layer of security here.
In order to make our project work securely, additional custom roles are needed and should be assigned to the user.
Additionally, the user must have the "SSH to HMC" authorization (it is not a security problem, as no SSH client program will be available in our Docker image).
the list below are for a V10R3 HMC
please be aware that the HMC user will get hard-coded in our ACS configuration file!
5.3.1 Tasks role
This describes the actions a user is authorized to, and of course can be used by all users.
You'll have to include:
- Managed System
- Partition
- Activate Partition
- Modify Partitions
- Connect 5250 VTerm
- View Partitions
- Manage Partition Serviceable Events
- Open 5250 VTerm
- Reboot Partition
- Shutdown Partition
5.3.2 Resource role
This describe all the configuration objects a user is authorized to. When creating a role, just select the system(s) and the partition(s) you want to be assigned to a user.
For this project, I only assigned a single testing partition, and it's hosting Power system.
5.4 LAN Console users
Untested by me
Create a DST user, then assign some permissions.
6. ACS configuration for user
As we want to provide our customers a pre-configured environment, we must create an ACS configuration file.
6.1 Allow configuration in Dockerized ACS
Do you remember the "ACS_noauto_root" Guacamole connection we created before? It will be of help here!
Launch it, but don't start ACS now.
Edit the /opt/ibm/iAccessClient/Solutions/AcsConfig.properties
to change the "IncludeComps" as (add cfg,
):
com.ibm.IncludeComps=console,vcp,hmc,cfg,
6.2 Create the configuration file
Then we can launch ACS, the "System Configurations" will be available to us:
Just create a system definition as usual (only the "Console" tab), test it, customize and save the 5250 terminal configuration if asked.
Important: use the customer HMC user (or LAN Console) you defined earlier, as it will be stored in configuration file!
Remember that you have a Firefox available, if you need to connect to the HMC 😊.
When done export the configuration ("File" menu) to (exactly) /root/x11docker_share/acs_bak.zip
.
This way the configuration file will be kept in host filesystem, everything else will be discarded!
You can now close this session ("Log Out").
6.3 Apply the configuration to the user
On host, move the configuration file:
cp -p /root/x11docker_share/acs_bak.zip /home/DockACS_lin_1/x11docker_share/
That's all! The ACS configuration file we included in the Docker image will automatically import this configuration, each time the image will get instanced to a new container.
You may want to archive this file somewhere else, as a reference.
7. User Guacamole connection
The final step will be to define a Guacamole connection, launching ACS automatically.
Hint: you can clone an existing Guacamole connection definition (button at the bottom), then edit it
For example:
- Protocol: RDP
- Hostname: the LAN IP address for your server
- Username, Password: the Linux user we defined earlier
- Initial Program:
sudo -E
/usr/local/bin/x11docker --desktop --network --fullscreen --clipboard
--share=/home/DockACS_lin_1/x11docker_share -- smanceau44/acs java -jar
/opt/ibm/iAccessClientSolutions/acsbundle.jar
- Keyboard: you may need to set it
- Color depth: I recommend "Low color (16-bit)"
- Disable audio: we don't have any
Notes about the command line:
- x11docker is to be run as root, so we use sudo
- the "desktop" and "fullscreen" options will provide a better experience
- "network" option is mandatory to provide network to the container
- the shared directory is mandatory, it contains the ACS configuration file
- don't forget the "--", x11docker need it for the command to be run inside the container ("java ...")
As a result, user will get a full-screen, fully configured ACS (closing all ACS windows will close the Guacamole connection):
User will be able to switch to Manual mode using VCP, then perform some operations (such as: change IPL source, power up/down or restart, ...).
8. Guacamole hints & tips
8.1 x11docker_share
I kept the default Read-Write, to provide users with a permanent storage. This can be useful for support, like screen history (set archive path in Preferences) or ACS support dumps.
I strongly advise to use a small, separate storage for each user (for example, a 1GB LVM volume, from a dedicated VG).
User will be able to see the acs_bak.zip
file, but cannot modify it.
8.2 Guacamole for users
Please provide users with a link to Guacamole documentation (https://guacamole.apache.org/doc/gug/using-guacamole.html).
At least, tell them about the left Shift
+ Ctrl
+ Alt
keys hint!
9 Enhancing security
9.1 Guacamole MFA
Although Guacamole supports a large variety of authentication source and MFA method, I will only cover "local" (database) authentication, which is the default for this project, and TOTP MFA.
TOTP is a rolling code that you can easily generate with apps like Aegis Authenticator (Android) or 2FAGuard (Windows)
TOTP is very easy to add, as all the extensions are already available in our Docker images!
Quick guide:
- get your Docker Compose project location with
docker compose ls
, cd
to it
- stop everything with
docker compose stop
- edit your
docker-compose.yml
file, add a line with TOTP_ENABLED: true
in "guacamole" service, "environment" section
- restart everything with
docker compose up -d
- at first login, each user will be displayed a QRCode to be added to an authenticator app!
More details here: https://guacamole.apache.org/doc/gug/totp-auth.html
9.2 Guacamole recording
Another nice feature, is the ability to record all user actions, in video!
I strongly advise to use a separate, quite fast, easily expandable (LVM) storage
As you may have noticed, a record
directory is already defined in docker-compose.yml
file. You can change the path (by default, relative to docker-compose.yml
file location, mount your dedicated storage, ...
In the Guacamole connection definition, "Screen Recording" section, set a path for records (I strongly suggest ${HISTORY_PATH}/${HISTORY_UUID}
) and check "Automatically create recording path". That's all!
More details here: https://guacamole.apache.org/doc/gug/recording-playback.html.
9.3 Restricting Docker networking
Docker isn't great at managing host networking: it tries to use all available network resources, including the default gateway, no matter what.
If you followed my advice to use a separate network for HMC or LAN Console communication, you'd like the dockerized containers to stick to it!
The solution is to define a dedicated Docker network.
First, create the Docker network with: docker
network create --attachable --driver=bridge --subnet=172.31.0.0/16
--opt 'com.docker.network.bridge.name=bridge-hmc' --opt
'com.docker.network.bridge.enable_ip_masquerade=false' bridge-hmc
.
This "bridge-hmc" network will use the 172.31.0.0/16 network, and won't be automatically added to iptables by Docker.
Then, create your personalized NAT rule with: nft add rule ip nat POSTROUTING ip saddr 172.31.0.0/16 oifname != "bridge-hmc" counter snat to 10.20.30.40
.
This will "force" all the packets from the "bridge-hmc" network to be outputted through the desired interface (replace 10.20.30.40 with your actual interface IP address).
Last, but not least, change the command in Guacamole connection definition to include the new Docker network: sudo
-E /usr/local/bin/x11docker --desktop --network=bridge-hmc --fullscreen
--clipboard --share=/home/DockACS_lin_1/x11docker_share --
smanceau44/acs java -jar /opt/ibm/iAccessClientSolutions/acsbundle.jar
.
nftables configuration may be reset after a reboot, please take a look et the nftables Systemd service
Thanks to the author of this blog article: https://medium.com/@havloujian.joachim/advanced-docker-networking-outgoing-ip-921fc3090b09.
9.4 Protecting the "user entry point" from evils
AKA the dockerized Gacamole, and especially the embedded nginx.
I found that Crowdsec is a very good solution, I used it for years. Unfortunately, actually there is no ppc64 package available for Centos: https://doc.crowdsec.net/docs/next/getting_started/versions_matrix. Maybe soon? 😉