I have Debian Stretch and I would like to have a custom grub entry in order to run the system without a graphical desktop. I thought that would be as easy as running a different runlevel, but reading about that, I was aware that, in systemd everything is different.

After reading this question about Red Hat and also this other for Debian Jessie, I learnt about systemd targets, and I think that what I want to do is running in multi-user.target.

I've found this fedora link, this archlinux kernel link and this other one. All them explain that there is one option "systemd.unit" that can be appended in the "linux" line in the grub menu entry. So, I searched for links to explain how to create a custom menu entry: this one. But, looking my own automatic grub entries with the key 'e' in the grub screen, they are more complex than the one in the link. The problem is that I don't know if I must copy all that stuff in the custom menu entry.

 setparams 'Debian gnu/linux, con linux 4.8.0-2-amd64'
 insmod gzio
 if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
 insmod part-msdos
 insmod ext2
 set root='hd0,msdos5'
 if [ x$feature_platform_search_hint = xy ]; then
    search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos5 --hint-efi=hd0,msdos5 --hint-baremetal=ahci0,msdos5  3202c741-ef05-40e4-9368-8617e7b1fb3c
    search --no-floppy --fs-uuid --set=root 3202c741-ef05-40e4-9368-8617e7b1fb3c
echo 'Cargando Linux 4.8...'
linux /vmlinuz-4.8.0-2-amd64 root=UUID=17f74892-fe09-46ec-91ca-2dca457565a1 ro quiet
echo 'Cargando imagen de memoria inicial...'
initrd /initrd.img-4.8.0-2-amd64

This is my automatically created entry for my last kernel. Can I simply copy all this in a custom menu entry and change only the

linux /vmlinuz-4.8.0-2-amd64 root=UUID=17f74892-fe09-46ec-91ca-2dca457565a1 ro quiet

line to be

linux /vmlinuz-4.8.0-2-amd64 root=UUID=17f74892-fe09-46ec-91ca-2dca457565a1 ro quiet systemd.unit=multi-user.target



After some days of researching, I have 3 approaches to the problem of creating custom entries for running a Systemd Debian without graphical desktop from the Grub. I think that the best approach is 1.

1. Creating a new /etc/grub.d/* configuration file

To do that, i copied /etc/grub.d/10_linux file as a template:

sudo cp /etc/grub.d/10_linux /etc/grub.d/11_multiuser

The original file creates the root entry for the latest kernel and also the "Advanced options" submenu. So, I edited my 11_multiuser file a little bit, just to create a new submenu for the multiuser options, and create inside a new option for each kernel, for the multiuser mode. Here I'll add a patch with the modified lines:

--- /etc/grub.d/10_linux
+++ /etc/grub.d/11_multiuser
@@ -118,6 +118,8 @@
       case $type in
          title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")" ;;
+      multiuser)
+          title="$(gettext_printf "%s, with Linux %s (multiuser)" "${os}" "${version}")" ;;
          title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "${type#init-}")" ;;
@@ -227,57 +229,18 @@

-cat << 'EOF'
-function gfxmode {
-   set gfxpayload="${1}"
-if [ "$vt_handoff" = 1 ]; then
-  cat << 'EOF'
-   if [ "${1}" = "keep" ]; then
-       set vt_handoff=vt.handoff=7
-   else
-       set vt_handoff=
-   fi
-cat << EOF
-# Use ELILO's generic "efifb" when it's known to be available.
-# FIXME: We need an interface to select vesafb in case efifb can't be used.
-if [ "x$GRUB_GFXPAYLOAD_LINUX" != x ] || [ "$gfxpayload_dynamic" = 0 ]; then
-  echo "set linux_gfx_mode=$GRUB_GFXPAYLOAD_LINUX"
-  cat << EOF
-if [ "\${recordfail}" != 1 ]; then
-  if [ -e \${prefix}/gfxblacklist.txt ]; then
-    if hwmatch \${prefix}/gfxblacklist.txt 3; then
-      if [ \${match} = 0 ]; then
-        set linux_gfx_mode=keep
-      else
-        set linux_gfx_mode=text
-      fi
-    else
-      set linux_gfx_mode=text
-    fi
-  else
-    set linux_gfx_mode=keep
-  fi
-  set linux_gfx_mode=text
-cat << EOF
-export linux_gfx_mode
 # Extra indentation to add to menu entries in a submenu. We're not in a submenu
 # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).

+# para el menu de multiuser
+if [ -z "$boot_device_id" ]; then
+  boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+gettext_printf "Agregando entradas multiuser...\n" >&2
+echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote) (MultiUser)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
 while [ "x$list" != "x" ] ; do
   linux=`version_find_latest $list`
   case $linux in
@@ -331,34 +294,9 @@

-  if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
-    linux_entry "${OS}" "${version}" simple \
-    submenu_indentation="$grub_tab"
-    if [ -z "$boot_device_id" ]; then
-   boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
-    fi
-    # TRANSLATORS: %s is replaced with an OS name
-    echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
-    is_top_level=false
-  fi
-  linux_entry "${OS}" "${version}" advanced \
-  for supported_init in ${SUPPORTED_INITS}; do
-    init_path="${supported_init#*:}"
-    if [ -x "${init_path}" ] && [ "$(readlink -f /sbin/init)" != "${init_path}" ]; then
-      linux_entry "${OS}" "${version}" "init-${supported_init%%:*}" \
-         "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} init=${init_path}"
-    fi
-  done
-  if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
-    linux_entry "${OS}" "${version}" recovery \
-  fi
+  linux_entry "${OS}" "${version}" multiuser \
+              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} systemd.unit=multi-user.target"

   list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`

With this solution, if I add/remove kernels, or perform some action that involves any reconfiguration of the grub menu, my desired multiuser entries will be automatically added for each kernel. Also, I think (but not completely sure) that, if i update the grub, my new configuration file 11_multiuser won't be removed, given that it's not part of the Grub's predefined configuration files.

2. Modifying /etc/grub.d/10_linux file

This is another approach, but i think this is worse than the first one. This way, you are modifying the official file, so you could break the Grub's configuration and the whole system startup. Also, if any update leads to the file replacement, you could loose your configuration. There is only one advantage on doing this: you could insert your multiuser entries in the "Advanced options" submenu.The patch added for the first approach is partially valid for this. Anyway, I totally disagree this approach.

3. Modifying /etc/grub.d/40_custom file

This file is intended to insert specific entries. You could copy the entry from /boot/grub/grub.cfg and paste it in this file adding the systemd.. It is perfectly ok, but the problem is that you must do it for every kernel you want. Also, when removing/adding new kernels to the system, you must maintain this file manually. Plus, these entries appears at the end of the grub menu, and if you have other operating systems like Windows, then your custom entries will be separated from the first Linux entries.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.