diff --git a/build-tests/x86/tumbleweed/test-image-agama/appliance.kiwi b/build-tests/x86/tumbleweed/test-image-agama/appliance.kiwi
new file mode 100644
index 00000000000..75b6ebbaadc
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/appliance.kiwi
@@ -0,0 +1,125 @@
+
+
+
+
+ YaST Team
+ yast2-maintainers@suse.de
+ Agama RamDisk Installer ISO
+
+
+ 1.0.1
+ zypper
+ en_US
+ us
+ Europe/Berlin
+ true
+ false
+ bgrt
+ openSUSE
+
+
+
+ true
+ true
+ /dev/ram1
+ false
+ false
+
+ 1900
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build-tests/x86/tumbleweed/test-image-agama/config.sh b/build-tests/x86/tumbleweed/test-image-agama/config.sh
new file mode 100755
index 00000000000..348ebb9d23e
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/config.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+set -ex
+
+label=${kiwi_install_volid:-$kiwi_iname}
+
+#======================================
+# Import repo keys
+#--------------------------------------
+rpm --import /tmp/systemsmanagement_key.gpg
+rpm --import /usr/lib/rpm/gnupg/keys/*.asc
+rm /tmp/systemsmanagement_key.gpg
+
+#======================================
+# Enable services
+#--------------------------------------
+systemctl enable sshd.service
+systemctl enable NetworkManager.service
+systemctl enable avahi-daemon.service
+systemctl enable agama.service
+systemctl enable agama-web-server.service
+systemctl enable agama-auto.service
+systemctl enable agama-hostname.service
+systemctl enable agama-proxy-setup.service
+systemctl enable agama-certificate-issue.path
+systemctl enable agama-certificate-wait.service
+systemctl enable agama-welcome-issue.service
+systemctl enable agama-avahi-issue.service
+systemctl enable agama-ssh-issue.service
+systemctl enable agama-self-update.service
+systemctl enable live-password-cmdline.service
+systemctl enable live-password-dialog.service
+systemctl enable live-password-iso.service
+systemctl enable live-password-random.service
+systemctl enable live-password-systemd.service
+systemctl enable setup-systemd-proxy-env.path
+systemctl enable x11-autologin.service
+systemctl enable spice-vdagentd.service
+systemctl enable zramswap
+
+#======================================
+# Default target
+#--------------------------------------
+systemctl set-default graphical.target
+
+#======================================
+# disable snapshot cleanup
+#--------------------------------------
+systemctl disable snapper-cleanup.timer
+systemctl disable snapper-timeline.timer
+
+#======================================
+# disable unused services
+#--------------------------------------
+systemctl disable YaST2-Firstboot.service
+systemctl disable YaST2-Second-Stage.service
+systemctl -f disable purge-kernels
+
+#======================================
+# setup dracut for live system
+#--------------------------------------
+echo "Setting default live root: live:LABEL=$label"
+mkdir -p /etc/cmdline.d
+echo "root=live:LABEL=$label" > \
+ /etc/cmdline.d/10-liveroot.conf
+echo "root_disk=live:LABEL=$label" >> \
+ /etc/cmdline.d/10-liveroot.conf
+echo 'install_items+=" /etc/cmdline.d/10-liveroot.conf "' > \
+ /etc/dracut.conf.d/10-liveroot-file.conf
+echo 'add_dracutmodules+=" dracut-menu "' >> \
+ /etc/dracut.conf.d/10-liveroot-file.conf
+echo 'add_drivers+=" brd "' >> \
+ /etc/dracut.conf.d/10-liveroot-file.conf
+
+#======================================
+# replace the @@LIVE_MEDIUM_LABEL@@
+#--------------------------------------
+sed -i -e "s/@@LIVE_MEDIUM_LABEL@@/$label/g" /usr/bin/live-password
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/.mozilla/firefox/profile/user.js.template b/build-tests/x86/tumbleweed/test-image-agama/root/.mozilla/firefox/profile/user.js.template
new file mode 100644
index 00000000000..afe9e19ccda
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/.mozilla/firefox/profile/user.js.template
@@ -0,0 +1,10 @@
+// Mozilla User Preferences
+
+// do not remember or generate passwords
+user_pref("signon.management.page.breach-alerts.enabled", false);
+user_pref("signon.rememberSignons", false);
+user_pref("signon.generation.enabled", false);
+// start always in the custom homepage
+user_pref("browser.startup.page", 1);
+// custom homepage: the value is expected to be replaced with the login URL by the startup script
+user_pref("browser.startup.homepage", "__HOMEPAGE__");
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/.xinitrc b/build-tests/x86/tumbleweed/test-image-agama/root/.xinitrc
new file mode 100644
index 00000000000..fd0aab570a0
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/.xinitrc
@@ -0,0 +1 @@
+icewm-session -c /etc/icewm/preferences.yast2
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/avahi/services/agama.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/avahi/services/agama.service
new file mode 100644
index 00000000000..b17aee6d4d5
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/avahi/services/agama.service
@@ -0,0 +1,11 @@
+
+
+
+
+ Agama Installer (https://%h.local)
+
+ _https._tcp
+ _agama._sub._https._tcp
+ 433
+
+
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/modules-load.d/10-multipath.conf b/build-tests/x86/tumbleweed/test-image-agama/root/etc/modules-load.d/10-multipath.conf
new file mode 100644
index 00000000000..78b1202ab80
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/modules-load.d/10-multipath.conf
@@ -0,0 +1 @@
+dm_multipath
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/multipath.conf b/build-tests/x86/tumbleweed/test-image-agama/root/etc/multipath.conf
new file mode 100644
index 00000000000..34d389ac337
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/multipath.conf
@@ -0,0 +1,3 @@
+defaults {
+ find_multipaths smart
+}
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/ssh/sshd_config.d/10_root_login.conf b/build-tests/x86/tumbleweed/test-image-agama/root/etc/ssh/sshd_config.d/10_root_login.conf
new file mode 100644
index 00000000000..1073982f77c
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/ssh/sshd_config.d/10_root_login.conf
@@ -0,0 +1 @@
+PermitRootLogin yes
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-avahi-issue.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-avahi-issue.service
new file mode 100644
index 00000000000..bb9bfe1fc2a
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-avahi-issue.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Generate issue file for Agama URL from Avahi
+
+After=avahi-daemon.service
+
+[Service]
+ExecStart=agama-issue-generator --watch-avahi
+Type=simple
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-issue.path b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-issue.path
new file mode 100644
index 00000000000..9d2b7dbdee2
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-issue.path
@@ -0,0 +1,10 @@
+[Unit]
+Description=Watch the Agama SSL certificate for changes
+Before=systemd-user-sessions.service
+
+[Path]
+Unit=agama-certificate-issue.service
+PathChanged=/etc/agama.d/ssl/cert.pem
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-issue.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-issue.service
new file mode 100644
index 00000000000..245aba998fc
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-issue.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Generate issue file for Agama SSL certificate
+
+[Service]
+Type=oneshot
+ExecStart=agama-issue-generator --ssl
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-wait.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-wait.service
new file mode 100644
index 00000000000..7eddd034740
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-certificate-wait.service
@@ -0,0 +1,27 @@
+[Unit]
+Description=Postpone login prompt after the SSL fingerprint issue is generated
+
+After=agama-web-server.service
+
+# copied from YaST2-Second-Stage.service
+Before=getty@tty1.service
+Before=getty@tty2.service
+Before=getty@tty3.service
+Before=getty@tty4.service
+Before=getty@tty5.service
+Before=getty@tty6.service
+Before=serial-getty@hvc0.service
+Before=serial-getty@sclp_line0.service
+Before=serial-getty@ttyAMA0.service
+Before=serial-getty@ttyS0.service
+Before=serial-getty@ttyS1.service
+Before=serial-getty@ttyS2.service
+Before=serial-getty@ttysclp0.service
+
+[Service]
+Type=oneshot
+# wait at most 15 seconds to not block
+ExecStart=agama-issue-generator --wait-for-ssl 15
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-hostname.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-hostname.service
new file mode 100644
index 00000000000..0d8d8988681
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-hostname.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Set Agama hostname
+# after running the default hostname systemd service
+After=systemd-hostnamed.target
+# but before starting the mDNS server
+Before=avahi-daemon.service
+# run only if the hostname has the default value, if it has been changed
+# by the hernel command line or systemd then keep it
+ConditionHost=localhost
+
+[Service]
+ExecStart=hostnamectl hostname --transient agama
+Type=oneshot
+User=root
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-self-update.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-self-update.service
new file mode 100644
index 00000000000..5d80b9ef551
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-self-update.service
@@ -0,0 +1,31 @@
+[Unit]
+Description=Agama self-update
+
+After=network-online.target
+
+# before starting the Agama servers so they use the new packages
+Before=agama-web-server.service
+Before=agama.service
+Before=x11-autologin.service
+# before interactive password services
+Before=live-password-dialog.service
+Before=live-password-systemd.service
+
+# kernel command line option
+ConditionKernelCommandLine=|agama.self_update
+# linuxrc/YaST backward compatibility
+ConditionKernelCommandLine=|agama.selfupdate
+
+[Service]
+Type=oneshot
+Environment=TERM=linux
+ExecStartPre=dmesg --console-off
+ExecStart=agama-self-update
+ExecStartPost=dmesg --console-on
+TTYReset=yes
+TTYVHangup=yes
+StandardInput=tty
+TimeoutSec=0
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-ssh-issue.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-ssh-issue.service
new file mode 100644
index 00000000000..fa133af5c93
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-ssh-issue.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Generate issue file for SSH host keys
+Before=systemd-user-sessions.service
+After=sshd.service
+
+[Service]
+Type=oneshot
+ExecStart=agama-issue-generator --ssh
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-welcome-issue.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-welcome-issue.service
new file mode 100644
index 00000000000..14cd96373cf
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/agama-welcome-issue.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Generate Agama welcome message
+Before=systemd-user-sessions.service
+
+[Service]
+Type=oneshot
+ExecStart=agama-issue-generator --welcome
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-cmdline.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-cmdline.service
new file mode 100644
index 00000000000..0893c64b19a
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-cmdline.service
@@ -0,0 +1,21 @@
+[Unit]
+Description=Set the root password from kernel command line
+
+# before starting the SSH and Agama server so they use the new password
+Before=sshd.service
+Before=agama-web-server.service
+
+# before the interactive setting methods so they can override it
+Before=live-password-dialog.service
+Before=live-password-systemd.service
+
+# plain text password or encrypted password passed via kernel command line
+ConditionKernelCommandLine=|live.password
+ConditionKernelCommandLine=|live.password_hash
+
+[Service]
+ExecStart=live-password --kernel
+Type=oneshot
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-dialog.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-dialog.service
new file mode 100644
index 00000000000..f463684ce16
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-dialog.service
@@ -0,0 +1,52 @@
+[Unit]
+Description=Interactively set the root password in a dialog
+
+# before starting the SSH and Agama server so they use the new password
+Before=sshd.service
+Before=agama-web-server.service
+# before X11 because it switches the terminal to VT7
+Before=x11-autologin.service
+
+# copied from YaST2-Second-Stage.service
+Before=getty@tty1.service
+Before=getty@tty2.service
+Before=getty@tty3.service
+Before=getty@tty4.service
+Before=getty@tty5.service
+Before=getty@tty6.service
+Before=serial-getty@hvc0.service
+Before=serial-getty@sclp_line0.service
+Before=serial-getty@ttyAMA0.service
+Before=serial-getty@ttyS0.service
+Before=serial-getty@ttyS1.service
+Before=serial-getty@ttyS2.service
+Before=serial-getty@ttysclp0.service
+
+# kernel command line option
+ConditionKernelCommandLine=live.password_dialog
+
+[Service]
+Type=oneshot
+Environment=TERM=linux
+
+# disable the kernel output on the console
+ExecStartPre=dmesg --console-off
+# disable the systemd status messages on the console
+ExecStartPre=kill -SIGRTMIN+21 1
+
+ExecStart=live-password --dialog
+
+# reset the console state after closing the dialog otherwise the dialog
+# content would stay on the screen
+ExecStartPost=reset
+# enable back the kernel output on the console
+ExecStartPost=dmesg --console-on
+# enable back the systemd status messages on the console
+ExecStartPost=kill -SIGRTMIN+20 1
+
+StandardInput=tty
+RemainAfterExit=true
+TimeoutSec=0
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-iso.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-iso.service
new file mode 100644
index 00000000000..5a6e0455198
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-iso.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Set the root password from the ISO application area
+
+# before starting the SSH and Agama server so they use the new password
+Before=sshd.service
+Before=agama-web-server.service
+
+# before the other password setting methods so they can override it
+Before=live-password-cmdline.service
+Before=live-password-dialog.service
+Before=live-password-systemd.service
+
+[Service]
+ExecStart=live-password --iso
+Type=oneshot
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-random.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-random.service
new file mode 100644
index 00000000000..3e22bf2832a
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-random.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Set a random password for root if not already set
+
+# before starting the SSH and Agama server so they use the new password
+Before=sshd.service
+Before=agama-web-server.service
+
+# after all other password services, this a fallback service
+After=live-password-cmdline.service
+After=live-password-dialog.service
+After=live-password-iso.service
+After=live-password-systemd.service
+
+[Service]
+ExecStart=live-password --random
+Type=oneshot
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-systemd.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-systemd.service
new file mode 100644
index 00000000000..eb81bae6c3e
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/live-password-systemd.service
@@ -0,0 +1,48 @@
+[Unit]
+Description=Interactively set the root password via systemd
+
+# before starting the SSH and Agama server so they use the new password
+Before=sshd.service
+Before=agama-web-server.service
+# before X11 because it switches the terminal to VT7
+Before=x11-autologin.service
+
+# copied from YaST2-Second-Stage.service
+Before=getty@tty1.service
+Before=getty@tty2.service
+Before=getty@tty3.service
+Before=getty@tty4.service
+Before=getty@tty5.service
+Before=getty@tty6.service
+Before=serial-getty@hvc0.service
+Before=serial-getty@sclp_line0.service
+Before=serial-getty@ttyAMA0.service
+Before=serial-getty@ttyS0.service
+Before=serial-getty@ttyS1.service
+Before=serial-getty@ttyS2.service
+Before=serial-getty@ttysclp0.service
+
+# kernel command line option
+ConditionKernelCommandLine=live.password_systemd
+
+[Service]
+Type=oneshot
+
+# disable the kernel output on the console
+ExecStartPre=dmesg --console-off
+# disable the systemd status messages on the console
+ExecStartPre=kill -SIGRTMIN+21 1
+
+ExecStart=live-password --systemd
+
+# enable back the kernel output on the console
+ExecStartPost=dmesg --console-on
+# enable back the systemd status messages on the console
+ExecStartPost=kill -SIGRTMIN+20 1
+
+StandardOutput=tty
+RemainAfterExit=true
+TimeoutSec=0
+
+[Install]
+WantedBy=default.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/x11-autologin.service b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/x11-autologin.service
new file mode 100644
index 00000000000..2927547e6e1
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/systemd/system/x11-autologin.service
@@ -0,0 +1,24 @@
+[Unit]
+Description=X11 session
+After=graphical.target systemd-user-sessions.service
+
+[Service]
+User=root
+WorkingDirectory=~
+
+PAMName=login
+Environment=XDG_SESSION_TYPE=x11
+TTYPath=/dev/tty7
+StandardInput=tty
+UnsetEnvironment=TERM
+
+UtmpIdentifier=tty7
+UtmpMode=user
+
+StandardOutput=journal
+ExecStartPre=/usr/bin/chvt 7
+ExecStart=/usr/bin/startx -- vt7 -keeptty -verbose 3 -logfile /dev/null
+Restart=no
+
+[Install]
+WantedBy=graphical.target
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/zypp/repos.d/agama-devel.repo b/build-tests/x86/tumbleweed/test-image-agama/root/etc/zypp/repos.d/agama-devel.repo
new file mode 100644
index 00000000000..fd862c4b4a5
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/zypp/repos.d/agama-devel.repo
@@ -0,0 +1,8 @@
+[agama-devel]
+name=Agama-Devel
+type=rpm-md
+enabled=1
+autorefresh=1
+gpgcheck=1
+baseurl=https://download.opensuse.org/repositories/systemsmanagement:/Agama:/Devel/openSUSE_Tumbleweed/
+gpgkey=https://download.opensuse.org/repositories/systemsmanagement:/Agama:/Devel/openSUSE_Tumbleweed/repodata/repomd.xml.key
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/etc/zypp/repos.d/repo-oss.repo b/build-tests/x86/tumbleweed/test-image-agama/root/etc/zypp/repos.d/repo-oss.repo
new file mode 100644
index 00000000000..39546139aa1
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/etc/zypp/repos.d/repo-oss.repo
@@ -0,0 +1,8 @@
+[repo-oss]
+name=openSUSE-Tumbleweed-Oss
+type=rpm-md
+enabled=1
+autorefresh=1
+gpgcheck=1
+baseurl=https://download.opensuse.org/tumbleweed/repo/oss
+
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/root/.icewm/startup b/build-tests/x86/tumbleweed/test-image-agama/root/root/.icewm/startup
new file mode 100755
index 00000000000..7f8d091d270
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/root/.icewm/startup
@@ -0,0 +1,9 @@
+#!/usr/bin/env sh
+# Start a browser to connect to Agama's web user interface skipping the authentication.
+
+TOKEN_FILE=/run/agama/token
+TOKEN=$(cat $TOKEN_FILE)
+PREFS=$HOME/.mozilla/firefox/profile/user.js
+
+sed -e "s/__HOMEPAGE__/http:\/\/localhost\/login?token=$TOKEN/" $PREFS.template > $PREFS
+firefox --kiosk --profile $HOME/.mozilla/firefox/profile
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/root/.mozilla/firefox/profile/user.js.template b/build-tests/x86/tumbleweed/test-image-agama/root/root/.mozilla/firefox/profile/user.js.template
new file mode 100644
index 00000000000..41166d8ab7a
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/root/.mozilla/firefox/profile/user.js.template
@@ -0,0 +1,11 @@
+// Mozilla User Preferences
+
+// do not remember or generate passwords
+user_pref("signon.management.page.breach-alerts.enabled", false);
+user_pref("signon.rememberSignons", false);
+user_pref("signon.generation.enabled", false);
+
+// start always in the custom homepage
+user_pref("browser.startup.page", 1);
+// custom homepage: the value is expected to be replaced with the login URL by the startup script
+user_pref("browser.startup.homepage", "__HOMEPAGE__");
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/root/.xinitrc b/build-tests/x86/tumbleweed/test-image-agama/root/root/.xinitrc
new file mode 100644
index 00000000000..fd0aab570a0
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/root/.xinitrc
@@ -0,0 +1 @@
+icewm-session -c /etc/icewm/preferences.yast2
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/tmp/fw_cleanup.rb b/build-tests/x86/tumbleweed/test-image-agama/root/tmp/fw_cleanup.rb
new file mode 100755
index 00000000000..e00830b80a0
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/tmp/fw_cleanup.rb
@@ -0,0 +1,43 @@
+#! /usr/bin/env ruby
+
+# This script removes unused firmware files (not referenced by any kernel
+# driver) from the system. By default the script runs in safe mode and only
+# lists the unused firmware file, use the "--delete" argument to delete the
+# found files.
+
+require "find"
+require "shellwords"
+
+fw_dir = "/lib/firmware/"
+
+dir = Dir["/lib/modules/*"].first
+puts "Scanning kernel modules in #{dir}..."
+
+# list of referenced firmware names from the kernel modules
+fw = []
+
+Find.find(dir) do |path|
+ if File.file?(path) && path.end_with?(".ko", ".ko.xz", ".ko.zst")
+ fw += `/usr/sbin/modinfo -F firmware #{path.shellescape}`.split("\n")
+ end
+end
+
+unused_size = 0
+
+Find.find(fw_dir) do |fw_path|
+ next unless File.file?(fw_path)
+
+ fw_name = fw_path.delete_prefix(fw_dir).delete_suffix(".xz").delete_suffix(".zstd")
+
+ if !fw.include?(fw_name)
+ unused_size += File.size(fw_path)
+ if (ARGV[0] == "--delete")
+ puts "Deleting firmware file #{fw_path}"
+ File.delete(fw_path)
+ else
+ puts "Found unused firmware #{fw_path}"
+ end
+ end
+end
+
+puts "Unused firmware size: #{unused_size} (#{unused_size/1024/1024} MiB)"
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/tmp/systemsmanagement_key.gpg b/build-tests/x86/tumbleweed/test-image-agama/root/tmp/systemsmanagement_key.gpg
new file mode 100644
index 00000000000..6719ec9f531
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/tmp/systemsmanagement_key.gpg
@@ -0,0 +1,21 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+mQENBFspGl8BCADC0Lmh3GGIaWI4FvekwxbCqsRlqWQhdtSgQiFXlzjKVPl5kPSt
+oYvvIVV5M33SaHK1s2/i2dbiL6vmw+NazQueOcHw//uAikugssmvwK1iYhbwl/TW
+EZDVfW0pW33XR9IHzhbONV2293pjwScemmcEYghrN7TDw6cwcMs14ju0Jbh03+jN
+lW+Ryrazeb7O9lkdeaA/Fq4c3miw156uWqdgKr7kPnp0GjMWRSBVIeUK936PJyNV
+ibcwsvP1K2sqF9TtbDzRMdqw5GOdHIUd0Ml0Tb8Sg+kSxdhkhgBUslZW77FrEWMS
+HJD1rw77VUL+v7BzKBKl7mLXlfaNpmfkXWJTABEBAAG0RHN5c3RlbXNtYW5hZ2Vt
+ZW50IE9CUyBQcm9qZWN0IDxzeXN0ZW1zbWFuYWdlbWVudEBidWlsZC5vcGVuc3Vz
+ZS5vcmc+iQE+BBMBCAAoBQJlcECTAhsDBQkOZdY0BgsJCAcDAgYVCAIJCgsEFgID
+AQIeAQIXgAAKCRCsqpz35uWiE9NYCAC4BiV/CV/9QzWbwUup/pmLOD84JPo72C15
+Z+FARqk2LS5JhfxZRFaG13S2/+Ua3gN4RG0WqOxRaA6oKPs2V81X3I3ysq9660MW
+4qPbhGVZaBzPLat+9Q6MaRaqu9G3sEePGDWR1sR3s/d3pJl0kRK2fyQILnUx65zb
+r77ErCox/kwAB5bu5Nv9d4YuwS7oY+b1Nw1vvmmBu8z8acd6iNX5inIX+Oy06WTE
+lO0gh54GjVWIK1WlJYcV73GIu2jUBQJhP3GAaf9kp2Mtv/W9+D2XxGaFslZShiMp
+/FBcmYQeJAfh8WmxdWFZRlvbpqNbC6Gxmb/+euIZz43U6B1qQhRgiEYEExECAAYF
+AlspGl8ACgkQOzARt2udZSOfAACdEKhSoziJSqKEvrsGEBq0QNc4CwcAniYQosXY
++OdtQPCAY1lf4oqKOLpD
+=/8kX
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/agama-issue-generator b/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/agama-issue-generator
new file mode 100755
index 00000000000..0f4b8dc3574
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/agama-issue-generator
@@ -0,0 +1,179 @@
+#!/bin/bash
+
+# This is a helper script which generates issue file displayed at the console
+# before logging in. Partly inspired by the issue-generator package
+# (https://github.com/thkukuk/issue-generator).
+#
+# Generates several issue files:
+# - Welcome message with Agama version number (--welcome option)
+# - Agama SSL certificate fingerprints (--ssl option)
+# - SSH host key fingerprints (--ssh option)
+# - Agama access URL for all network devices (--network option), this is
+# triggered via udev rules
+# - Agama access URL using the mDNS (Avahi) URL (--watch-avahi option),
+# NOTE: in this case the script does not finish, it watches the changes in
+# the Avahi service and updates the URL if needed
+#
+
+# issue location for the Agama SSL certificate fingerprints, it is generated as
+# the last one and is used as a trigger to allow refreshing all other generated
+# issues
+CERT_ISSUE=/run/issue.d/50-agama-ssl-certificate.issue
+
+# a helper function which generates the Agama welcome message displayed at the
+# console
+generate_welcome() {
+ # get the latest version of any Agama package
+ AGAMA_VERSION=$(rpm -qa | grep agama | xargs rpm -q --queryformat \
+ "%{VERSION}\n" | sed -e "s/\\.devel/+/" -e 's/+0$//' | sort -V | tail -n 1)
+
+ ISSUE=/run/issue.d/10-agama-welcome.issue
+ printf "Welcome to \\\\e{lightgreen}Agama\\\\e{reset} installer version %s! (\\\\l)\n\n" "$AGAMA_VERSION" > "$ISSUE"
+}
+
+# a helper function which displays the SSH host key fingerprints at the console
+generate_ssh_fingerprints() {
+ FINGERPRINTS=$(find /etc/ssh -type f -name "ssh_host_*_key" -exec ssh-keygen -l -f \{\} \; | cut -d ' ' -f 2,4 | sed -e "s/^/ /")
+ ISSUE=/run/issue.d/30-live-ssh-fingerprints.issue
+
+ printf "SSH host key fingerprints:\n%s\n\n" "$FINGERPRINTS" > "$ISSUE"
+}
+
+# a helper function which generates the Agama SSL certificate fingerprints
+# displayed at the console
+generate_certificate_fingerprints() {
+ AGAMA_CERT=/etc/agama.d/ssl/cert.pem
+
+ # delete the previous file if it is there
+ rm -f "$CERT_ISSUE"
+
+ if [ -e "$AGAMA_CERT" ]; then
+ SHA256=$(openssl x509 -fingerprint -sha256 -noout -in "$AGAMA_CERT" | sed -e "s/^sha256 Fingerprint=//")
+ SHA1=$(openssl x509 -fingerprint -sha1 -noout -in "$AGAMA_CERT" | sed -e "s/^sha1 Fingerprint=//")
+
+ if [ -n "$SHA256" ] && [ -n "$SHA1" ]; then
+ printf "Agama installer SSL certificate fingerprints:\n SHA256: %s\n SHA1: %s\n\n" "$SHA256" "$SHA1" \
+ > "$CERT_ISSUE"
+ fi
+ fi
+
+ # tell agetty to use the issues from /run
+ touch /run/issue
+
+ # reload the issues to activate the changes
+ touch /run/agetty.reload
+}
+
+# a helper function which generates the mDNS URL for accessing the Agama server
+# displayed at the console
+generate_avahi_url() {
+ # issue file for the Agama mDNS URL
+ ISSUE=/run/issue.d/70-agama-connect-avahi.issue
+ # track the name, update the issue file only if the name is changed
+ OLDNAME=""
+
+ # watch for a systemd signal describing the status message change from the Avahi daemon
+ dbus-monitor --system "sender='org.freedesktop.systemd1',\
+ interface='org.freedesktop.DBus.Properties',\
+ path='/org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice',type=signal" \
+ 2> /dev/null | while read -r line;
+ do
+ AVAHINAME=$(echo "$line" | grep "Server startup complete. Host name is" \
+ | sed -e "s/^.*Server startup complete. Host name is \(.*\)\. Local.*$/\\1/")
+
+ # mDNS host name found and it is different than the previous one (or the initial value)
+ if [ -n "$AVAHINAME" ] && [ "$AVAHINAME" != "$OLDNAME" ]; then
+ OLDNAME="$AVAHINAME"
+ echo " https://$AVAHINAME" > "$ISSUE"
+
+ # reload if not in the initial state
+ if [ -e "$CERT_ISSUE" ]; then
+ touch /run/agetty.reload
+ fi
+ fi
+
+ # daemon stopped, remove the issue file
+ if echo "$line" | grep -q "avahi-daemon .* exiting"; then
+ OLDNAME=""
+ rm -f "$ISSUE"
+ touch /run/agetty.reload
+ fi
+ done
+}
+
+# a helper function which generates the URLs for accessing the Agama server
+# displayed at the console
+generate_network_url() {
+ # the interface might be a device path, use the base name
+ if [[ "$2" =~ ^/ ]]; then
+ IFACE="${2##*/}"
+ else
+ IFACE="${2}"
+ fi
+
+ ACTION="$1"
+ ISSUE="/run/issue.d/70-agama-connect-$IFACE.issue"
+ # generate a header and footer around the Agama URL issues
+ ISSUE_HEADER=/run/issue.d/69-agama-connect.issue
+ ISSUE_FOOTER=/run/issue.d/71-agama-connect.issue
+
+ # only handle interfaces starting with ^[bew]
+ # (bridges, ethernet and wifi devices), same as in the issue-generator
+ [[ "$IFACE" =~ ^[bew] ]] || exit 0
+
+ case "$ACTION" in
+ add)
+ # \4{} is a placeholder supported directly by the agetty issue reader
+ # see "man agetty"
+ echo " https://\\4{$IFACE} " > "$ISSUE"
+ ;;
+ remove)
+ rm -f "$ISSUE"
+ ;;
+ esac
+
+ # check the number of URL messages
+ ISSUES=$(ls /run/issue.d/70-agama-connect-*.issue 2> /dev/null)
+ if [ -n "$ISSUES" ]; then
+ # at least one message present, display the header and footer
+ echo "Connect to the Agama installer using these URLs:" > "$ISSUE_HEADER"
+ echo > "$ISSUE_FOOTER"
+ else
+ # no messages, delete the header and footer
+ rm -f "$ISSUE_HEADER" "$ISSUE_FOOTER"
+ fi
+
+ # reload if not in the initial state
+ if [ -e "$CERT_ISSUE" ]; then
+ touch /run/agetty.reload
+ fi
+}
+
+# wait until the SSL fingreprint issue is create, but at most 10 seconds
+wait_for_ssl_issue() {
+ for i in $(seq 1 "$1"); do
+ [ -f "$CERT_ISSUE" ] && exit 0
+ sleep 1
+ done
+}
+
+# make sure the parent directory for the issues exists
+mkdir -p /run/issue.d
+
+# create the issue file for specified item
+if [ "$1" = "--welcome" ]; then
+ generate_welcome
+elif [ "$1" = "--ssh" ]; then
+ generate_ssh_fingerprints
+elif [ "$1" = "--ssl" ]; then
+ generate_certificate_fingerprints
+elif [ "$1" = "--wait-for-ssl" ]; then
+ wait_for_ssl_issue "$2"
+elif [ "$1" = "--network" ]; then
+ generate_network_url "$2" "$3"
+elif [ "$1" = "--watch-avahi" ]; then
+ generate_avahi_url
+else
+ echo "Missing argument"
+ exit 1
+fi
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/agama-self-update b/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/agama-self-update
new file mode 100755
index 00000000000..b35393fb694
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/agama-self-update
@@ -0,0 +1,26 @@
+#! /bin/sh
+
+# Experimental Agama self-update script
+#
+# This script updates the Agama packages in the Live system from the
+# Agama Devel OBS project.
+
+
+# first try a quick and simple solution, refreshing the OSS repository takes a
+# lot of time so try using only the agama-devel for update
+zypper modifyrepo --disable repo-oss
+zypper refresh
+zypper --non-interactive dup --details --from agama-devel
+STATUS=$?
+
+# enable OSS back
+zypper modifyrepo --enable repo-oss
+
+# if it failed try it again with the OSS repo enabled, maybe there was some
+# dependency problem which hopefully will be OK now
+if [ "$?" != "0" ]; then
+ zypper --non-interactive dup --details --from agama-devel
+fi
+
+# clean all repository caches to save space in RAM disk
+zypper clean --all
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/live-password b/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/live-password
new file mode 100755
index 00000000000..76ebf390d98
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/bin/live-password
@@ -0,0 +1,162 @@
+#!/usr/bin/sh
+
+# Helper script wich sets the root pasword from several sources
+# - Kernel boot command line (use --kernel option)
+# - Systemd ask password tool (use --systemd option)
+# - Interactively using a dialog (use --dialog option)
+# - ISO file metadata (use --iso option)
+# - Generates a random password unless already set (use --random option)
+
+MYDIR=$(realpath "$(dirname "$0")")
+export DIALOGRC="$MYDIR/../share/live/misc/dialog.conf"
+
+# dialog titles
+BTITLE="Live System Configuration (Press Ctrl+L to refresh the screen)"
+TITLE="Set Login Password"
+
+# functions for entering the password in an interactive dialog
+confirm_exit() {
+ # --keep-tite is not a misspelling of "title"
+ if dialog --keep-tite --backtitle "$BTITLE" --defaultno --yesno "Are you sure you want to cancel?" 5 40; then
+ exit 1
+ fi
+}
+
+msg_box() {
+ dialog --keep-tite --backtitle "$BTITLE" --msgbox "$1" 6 30
+}
+
+ask_password() {
+ if ! PWD1=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Password:" 8 40); then
+ confirm_exit
+ ask_password
+ fi
+
+ if ! PWD2=$(dialog --keep-tite --title "$TITLE" --backtitle "$BTITLE" --stdout --insecure --passwordbox "Verify Password:" 8 40); then
+ confirm_exit
+ ask_password
+ fi
+
+ if [ "$PWD1" != "$PWD2" ]; then
+ msg_box "Passwords do not match.\nPlease try again."
+ ask_password
+ elif [ -z "$PWD1" ]; then
+ msg_box "Password cannot be empty.\nPlease try again."
+ ask_password
+ else
+ echo "$PWD1" | passwd --stdin
+ exit 0
+ fi
+}
+
+# functions for entering the password using the "systemd-ask-password" tool
+ask_password_systemd() {
+ if ! PWD1=$(systemd-ask-password --timeout=0 "Set login password: "); then
+ exit 1
+ fi
+
+ if ! PWD2=$(systemd-ask-password --timeout=0 "Verify password: "); then
+ exit 1
+ fi
+
+ if [ "$PWD1" != "$PWD2" ]; then
+ echo "Passwords do not match, please try again."
+ ask_password_systemd
+ elif [ -z "$PWD1" ]; then
+ echo "Password cannot be empty, please try again. To skip the password configuration press Ctrl+C."
+ ask_password_systemd
+ else
+ echo "$PWD1" | passwd --stdin
+ exit 0
+ fi
+}
+
+# check if the root password is present in the ISO file metadata
+password_from_iso() {
+ # get the partition where the live ISO is mounted, the real name is set by the
+ # config.sh script which gets the live partition label name from KIWI
+ PARTITION=$(blkid -L "@@LIVE_MEDIUM_LABEL@@")
+
+ if [ -z "$PARTITION" ]; then
+ echo "Live ISO partition not found, skipping password configuration"
+ exit 0
+ fi
+
+ # get the parent device name for the partition (/dev/sda2 -> /dev/sda),
+ # for some devices just removing the trailing number does not work
+ DEVICE=$(lsblk --noheadings --output PKNAME "$PARTITION")
+
+ # if there is no parent device use the device itself (e.g. /dev/sr0)
+ if [ -z "$DEVICE" ]; then
+ DEVICE="$PARTITION"
+ else
+ # add the /dev/ prefix
+ DEVICE="/dev/$DEVICE"
+ fi
+
+ echo "Reading password from $DEVICE..."
+
+ # run tagmedia and extract the password value
+ TAG=$(tagmedia "$DEVICE" | grep "^live_password = " | sed -e "s/^live_password = //")
+
+ if [ -z "$TAG" ]; then
+ echo "Password not found at $DEVICE"
+ exit 0
+ fi
+
+ if PWD=$(echo "$TAG" | base64 -d); then
+ usermod -p "$PWD" root
+ else
+ echo "Base64 decoding of the password failed!"
+ exit 1
+ fi
+}
+
+# generate a random password unless a password is already set
+random_password() {
+ if grep -q '^root:!\*:' /etc/shadow; then
+ echo "Root password not set, generating a random password..."
+ # generate a random password, omit symbols and confusing characters to avoid
+ # mistakes, the password will be very likely re-typed in a different device
+ # so make the password easy to type (it cannot be copy pasted)
+ #
+ # TODO: check this with the security team
+ PASSWD=$(base64 -w 0 < /dev/random | tr -d "+/0OolI1" | head -c 8)
+
+ if [ -n "$PASSWD" ]; then
+ echo "$PASSWD" | passwd --stdin
+ else
+ # uh, the user cannot login now... =:-o
+ echo "Failed to generate a password"
+ exit 1
+ fi
+
+ # display the generated password in the console
+ mkdir -p /run/issue.d
+ echo "Password for root user: \e{lightcyan}$PASSWD\e{reset}" > /run/issue.d/99-live-password.issue
+ # the /etc/issue or /run/issue file must exist to show the issues in console
+ # hint: run "agetty --show-issue" to see what will be displayed
+ touch /run/issue
+ fi
+}
+
+if [ "$1" = "--kernel" ]; then
+ # get the password from the kernel command line
+ PWD=$(awk -F 'live.password=' '{sub(/ .*$/, "", $2); print $2}' < /proc/cmdline)
+ if [ -n "$PWD" ]; then
+ echo "$PWD" | passwd --stdin
+ fi
+
+ PWD=$(awk -F 'live.password_hash=' '{sub(/ .*$/, "", $2); print $2}' < /proc/cmdline)
+ if [ -n "$PWD" ]; then
+ usermod -p "$PWD" root
+ fi
+elif [ "$1" = "--dialog" ]; then
+ ask_password
+elif [ "$1" = "--systemd" ]; then
+ ask_password_systemd
+elif [ "$1" = "--iso" ]; then
+ password_from_iso
+elif [ "$1" = "--random" ]; then
+ random_password
+fi
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/dracut-cmdline-menu.service b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/dracut-cmdline-menu.service
new file mode 100644
index 00000000000..fcf020f1ac3
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/dracut-cmdline-menu.service
@@ -0,0 +1,32 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut menu for additional cmdline parameters
+Documentation=man:dracut.bootup(7)
+DefaultDependencies=no
+Before=dracut-cmdline-ask.service
+Wants=systemd-journald.socket
+After=systemd-journald.socket
+Wants=systemd-vconsole-setup.service
+After=systemd-vconsole-setup.service
+
+ConditionPathExists=/usr/lib/initrd-release
+ConditionKernelCommandLine=|rd.cmdline=menu
+ConditionPathExistsGlob=|/etc/cmdline.d/*.conf
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-cmdline-menu
+StandardInput=tty
+StandardOutput=inherit
+StandardError=inherit
+RemainAfterExit=yes
+KillMode=process
+IgnoreSIGPIPE=no
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/dracut-cmdline-menu.sh b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/dracut-cmdline-menu.sh
new file mode 100755
index 00000000000..8a691188665
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/dracut-cmdline-menu.sh
@@ -0,0 +1,145 @@
+#!/bin/sh
+
+if [ -d /sysroot ] ; then
+ type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+ getarg "rd.cmdline=menu" || exit 0
+fi
+
+# -----------------------------------------------------------------------------
+
+
+# usage example:
+#
+# title="Foo menu"
+# items=("Foo A" "Foo B" "Foo C")
+#
+# dia_menu title items selected_item
+#
+# echo "selected_item=$selected_item"
+#
+dia_menu () {
+ local -n x_title=$1
+ local -n x_list=$2
+ local -n x_item=$3
+
+ local tmp i ind ok
+
+ until [[ "$ok" ]] ; do
+ echo -e "\n$x_title\n"
+
+ echo "0) <-- Back <--"
+ ind=1
+ for i in "${x_list[@]}" ; do
+ echo "$ind) $i"
+ ind=$((ind + 1))
+ done
+
+ echo
+
+ read -e -r -p "> " x_item tmp
+
+ [[ ( -z "$x_item" || "$x_item" = $((x_item)) ) && "$x_item" -lt $ind ]] && ok=1
+ done
+
+ x_item=$((x_item))
+
+ return 0
+}
+
+
+# usage example
+#
+# title="Foo input"
+# value="foo bar"
+# dia_input title value
+# aborted=$?
+#
+# if [ $aborted = 1 ] ; then
+# echo aborted
+# else
+# echo -e "input=\"$value\""
+# fi
+#
+dia_input () {
+ local -n x_title=$1
+ local -n x_value=$2
+
+ local tmp="$x_value"
+
+ echo -e "\n${x_title}. (Enter '+++' to abort.)\n"
+
+ read -e -r -p "[$tmp]> " -i "$tmp" tmp
+
+ if [[ "$tmp" = "${tmp%+++}+++" ]] ; then
+ return 1
+ else
+ x_value="$tmp"
+ fi
+
+ return 0
+}
+
+# -----------------------------------------------------------------------------
+
+echo
+echo "== Additional parameters =="
+
+live_root=$(getarg "root=")
+live_root_disk=$(getarg "root_disk=")
+live_root_net=$(getarg "root_net=")
+live_proxy=$(getarg "proxy=")
+
+live_root_disk=${live_root_disk:-$live_root}
+
+live_root=${live_root#live:}
+live_root_disk=${live_root_disk#live:}
+live_root_net=${live_root_net#live:}
+
+aborted=1
+
+while [ "$aborted" != 0 ] ; do
+ echo -n > /etc/cmdline.d/98-cmdline-menu.conf
+
+ title="Live image location"
+ items=("Disk / DVD" "Network")
+ dia_menu title items selected_item
+
+ aborted=$?
+ [[ $aborted != 0 ]] && continue
+
+ case $selected_item in
+ 1) live_root="$live_root_disk" ;;
+ 2) live_root="$live_root_net" ;;
+ esac
+
+ if [[ "$selected_item" = 2 ]] ; then
+ title="Live image location (e.g. http://example.com/live.iso)"
+ dia_input title live_root
+ aborted=$?
+ [[ $aborted != 0 ]] && continue
+
+ live_root_net="$live_root"
+
+ title="Proxy Settings (e.g. http://proxy.example.com)"
+ dia_input title live_proxy
+
+ aborted=$?
+ [[ $aborted != 0 ]] && continue
+ fi
+
+ echo "root=live:$live_root" >> /etc/cmdline.d/98-cmdline-menu.conf
+ echo "proxy=$live_proxy" >> /etc/cmdline.d/98-cmdline-menu.conf
+
+ echo
+ echo "== Updated settings =="
+ echo
+ cat /etc/cmdline.d/98-cmdline-menu.conf
+
+ title="Settings ok?"
+ items=("Yes" "No")
+ dia_menu title items selected_item
+
+ [[ $selected_item = 1 ]] && break
+
+ aborted=1
+done
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/module-setup.sh b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/module-setup.sh
new file mode 100755
index 00000000000..71350e96f6e
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/module-setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo "dracut-systemd"
+
+ return 0
+}
+
+installkernel() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_script "$moddir/dracut-cmdline-menu.sh" /bin/dracut-cmdline-menu
+
+ inst_simple "$moddir/dracut-cmdline-menu.service" "$systemdsystemunitdir/dracut-cmdline-menu.service"
+ $SYSTEMCTL -q --root "$initdir" add-wants initrd.target dracut-cmdline-menu.service
+
+ inst_hook pre-pivot 98 "$moddir/save-cmdline.sh"
+}
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/save-cmdline.sh b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/save-cmdline.sh
new file mode 100644
index 00000000000..9f3b55465ab
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/dracut/modules.d/98dracut-menu/save-cmdline.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+[ -e /dracut-state.sh ] && . /dracut-state.sh
+
+rm -f "$NEWROOT/etc/cmdline.d/10-liveroot.conf"
+
+if [ -e /etc/cmdline.d/98-cmdline-menu.conf ] ; then
+ cp /etc/cmdline.d/98-cmdline-menu.conf "$NEWROOT/etc/cmdline-menu.conf"
+else
+ echo "root=$root" >"$NEWROOT/etc/cmdline-menu.conf"
+fi
+
+echo "$CMDLINE" >"$NEWROOT/etc/cmdline-full.conf"
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/udev/rules.d/80-agama-connect-issue.rules b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/udev/rules.d/80-agama-connect-issue.rules
new file mode 100644
index 00000000000..2ba3202a237
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/lib/udev/rules.d/80-agama-connect-issue.rules
@@ -0,0 +1,5 @@
+# udev rules for generating the Agama access URLs displayed at the console
+ACTION=="add", SUBSYSTEM=="net", RUN+="/usr/bin/agama-issue-generator --network add $env{INTERFACE}"
+ACTION=="remove", SUBSYSTEM=="net", RUN+="/usr/bin/agama-issue-generator --network rm $env{INTERFACE}"
+ACTION=="move", SUBSYSTEM=="net", RUN+="/usr/bin/agama-issue-generator --network add $env{INTERFACE}"
+ACTION=="move", SUBSYSTEM=="net", RUN+="/usr/bin/agama-issue-generator --network rm $env{DEVPATH_OLD}"
diff --git a/build-tests/x86/tumbleweed/test-image-agama/root/usr/share/live/misc/dialog.conf b/build-tests/x86/tumbleweed/test-image-agama/root/usr/share/live/misc/dialog.conf
new file mode 100644
index 00000000000..4284be71e11
--- /dev/null
+++ b/build-tests/x86/tumbleweed/test-image-agama/root/usr/share/live/misc/dialog.conf
@@ -0,0 +1,10 @@
+#
+# Configuration file for the "dialog" tool
+#
+# To generate a full template with all options run:
+#
+# dialog --create-rc dialog.conf
+#
+
+# Background screen color
+screen_color = (WHITE,CYAN,ON)