3 # This script should be run after the webmin archive is unpacked, in order
4 # to setup the various config files
9 # Find install directory
12 if ($0 =~ /^(.*)\//) {
16 $wadir =~ s/\\/\//g; # always use / separator on windows
18 open(VERSION, "$wadir/version") ||
19 &errorexit("Cannot find the Webmin install directory");
20 chop($ver = <VERSION>);
23 print "***********************************************************************\n";
24 print "* Welcome to the Webmin setup script, version $ver *\n";
25 print "***********************************************************************\n";
26 print "Webmin is a web-based interface that allows Unix-like operating\n";
27 print "systems and common Unix services to be easily administered.\n";
30 # Only root can run this
32 &errorexit("The Webmin install script must be run as root");
35 # Use the supplied destination directory, if any
38 $wadir =~ s/\\/\//g; # always use / separator on windows
39 print "Installing Webmin from $srcdir to $wadir ...\n";
41 mkdir($wadir, 0755) || &errorexit("Failed to create $wadir");
44 # Make sure dest dir is not in use
45 @files = grep { !/rpmsave/ } &files_in_dir($wadir);
46 if (@files && !-r "$wadir/setup.pl") {
47 &errorexit("Installation directory $wadir contains other files");
52 print "Installing Webmin in $wadir ...\n"
55 # Work out perl library path
56 $ENV{'PERLLIB'} = $wadir;
57 if ($ENV{'perllib'}) {
58 $ENV{'PERLLIB'} .= ":".$ENV{'perllib'};
61 # Validate source directory
62 @allmods = map { s/\/module.info$//; $_ } glob("*/module.info");
64 &errorexit("ERROR: Failed to get module list");
66 $allmods = join(" ", @allmods);
71 # Load package-defined variable overrides
72 if (-r "$srcdir/setup-pre.pl") {
73 require "$srcdir/setup-pre.pl";
76 # Ask for webmin config directory
77 print "***********************************************************************\n";
78 print "Webmin uses separate directories for configuration files and log files.\n";
79 print "Unless you want to run multiple versions of Webmin at the same time\n";
80 print "you can just accept the defaults.\n";
82 print "Config file directory [/etc/webmin]: ";
83 if ($ENV{'config_directory'}) {
84 $config_directory = $ENV{'config_directory'};
87 chop($config_directory = <STDIN>);
89 $config_directory ||= "/etc/webmin";
90 $config_directory =~ s/\\/\//g;
91 if ($config_directory !~ /^([a-z]:)?\//i) {
92 &errorexit("Config directory must be an absolute path");
94 if (!-d $config_directory) {
95 mkdir($config_directory, 0755) ||
96 &errorexit("Failed to create directory $config_directory");
98 if (-r "$config_directory/config") {
99 print "Found existing Webmin configuration in $config_directory\n";
104 # We can now load the main Webmin library
105 $ENV{'WEBMIN_CONFIG'} = $config_directory;
106 $ENV{'WEBMIN_VAR'} = "/var/webmin"; # not really used
107 require "$wadir/web-lib.pl";
109 # Check if upgrading from an old version
113 # Get current var path
114 open(VAR, "$config_directory/var-path");
115 chop($var_dir = <VAR>);
116 $var_directory = $var_dir;
119 # Force creation if non-existant
120 mkdir($var_dir, 0755);
122 # Get current perl path
123 $perl = &get_perl_path();
125 # Get old os name and version
126 &read_file("$config_directory/config", \%gconfig);
127 $os_type = $gconfig{'os_type'};
128 $os_version = $gconfig{'os_version'};
129 $real_os_type = $gconfig{'real_os_type'};
130 $real_os_version = $gconfig{'real_os_version'};
131 &get_miniserv_config(\%miniserv);
132 $oldwadir = $miniserv{'root'};
133 $path_separator = $gconfig{'os_type'} eq 'windows' ? ';' : ':';
135 if (!$miniserv{'inetd'}) {
137 if ($os_type eq "windows") {
138 system("$config_directory/stop.bat >/dev/null 2>&1");
141 system("$config_directory/stop >/dev/null 2>&1");
145 # Copy files to target directory
149 system("$perl "."e_path("$wadir/newmods.pl")." $config_directory $allmods");
151 # Update miniserv.conf with new root directory and mime types file
152 $miniserv{'root'} = $wadir;
153 $miniserv{'mimetypes'} = "$wadir/mime.types";
154 &put_miniserv_config(\%miniserv);
156 # Check for third-party modules in old version
157 if ($wadir ne $oldwadir) {
158 print "Checking for third-party modules ..\n";
159 if ($ENV{'webmin_upgrade"'}) {
162 system("$perl "."e_path("$wadir/thirdparty.pl")." "."e_path($wadir)." "."e_path($oldwadir)." $autothird");
167 # Remove old cache of module infos
168 unlink("$config_directory/module.infos.cache");
171 # Config directory exists .. make sure it is not in use
172 @files = grep { !/rpmsave/ } &files_in_dir($config_directory);
173 if (@files && $config_directory ne "/etc/webmin") {
174 &errorexit("Config directory $config_directory is not empty");
177 # Ask for log directory
178 print "Log file directory [/var/webmin]: ";
179 if ($ENV{'var_dir'}) {
180 $var_dir = $ENV{'var_dir'};
183 chop($var_dir = <STDIN>);
185 $var_dir ||= "/var/webmin";
186 $var_dir =~ s/\\/\//g;
187 $var_directory = $var_dir;
188 if ($var_dir !~ /^([a-z]:)?\//i) {
189 &errorexit("Log file directory must be an absolute path");
191 if ($var_dir eq "/" || $var_dir =~ /^[a-z]:\/$/) {
192 &errorexit("Log directory cannot be /");
195 mkdir($var_dir, 0755) ||
196 &errorexit("Failed to create directory $var_dir");
200 # No need to ask where Perl is, because we already have it!
201 $perl = &has_command($^X) || $^X;
203 &errorexit("Failed to find Perl at $perl");
206 &errorexit("Detected old perl version. Webmin requires perl 5.002 or better to run");
208 print "Perl seems to be installed ok\n";
211 # Ask for operating system type
212 print "***********************************************************************\n";
213 $autoos = $ENV{'autoos'} || 2;
215 $ex = system("$perl "."e_path("$srcdir/oschooser.pl")." "."e_path("$srcdir/os_list.txt")." $temp $autoos");
217 &read_env_file($temp, \%osinfo);
218 $os_type = $osinfo{'os_type'};
219 $os_version = $osinfo{'os_version'};
220 $real_os_type = $osinfo{'real_os_type'};
221 $real_os_version = $osinfo{'real_os_version'};
222 $gconfig{'os_type'} = $os_type;
223 $gconfig{'os_version'} = $os_version;
224 $gconfig{'real_os_type'} = $real_os_type;
225 $gconfig{'real_os_version'} = $real_os_version;
226 $path_separator = $gconfig{'os_type'} eq 'windows' ? ';' : ':';
228 print "Operating system name: $real_os_type\n";
229 print "Operating system version: $real_os_version\n";
232 if ($os_type eq "windows") {
233 # Check Windows dependencies
234 if (!&has_command("process.exe")) {
235 &errorexit("The command process.exe must be installed to run Webmin on Windows");
237 eval "use Win32::Daemon";
239 &errorexit("The Perl module Win32::Daemon must be installed to run Webmin on Windows");
243 # Ask for web server port, name and password
244 print "***********************************************************************\n";
245 print "Webmin uses its own password protected web server to provide access\n";
246 print "to the administration programs. The setup script needs to know :\n";
247 print " - What port to run the web server on. There must not be another\n";
248 print " web server already using this port.\n";
249 print " - The login name required to access the web server.\n";
250 print " - The password required to access the web server.\n";
251 print " - If the webserver should use SSL (if your system supports it).\n";
252 print " - Whether to start webmin at boot time.\n";
254 print "Web server port (default 10000): ";
256 $port = $ENV{'port'};
259 chop($port = <STDIN>);
262 if ($port < 1 || $port > 65535) {
263 &errorexit("$port is not a valid port number");
265 socket(FOO, PF_INET, SOCK_STREAM, getprotobyname("tcp"));
266 setsockopt(FOO, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
267 bind(FOO, pack_sockaddr_in($port, INADDR_ANY)) ||
268 &errorexit("TCP port $port is already in use by another program");
271 print "Login name (default admin): ";
273 $login = $ENV{'login'};
276 chop($login = <STDIN>);
280 &errorexit("Username contains a : character");
282 if ($login =~ /\s/) {
283 &errorexit("Username contains a space");
285 if ($login eq "webmin") {
286 &errorexit("Username 'webmin' is reserved for internal use");
288 print "Login password: ";
289 if ($ENV{'password'}) {
290 $password = $ENV{'password'};
292 elsif ($ENV{'crypt'}) {
293 $crypt = $ENV{'crypt'};
296 chop($password = <STDIN>);
297 print "Password again: ";
298 chop($password2 = <STDIN>);
299 if ($password ne $password2) {
300 &errorexit("Passwords don't match");
302 if ($password =~ /:/) {
303 &errorexit("Password contains a : character");
307 # Ask the user if SSL should be used
308 if ($ENV{'ssl'} ne '') {
313 eval "use Net::SSLeay";
315 print "Use SSL (y/n): ";
316 chop($sslyn = <STDIN>);
317 if ($sslyn =~ /^y/i) {
322 print "The Perl SSLeay library is not installed. SSL not available.\n"
326 # Don't use SSL if missing Net::SSLeay
328 eval "use Net::SSLeay";
334 # Ask whether to run at boot time
335 if ($ENV{'atboot'}) {
336 $atboot = $ENV{'atboot'};
340 print "Start Webmin at boot time (y/n): ";
341 chop($atbootyn = <STDIN>);
342 if ($atbootyn =~ /^y/i) {
348 # Copy files to target directory
349 print "***********************************************************************\n";
352 # Create webserver config file
353 open(PERL, ">$config_directory/perl-path");
354 print PERL $perl,"\n";
356 open(VAR, ">$config_directory/var-path");
357 print VAR $var_dir,"\n";
360 print "Creating web server config files..";
361 $ufile = "$config_directory/miniserv.users";
362 $kfile = "$config_directory/miniserv.pem";
363 %miniserv = ( 'port' => $port,
365 'mimetypes' => "$wadir/mime.types",
366 'addtype_cgi' => 'internal/cgi',
367 'realm' => 'Webmin Server',
368 'logfile' => "$var_dir/miniserv.log",
369 'errorlog' => "$var_dir/miniserv.error",
370 'pidfile' => "$var_dir/miniserv.pid",
374 'env_WEBMIN_CONFIG' => $config_directory,
375 'env_WEBMIN_VAR' => $var_dir,
377 'logout' => "$config_directory/logout-flag",
379 'denyfile' => "\\.pl\$",
381 'blockhost_failures' => 5,
382 'blockhost_time' => 60,
383 'syslog' => $os_type eq 'windows' ? 0 : 1,
384 'userfile' => $ufile,
386 'preload' => 'main=web-lib-funcs.pl',
389 $miniserv{'allow'} = $ENV{'allow'};
391 if ($ENV{'session'} eq '') {
392 $miniserv{'session'} = $os_type eq 'windows' ? 0 : 1;
395 $miniserv{'session'} = $ENV{'session'};
397 if ($os_type eq 'windows') {
398 $miniserv{'no_pam'} = 1;
400 elsif ($ENV{'pam'}) {
401 $miniserv{'pam'} = $ENV{'pam'};
403 if ($os_type eq 'windows') {
404 $miniserv{'nofork'} = 1;
405 $miniserv{'restartflag'} = "$var_dir/restart.flag";
406 $miniserv{'reloadflag'} = "$var_dir/reload.flag";
407 $miniserv{'forkcgis'} = 1; # Avoid memory leaks
409 &put_miniserv_config(\%miniserv);
411 # Test MD5 password encryption
412 if (&unix_crypt("test", "\\$1\\$A9wB3O18\\$zaZgqrEmb9VNltWTL454R/") eq "\\$1\\$A9wB3O18\\$zaZgqrEmb9VNltWTL454R/") {
417 open(UFILE, ">$ufile");
419 print UFILE "$login:$crypt:0\n";
422 print UFILE $login,":",&unix_crypt($password, "\$1\$XXXXXXXX"),"\n";
425 print UFILE $login,":",&unix_crypt($password, "XX"),"\n";
431 if (system("openssl version >/dev/null 2>&1") == 0) {
432 # We can generate a new SSL key for this host
433 $host = &get_system_hostname();
436 open(SSL, "| openssl req -newkey rsa:512 -x509 -nodes -out $cert -keyout $key -days 1825 >/dev/null 2>&1");
440 print SSL "Webmin Webserver on $host\n";
443 print SSL "root\@$host\n";
448 open(OUT, ">$kfile");
462 # Fall back to the built-in key
463 ©_source_dest("$wadir/miniserv.pem", $kfile);
469 print "Creating access control file..\n";
470 $afile = "$config_directory/webmin.acl";
471 open(AFILE, ">$afile");
472 if ($ENV{'defaultmods'}) {
473 print AFILE "$login: $ENV{'defaultmods'}\n";
476 print AFILE "$login: $allmods\n";
483 if ($login ne "root" && $login ne "admin") {
484 # Allow use of RPC by this user
485 open(ACL, ">$config_directory/$login.acl");
491 if (!$ENV{'noperlpath"'} && $os_type ne 'windows') {
492 print "Inserting path to perl into scripts..\n";
493 system("(find "."e_path($wadir)." -name '*.cgi' -print ; find "."e_path($wadir)." -name '*.pl' -print) | $perl "."e_path("$wadir/perlpath.pl")." $perl -");
498 print "Creating start and stop scripts..\n";
499 if ($os_type eq "windows") {
500 open(START, ">>$config_directory/start.bat");
501 print START "$perl \"$wadir/miniserv.pl\" $config_directory/miniserv.conf\n";
503 $start_cmd = "sc start ".($ENV{'bootscript'} || "webmin");
505 open(STOP, ">>$config_directory/stop.bat");
506 print STOP "echo Not implemented\n";
510 open(START, ">$config_directory/start");
511 print START "#!/bin/sh\n";
512 print START "echo Starting Webmin server in $wadir\n";
513 print START "trap '' 1\n";
514 print START "LANG=\n";
515 print START "export LANG\n";
516 print START "unset PERLIO\n";
517 print START "export PERLIO\n";
518 print START "PERLLIB=$perllib\n";
519 print START "export PERLLIB\n";
520 if ($os_type eq "hpux") {
521 print START "exec '$wadir/miniserv.pl' $config_directory/miniserv.conf &\n";
524 print START "exec '$wadir/miniserv.pl' $config_directory/miniserv.conf\n";
527 $start_cmd = "$config_directory/start";
529 open(STOP, ">$config_directory/stop");
530 print STOP "#!/bin/sh\n";
531 print STOP "echo Stopping Webmin server in $wadir\n";
532 print STOP "pidfile=\`grep \"^pidfile=\" $config_directory/miniserv.conf | sed -e 's/pidfile=//g'\`\n";
533 print STOP "kill \`cat \$pidfile\`\n";
536 open(RESTART, ">$config_directory/restart");
537 print RESTART "#!/bin/sh\n";
538 print RESTART "$config_directory/stop && $config_directory/start\n";
541 chmod(0755, "$config_directory/start", "$config_directory/stop",
542 "$config_directory/restart");
548 print "Updating config files..\n";
551 print "Copying config files..\n";
553 system("$perl "."e_path("$wadir/copyconfig.pl")." "."e_path("$os_type/$real_os_type")." "."e_path("$os_version/$real_os_version")." "."e_path($wadir)." ".$config_directory." \"\" ".$allmods);
555 # Store the OS and version
556 &read_file("$config_directory/config", \%gconfig);
557 $gconfig{'os_type'} = $os_type;
558 $gconfig{'os_version'} = $os_version;
559 $gconfig{'real_os_type'} = $real_os_type;
560 $gconfig{'real_os_version'} = $real_os_version;
562 &write_file("$config_directory/config", \%gconfig);
564 open(VER, ">$config_directory/version");
570 # Set passwd_ fields in miniserv.conf from global config
571 &get_miniserv_config(\%miniserv);
572 foreach $field ("passwd_file", "passwd_uindex", "passwd_pindex", "passwd_cindex", "passwd_mindex") {
573 if ($gconfig{$field}) {
574 $miniserv{$field} = $gconfig{$field};
577 if (!defined($miniserv{'passwd_mode'})) {
578 $miniserv{'passwd_mode'} = 0;
581 # If Perl crypt supports MD5, then make it the default
583 $gconfig{'md5pass'} = 1;
586 # Set a special theme if none was set before
588 $theme = $ENV{'theme'};
590 elsif (open(THEME, "$wadir/defaulttheme")) {
591 chop($theme = <THEME>);
594 if ($theme && -d "$wadir/$theme") {
595 $gconfig{'theme'} = $theme;
596 $miniserv{'preroot'} = $theme;
599 # Set the product field in the global config
600 $gconfig{'product'} ||= "webmin";
603 print "Configuring Webmin to start at boot time..\n";
604 chdir("$wadir/init");
605 system("$perl "."e_path("$wadir/init/atboot.pl")." ".$ENV{'bootscript'});
611 # If password delays are not specifically disabled, enable them
612 if (!defined($miniserv{'passdelay'}) && $os_type ne 'windows') {
613 $miniserv{'passdelay'} = 1;
617 &put_miniserv_config(\%miniserv);
618 &write_file("$config_directory/config", \%gconfig);
620 if (!$ENV{'nouninstall'} && $os_type ne "windows") {
621 print "Creating uninstall script $config_directory/uninstall.sh ..\n";
622 open(UN, ">$config_directory/uninstall.sh");
625 printf "Are you sure you want to uninstall Webmin? (y/n) : "
628 if [ "\$answer" = "y" ]; then
629 $config_directory/stop
630 echo "Running uninstall scripts .."
631 (cd "$wadir" ; WEBMIN_CONFIG=$config_directory WEBMIN_VAR=$var_dir LANG= "$wadir/run-uninstalls.pl")
632 echo "Deleting $wadir .."
634 echo "Deleting $config_directory .."
635 rm -rf "$config_directory"
639 chmod(0755, "$config_directory/uninstall.sh");
644 if ($os_type ne "windows") {
645 print "Changing ownership and permissions ..\n";
646 system("chown -R root $config_directory");
647 system("chgrp -R bin $config_directory");
648 system("chmod -R og-rw $config_directory");
649 system("chmod 755 $config_directory/{sendmail,qmailadmin,postfix}*/config >/dev/null 2>&1");
650 system("chmod 755 $config_directory/{sendmail,qmailadmin,postfix}*/autoreply.pl >/dev/null 2>&1");
651 system("chmod 755 $config_directory/{sendmail,qmailadmin,postfix}*/filter.pl >/dev/null 2>&1");
652 system("chmod 755 $config_directory/squid*/squid-auth.pl >/dev/null 2>&1");
653 system("chmod 755 $config_directory/squid*/users >/dev/null 2>&1");
654 system("chmod 755 $config_directory/cron*/range.pl >/dev/null 2>&1");
655 system("chmod +r $config_directory/version");
656 if (!$ENV{'nochown'}) {
657 system("chown -R root \"$wadir\"");
658 system("chgrp -R bin \"$wadir\"");
659 system("chmod -R og-w \"$wadir\"");
660 system("chmod -R a+rx \"$wadir\"");
662 if ($var_dir ne "/var") {
663 system("chown -R root $var_dir");
664 system("chgrp -R bin $var_dir");
665 system("chmod -R og-rwx $var_dir");
671 # Save target directory if one was specified
672 if ($wadir ne $srcdir) {
673 open(INSTALL, ">$config_directory/install-dir");
674 print INSTALL $wadir,"\n";
678 unlink("$config_directory/install-dir");
681 if (!$ENV{'nopostinstall'}) {
682 print "Running postinstall scripts ..\n";
684 system("$perl "."e_path("$wadir/run-postinstalls.pl"));
689 # Run package-defined post-install script
690 if (-r "$srcdir/setup-post.pl") {
691 require "$srcdir/setup-post.pl";
694 if (!$ENV{'nostart'}) {
695 if (!$miniserv{'inetd'}) {
696 print "Attempting to start Webmin mini web server..\n";
697 $ex = system($start_cmd);
699 &errorexit("Failed to start web server!");
705 print "***********************************************************************\n";
706 print "Webmin has been installed and started successfully. Use your web\n";
707 print "browser to go to\n";
709 $host = &get_system_hostname();
711 print " https://$host:$miniserv{'port'}/\n";
714 print " http://$host:$miniserv{'port'}/\n";
717 print "and login with the name and password you entered previously.\n";
720 print "Because Webmin uses SSL for encryption only, the certificate\n";
721 print "it uses is not signed by one of the recognized CAs such as\n";
722 print "Verisign. When you first connect to the Webmin server, your\n";
723 print "browser will ask you if you want to accept the certificate\n";
724 print "presented, as it does not recognize the CA. Say yes.\n";
729 if ($oldwadir ne $wadir && $upgrading && !$ENV{'deletedold'}) {
730 print "The directory from the previous version of Webmin\n";
731 print " $oldwadir\n";
732 print "Can now be safely deleted to free up disk space, assuming\n";
733 print "that all third-party modules have been copied to the new\n";
740 print "ERROR: ",@_,"\n";
747 if ($wadir ne $srcdir) {
748 print "Copying files to $wadir ..\n";
749 if (&has_command("tar")) {
751 system("cd "."e_path($srcdir)." && tar cf - . | (cd "."e_path($wadir)." ; tar xf -)");
754 # Looks like Windows .. use xcopy command
755 system("xcopy \"$srcdir\" \"$wadir\" /Y /E /I");
765 local @rv = grep { $_ ne "." && $_ ne ".." } readdir(DIR);