Files
webmin/systemd/set_linger.cgi
Ilia Ross d94000afbd Add Systemd Services and Units module
This PR adds a standalone Systemd Services and Units module for managing systemd units across system and user scopes.

The module keeps systemd-specific behavior separate from the legacy Bootup and Shutdown module and is implemented as standalone `strict`/`warnings` Perl code rather than depending on its existing init helpers. Those helpers intentionally smooth over multiple init systems, while this module keeps systemd-specific file handling, user-manager behavior, ACL checks, and control operations explicit, scoped, and easier to audit.

It includes:

- Tabbed views for services, timers, sockets, paths, targets, storage, resources, devices, and user units
- Guided creation and editing for common unit types, with contextual fields, validation, and help
- User-scoped unit management with linger support and safe handling of home-directory unit files
- Runtime actions for start, stop, restart, enable, disable, status, logs, properties, dependencies, and system-unit mask/unmask
- Drop-in override inventory plus create, edit, and delete flows
- Manual unit-file editing with daemon reload reminders and actions
- Configurable module behavior, visible tabs, display options, and post-create navigation
- Comprehensive ACL controls for system/user scopes, actions, manual edits, drop-ins, linger, reload, backup, and user filters
- Safe Webmin user support through a scoped safe ACL preset
- Virtualmin integration for granting domain owners access to their own systemd user units
- Tests for unit generation, safety checks, ACL behavior, user-unit handling, backup coverage, and Perl::Critic compatibility

A companion Virtualmin PR adds template integration so domain owners can be granted scoped access to their own systemd user units when this module is installed.
2026-06-12 20:55:28 +02:00

51 lines
1.5 KiB
Perl
Executable File

#!/usr/local/bin/perl
# Toggle linger for a systemd user manager
use strict;
use warnings;
require './systemd-lib.pl'; ## no critic
our (%access, %in, %text);
# This page is reached from the index linger toggle links.
error_setup($text{'systemd_linger_err'});
ReadParse();
# Validate the requested user and linger state before calling loginctl.
my $user = clean_unit_value($in{'user'});
my $enabled = $in{'enabled'};
get_user_details($user) || error($text{'systemd_euser'});
systemd_can_linger(\%access, $user) || systemd_acl_error('plinger');
if (!defined($enabled) || $enabled !~ /^[01]$/) {
error($text{'systemd_elinger'});
}
# Apply the requested linger state through loginctl.
my ($ok, $out) = set_user_linger($user, $enabled);
$ok || error_linger_command($user, $out);
# Enabling linger should also bring up the user manager immediately.
if ($enabled) {
($ok, $out) = start_user_manager($user);
$ok || error_linger_command($user, $out);
}
# Record the change and return to the User units tab for the same owner.
webmin_log("linger", "systemd-user", $user,
{ 'user' => $user, 'enabled' => $enabled });
redirect(index_url(undef, 1, $user));
# error_linger_command(user, output)
# Shows escaped loginctl or systemctl output from a failed operation.
sub error_linger_command
{
my ($user, $out) = @_;
$out ||= $text{'systemd_euser'};
# Show command output as escaped preformatted text for easier diagnosis.
error(text('systemd_eusercmd',
ui_tag('tt', html_escape($user)),
ui_tag('pre', html_escape($out))));
}