What is needed for a minimal systemd boot to launch getty on a virtual console?

First of all, systemd is not a traditional unix init. Systemd is so much more, so it's a bit unfair to compare the two.

To answer the question, what appears to be necessary are some binaries and the following configuration files:

/usr/lib/systemd/system/default.target
/usr/lib/systemd/system/basic.target
/usr/lib/systemd/system/sysinit.target
/usr/lib/systemd/system/getty.target
/usr/lib/systemd/system/[email protected]
/usr/lib/systemd/system/console-getty.service

issuing systemctl enable console-getty.service [email protected] then creates these symlinks:

/etc/systemd/system/default.target.wants/[email protected] -> /lib/systemd/system/getty@service
/etc/systemd/system/getty.target.wants/console-getty.service -> /lib/systemd/system/console-getty.service

NOTE: To utilize systemd's special features for starting agetty dynamically, on-demand when pressing Alt+F3 and so on, it appears that you must also have at least these two files:

/etc/systemd/logind.conf
/lib/systemd/system/[email protected]

where [email protected] is a symlink to [email protected].

Contents of configuration files:

The default.target, getty.target, sysinit.target files can be empty except for the [Unit] tag and (probably) Description=xxx.

basic.target also contains dependency information:

[Unit]
Description=Basic System
Requires=sysinit.target
Wants=sockets.target timers.target paths.target slices.target
After=sysinit.target sockets.target timers.target paths.target slices.target

I'm not sure if the references to targets that don't exist as files are needed or not. They are described on the systemd.special(7) man page.


console-getty.service: (Special case for agetty on the console)

[Unit]
Description=Console Getty
After=systemd-user-sessions.service plymouth-quit-wait.service
Before=getty.target

[Service]
ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=cons
TTYPath=/dev/console
TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

[Install]
WantedBy=getty.target

[email protected]: (generic config for all getty services except console)

[Unit]
Description=Getty on %I
After=systemd-user-sessions.service plymouth-quit-wait.service
Before=getty.target
IgnoreOnIsolate=yes
ConditionPathExists=/dev/tty0

[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=no
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

[Install]
WantedBy=getty.target
DefaultInstance=tty1

Finally you probably need a few of these special binaries (I haven't tried which ones are crucial):

/lib/systemd/systemd (/sbin/init usually points to this)
/lib/systemd/systemd-logind
/lib/systemd/systemd-cgroups-agent
/lib/systemd/systemd-user-sessions
/lib/systemd/systemd-vconsole-setup
/lib/systemd/systemd-update-utmp
/lib/systemd/systemd-sleep
/lib/systemd/systemd-sysctl
/lib/systemd/systemd-initctl
/lib/systemd/systemd-reply-password
/lib/systemd/systemd-ac-power
/lib/systemd/systemd-activate
/lib/systemd/systemd-backlight
/lib/systemd/systemd-binfmt
/lib/systemd/systemd-bootchart
/lib/systemd/systemd-bus-proxyd
/lib/systemd/systemd-coredump
/lib/systemd/systemd-cryptsetup
/lib/systemd/systemd-fsck
/lib/systemd/systemd-hostnamed
/lib/systemd/systemd-journald
/lib/systemd/systemd-journal-gatewayd
/lib/systemd/systemd-journal-remote
/lib/systemd/systemd-localed
/lib/systemd/systemd-machined
/lib/systemd/systemd-modules-load
/lib/systemd/systemd-multi-seat-x
/lib/systemd/systemd-networkd
/lib/systemd/systemd-networkd-wait-online
/lib/systemd/systemd-quotacheck
/lib/systemd/systemd-random-seed
/lib/systemd/systemd-readahead
/lib/systemd/systemd-remount-fs
/lib/systemd/systemd-resolved
/lib/systemd/systemd-rfkill
/lib/systemd/systemd-shutdown
/lib/systemd/systemd-shutdownd
/lib/systemd/systemd-socket-proxyd
/lib/systemd/systemd-timedated
/lib/systemd/systemd-timesyncd
/lib/systemd/systemd-udevd
/lib/systemd/systemd-update-done

To summarize the systemd start process, I think it works something like this:

  1. systemd locates basic.target (or all *.target files?)
  2. dependencies are resolved based on WantedBy=, Wants=, Before=, After=... directives in the [Install] section of the *.service and *.target configuration files.
  3. *.services that should start (that are not "special" services), have a [Service] section with a ExecStart= directive, that points out the executable to start.

systemd automatically creates a getty when you switch to the terminals, up to a certain maximum number. The default is 6 (so you get automatically a getty for alt+f1 to alt+f6). If you want to change this parameter you can edit /etc/systemd/logind.conf to change NAutoVTs parameter to some other number (max 12)

If you want a getty to spawn even if you don't manually switch you can add a symlink to /usr/lib/systemd/system/[email protected] to the /etc/systemd/system/getty.target.wants/ directory:

ln -sf /usr/lib/systemd/system/[email protected] /etc/systemd/system/getty.target.wants/[email protected]

this will result in the getty.target requiring one more getty@ service. A target is a collection of services that need to be spawned, replacement of runlevels which supports dependencies. The default target depends on getty.target

See at systemd FAQ in ArchWiki

edit: I researched a bit more in the documentation.

At boot the systemd daemon loads all systems in the default target and their dependencies. A target is defined by the files

/etc/systemd/system/default.target
/usr/lib/systemd/system/default.target

A target has a list of attached services specified by symlinks in the directories

/etc/systemd/system/default.target.wants
/usr/lib/systemd/system/default.target.wants

The /etc version overrides the distribution defaults in /usr/lib. Only one of the .target files is required, while none of the directory is required

getty is just one of the services among others which can be run by init scripts. In the distribution I checked (fedora, arch) getty is run in two different ways:

  1. Started by specific scripts for each terminal (links to the /usr/lib/systemd/system/[email protected] file in which the tty name is substituted in by systemd from the link filename)
  2. Automatically brought up as needed by the logind when the user switch to a virtual terminal (similar to the way old inetd brought up services only when a request arrives). logind is a different daemon distributed with systemd, and reads its configuration from the /etc/systemd/logind.conf file.

Hope this is satisfying.

Tags:

Boot

Systemd