HEX
Server: Apache
System: Linux vps-cdc32557.vps.ovh.ca 5.15.0-156-generic #166-Ubuntu SMP Sat Aug 9 00:02:46 UTC 2025 x86_64
User: hanode (1017)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //usr/share/perl5/Virtualmin/Config/Plugin/Virtualmin.pm
package Virtualmin::Config::Plugin::Virtualmin;
use strict;
use warnings;
no warnings qw(once);
no warnings 'uninitialized';
use parent 'Virtualmin::Config::Plugin';

our $config_directory;
our (%gconfig, %miniserv);
our (%config, $module_config_file);
our $trust_unknown_referers = 1;

sub new {
  my ($class, %args) = @_;

  # inherit from Plugin
  my $self
    = $class->SUPER::new(name => 'Virtualmin', depends => ['Usermin'], %args);

  return $self;
}

# actions method performs whatever configuration is needed for this
# plugin. XXX Needs to make a backup so changes can be reverted.
sub actions {
  my $self = shift;

  use Cwd;
  my $cwd  = getcwd();
  my $root = $self->root();
  chdir($root);
  $0 = "$root/virtual-server/config-system.pl";
  push(@INC, $root);
  push(@INC, "$root/vendor_perl");
  eval 'use WebminCore';    ## no critic
  init_config();

  $self->spin();
  eval {
    foreign_require("virtual-server");
    $virtual_server::config{'mail_system'}          = 0;
    $virtual_server::config{'nopostfix_extra_user'} = 1;
    $virtual_server::config{'aliascopy'}            = 1;
    $virtual_server::config{'home_base'}            = "/home";
    $virtual_server::config{'webalizer'}            = 0;

    # XXX If not run as part of bundle, it'll skip doing these mail-related configs, which is maybe sub-optimal
    if (defined $self->bundle() &&
        ($self->bundle() eq "MiniLEMP" ||
         $self->bundle() eq "MiniLAMP"))
    {
      $virtual_server::config{'spam'}       = 0;
      $virtual_server::config{'virus'}      = 0;
      $virtual_server::config{'postgresql'} = 0;
    }
    elsif (defined $self->bundle()) {
      $virtual_server::config{'spam'}       = 1;
      $virtual_server::config{'virus'}      = 1;
      $virtual_server::config{'postgresql'} = 1;
    }
    $virtual_server::config{'ftp'}              = 0;
    $virtual_server::config{'logrotate'}        = 3;
    $virtual_server::config{'default_procmail'} = 1;
    $virtual_server::config{'bind_spfall'}      = 0;
    $virtual_server::config{'bind_spf'}         = "yes";
    $virtual_server::config{'spam_delivery'}    = "\$HOME/Maildir/.spam/";
    $virtual_server::config{'bccs'}             = 1;
    $virtual_server::config{'reseller_theme'}   = "authentic-theme";
    $virtual_server::config{'append_style'}     = 6;

    if ($self->bundle() eq "LEMP" || $self->bundle() eq "MiniLEMP") {
      $virtual_server::config{'ssl'}                = 0;
      $virtual_server::config{'web'}                = 0;
      $virtual_server::config{'backup_feature_ssl'} = 0;
    }
    elsif (defined $self->bundle()) {
      $virtual_server::config{'ssl'} = 3;
    }
    if (!defined($virtual_server::config{'plugins'})) {
      # Enable extra default modules
      $virtual_server::config{'plugins'} = 'virtualmin-awstats virtualmin-htpasswd';
    }
    if (-e "/etc/debian_version" || -e "/etc/lsb-release") {
      $virtual_server::config{'proftpd_config'}
        = 'ServerName ${DOM}	<Anonymous ${HOME}/ftp>	User ftp	Group nogroup	UserAlias anonymous ftp	<Limit WRITE>	DenyAll	</Limit>	RequireValidShell off	</Anonymous>';
    }

    # Make the Virtualmin web directories a bit more secure
    # FreeBSD has a low secondary groups limit..skip this bit.
    # XXX ACLs can reportedly deal with this...needs research.
    unless ($gconfig{'os_type'} eq 'freebsd') {
      if (defined(getpwnam("www-data"))) {
        $virtual_server::config{'web_user'} = "www-data";
      }
      else {
        $virtual_server::config{'web_user'} = "apache";
      }
      $virtual_server::config{'html_perms'} = "0750";
    }

    # Always force PHP-FPM mode
    $virtual_server::config{'php_suexec'} = 3;

    # If system doesn't have Jailkit support, disable it
    if (!has_command('jk_init')) {
      $virtual_server::config{'jailkit_disabled'} = 1;
    }

    # If system doesn't have AWStats support, disable it
    if (foreign_check("virtualmin-awstats")) {
      my %awstats_config = foreign_config("virtualmin-awstats");
      if ($awstats_config{'awstats'} && !-r $awstats_config{'awstats'}) {
        my @plugins = split(/\s/, $virtual_server::config{'plugins'});
        @plugins = grep { $_ ne 'virtualmin-awstats' } @plugins;
        $virtual_server::config{'plugins'} = join(' ', @plugins);
      }
    }

    # Enable DKIM at install time
    if (-r "/etc/opendkim.conf") {
      my $dkim = virtual_server::get_dkim_config();
      if (ref($dkim) && !$dkim->{'enabled'}) {
        $dkim->{'selector'} = virtual_server::get_default_dkim_selector();
        $dkim->{'sign'} = 1;
        $dkim->{'enabled'} = 1;
        $dkim->{'extra'} = [ get_system_hostname() ];
        virtual_server::push_all_print();
        virtual_server::set_all_null_print();
        my $ok = virtual_server::enable_dkim($dkim, 1, 2048);
        virtual_server::pop_all_print();
        if ($ok) {
          $virtual_server::config{'dkim_enabled'} = 1;
        }
      }
    }

    # Try to request SSL certificate for the hostname
    if (defined($ENV{'VIRTUALMIN_INSTALL_TEMPDIR'}) &&
        !$virtual_server::config{'default_domain_ssl'} &&
        !$virtual_server::config{'wizard_run'})
    {
      my ($ok, $error) = virtual_server::setup_virtualmin_default_hostname_ssl();
      write_file_contents("$ENV{'VIRTUALMIN_INSTALL_TEMPDIR'}/virtualmin_ssl_host_status",
                          "SSL certificate request for the hostname : $ok : @{[html_strip($error)]}");
      if ($ok) {
        mkdir("$ENV{'VIRTUALMIN_INSTALL_TEMPDIR'}/virtualmin_ssl_host_success");
      }
      else {
        virtual_server::delete_virtualmin_default_hostname_ssl();
      }
    }

    # Save Virtualmin configuration after all changes are made
    lock_file($module_config_file);
    save_module_config(\%virtual_server::config);
    unlock_file($module_config_file);

    # Configure the Read User Mail module to look for sub-folders
    # under ~/Maildir
    my %mconfig = foreign_config("mailboxes");
    $mconfig{'mail_usermin'}    = "Maildir";
    $mconfig{'from_virtualmin'} = 1;
    save_module_config(\%mconfig, "mailboxes");

    # Setup the Usermin read mail module
    foreign_require("usermin", "usermin-lib.pl");
    my $cfile = "$usermin::config{'usermin_dir'}/mailbox/config";
    my %mailconfig;
    read_file($cfile, \%mailconfig);
    foreign_require("postfix", "postfix-lib.pl");
    my ($map)
      = postfix::get_maps_files(
      postfix::get_real_value($postfix::virtual_maps));
    $map ||= "/etc/postfix/virtual";
    $mailconfig{'from_map'}         = $map;
    $mailconfig{'from_format'}      = 1;
    $mailconfig{'mail_system'}      = 4;
    $mailconfig{'pop3_server'}      = 'localhost';
    $mailconfig{'mail_qmail'}       = undef;
    $mailconfig{'mail_dir_qmail'}   = 'Maildir';
    $mailconfig{'server_attach'}    = 0;
    $mailconfig{'send_mode'}        = 'localhost';
    $mailconfig{'nologout'}         = 1;
    $mailconfig{'noindex_hostname'} = 1;
    $mailconfig{'edit_from'}        = 0;
    write_file($cfile, \%mailconfig);

    # Set the mail folders subdir to Maildir
    my $ucfile = "$usermin::config{'usermin_dir'}/mailbox/uconfig";
    my %umailconfig;
    read_file($ucfile, \%umailconfig);
    $umailconfig{'mailbox_dir'} = 'Maildir';
    $umailconfig{'view_html'}   = 2;
    $umailconfig{'view_images'} = 1;

    # Configure the Usermin Mailbox module to display buttons on the top too
    $umailconfig{'top_buttons'} = 2;

    # Configure the Usermin Mailbox module not to display send buttons twice
    $umailconfig{'send_buttons'} = 0;

    # Configure the Usermin Mailbox module to always start with one attachment for type
    $umailconfig{'def_attach'} = 1;

    # Default mailbox name for Sent mail
    $umailconfig{'sent_name'} = 'Sent';
    write_file($ucfile, \%umailconfig);

    # Set the default Usermin ACL to only allow access to email modules
    usermin::save_usermin_acl(
      "user",
      [
        "mailbox",  "changepass", "spam",    "filter",
        "language", "forward",    "cron",    "fetchmail",
        "updown",   "schedule",   "filemin", "gnupg"
      ]
    );

    # Update user.acl
    my $afile = "$usermin::config{'usermin_dir'}/user.acl";
    my %uacl;
    read_file($afile, \%uacl);
    $uacl{'root'} = '';
    write_file($afile, \%uacl);

    # Configure the Usermin Change Password module to use Virtualmin's
    # change-password.pl script
    $cfile = "$usermin::config{'usermin_dir'}/changepass/config";
    my %cpconfig;
    read_file($cfile, \%cpconfig);
    $cpconfig{'passwd_cmd'}
      = $config_directory eq "/etc/webmin"
      ? "$root/virtual-server/change-password.pl"
      : "virtualmin change-password";
    $cpconfig{'cmd_mode'} = 1;
    write_file($cfile, \%cpconfig);

    # Also do the same thing for expired password changes
    $cfile = "$usermin::config{'usermin_dir'}/config";
    my %umconfig;
    read_file($cfile, \%umconfig);
    $umconfig{'passwd_cmd'} = "$root/virtual-server/change-password.pl";
    write_file($cfile, \%umconfig);

    # Configure the Usermin Filter module to use the right path for
    # Webmin config files. The defaults are incorrect on FreeBSD, where
    # we install under /usr/local/etc/webmin
    $cfile = "$usermin::config{'usermin_dir'}/filter/config";
    my %ficonfig;
    read_file($cfile, \%ficonfig);
    $ficonfig{'virtualmin_config'} = "$config_directory/virtual-server";
    $ficonfig{'virtualmin_spam'}
      = "$config_directory/virtual-server/lookup-domain.pl";
    write_file($cfile, \%ficonfig);

    # Same for Usermin custom commands
    $cfile = "$usermin::config{'usermin_dir'}/commands/config";
    my %ccconfig;
    read_file($cfile, \%ccconfig);
    $ccconfig{'webmin_config'} = "$config_directory/custom";
    write_file($cfile, \%ccconfig);

    # Same for Usermin .htaccess files
    $cfile = "$usermin::config{'usermin_dir'}/htaccess/config";
    my %htconfig;
    read_file($cfile, \%htconfig);
    $htconfig{'webmin_apache'} = "$config_directory/apache";
    write_file($cfile, \%htconfig);

    # Setup the Apache, BIND and DB modules to use tables for lists
    foreach my $t (
      ['apache',     'show_list'],
      ['bind8',      'show_list'],
      ['mysql',      'style'],
      ['postgresql', 'style']
      )
    {
      my %mconfig = foreign_config($t->[0]);
      $mconfig{$t->[1]} = 1;
      save_module_config(\%mconfig, $t->[0]);
    }

    # Make the default home directory permissions 750
    my %uconfig = foreign_config("useradmin");
    if ($gconfig{'os_type'} eq 'freebsd') {
      $uconfig{'homedir_perms'} = "0751";
    }
    else { $uconfig{'homedir_perms'} = "0750"; }
    save_module_config(\%uconfig, "useradmin");

    # Turn on caching for downloads by Virtualmin
    if (!$gconfig{'cache_size'}) {
      $gconfig{'cache_size'} = 50 * 1024 * 1024;
      $gconfig{'cache_mods'} = "virtual-server";
      write_file("$config_directory/config", \%gconfig);
    }

    # Fix to extend Jailkit [basicshell] paths
    if (has_command('jk_init') && foreign_check('jailkit')) {
      foreign_require('jailkit');
      my $jk_init_conf        = &jailkit::get_jk_init_ini();
      my $jk_basicshell_paths = $jk_init_conf->val('basicshell', 'paths');
      my @jk_basicshell_paths = split(/\s*,\s*/, $jk_basicshell_paths);
      my @jk_params           = (
        ['zsh', '/etc/zsh/zshrc', '/etc/zsh/zshenv'],
        ['rbash'], ['id', 'groups'],
      );

    JKPARAMS:
      foreach my $jk_params (@jk_params) {
        foreach my $jk_param (@{$jk_params}) {
          if (grep(/^$jk_param$/, @jk_basicshell_paths)) {
            next JKPARAMS;
          }
        }
        $jk_basicshell_paths .= ", @{[join(', ', @{$jk_params})]}";
      }

      $jk_init_conf->newval('basicshell', 'paths', $jk_basicshell_paths);
      &jailkit::write_jk_init_ini($jk_init_conf);
    }

    # Disable and stop certbot timer
    if (has_command('certbot')) {
      foreign_require('init', 'init-lib.pl');

      # Unit name is differnet on different distros
      my @certbot_units = ('certbot-renew.timer', 'certbot.timer');
      foreach my $certbot_unit (@certbot_units) {
        if (init::is_systemd_service($certbot_unit)) {
          init::disable_at_boot($certbot_unit);
          init::stop_action($certbot_unit);
          if (defined(&init::mask_action)) {
            init::mask_action($certbot_unit);
          }
        }
      }
    }

    # Terminal on the new installs
    # is allowed to have colors on
    if (&foreign_check('xterm')) {
      my %xterm_config = foreign_config("xterm");
      $xterm_config{'rcfile'} = 1;
      save_module_config(\%xterm_config, "xterm");
    }

    # Add PHP alias so users could execute
    # specific to virtual server PHP version
    my $profiled = "/etc/profile.d";
    if (-d $profiled) {
      my $profiledphpalias = "$profiled/virtualmin-phpalias.sh";
      my $phpalias
        = "php=\`which php 2>/dev/null\`\n"
        . "if \[ -x \"\$php\" \]; then\n"
        . "  alias php='\$\(phpdom=\"bin/php\" ; \(while [ ! -f \"\$phpdom\" ] && [ \"\$PWD\" != \"/\" ]; do cd \"\$\(dirname \"\$PWD\"\)\" || \"\$php\" ; done ; if [ -f \"\$phpdom\" ] ; then echo \"\$PWD/\$phpdom\" ; else echo \"\$php\" ; fi\)\)'\n"
        . "fi\n";
      write_file_contents($profiledphpalias, $phpalias);
    }

    # OpenSUSE PHP related fixes
    if ($gconfig{'os_type'} eq "suse-linux") {
      system("mv /etc/php8/fpm/php-fpm.conf.default /etc/php8/fpm/php-fpm.conf >/dev/null 2>&1");
    }

    # Disable mod_php in package managers
    if ($gconfig{'os_type'} =~ /debian-linux|ubuntu-linux/) {
      # Disable libapache2-mod-php* in Ubuntu/Debian
      my $fpref = $gconfig{'real_os_type'} =~ /ubuntu/i ? 'ubuntu' : 'debian';
      my $apt_pref_dir = "/etc/apt/preferences.d";
      # Create a file to restrict libapache2-mod-php* packages
      $self->logsystem(
        "echo \"Package: libapache2-mod-php*\nPin: release *\nPin-Priority: -1\" > ".
          "$apt_pref_dir/$fpref-virtualmin-restricted-packages");
    } else {
      # Disable php and php*-php in RHEL and derivatives
      my $dnf_conf = "/etc/dnf/dnf.conf";
      if (-f $dnf_conf) {
        lock_file($dnf_conf);
        my $lref = read_file_lines($dnf_conf);
        my $lnum;
        foreach my $i (0 .. $#$lref) {
          # If main section is found
          if ($lref->[$i] =~ /^\[main\]/) {
              $lnum = $i;
          }
          # If exclude= line is found, don't add another one
          if ($lref->[$i] =~ /^exclude=/) {
              $lnum = undef;
          }
        }
        # Add exclude= line if it's not
        # found right after [main]
        if (defined($lnum)) {
          $lref->[$lnum] .= "\nexclude=php php*-php";
        }
        flush_file_lines($dnf_conf);
        unlock_file($dnf_conf);
      }
    }

    $self->done(1);    # OK!
  };
  if ($@) {
    $self->done(0);
  }
}

1;