How to Restrict Active Consoles to TTY1 in Linux

In this post, we’ll look at a simple script to limit active virtual consoles (TTYs) on Linux to TTY1 only. This can help reduce potential access, save system resources, or align with specific security requirements.

How to Restrict Active Consoles to TTY1 in Linux

This post is an explanation for a short script that I shared on my GitHub page. The initial script provided a quick solution for limiting TTY access and now is time to explain its inner workings and why these specific commands were chosen. This expanded post breaks down each command step-by-step, highlighting both the how and why behind restricting consoles to TTY1. Hopefully, this deep dive provides clarity and helps you customize similar scripts for your own server environments!

In Linux environments, we sometimes need to restrict physical console access, allowing only TTY1 for security and simplicity. TTY (TeleTYpe) consoles are virtual terminals that provide command-line interfaces, and Linux distributions typically enable several by default. This script limits access to TTY1 only, disabling TTYs 2-6, and is designed to work across various Linux distributions and init systems.

Here's a fully detailed blog post explaining each step of this cross-distribution script to restrict console access to TTY1.

Script Overview

This script identifies the Linux distribution and init system (Upstart or systemd) before applying the appropriate method to disable TTYs 2-6. Additionally, it updates /etc/default/console-setup (if available) to ensure the system only enables TTY1.

The Code

Here’s the complete script:

#!/bin/bash -ex

# init.sh - Initial server setup or system initialization.

# Function to detect the init system (systemd or upstart) and distribution
get_distro_and_init() {
  if [[ -f /etc/os-release ]]; then
    . /etc/os-release
    DISTRO="$ID"
  else
    DISTRO="unknown"
  fi

  if pidof systemd &>/dev/null; then
    INIT="systemd"
  elif [[ -d /etc/init ]]; then
    INIT="upstart"
  else
    INIT="unknown"
  fi
}

# Function to update ACTIVE_CONSOLES setting if console-setup file exists
update_active_consoles() {
  if [[ -f /etc/default/console-setup ]]; then
    echo "==> Setting ACTIVE_CONSOLES to TTY1 in /etc/default/console-setup"
    sed -i -e 's,^\(ACTIVE_CONSOLES="/dev/tty\).*,\11",' /etc/default/console-setup
  else
    echo "==> /etc/default/console-setup file not found, skipping ACTIVE_CONSOLES setting."
  fi
}

# Function to disable TTYs 2-6 on Upstart-based systems
disable_ttys_upstart() {
  echo "==> Upstart detected. Disabling TTYs 2-6 by renaming configuration files..."
  for f in /etc/init/tty[^1]*.conf; do
    if [[ -f "$f" ]]; then
      mv "$f" "$f.bak"
    fi
  done
}

# Function to disable TTYs 2-6 on systemd-based systems
disable_ttys_systemd() {
  echo "==> Systemd detected. Disabling TTYs 2-6 by masking getty services..."
  for tty in {2..6}; do
    systemctl mask getty@tty${tty}.service
  done

  # Ensure TTY1 is active
  systemctl unmask getty@tty1.service
  systemctl start getty@tty1.service
}

# Function to disable TTYs for distributions without Upstart or systemd, if applicable
disable_ttys_generic() {
  case "$DISTRO" in
    arch|manjaro)
      echo "==> Arch-based system detected. Masking getty services for TTYs 2-6..."
      ;;
    fedora|centos|rhel)
      echo "==> Red Hat-based system detected. Masking getty services for TTYs 2-6..."
      ;;
    suse|opensuse)
      echo "==> SUSE-based system detected. Masking getty services for TTYs 2-6..."
      ;;
    *)
      echo "==> Unsupported distribution or init system. Unable to apply TTY restrictions."
      exit 1
      ;;
  esac
  for tty in {2..6}; do
    systemctl mask getty@tty${tty}.service
  done
  systemctl unmask getty@tty1.service
  systemctl start getty@tty1.service
}

# Main script execution
get_distro_and_init
update_active_consoles

if [[ "$INIT" == "upstart" ]]; then
  disable_ttys_upstart
elif [[ "$INIT" == "systemd" ]]; then
  disable_ttys_systemd
else
  disable_ttys_generic
fi

echo "Console restriction to TTY1 applied successfully."

Step-by-Step Explanation

Step 1. Detecting the Linux Distribution and Init System

The function get_distro_and_init determines:

  • The distribution ID by sourcing /etc/os-release, which defines variables specific to the Linux distribution.
  • The init system by checking if systemd is active or if the /etc/init directory (indicating Upstart) is present.

Based on this detection, the script knows which method to use for managing TTYs.

Step 2. Updating ACTIVE_CONSOLES in /etc/default/console-setup

The update_active_consoles function modifies /etc/default/console-setup (if available) to restrict the ACTIVE_CONSOLES setting to TTY1:

sed -i -e 's,^\(ACTIVE_CONSOLES="/dev/tty\).*,\11",' /etc/default/console-setup

This line uses sed to search and replace the ACTIVE_CONSOLES variable, setting it to only enable TTY1.

Step 3. Disabling TTYs for Upstart Systems

If Upstart is detected, disable_ttys_upstart renames TTY configuration files for TTYs 2-6, making them inaccessible:

for f in /etc/init/tty[^1]*.conf; do
    if [[ -f "$f" ]]; then
        mv "$f" "$f.bak"
    fi
done

This command renames each relevant TTY configuration file, effectively disabling it by preventing Upstart from loading it at boot.

Step 4. Disabling TTYs for Systemd Systems

If systemd is detected, disable_ttys_systemd uses systemctl mask to prevent TTYs 2-6 from starting:

for tty in {2..6}; do
    systemctl mask getty@tty${tty}.service
done

After masking TTYs 2-6, the function unmask and start TTY1 to ensure it remains accessible.

Step 5. Disabling TTYs on Generic Distributions

The disable_ttys_generic function handles other distributions by applying systemd-based methods where appropriate:

  • Arch-based: Masks TTY services similar to systemd.
  • Red Hat-based: Masks TTYs using systemd.
  • SUSE-based: Masks TTYs using systemd.

Each case masks the same TTY services and unmask TTY1.

Final Thoughts

With this script, only TTY1 is available across various distributions and init systems, enhancing security by limiting local console access. As Linux environments can vary greatly, the script's versatility ensures a streamlined approach to controlling console access on both popular and alternative systems.

Read next

Systemd’s Role in Suspend/Resume

Systemd orchestrates Linux suspend and resume. From systemd-logind deciding when to sleep, to inhibitors blocking it, to pre/post scripts and sleep.conf tuning defaults, learn how systemd coordinates kernel and user-space for reliable power management.