]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vmspawn: Add headless console support
authorDaan De Meyer <daan@amutable.com>
Mon, 23 Mar 2026 21:00:03 +0000 (22:00 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 24 Mar 2026 20:36:19 +0000 (21:36 +0100)
man/systemd-vmspawn.xml
shell-completion/bash/systemd-vmspawn
src/vmspawn/vmspawn-settings.c
src/vmspawn/vmspawn-settings.h
src/vmspawn/vmspawn.c

index 331c7c16fd699bc28d5534188a475bec61b10e63..23ecc51bac3ee6bc44acb01e6ab100fd53e3892d 100644 (file)
 
           <listitem><para>Configures how to set up the console of the VM. Takes one of
           <literal>interactive</literal>, <literal>read-only</literal>, <literal>native</literal>,
-          <literal>gui</literal>. Defaults to <literal>interactive</literal>. <literal>interactive</literal>
-          provides an interactive terminal interface to the VM. <literal>read-only</literal> is similar, but
-          is strictly read-only, i.e. does not accept any input from the user. <literal>native</literal> also
-          provides a TTY-based interface, but uses qemu native implementation (which means the qemu monitor
-          is available). <literal>gui</literal> shows the qemu graphical UI.</para>
+          <literal>gui</literal>, <literal>headless</literal>. Defaults to <literal>interactive</literal>.
+          <literal>interactive</literal> provides an interactive terminal interface to the VM.
+          <literal>read-only</literal> is similar, but is strictly read-only, i.e. does not accept any input
+          from the user. <literal>native</literal> also provides a TTY-based interface, but uses qemu native
+          implementation (which means the qemu monitor is available). <literal>gui</literal> shows the qemu
+          graphical UI. <literal>headless</literal> runs the VM without any console, which is useful for
+          automated or scripted usage.</para>
 
           <xi:include href="version-info.xml" xpointer="v256"/></listitem>
         </varlistentry>
index b17586de14555b4e9f3e46937c7600a50c1d95c4..08e92e0a4b503d80583851e4b2fc500ef09b0f43 100644 (file)
@@ -56,7 +56,7 @@ _systemd_vmspawn() {
     elif __contains_word "$prev" ${OPTS[SSH_KEY]}; then
         comps='dsa ecdsa ecdsa-sk ed25519 ed25519-sk rsa'
     elif __contains_word "$prev" ${OPTS[CONSOLE]}; then
-        comps='interactive native gui'
+        comps='interactive native gui read-only headless'
     elif __contains_word "$prev" ${OPTS[IMAGE_FORMAT]}; then
         comps='raw qcow2'
     elif __contains_word "$prev" ${OPTS[ARG]}; then
index 46dda4bfc325ff4fca6b56fae7568c1ad49c7a3f..1c4bc102b94e3b78beedea8fbcd8b2f67c47a993 100644 (file)
@@ -24,6 +24,7 @@ static const char *const console_mode_table[_CONSOLE_MODE_MAX] = {
         [CONSOLE_READ_ONLY]   = "read-only",
         [CONSOLE_NATIVE]      = "native",
         [CONSOLE_GUI]         = "gui",
+        [CONSOLE_HEADLESS]    = "headless",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(console_mode, ConsoleMode);
index ee937c993ac8873dfd25b127470fc0d3a5729efe..1d59db6418b5239a2a7570abe8d9b83c98e32f8a 100644 (file)
@@ -27,6 +27,7 @@ typedef enum ConsoleMode {
         CONSOLE_READ_ONLY,      /* ptyfwd, but in read-only mode */
         CONSOLE_NATIVE,         /* qemu's native TTY handling */
         CONSOLE_GUI,            /* qemu's graphical UI */
+        CONSOLE_HEADLESS,       /* no console */
         _CONSOLE_MODE_MAX,
         _CONSOLE_MODE_INVALID = -EINVAL,
 } ConsoleMode;
index a65f879449e6aa128223408492f8e2dab585917f..d41a9203891a8c8c27edf330edfbed79b993a38d 100644 (file)
@@ -260,7 +260,7 @@ static int help(void) {
                "     --pass-ssh-key=BOOL   Create an SSH key to access the VM\n"
                "     --ssh-key-type=TYPE   Choose what type of SSH key to pass\n"
                "\n%3$sInput/Output:%4$s\n"
-               "     --console=MODE        Console mode (interactive, native, gui)\n"
+               "     --console=MODE        Console mode (interactive, native, gui, read-only, headless)\n"
                "     --background=COLOR    Set ANSI color for background\n"
                "\n%3$sCredentials:%4$s\n"
                "     --set-credential=ID:VALUE\n"
@@ -2365,6 +2365,13 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
                                 "-mon", "console");
                 break;
 
+        case CONSOLE_HEADLESS:
+                r = strv_extend_many(
+                                &cmdline,
+                                "-nographic",
+                                "-nodefaults");
+                break;
+
         default:
                 assert_not_reached();
         }
@@ -2641,7 +2648,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
                         return log_oom();
         }
 
-        if (arg_console_mode != CONSOLE_GUI) {
+        if (!IN_SET(arg_console_mode, CONSOLE_GUI, CONSOLE_HEADLESS)) {
                 r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
                 if (r < 0)
                         return log_oom();