Systemd Service After Networking, Before Login: A Comprehensive Guide

This guide provides detailed instructions on configuring a systemd service to run after network initialization but before the login screen appears, specifically for Debian Buster, Bookworm, and Trixie systems. We will focus on ensuring the service runs as the final step before the login manager, and waits for its completion before presenting the login prompt, even with a terminal-based (non-graphical) login.

Understanding Systemd Dependencies and Ordering

Systemd uses a sophisticated dependency system to manage service startup order. Successfully placing our service requires a deep understanding of these dependencies. The core concept revolves around After=, Before=, Requires=, and Wants= directives within the service unit file.

Defining Service Dependencies

The After= directive specifies that a service should start after another service has finished its startup process. This does not imply a direct dependency, only a timing constraint. Conversely, Before= mandates that the service start before the specified service.

The Requires= directive establishes a hard dependency. The service requiring another will fail to start if the required service fails to start or remain running. Wants= is similar but indicates a soft dependency; failure of the wanted service does not automatically prevent startup, but the service manager might log warnings.

Leveraging After= for Precise Timing

To run after network initialization, we need to identify the relevant networking services. On Debian-based systems, this typically involves services like networking.service, resolvconf.service, and potentially others depending on your specific network configuration. These vary slightly between versions. For Buster you might target networking services more directly, while Bookworm and Trixie offer more refined targets.

Crafting the Systemd Service File

Let’s construct the service file (/etc/systemd/system/my-service.service) for our specific needs. This example presumes your service executable is located at /usr/local/bin/my-service-script. Remember to adjust the paths accordingly.

[Unit]
Description=My Post-Network Service
After=network-online.target
After=sysinit.target
After=getty@tty1.service  ; Adjust for your tty if different
Before=getty.target
Requires=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/my-service-script
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Detailed Breakdown of the Unit Section

  • Description=: A human-readable description of the service.
  • After=network-online.target: Ensures the service starts after the network is fully online. This target is the common end point for various networking service starts across all our target Debian releases.
  • After=sysinit.target: Ensures the service starts after basic system initialization is complete. This is a very general target to make sure that system resources are generally stable.
  • After=getty@tty1.service: Crucial for correct ordering, this ensures the service runs after the getty process for the primary terminal (tty1, adjust if needed). This prevents conflicts with the login process.
  • Before=getty.target: This directive prevents the login screen from appearing until our service completes. This ensures our service runs to completion before the user can log in.
  • Requires=network-online.target: This creates a hard dependency on network availability. The service will fail to start if the network is unavailable.
  • Wants=network-online.target: Similar to Requires, adds a secondary validation check on network readiness.

Dissecting the Service Section

  • Type=oneshot: Specifies that the service runs only once and then exits. This is appropriate for tasks that only need to run before login.
  • ExecStart=/usr/local/bin/my-service-script: The path to the script or executable your service runs. Ensure the script is executable (chmod +x /usr/local/bin/my-service-script).
  • RemainAfterExit=yes: This is critical. It prevents systemd from immediately shutting down the service after it exits. This ensures systemd waits for the service completion before proceeding to the next step which is the login screen.

Understanding the Install Section

  • WantedBy=multi-user.target: This ensures the service is started when the system enters multi-user mode, which happens before the login screen.

Implementing the Service Script

The /usr/local/bin/my-service-script needs to perform your desired task. This script must be designed to gracefully exit, signalling completion to systemd. A simple example in Bash:

#!/bin/bash

# Your service logic here...
echo "Starting my service..."
# Perform Network-dependent operations
sleep 10  # Simulate some work;  Replace this
echo "My service completed."
exit 0

Remember to make this script executable using chmod +x /usr/local/bin/my-service-script.

Enabling and Testing the Service

After creating and saving the service file, enable and start it using the following commands:

sudo systemctl enable my-service.service
sudo systemctl start my-service.service
sudo systemctl status my-service.service  # Check status

The status command provides detailed information about the service, including any errors that might have occurred. Careful examination of the logs (journalctl -u my-service.service) is crucial for debugging.

Handling Potential Issues and Troubleshooting

Several issues might arise. Check your service file carefully for typos and ensure all paths are correct. Inconsistent behaviour across different Debian versions could be due to subtle differences in the provided targets. If necessary, experiment with different After= and Before= directives, relying heavily on journalctl logs to diagnose problems. Always consult the systemd documentation for further insight.

Advanced Configuration Options

For more complex scenarios, consider exploring advanced systemd features like:

  • TimeoutStartSec=: Sets a timeout for the service to start.
  • Restart=: Configures automatic restarts on failure.
  • User= and Group=: Specifies the user and group to run the service under, for security.

This comprehensive guide provides a robust foundation for deploying a systemd service that runs precisely after networking but before the login screen, regardless of the Debian version you’re using. By meticulously following these steps and diligently troubleshooting, you can reliably integrate your service into the boot process. Remember, consistently monitoring logs is paramount to ensuring your service’s smooth operation.