1#!/usr/bin/env perl 2#============================================================= -*-perl-*- 3# 4# configure.pl: Configuration and installation program for BackupPC 5# 6# DESCRIPTION 7# 8# This script should be run as root: 9# 10# perl configure.pl 11# 12# To read about the command-line options for this configure script: 13# 14# perldoc configure.pl 15# 16# The installation steps are described as the script runs. 17# 18# AUTHOR 19# Craig Barratt <cbarratt@users.sourceforge.net> 20# 21# COPYRIGHT 22# Copyright (C) 2001-2017 Craig Barratt 23# 24# This program is free software: you can redistribute it and/or modify 25# it under the terms of the GNU General Public License as published by 26# the Free Software Foundation, either version 3 of the License, or 27# (at your option) any later version. 28# 29# This program is distributed in the hope that it will be useful, 30# but WITHOUT ANY WARRANTY; without even the implied warranty of 31# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32# GNU General Public License for more details. 33# 34# You should have received a copy of the GNU General Public License 35# along with this program. If not, see <http://www.gnu.org/licenses/>. 36# 37#======================================================================== 38# 39# Version __VERSION__, released __RELEASEDATE__. 40# 41# See http://backuppc.sourceforge.net. 42# 43#======================================================================== 44 45use strict; 46no utf8; 47use vars qw(%Conf %OrigConf $Upgrade); 48use lib "./lib"; 49 50# 51# The two strings below are replaced with the full list of BackupPC executables 52# and libraries by makeDist. 53# 54my @ConfigureBinList = qw( 55 __CONFIGURE_BIN_LIST__ 56 ); 57my @ConfigureLibList = qw( 58 __CONFIGURE_LIB_LIST__ 59 ); 60 61# 62# Check that makeDist has been run; need to avoid having the magic string 63# appear exactly (otherwise makeDist will replace it), so compute it instead 64# 65if ( $ConfigureBinList[0] eq "__" . "CONFIGURE_BIN_LIST__" ) { 66 die <<EOF; 67You need to run makeDist first to create a tarball release that includes an 68updated configure.pl. After you unpack the tarball, run configure.pl from 69there. 70EOF 71} 72 73my @Packages = qw(version Encode Socket File::Path File::Spec File::Copy 74 Digest::MD5 Data::Dumper Getopt::Std Getopt::Long Pod::Usage 75 File::Listing CGI BackupPC::XS BackupPC::Lib); 76 77my $PackageVersion = { 78 "Encode" => "1.99", 79 "BackupPC::XS" => "0.53", 80 }; 81 82foreach my $pkg ( @Packages ) { 83 eval "use $pkg"; 84 if ( !$@ ) { 85 next if ( !defined($PackageVersion->{$pkg}) ); 86 my $ver = eval "\$${pkg}::VERSION"; 87 next if ( version->parse($ver) >= version->parse($PackageVersion->{$pkg}) ); 88 die <<EOF; 89 90Perl package $pkg needs to be at least version $PackageVersion->{$pkg}. 91The currently installed $pkg is version $ver. 92 93Please upgrade package $pkg to the latest version and then re-run 94this script. 95EOF 96 } 97 if ( $pkg =~ /BackupPC::Lib/ ) { 98 die <<EOF; 99 100Error loading $pkg: $@ 101BackupPC cannot load the package $pkg, which is included in the 102BackupPC distribution. This probably means you did not cd to the 103unpacked BackupPC distribution before running configure.pl, eg: 104 105 cd BackupPC-__VERSION__ 106 ./configure.pl 107 108Please try again. 109 110EOF 111 } 112 die <<EOF; 113 114BackupPC needs the perl package "$pkg". Please install "$pkg" 115(eg, using cpan) before installing BackupPC. 116 117EOF 118} 119 120my %opts; 121$opts{"set-perms"} = 1; 122if ( !GetOptions( 123 \%opts, 124 "batch", 125 "backuppc-user=s", 126 "bin-path=s%", 127 "cgi-dir=s", 128 "compress-level=i", 129 "config-path=s", 130 "config-override=s%", 131 "config-dir=s", 132 "config-only", 133 "data-dir=s", 134 "dest-dir=s", 135 "fhs!", 136 "help|?", 137 "hostname=s", 138 "html-dir=s", 139 "html-dir-url=s", 140 "install-dir=s", 141 "log-dir=s", 142 "man", 143 "run-dir=s", 144 "scgi-port=i", 145 "set-perms!", 146 "uid-ignore!", 147 ) || @ARGV ) { 148 pod2usage(2); 149} 150pod2usage(1) if ( $opts{help} ); 151pod2usage(-exitstatus => 0, -verbose => 2) if $opts{man}; 152 153my $DestDir = $opts{"dest-dir"}; 154$DestDir = "" if ( $DestDir eq "/" ); 155 156if ( !$opts{"uid-ignore"} && $< != 0 ) { 157 print <<EOF; 158 159This configure script should be run as root, rather than uid $<. 160Provided uid $< has sufficient permissions to create the data and 161install directories, then it should be ok to proceed. Otherwise, 162please quit and restart as root. 163 164EOF 165 exit(1) if ( prompt("--> Do you want to continue?", 166 "y") !~ /y/i ); 167 exit(1) if ( $opts{batch} && !$opts{"uid-ignore"} ); 168} 169 170# 171# Whether we use the file system hierarchy conventions or not. 172# Older versions did not. BackupPC used to be installed in 173# two main directories (in addition to CGI and html pages) 174# 175# TopDir which includes subdirs conf, log, pc, pool, cpool 176# 177# InstallDir which includes subdirs bin, lib, share/doc/BackupPC 178# 179# With FHS enabled (which is the default for new installations) 180# the config files move to /etc/BackupPC and log files to /var/log: 181# 182# /etc/BackupPC/config.pl main config file (was $TopDir/conf/config.pl) 183# /etc/BackupPC/hosts hosts file (was $TopDir/conf/hosts) 184# /etc/BackupPC/pc/HOST.pl per-pc config file (was $TopDir/pc/HOST/config.pl) 185# /var/log/BackupPC log files (was $TopDir/log) 186# /var/log/BackupPC Pid, status and email info (was $TopDir/log) 187# 188 189# 190# Check if this is an upgrade, in which case read the existing 191# config file to get all the defaults. 192# 193my $ConfigDir = $opts{"config-dir"} || "/etc/BackupPC"; 194my $ConfigPath = ""; 195my $ConfigFileOK = 1; 196while ( 1 ) { 197 if ( $ConfigFileOK && -f "$DestDir$ConfigDir/config.pl" 198 && (!defined($opts{fhs}) || $opts{fhs}) && !defined($opts{"config-path"}) ) { 199 $ConfigPath = "$ConfigDir/config.pl"; 200 $opts{fhs} = 1 if ( !defined($opts{fhs}) ); 201 print <<EOF; 202 203Found $DestDir$ConfigDir/config.pl, so this is an upgrade of an 204existing BackupPC installation. We will verify some existing 205information, but you will probably not need to make any 206changes - just hit ENTER to each question. 207EOF 208 } else { 209 print <<EOF; 210 211Is this a new installation or upgrade for BackupPC? If this is 212an upgrade please tell me the full path of the existing BackupPC 213configuration file (eg: $ConfigDir/config.pl). Otherwise, just 214hit return. 215 216EOF 217 $ConfigPath = prompt("--> Full path to existing main config.pl", 218 $ConfigPath, 219 "config-path"); 220 } 221 last if ( $ConfigPath eq "" 222 || ($ConfigPath =~ /^\// && -f "$DestDir$ConfigPath" && -w "$DestDir$ConfigPath") ); 223 my $problem = "is not an absolute path"; 224 $problem = "is not writable" if ( !-w $ConfigPath ); 225 $problem = "is not readable" if ( !-r $ConfigPath ); 226 $problem = "is not a regular file" if ( !-f $ConfigPath ); 227 $problem = "doesn't exist" if ( !-e $ConfigPath ); 228 print("The file '$DestDir$ConfigPath' $problem.\n"); 229 if ( $opts{batch} ) { 230 print("Need to specify a valid --config-path for upgrade\n"); 231 exit(1); 232 } 233 $ConfigFileOK = 0; 234} 235$opts{fhs} = 1 if ( !defined($opts{fhs}) && $ConfigPath eq "" ); 236 237my $bpc; 238if ( $ConfigPath ne "" && -r "$DestDir$ConfigPath" ) { 239 ($ConfigDir = $ConfigPath) =~ s{/[^/]+$}{}; 240 241 # In config-only mode use installed BackupPC if distribution files are not available. 242 my $libPath = ($opts{"config-only"} && ($INC{"BackupPC/Lib.pm"} ne "lib/BackupPC/Lib.pm")) 243 ? "" : "."; 244 245 die("BackupPC::Lib->new failed\n") 246 if ( !($bpc = BackupPC::Lib->new(".", $libPath, "$DestDir$ConfigDir", 1)) ); 247 %Conf = $bpc->Conf(); 248 %OrigConf = %Conf; 249 $Upgrade = 1; 250 if ( !defined($opts{fhs}) ) { 251 if ( $ConfigPath eq "$Conf{TopDir}/conf/config.pl" ) { 252 $opts{fhs} = 0; 253 } else { 254 $opts{fhs} = 1; 255 } 256 } 257 if ( !$opts{fhs} ) { 258 ($Conf{TopDir} = $ConfigPath) =~ s{/[^/]+/[^/]+$}{} 259 if ( $Conf{TopDir} eq '' ); 260 $bpc->{LogDir} = $Conf{LogDir} = "$Conf{TopDir}/log" 261 if ( $Conf{LogDir} eq '' ); 262 $bpc->{RunDir} = $Conf{RunDir} = "$Conf{TopDir}/log" 263 if ( $Conf{RunDir} eq '' ); 264 } 265 $bpc->{ConfDir} = $Conf{ConfDir} = $ConfigDir; 266 if ( !length($DestDir) ) { 267 my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}, 1); 268 if ( $err eq "" ) { 269 print <<EOF; 270 271BackupPC is running on $Conf{ServerHost}. You need to stop BackupPC before 272you can upgrade the code. Depending upon your installation, you could 273run "systemctl stop backuppc.service" if you use systemd, 274or "/etc/init.d/backuppc stop" if you use init.d. 275 276EOF 277 exit(1); 278 } 279 } 280} 281 282# 283# Create filesystem hierarchy defaults 284# 285$Conf{TopDir} ||= $opts{"data-dir"} || "/data/BackupPC"; 286$Conf{InstallDir} ||= $opts{"install-dir"} || "/usr/local/BackupPC"; 287 288# 289# These are the programs whose paths we need to find 290# 291my %Programs = ( 292 perl => "PerlPath", 293 rsync_bpc => "RsyncBackupPCPath", 294 'gtar/tar' => "TarClientPath", 295 smbclient => "SmbClientPath", 296 nmblookup => "NmbLookupPath", 297 rsync => "RsyncClientPath", 298 ping => "PingPath", 299 ping6 => "Ping6Path", 300 df => "DfPath", 301 'ssh/ssh2' => "SshPath", 302 sendmail => "SendmailPath", 303 hostname => "HostnamePath", 304 split => "SplitPath", 305 par2 => "ParPath", 306 cat => "CatPath", 307 gzip => "GzipPath", 308 bzip2 => "Bzip2Path", 309 rrdtool => "RrdToolPath", 310); 311 312foreach my $prog ( sort(keys(%Programs)) ) { 313 my $path; 314 foreach my $subProg ( split(/\//, $prog) ) { 315 $path = FindProgram("$ENV{PATH}:/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/bin", 316 $subProg) if ( !length($path) ); 317 } 318 $Conf{$Programs{$prog}} = $path if ( !length($Conf{$Programs{$prog}}) ); 319} 320 321while ( 1 ) { 322 print <<EOF; 323 324I found the following locations for these programs: 325 326EOF 327 foreach my $prog ( sort(keys(%Programs)) ) { 328 printf(" %-12s => %s\n", $prog, $Conf{$Programs{$prog}}); 329 } 330 print "\n"; 331 last if (prompt('--> Are these paths correct?', 'y') =~ /^y/i); 332 foreach my $prog ( sort(keys(%Programs)) ) { 333 $Conf{$Programs{$prog}} = prompt("--> $prog path", 334 $Conf{$Programs{$prog}}); 335 } 336} 337 338my $Perl58 = system($Conf{PerlPath} 339 . q{ -e 'exit($^V && $^V ge v5.8.0 ? 1 : 0);'}); 340 341if ( !$Perl58 ) { 342 print <<EOF; 343 344BackupPC needs perl version 5.8.0 or later. $Conf{PerlPath} appears 345to be an older version. Please upgrade to a newer version of perl 346and re-run this configure script. 347 348EOF 349 exit(1); 350} 351 352print <<EOF; 353 354Please tell me the hostname of the machine that BackupPC will run on. 355 356EOF 357chomp($Conf{ServerHost} = `$Conf{HostnamePath}`) 358 if ( defined($Conf{HostnamePath}) && !defined($Conf{ServerHost}) ); 359$Conf{ServerHost} = prompt("--> BackupPC will run on host", 360 $Conf{ServerHost}, 361 "hostname"); 362 363print <<EOF; 364 365BackupPC should run as a dedicated user with limited privileges. You 366need to create a user. This user will need read/write permission on 367the main data directory and read/execute permission on the install 368directory (these directories will be setup shortly). 369 370The primary group for this user should also be chosen carefully. 371The data directories and files will have group read permission, 372so group members can access backup files. 373 374EOF 375my($name, $passwd, $Uid, $Gid); 376while ( 1 ) { 377 $Conf{BackupPCUser} = prompt("--> BackupPC should run as user", 378 $Conf{BackupPCUser} || "backuppc", 379 "backuppc-user"); 380 if ( $opts{"set-perms"} ) { 381 ($name, $passwd, $Uid, $Gid) = getpwnam($Conf{BackupPCUser}); 382 last if ( $name ne "" ); 383 print <<EOF; 384 385getpwnam() says that user $Conf{BackupPCUser} doesn't exist. Please 386check the name and verify that this user is in the passwd file. 387 388EOF 389 exit(1) if ( $opts{batch} ); 390 } else { 391 last; 392 } 393} 394 395print <<EOF; 396 397Please specify an install directory for BackupPC. This is where the 398BackupPC scripts, library and documentation will be installed. 399 400EOF 401 402while ( 1 ) { 403 $Conf{InstallDir} = prompt("--> Install directory (full path)", 404 $Conf{InstallDir}, 405 "install-dir"); 406 last if ( $Conf{InstallDir} =~ /^\// ); 407 if ( $opts{batch} ) { 408 print("Need to specify --install-dir for new installation\n"); 409 exit(1); 410 } 411} 412 413print <<EOF; 414 415Please specify a data directory for BackupPC. This is where all the 416PC backup data is stored. This file system needs to be big enough to 417accommodate all the PCs you expect to backup (eg: at least several GB 418per machine). 419 420EOF 421 422while ( 1 ) { 423 $Conf{TopDir} = prompt("--> Data directory (full path)", 424 $Conf{TopDir}, 425 "data-dir"); 426 last if ( $Conf{TopDir} =~ /^\// ); 427 if ( $opts{batch} ) { 428 print("Need to specify --data-dir for new installation\n"); 429 exit(1); 430 } 431} 432 433if ( $opts{fhs} ) { 434 $Conf{ConfDir} ||= $ConfigDir || "/etc/BackupPC"; 435 $Conf{LogDir} ||= $opts{"log-dir"} || "/var/log/BackupPC"; 436 $Conf{RunDir} ||= $opts{"run-dir"} || "/var/run/BackupPC"; 437} else { 438 $Conf{ConfDir} ||= $ConfigDir || "$Conf{TopDir}/conf"; 439 $Conf{LogDir} ||= $opts{"log-dir"} || "$Conf{TopDir}/log"; 440 $Conf{RunDir} ||= $opts{"run-dir"} || "$Conf{TopDir}/log"; 441} 442 443$Conf{CompressLevel} = $opts{"compress-level"} 444 if ( defined($opts{"compress-level"}) ); 445 446print <<EOF; 447 448BackupPC has SCGI and CGI perl interfaces that run under Apache. You need 449to pick which one to run. 450 451For SCGI, Apache uses the scgi_mod module to communicate with BackupPC_Admin_SCGI, 452which handles the requests. This allows Apache to run as a different user as 453$Conf{BackupPCUser}. To use SCGI you need to set SCGIServerPort to any spare 454non-privileged TCP port number. A negative value disables SCGI. 455 456Important security warning!! The SCGIServerPort must not be accessible by 457anyone untrusted. That means you can't allow untrusted users access to the 458BackupPC server, and you should block the SCGIServerPort TCP port from 459network access. 460 461The traditional alternative is to use CGI. In this case, an executable needs 462to be installed Apache's cgi-bin directory. This executable needs to run as 463set-uid $Conf{BackupPCUser}, or it can be run under mod_perl with Apache 464running as user $Conf{BackupPCUser}. 465 466EOF 467 468$Conf{SCGIServerPort} = prompt("--> SCGI port (-1 to disable)", 469 $Conf{SCGIServerPort} || -1, 470 "scgi-port"); 471 472if ( $Conf{SCGIServerPort} < 0 ) { 473 while ( 1 ) { 474 $Conf{CgiDir} = prompt("--> CGI bin directory (full path, or empty for no CGI)", 475 $Conf{CgiDir}, 476 "cgi-dir"); 477 last if ( $Conf{CgiDir} =~ /^\// || $Conf{CgiDir} eq "" ); 478 if ( $opts{batch} ) { 479 print("Need to specify --cgi-dir for new installation\n"); 480 exit(1); 481 } 482 } 483} 484 485if ( $Conf{SCGIServerPort} > 0 || $Conf{CgiDir} ne "" ) { 486 print <<EOF; 487 488BackupPC's CGI and SCGI script need to display various PNG/GIF 489images that should be stored where Apache can serve them. They 490should be placed somewhere under Apache's DocumentRoot. BackupPC 491also needs to know the URL to access these images. Example: 492 493 Apache image directory: /var/www/htdocs/BackupPC 494 URL for image directory: /BackupPC 495 496The URL for the image directory should start with a slash. 497 498EOF 499 while ( 1 ) { 500 $Conf{CgiImageDir} = prompt("--> Apache image directory (full path, or empty for no S/CGI)", 501 $Conf{CgiImageDir}, 502 "html-dir"); 503 last if ( $Conf{CgiImageDir} =~ /^\// || $Conf{CgiImageDir} eq "" ); 504 if ( $opts{batch} ) { 505 print("Need to specify --html-dir for new installation\n"); 506 exit(1); 507 } 508 } 509 while ( 1 ) { 510 $Conf{CgiImageDirURL} = prompt("--> URL for image directory (omit http://host; starts with '/', or empty for no S/CGI)", 511 $Conf{CgiImageDirURL}, 512 "html-dir-url"); 513 last if ( $Conf{CgiImageDirURL} =~ /^\// || $Conf{CgiImageDirURL} eq "" ); 514 if ( $opts{batch} ) { 515 print("Need to specify --html-dir-url for new installation\n"); 516 exit(1); 517 } 518 } 519} 520 521print <<EOF; 522 523Ok, we're about to: 524 525EOF 526 527print <<EOF if ( !$opts{"config-only"} ); 528 - install the binaries, lib and docs in $DestDir$Conf{InstallDir} 529 - create the data directory $DestDir$Conf{TopDir} 530 - optionally install the cgi-bin interface 531EOF 532 533print <<EOF; 534 - create/update the config.pl file $DestDir$Conf{ConfDir}/config.pl 535 536EOF 537 538exit unless prompt("--> Do you want to continue?", "y") =~ /y/i; 539 540CleanPidSock(); 541 542DoInstall() if ( !$opts{"config-only"} ); 543 544print("Installing config.pl and hosts in $DestDir$Conf{ConfDir}\n"); 545InstallFile("conf/hosts", "$DestDir$Conf{ConfDir}/hosts.sample", 0644) 546 if ( !$opts{"config-only"} ); 547my $hostsSample = $opts{"config-only"} ? "$DestDir$Conf{ConfDir}/hosts.sample" : "conf/hosts"; 548InstallFile($hostsSample, "$DestDir$Conf{ConfDir}/hosts", 0644) 549 if ( !-f "$DestDir$Conf{ConfDir}/hosts" ); 550 551# 552# Now do the config file. If there is an existing config file we 553# merge in the new config file, adding any new configuration 554# parameters and deleting ones that are no longer needed. 555# 556my $dest = "$DestDir$Conf{ConfDir}/config.pl"; 557my $configSample = $opts{"config-only"} ? "$DestDir$Conf{ConfDir}/config.pl.sample" : "conf/config.pl"; 558my ($distConf, $distVars) = ConfigParse($configSample); 559my ($oldConf, $oldVars); 560my ($newConf, $newVars) = ($distConf, $distVars); 561if ( -f $dest ) { 562 ($oldConf, $oldVars) = ConfigParse($dest); 563 ($newConf, $newVars) = ConfigMerge($oldConf, $oldVars, $distConf, $distVars); 564} 565 566# 567# Update various config parameters. The old config is in Conf{} 568# and the new config is an array in text form in $newConf->[]. 569# 570$Conf{EMailFromUserName} ||= $Conf{BackupPCUser}; 571$Conf{EMailAdminUserName} ||= $Conf{BackupPCUser}; 572 573# 574# Guess $Conf{CgiURL} 575# 576if ( $Conf{CgiURL} eq '' ) { 577 if ( $Conf{CgiDir} =~ m{cgi-bin(/.*)} ) { 578 $Conf{CgiURL} = "http://$Conf{ServerHost}/cgi-bin$1/BackupPC_Admin"; 579 } else { 580 $Conf{CgiURL} = "http://$Conf{ServerHost}/cgi-bin/BackupPC_Admin"; 581 } 582} 583 584# 585# The smbclient commands have moved from hard-coded to the config file. 586# $Conf{SmbClientArgs} no longer exists, so merge it into the new 587# commands if it still exists. 588# 589if ( defined($Conf{SmbClientArgs}) ) { 590 if ( $Conf{SmbClientArgs} ne "" ) { 591 foreach my $param ( qw(SmbClientRestoreCmd SmbClientFullCmd 592 SmbClientIncrCmd) ) { 593 $newConf->[$newVars->{$param}]{text} 594 =~ s/(-E\s+-N)/$1 $Conf{SmbClientArgs}/; 595 } 596 } 597 delete($Conf{SmbClientArgs}); 598} 599 600# 601# CSS is now stored in a file rather than a big config variable. 602# 603delete($Conf{CSSstylesheet}); 604 605# 606# The blackout timing settings are now stored in a list of hashes, rather 607# than three scalar parameters. 608# 609if ( defined($Conf{BlackoutHourBegin}) ) { 610 $Conf{BlackoutPeriods} = [ 611 { 612 hourBegin => $Conf{BlackoutHourBegin}, 613 hourEnd => $Conf{BlackoutHourEnd}, 614 weekDays => $Conf{BlackoutWeekDays}, 615 } 616 ]; 617 delete($Conf{BlackoutHourBegin}); 618 delete($Conf{BlackoutHourEnd}); 619 delete($Conf{BlackoutWeekDays}); 620} 621 622# 623# $Conf{RsyncLogLevel} has been replaced by $Conf{XferLogLevel} 624# 625if ( defined($Conf{RsyncLogLevel}) ) { 626 $Conf{XferLogLevel} = $Conf{RsyncLogLevel}; 627 delete($Conf{RsyncLogLevel}); 628} 629 630# 631# Since 2.1.0 the default for $Conf{CgiNavBarAdminAllHosts} is now 1 632# 633$Conf{CgiNavBarAdminAllHosts} = 1; 634 635# 636# Empty $Conf{ParPath} if it isn't a valid executable 637# (pre-3.0.0 configure.pl incorrectly set it to a 638# hardcoded value). 639# 640$Conf{ParPath} = '' if ( $Conf{ParPath} ne '' && !-x $Conf{ParPath} ); 641 642# 643# Figure out sensible arguments for the ping command 644# 645if ( defined($Conf{PingArgs}) ) { 646 $Conf{PingCmd} = '$pingPath ' . $Conf{PingArgs}; 647 delete($Conf{PingArgs}); 648} elsif ( $Upgrade && !defined($Conf{PingCmd}) ) { 649 if ( $^O eq "solaris" || $^O eq "sunos" ) { 650 $Conf{PingCmd} = '$pingPath -s $host 56 1'; 651 } elsif ( ($^O eq "linux" || $^O eq "openbsd" || $^O eq "netbsd") 652 && !system("$Conf{PingPath} -c 1 -w 3 localhost") ) { 653 $Conf{PingCmd} = '$pingPath -c 1 -w 3 $host'; 654 } else { 655 $Conf{PingCmd} = '$pingPath -c 1 $host'; 656 } 657} 658 659# 660# Figure out sensible arguments for the df command 661# 662if ( !defined($Conf{DfCmd}) ) { 663 if ( $^O eq "solaris" || $^O eq "sunos" ) { 664 $Conf{DfCmd} = '$dfPath -k $topDir'; 665 } 666} 667 668# 669# $Conf{SmbClientTimeout} is now $Conf{ClientTimeout} 670# 671if ( defined($Conf{SmbClientTimeout}) ) { 672 $Conf{ClientTimeout} = $Conf{SmbClientTimeout}; 673 delete($Conf{SmbClientTimeout}); 674} 675 676# 677# Replace --devices with -D in RsyncArgs and RsyncRestoreArgs 678# 679foreach my $param ( qw(RsyncArgs RsyncRestoreArgs) ) { 680 next if ( !defined($newVars->{$param}) ); 681 $newConf->[$newVars->{$param}]{text} =~ s/--devices/-D/g; 682} 683 684# 685# Merge any new user-editable parameters into CgiUserConfigEdit 686# by copying the old settings forward. 687# 688if ( defined($Conf{CgiUserConfigEdit}) ) { 689 # 690 # This is a real hack. The config file merging is done in text 691 # form without actually instantiating the new conf structure. 692 # So we need to extract the new hash of settings, update it, 693 # and merge the text. Ugh... 694 # 695 my $new; 696 my $str = $distConf->[$distVars->{CgiUserConfigEdit}]{text}; 697 698 $str =~ s/^\s*\$Conf\{.*?\}\s*=\s*/\$new = /m; 699 eval($str); 700 foreach my $p ( keys(%$new) ) { 701 $new->{$p} = $Conf{CgiUserConfigEdit}{$p} 702 if ( defined($Conf{CgiUserConfigEdit}{$p}) ); 703 } 704 $Conf{CgiUserConfigEdit} = $new; 705 my $d = Data::Dumper->new([$new], [*value]); 706 $d->Indent(1); 707 $d->Terse(1); 708 $d->Sortkeys(1); 709 my $value = $d->Dump; 710 $value =~ s/(.*)\n/$1;\n/s; 711 $newConf->[$newVars->{CgiUserConfigEdit}]{text} 712 =~ s/^(\s*\$Conf\{.*?\}\s*=\s*).*/$1$value/ms; 713} 714 715# 716# If this is an upgrade from V3, then set $Conf{PoolV3Enabled} 717# and update $Conf{RsyncArgs} and $Conf{RsyncRestoreArgs}. 718# 719if ( $Upgrade && !defined($Conf{PoolV3Enabled}) ) { 720 $Conf{PoolV3Enabled} = 1; 721 # 722 # for an upgrade, remove the new --one-file-system flag if it wasn't there before 723 # 724 if ( $oldConf->[$oldVars->{RsyncArgs}]{text} !~ /--one-file-system/ ) { 725 $distConf->[$distVars->{RsyncArgs}]{text} =~ s/\n\s*'--one-file-system',\n/\n/; 726 } 727 $newConf->[$newVars->{RsyncArgs}]{text} = $distConf->[$distVars->{RsyncArgs}]{text}; 728 $newConf->[$newVars->{RsyncRestoreArgs}]{text} = $distConf->[$distVars->{RsyncRestoreArgs}]{text}; 729 # 730 # If it exists, use $Conf{RsyncClientCmd} to create the default $Conf{RsyncSshArgs}. 731 # 732 if ( $Conf{RsyncClientCmd} =~ /(\$sshPath.* +-l +\S+)/ && defined($newVars->{RsyncSshArgs}) ) { 733 my $value = "[\n '-e', '$1',\n];\n\n"; 734 $newConf->[$newVars->{RsyncSshArgs}]{text} 735 =~ s/^(\s*\$Conf\{RsyncSshArgs}\s*=\s*).*/$1$value/ms; 736 } 737} 738 739# 740# Update $Conf{CgiNavBarLinks} with github URLs 741# 742$newConf->[$newVars->{CgiNavBarLinks}]{text} =~ s{http://backuppc.wiki.sourceforge.net}{https://github.com/backuppc/backuppc/wiki}g; 743$newConf->[$newVars->{CgiNavBarLinks}]{text} =~ s{http://backuppc.sourceforge.net}{https://backuppc.github.io/backuppc}g; 744$newConf->[$newVars->{CgiNavBarLinks}]{text} =~ s{SourceForge}{Homepage}g; 745 746# 747# Apply any command-line configuration parameter settings 748# 749foreach my $param ( keys(%{$opts{"config-override"}}) ) { 750 my $value = $opts{"config-override"}{$param}; 751 my $val = eval { $value }; 752 if ( @$ ) { 753 printf("Can't eval --config-override setting %s=%s\n", 754 $param, $opts{"config-override"}{$param}); 755 exit(1); 756 } 757 if ( !defined($newVars->{$param}) ) { 758 printf("Unkown config parameter %s in --config-override\n", $param); 759 exit(1); 760 } 761 $value .= ";\n\n"; 762 $newConf->[$newVars->{$param}]{text} 763 =~ s/^(\s*\$Conf\{$param}\s*=\s*).*/$1$value/ms; 764} 765 766# 767# Now backup and write the config file 768# 769my $confCopy = "$dest.pre-__VERSION__"; 770if ( -f $dest && !-f $confCopy ) { 771 # 772 # Make copy of config file, preserving ownership and modes 773 # 774 print("Making backup copy of $dest -> $confCopy\n"); 775 my @stat = stat($dest); 776 my $mode = $stat[2]; 777 my $uid = $stat[4]; 778 my $gid = $stat[5]; 779 die("can't copy($dest, $confCopy)\n") 780 unless copy($dest, $confCopy); 781 die("can't chown $uid, $gid $confCopy\n") 782 unless my_chown($uid, $gid, $confCopy); 783 die("can't chmod $mode $confCopy\n") 784 unless my_chmod($mode, $confCopy); 785} 786open(OUT, ">", $dest) || die("can't open $dest for writing\n"); 787binmode(OUT); 788my $blockComment; 789foreach my $var ( @$newConf ) { 790 if ( length($blockComment) 791 && substr($var->{text}, 0, length($blockComment)) eq $blockComment ) { 792 $var->{text} = substr($var->{text}, length($blockComment)); 793 $blockComment = undef; 794 } 795 $blockComment = $1 if ( $var->{text} =~ /^([\s\n]*#{70}.*#{70}[\s\n]+)/s ); 796 $var->{text} =~ s/^\s*\$Conf\{(.*?)\}(\s*=\s*['"]?)(.*?)(['"]?\s*;)/ 797 my $varName = $1; 798 my $a = $2; 799 my $varValue = $3; 800 my $b = $4; 801 # Get quotes from default config to avoid missing or extra quotes 802 # when replacing misused undef or empty string values 803 ($a, $b) = GetQuotes($varName) 804 if ( (!defined($OrigConf{$varName}) || $OrigConf{$varName} eq "") 805 && $Conf{$varName} ne $OrigConf{$varName} ); 806 807 defined($Conf{$varName}) && ref($Conf{$varName}) eq "" 808 && !defined($opts{"config-override"}{$varName}) 809 && $Conf{$varName} ne $OrigConf{$varName} 810 ? "\$Conf{$varName}$a$Conf{$varName}$b" 811 : "\$Conf{$varName}$a$varValue$b"/emg; 812 print OUT $var->{text}; 813} 814close(OUT); 815if ( !defined($oldConf) ) { 816 die("can't chmod 0640 mode $dest\n") unless my_chmod(0640, $dest); 817 die("can't chown $Uid, $Gid $dest\n") unless my_chown($Uid, $Gid, $dest); 818} 819 820InstallFile($dest, "$DestDir$Conf{ConfDir}/config.pl.sample", 0644) 821 if ( !$opts{"config-only"} ); 822 823print <<EOF; 824 825Ok, it looks like we are finished. There are several more things you 826will need to do: 827 828 - Browse through the config file, $Conf{ConfDir}/config.pl, 829 and make sure all the settings are correct. In particular, 830 you will need to set \$Conf{CgiAdminUsers} so you have 831 administration privileges in the CGI interface. 832 833 - Edit the list of hosts to backup in $Conf{ConfDir}/hosts. 834 835 - Read the documentation in $Conf{InstallDir}/doc/BackupPC.html. 836 Please pay special attention to the security section. 837 838 - Verify that the CGI script BackupPC_Admin runs correctly. You might 839 need to change the permissions or group ownership of BackupPC_Admin. 840 If this is an upgrade and you are using mod_perl, you will need 841 to restart Apache. Otherwise it will have stale code. 842 843 - BackupPC should be ready to start. Don't forget to run it 844 as user $Conf{BackupPCUser}! The installation also contains 845 a systemd/backuppc.service script that can be installed so 846 that BackupPC can auto-start on boot. This will also enable 847 administrative users to start the server from the CGI interface. 848 See systemd/README. 849 850Enjoy! 851EOF 852 853if ( `$Conf{PerlPath} -V` =~ /uselargefiles=undef/ ) { 854 print <<EOF; 855 856Warning: your perl, $Conf{PerlPath}, does not support large files. 857This means BackupPC won't be able to backup files larger than 2GB. 858To solve this problem you should build/install a new version of perl 859with large file support enabled. Use 860 861 $Conf{PerlPath} -V | egrep uselargefiles 862 863to check if perl has large file support (undef means no support). 864EOF 865} 866 867exit(0); 868 869########################################################################### 870# Subroutines 871########################################################################### 872 873sub DoInstall 874{ 875 # 876 # Create install directories 877 # 878 foreach my $dir ( qw(bin 879 share share/doc share/doc/BackupPC 880 lib lib/BackupPC 881 lib/BackupPC/CGI 882 lib/BackupPC/Config 883 lib/BackupPC/Lang 884 lib/BackupPC/Storage 885 lib/BackupPC/Xfer 886 lib/BackupPC/Zip 887 lib/Net lib/Net/FTP 888 ) ) { 889 next if ( -d "$DestDir$Conf{InstallDir}/$dir" ); 890 mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0755); 891 if ( !-d "$DestDir$Conf{InstallDir}/$dir" 892 || !my_chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) { 893 die("Failed to create or chown $DestDir$Conf{InstallDir}/$dir\n"); 894 } else { 895 print("Created $DestDir$Conf{InstallDir}/$dir\n"); 896 } 897 } 898 899 # 900 # Create CGI image directory 901 # 902 foreach my $dir ( ($Conf{CgiImageDir}) ) { 903 next if ( $dir eq "" || -d "$DestDir$dir" ); 904 mkpath("$DestDir$dir", 0, 0755); 905 if ( !-d "$DestDir$dir" || !my_chown($Uid, $Gid, "$DestDir$dir") ) { 906 die("Failed to create or chown $DestDir$dir"); 907 } else { 908 print("Created $DestDir$dir\n"); 909 } 910 } 911 912 # 913 # Create other directories 914 # 915 foreach my $dir ( ( 916 "$Conf{TopDir}", 917 "$Conf{TopDir}/pool", 918 "$Conf{TopDir}/cpool", 919 "$Conf{TopDir}/pc", 920 "$Conf{ConfDir}", 921 "$Conf{LogDir}", 922 "$Conf{RunDir}", 923 ) ) { 924 eval { mkpath("$DestDir$dir", 0, 0750) } if ( !-d "$DestDir$dir" ); 925 if ( $@ || !-d "$DestDir$dir" 926 || !my_chown($Uid, $Gid, "$DestDir$dir") ) { 927 if ( $dir eq $Conf{RunDir} ) { 928 print("Failed to create or chown $DestDir$dir... continuing\n"); 929 } else { 930 die("Failed to create or chown $DestDir$dir\n"); 931 } 932 } else { 933 print("Created $DestDir$dir\n"); 934 } 935 } 936 937 print("Installing binaries in $DestDir$Conf{InstallDir}/bin\n"); 938 foreach my $prog ( @ConfigureBinList ) { 939 InstallFile($prog, "$DestDir$Conf{InstallDir}/$prog", 0555); 940 } 941 942 # 943 # remove old pre-v4 programs 944 # 945 foreach my $prog ( qw( 946 bin/BackupPC_link 947 bin/BackupPC_tarPCCopy 948 bin/BackupPC_trashClean 949 bin/BackupPC_compressPool 950 ) ) { 951 unlink("$DestDir$Conf{InstallDir}/$prog"); 952 } 953 954 print("Installing library in $DestDir$Conf{InstallDir}/lib\n"); 955 foreach my $lib ( @ConfigureLibList ) { 956 InstallFile($lib, "$DestDir$Conf{InstallDir}/$lib", 0444); 957 } 958 959 # 960 # remove old pre-v4 libraries 961 # 962 foreach my $lib ( qw( 963 lib/BackupPC/Attrib.pm 964 lib/BackupPC/Config.pm 965 lib/BackupPC/FileZIO.pm 966 lib/BackupPC/PoolWrite.pm 967 lib/BackupPC/Xfer/RsyncDigest.pm 968 lib/BackupPC/Xfer/RsyncFileIO.pm 969 ) ) { 970 unlink("$DestDir$Conf{InstallDir}/$lib"); 971 } 972 973 if ( $Conf{CgiImageDir} ne "" ) { 974 print("Installing images in $DestDir$Conf{CgiImageDir}\n"); 975 foreach my $img ( <images/*> ) { 976 (my $destImg = $img) =~ s{^images/}{}; 977 InstallFile($img, "$DestDir$Conf{CgiImageDir}/$destImg", 0444, 1); 978 } 979 980 # 981 # Install new CSS file, making a backup copy if necessary 982 # 983 my $cssBackup = "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css.pre-__VERSION__"; 984 if ( -f "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css" && !-f $cssBackup ) { 985 rename("$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", $cssBackup); 986 } 987 InstallFile("conf/BackupPC_stnd.css", 988 "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", 0444, 0); 989 InstallFile("conf/BackupPC_retro_v2.css", 990 "$DestDir$Conf{CgiImageDir}/BackupPC_retro_v2.css", 0444, 0); 991 InstallFile("conf/BackupPC_retro_v3.css", 992 "$DestDir$Conf{CgiImageDir}/BackupPC_retro_v3.css", 0444, 0); 993 InstallFile("conf/sorttable.js", 994 "$DestDir$Conf{CgiImageDir}/sorttable.js", 0444, 0); 995 } 996 997 print("Making systemd and init.d scripts\n"); 998 foreach my $dir ( qw(systemd systemd/init.d) ) { 999 mkpath($dir, 0, 0755); 1000 if ( !-d $dir || !my_chown($Uid, $Gid, $dir) ) { 1001 die("Failed to create or chown $dir\n"); 1002 } 1003 } 1004 InstallFile("systemd/src/backuppc.service", "systemd/backuppc.service", 0644); 1005 foreach my $init ( qw(init.d/gentoo-backuppc init.d/gentoo-backuppc.conf 1006 init.d/linux-backuppc init.d/solaris-backuppc init.d/debian-backuppc 1007 init.d/freebsd-backuppc init.d/freebsd-backuppc2 init.d/suse-backuppc 1008 init.d/slackware-backuppc init.d/ubuntu-backuppc ) ) { 1009 InstallFile("systemd/src/$init", "systemd/$init", 0755); 1010 } 1011 1012 print("Making Apache configuration file for suid-perl\n"); 1013 InstallFile("httpd/src/BackupPC.conf", "httpd/BackupPC.conf", 0644); 1014 1015 print("Installing docs in $DestDir$Conf{InstallDir}/share/doc/BackupPC\n"); 1016 foreach my $doc ( qw(BackupPC.pod BackupPC.html) ) { 1017 InstallFile("doc/$doc", "$DestDir$Conf{InstallDir}/share/doc/BackupPC/$doc", 0444); 1018 # 1019 # clean up files from old directory 1020 # 1021 unlink("$DestDir$Conf{InstallDir}/doc/$doc") if ( -f "$DestDir$Conf{InstallDir}/doc/$doc" ); 1022 } 1023 # 1024 # clean up old directory (ok if it quietly fails if there are other files in that directory) 1025 # 1026 rmdir("$DestDir$Conf{InstallDir}/doc") if ( -d "$DestDir$Conf{InstallDir}/doc" ); 1027 1028 if ( $Conf{CgiDir} ne "" ) { 1029 print("Installing cgi script BackupPC_Admin in $DestDir$Conf{CgiDir}\n"); 1030 mkpath("$DestDir$Conf{CgiDir}", 0, 0755); 1031 InstallFile("cgi-bin/BackupPC_Admin", "$DestDir$Conf{CgiDir}/BackupPC_Admin", 1032 04554); 1033 } 1034} 1035 1036sub CleanPidSock 1037{ 1038 # 1039 # clean pid and sock files from old location (they are now in $Conf{RunDir}, and they 1040 # get re-created each time BackupPC starts, so it's ok if RunDir eq LogDir). 1041 # 1042 unlink("$DestDir$Conf{LogDir}/BackupPC.pid") if ( -f "$DestDir$Conf{LogDir}/BackupPC.pid" ); 1043 unlink("$DestDir$Conf{LogDir}/BackupPC.sock") if ( -e "$DestDir$Conf{LogDir}/BackupPC.sock" ); 1044} 1045 1046sub InstallFile 1047{ 1048 my($prog, $dest, $mode, $binary) = @_; 1049 my $first = 1; 1050 my($uid, $gid) = ($Uid, $Gid); 1051 1052 if ( -f $dest ) { 1053 # 1054 # preserve ownership and modes of files that already exist 1055 # 1056 my @stat = stat($dest); 1057 $mode = $stat[2]; 1058 $uid = $stat[4]; 1059 $gid = $stat[5]; 1060 } 1061 unlink($dest) if ( -f $dest ); 1062 if ( $binary ) { 1063 die("can't copy($prog, $dest)\n") unless copy($prog, $dest); 1064 } else { 1065 open(PROG, $prog) || die("can't open $prog for reading\n"); 1066 open(OUT, ">", $dest) || die("can't open $dest for writing\n"); 1067 binmode(PROG); 1068 binmode(OUT); 1069 while ( <PROG> ) { 1070 s/__INSTALLDIR__/$Conf{InstallDir}/g; 1071 s/__LOGDIR__/$Conf{LogDir}/g; 1072 s/__RUNDIR__/$Conf{RunDir}/g; 1073 s/__CONFDIR__/$Conf{ConfDir}/g; 1074 s/__TOPDIR__/$Conf{TopDir}/g; 1075 s/^(\s*my \$useFHS\s*=\s*)\d;/${1}$opts{fhs};/ 1076 if ( $prog =~ /Lib.pm/ ); 1077 s/__BACKUPPCUSER__/$Conf{BackupPCUser}/g; 1078 s/__CGIDIR__/$Conf{CgiDir}/g; 1079 s/__IMAGEDIR__/$Conf{CgiImageDir}/g; 1080 s/__IMAGEDIRURL__/$Conf{CgiImageDirURL}/g; 1081 if ( $first && /^#.*bin\/perl/ ) { 1082 # 1083 # Fill in correct path to perl (no taint for >= 2.0.1). 1084 # 1085 print OUT "#!$Conf{PerlPath}\n"; 1086 } else { 1087 print OUT; 1088 } 1089 $first = 0; 1090 } 1091 close(PROG); 1092 close(OUT); 1093 } 1094 die("can't chown $uid, $gid $dest") unless my_chown($uid, $gid, $dest); 1095 die("can't chmod $mode $dest") unless my_chmod($mode, $dest); 1096} 1097 1098sub FindProgram 1099{ 1100 my($path, $prog) = @_; 1101 1102 if ( defined($opts{"bin-path"}{$prog}) ) { 1103 return $opts{"bin-path"}{$prog}; 1104 } 1105 foreach my $dir ( split(/:/, $path) ) { 1106 my $file = File::Spec->catfile($dir, $prog); 1107 return $file if ( -x $file ); 1108 } 1109 return; 1110} 1111 1112sub ConfigParse 1113{ 1114 my($file) = @_; 1115 open(C, $file) || die("can't open $file"); 1116 binmode(C); 1117 my($out, @conf, $var); 1118 my $comment = 1; 1119 my $allVars = {}; 1120 my $endLine = undef; 1121 while ( <C> ) { 1122 if ( /^#/ && !defined($endLine) ) { 1123 if ( $comment ) { 1124 $out .= $_; 1125 } else { 1126 if ( $out ne "" ) { 1127 $allVars->{$var} = @conf if ( defined($var) ); 1128 push(@conf, { 1129 text => $out, 1130 var => $var, 1131 }); 1132 } 1133 $var = undef; 1134 $comment = 1; 1135 $out = $_; 1136 } 1137 } elsif ( /^\s*\$Conf\{([^}]*)/ ) { 1138 $comment = 0; 1139 if ( defined($var) ) { 1140 $allVars->{$var} = @conf if ( defined($var) ); 1141 push(@conf, { 1142 text => $out, 1143 var => $var, 1144 }); 1145 $out = $_; 1146 } else { 1147 $out .= $_; 1148 } 1149 $var = $1; 1150 $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<(.*);/ ); 1151 $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<'(.*)';/ ); 1152 } else { 1153 $endLine = undef if ( defined($endLine) && /^\Q$endLine\E[\n\r]*$/ ); 1154 $out .= $_; 1155 } 1156 } 1157 if ( $out ne "" ) { 1158 $allVars->{$var} = @conf if ( defined($var) ); 1159 push(@conf, { 1160 text => $out, 1161 var => $var, 1162 }); 1163 } 1164 close(C); 1165 return (\@conf, $allVars); 1166} 1167 1168sub ConfigMerge 1169{ 1170 my($old, $oldVars, $new, $newVars) = @_; 1171 my $posn = 0; 1172 my($res, $resVars); 1173 1174 # 1175 # Find which config parameters are not needed any longer 1176 # 1177 foreach my $var ( @$old ) { 1178 next if ( !defined($var->{var}) || defined($newVars->{$var->{var}}) ); 1179 #print(STDERR "Deleting old config parameter $var->{var}\n"); 1180 $var->{delete} = 1; 1181 } 1182 # 1183 # Find which config parameters are new 1184 # 1185 foreach my $var ( @$new ) { 1186 next if ( !defined($var->{var}) ); 1187 if ( defined($oldVars->{$var->{var}}) ) { 1188 $posn = $oldVars->{$var->{var}}; 1189 } else { 1190 #print(STDERR "New config parameter $var->{var}: $var->{text}\n"); 1191 push(@{$old->[$posn]{new}}, $var); 1192 } 1193 } 1194 # 1195 # Create merged config file 1196 # 1197 foreach my $var ( @$old ) { 1198 next if ( $var->{delete} ); 1199 push(@$res, $var); 1200 foreach my $new ( @{$var->{new}} ) { 1201 push(@$res, $new); 1202 } 1203 } 1204 for ( my $i = 0 ; $i < @$res ; $i++ ) { 1205 $resVars->{$res->[$i]{var}} = $i; 1206 } 1207 return ($res, $resVars); 1208} 1209 1210sub GetQuotes 1211{ 1212 my($varName) = @_; 1213 1214 my $posn = $distVars->{$varName}; 1215 $distConf->[$posn]->{text} =~ /^\s*\$Conf\{.*?\}(\s*=\s*['"]?).*?(['"]?\s*;)/mg; 1216 return ($1, $2); 1217} 1218 1219sub my_chown 1220{ 1221 my($uid, $gid, $file) = @_; 1222 1223 return 1 if ( !$opts{"set-perms"} ); 1224 return chown($uid, $gid, $file); 1225} 1226 1227sub my_chmod 1228{ 1229 my ($mode, $file) = @_; 1230 1231 return 1 if ( !$opts{"set-perms"} ); 1232 return chmod($mode, $file); 1233} 1234 1235sub prompt 1236{ 1237 my($question, $default, $option) = @_; 1238 1239 $default = $opts{$option} if ( defined($opts{$option}) ); 1240 if ( $opts{batch} ) { 1241 print("$question [$default]\n"); 1242 return $default; 1243 } 1244 print("$question [$default]? "); 1245 my $reply = <STDIN>; 1246 $reply =~ s/[\n\r]*//g; 1247 return $reply if ( $reply !~ /^$/ ); 1248 return $default; 1249} 1250 1251__END__ 1252 1253=head1 SYNOPSIS 1254 1255configure.pl [options] 1256 1257=head1 DESCRIPTION 1258 1259configure.pl is a script that is used to install or upgrade a BackupPC 1260installation. It is usually run interactively without arguments. It 1261also supports a batch mode where all the options can be specified 1262via the command-line. 1263 1264For upgrading BackupPC you need to make sure that BackupPC is not 1265running prior to running BackupPC. 1266 1267Typically configure.pl needs to run as the super user (root). 1268 1269=head1 OPTIONS 1270 1271=over 8 1272 1273=item B<--batch> 1274 1275Run configure.pl in batch mode. configure.pl will run without 1276prompting the user. The other command-line options are used 1277to specify the settings that the user is usually prompted for. 1278 1279=item B<--backuppc-user=USER> 1280 1281Specify the BackupPC user name that owns all the BackupPC 1282files and runs the BackupPC programs. Default is backuppc. 1283 1284=item B<--bin-path PROG=PATH> 1285 1286Specify the path for various external programs that BackupPC 1287uses. Several --bin-path options may be specified. configure.pl 1288usually finds sensible defaults based on searching the PATH. 1289The format is: 1290 1291 --bin-path PROG=PATH 1292 1293where PROG is one of perl, tar, smbclient, nmblookup, rsync, rsync_bpc, 1294ping, df, ssh, sendmail, hostname, split, par2, cat, gzip, bzip2 and 1295PATH is that full path to that program. 1296 1297Examples 1298 1299 --bin-path cat=/bin/cat --bin-path bzip2=/home/user/bzip2 1300 1301=item B<--compress-level=N> 1302 1303Set the configuration compression level to N. Default is 3. 1304 1305=item B<--config-dir CONFIG_DIR> 1306 1307Configuration directory. Defaults to /etc/BackupPC with FHS. 1308Automatically extracted from --config-path for existing installations. 1309 1310=item B<--config-override name=value> 1311 1312Override a specific configuration parameter. Can be specified multiple 1313times. "Name" is the parameter name and "value" is the exact text that 1314is inserted in the config.pl file (so you will need to escape quotes etc). 1315For example, to override $Conf{ServerHost} you would specify: 1316 1317 --config-override ServerHost=\"myhost\" 1318 1319=item B<--config-only> 1320 1321Do not install anything else, just create or update the config.pl and hosts 1322configuration files. This option can be used for automatic update of the 1323configuration after upgrading BackupPC using a package. With this option enabled 1324the configure.pl can be used separately from the rest of BackupPC distribution 1325files. In this case you should tell it where to look for installed BackupPC 1326files. 1327 1328So you will need to define the PERL5LIB environmental variable, for example for 1329Bourne shell: 1330 1331 PERL5LIB=/usr/local/lib; export PERL5LIB 1332 configure.pl --config-only 1333 1334or specify the path via Perl -I flag: 1335 1336 perl -I /usr/local/lib configure.pl 1337 1338=item B<--config-path CONFIG_PATH> 1339 1340Path to the existing config.pl configuration file for BackupPC. 1341This option should be specified for batch upgrades to an 1342existing installation. The option should be omitted when 1343doing a batch new install. 1344 1345=item B<--cgi-dir CGI_DIR> 1346 1347Path to Apache's cgi-bin directory where the BackupPC_Admin 1348script will be installed. This option only needs to be 1349specified for a batch new install. 1350 1351=item B<--scgi-port N> 1352 1353Numeric TCP port that is used for communication between Apache 1354and BackupPC_Admin_SCGI. A negative value disables SCGI. 1355 1356=item B<--data-dir DATA_DIR> 1357 1358Path to the BackupPC data directory. This is where all the backup 1359data is stored, and it should be on a large file system. This option 1360only needs to be specified for a batch new install. 1361 1362Example: 1363 1364 --data-dir /data/BackupPC 1365 1366=item B<--dest-dir DEST_DIR> 1367 1368An optional prefix to apply to all installation directories. Usually this 1369is not needed, but is used by package creators, or certain auto-installers 1370that like to stage an install in a temporary directory, and then copy 1371the files to their real destination. This option can be used to specify 1372the target directory prefix. If you specify this option any existing 1373installation should be ignored. Note that BackupPC won't run correctly if 1374you try to run it from below the --dest-dir directory, since all the paths 1375are set assuming BackupPC is installed in the intended final locations. 1376 1377=item B<--fhs> 1378 1379Use locations specified by the Filesystem Hierarchy Standard 1380for installing BackupPC. This is enabled by default for new 1381installations. To use the pre-3.0 installation locations, 1382specify --no-fhs. 1383 1384=item B<--help|?> 1385 1386Print a brief help message and exits. 1387 1388=item B<--hostname HOSTNAME> 1389 1390Host name (this machine's name) on which BackupPC is being installed. 1391This option only needs to be specified for a batch new install. 1392 1393=item B<--html-dir HTML_DIR> 1394 1395Path to an Apache html directory where various BackupPC image files 1396and the CSS files will be installed. This is typically a directory 1397below Apache's DocumentRoot directory. This option only needs to be 1398specified for a batch new install. 1399 1400Example: 1401 1402 --html-dir /var/www/htdocs/BackupPC 1403 1404=item B<--html-dir-url URL> 1405 1406The URL (without http://hostname) required to access the BackupPC html 1407directory specified with the --html-dir option. This option only needs 1408to be specified for a batch new install. 1409 1410Example: 1411 1412 --html-dir-url /BackupPC 1413 1414=item B<--install-dir INSTALL_DIR> 1415 1416Installation directory for BackupPC scripts, libraries, and 1417documentation. This option only needs to be specified for a 1418batch new install. 1419 1420Example: 1421 1422 --install-dir /usr/local/BackupPC 1423 1424=item B<--log-dir LOG_DIR> 1425 1426Log directory. Defaults to /var/log/BackupPC with FHS. 1427 1428=item B<--man> 1429 1430Prints the manual page and exits. 1431 1432=item B<--run-dir RUN_DIR> 1433 1434Run directory. Defaults to /var/run/BackupPC with FHS. 1435 1436=item B<--set-perms> 1437 1438When installing files and creating directories, chown them to 1439the BackupPC user and chmod them too. This is enabled by default. 1440To disable (for example, if staging a destination directory) 1441then specify --no-set-perms. 1442 1443=item B<--uid-ignore> 1444 1445configure.pl verifies that the script is being run as the super user 1446(root). Without the --uid-ignore option, in batch mode the script will 1447exit with an error if not run as the super user, and in interactive mode 1448the user will be prompted. Specifying this option will cause the script 1449to continue even if the user id is not root. 1450 1451=back 1452 1453=head1 EXAMPLES 1454 1455For a standard interactive install, run without arguments: 1456 1457 configure.pl 1458 1459For a batch new install you need to specify answers to all the 1460questions that are normally prompted: 1461 1462 configure.pl \ 1463 --batch \ 1464 --cgi-dir /var/www/cgi-bin/BackupPC \ 1465 --data-dir /data/BackupPC \ 1466 --hostname myHost \ 1467 --html-dir /var/www/html/BackupPC \ 1468 --html-dir-url /BackupPC \ 1469 --install-dir /usr/local/BackupPC 1470 1471For a batch upgrade, you only need to specify the path to the 1472configuration file: 1473 1474 configure.pl --batch --config-path /data/BackupPC/conf/config.pl 1475 1476=head1 AUTHOR 1477 1478Craig Barratt <cbarratt@users.sourceforge.net> 1479 1480=head1 COPYRIGHT 1481 1482Copyright (C) 2001-2010 Craig Barratt. 1483 1484This program is free software; you can redistribute it and/or modify 1485it under the terms of the GNU General Public License as published by 1486the Free Software Foundation; either version 2 of the License, or 1487(at your option) any later version. 1488 1489=cut 1490