====== CentOS / RHEL7 / Fedora + Nginx + Backuppc ====== This combination gave me no documentation online, Recently Backuppc is available as SCGI Script version.\\ I did not had luck setting that up, as nginx lack documentation for scgi. So let's get started, If you are here you might already know there is no packaged version of Backuppc 4.x available. I've decided to take shortcut and repackaged latest version available from fedora 27. Once you install the package you should be good to go, configuration and all needed files are in place. ==== Installation ==== yum install -y BackupPC-4.1.5-1.el7.x86_64.rpm BackupPC-XS-0.57-1.el7.x86_64.rpm rsync-bpc-3.0.9.11-1.el7.x86_64.rpm nginx Optional : CPAN Module only needed if you are planning to use scgi version. cpan install SCGI ==== Configuration ==== === In configuration i've only changed few of the options to make it work under browser. === --- config.pl.sample 2018-02-14 13:48:27.000000000 -0500 +++ config.pl 2018-02-14 17:52:05.123281171 -0500 @@ -41,7 +41,7 @@ # # Host name on which the BackupPC server is running. # -$Conf{ServerHost} = 'localhost'; +$Conf{ServerHost} = 'backup.k2patel.in'; # # TCP port number on which the BackupPC server listens for and accepts @@ -257,7 +281,7 @@ # Full path to the df command. Security caution: normal users # should not allowed to write to this file or directory. # -$Conf{DfPath} = '/bin/df'; +$Conf{DfPath} = '/usr/bin/df'; # # Command to run df. The following variables are substituted at run-time: @@ -274,15 +298,15 @@ # # Full path to various commands for archiving # -$Conf{SplitPath} = '/bin/split'; -$Conf{ParPath} = "/usr/bin/par2"; +$Conf{SplitPath} = '/usr/bin/split'; +$Conf{ParPath} = '/usr/bin/par2'; -$Conf{CatPath} = '/bin/cat'; -$Conf{GzipPath} = '/bin/gzip'; -$Conf{Bzip2Path} = '/bin/bzip2'; +$Conf{CatPath} = '/usr/bin/cat'; +$Conf{GzipPath} = '/usr/bin/gzip'; +$Conf{Bzip2Path} = '/usr/bin/bzip2'; # -# Maximum threshold for disk utilization on the /var/lib/BackupPC/ filesystem. +# Maximum threshold for disk utilization on the __TOPDIR__ filesystem. # If the output from $Conf{DfPath} reports a percentage larger than # this number then no new regularly scheduled backups will be run. # However, user requested backups (which are usually incremental and @@ -349,12 +373,12 @@ # a symbolic link to the new location, or mount the new BackupPC # store at the existing $Conf{TopDir} setting. # -$Conf{TopDir} = '/var/lib/BackupPC/'; -$Conf{ConfDir} = '/etc/BackupPC/'; -$Conf{LogDir} = '/var/log/BackupPC'; -$Conf{RunDir} = '/var/run/BackupPC'; -$Conf{InstallDir} = '/usr/share/BackupPC'; -$Conf{CgiDir} = '/usr/libexec/BackupPC'; +$Conf{TopDir} = '/var/lib/libvirt/images'; +$Conf{ConfDir} = '/etc/BackupPC/'; +$Conf{LogDir} = '/var/log/BackupPC'; +$Conf{RunDir} = '/var/run/BackupPC'; +$Conf{InstallDir} = '/usr/share/BackupPC'; +$Conf{CgiDir} = '/usr/libexec/BackupPC'; @@ -1984,8 +2001,8 @@ # $Conf{CgiAdminUsers} = 'craig celia'; # --> administrative users are only craig and celia'. # -$Conf{CgiAdminUserGroup} = ''; -$Conf{CgiAdminUsers} = ''; +$Conf{CgiAdminUserGroup} = 'admin'; +$Conf{CgiAdminUsers} = 'admin'; # # TCP port number of the SCGI server. A negative value disables the @@ -2016,7 +2033,7 @@ # Full URL of the BackupPC_Admin CGI script, or the configured path # for SCGI. Used for links in email messages. # -$Conf{CgiURL} = "http://localhost/BackupPC"; +$Conf{CgiURL} = 'https://backup.k2patel.in/cgi-bin/BackupPC_Admin'; # # Full path to the rrdtool command. If available, graphs of pool usage @@ -2151,7 +2171,7 @@ # Example: # $Conf{CgiImageDirURL} = '/BackupPC'; # -$Conf{CgiImageDirURL} = '/BackupPC/images'; +$Conf{CgiImageDirURL} = '/BackupPC'; # # CSS stylesheet "skin" for the CGI interface. It is stored === Nginx Configuration === worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; server { listen 80; server_name backup.k2patel.in; return 302 https://backup.k2patel.in$request_uri; } server { listen 443 ssl http2; server_name backup.k2patel.in; ssl on; ssl_certificate /etc/pki/tls/certs/k2patel.in.crt; ssl_certificate_key /etc/pki/tls/private/k2patel.in.key; ssl_trusted_certificate /etc/pki/tls/certs/k2patel.in.int.ca; # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) add_header Strict-Transport-Security max-age=63072000; # OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify off; # modern configuration. tweak to your needs. ssl_protocols TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; ssl_prefer_server_ciphers on; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; add_header Strict-Transport-Security max-age=63072000; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } access_log /var/log/nginx/backuppc.access.log; error_log /var/log/nginx/backuppc.error.log; location / { auth_basic "Backup"; auth_basic_user_file /usr/local/etc/nginx/backuppc.users; root /usr/share/BackupPC/html; return 302 http://backup.k2patel.in/cgi-bin/BackupPC_Admin; index BackupPC.html; } location /BackupPC { alias /usr/share/BackupPC/html; index BackupPC.html; } #location ~\.cgi$ { location ~ ^/cgi-bin/BackupPC_Admin(/|$) { auth_basic "Backup"; auth_basic_user_file /etc/nginx/backuppc.users; gzip off; include /etc/nginx/fastcgi_params; fastcgi_pass localhost:8999; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_USER $remote_user; fastcgi_param SCRIPT_FILENAME /usr/share/BackupPC/sbin/BackupPC_Admin; } location ~ /\.ht { deny all; } } } ==== Required Third party scripts ==== #!/usr/bin/perl use FCGI; use Socket; use POSIX qw(setsid); require 'syscall.ph'; &daemonize; #this keeps the program alive or something after exec'ing perl scripts END() { } BEGIN() { } *CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; }; eval q{exit}; if ($@) { exit unless $@ =~ /^fakeexit/; }; &main; sub daemonize() { chdir '/' or die "Can't chdir to /: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; umask 0; } sub main { $socket = FCGI::OpenSocket( "127.0.0.1:8999", 10 ); #use IP sockets $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket ); if ($request) { request_loop()}; FCGI::CloseSocket( $socket ); } sub request_loop { while( $request->Accept() >= 0 ) { #processing any STDIN input from WebServer (for CGI-POST actions) $stdin_passthrough =''; $req_len = 0 + $req_params{'CONTENT_LENGTH'}; if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){ my $bytes_read = 0; while ($bytes_read < $req_len) { my $data = ''; my $bytes = read(STDIN, $data, ($req_len - $bytes_read)); last if ($bytes == 0 || !defined($bytes)); $stdin_passthrough .= $data; $bytes_read += $bytes; } } #running the cgi app if ( (-x $req_params{SCRIPT_FILENAME}) && #can I execute this? (-s $req_params{SCRIPT_FILENAME}) && #Is this file empty? (-r $req_params{SCRIPT_FILENAME}) #can I read this file? ){ pipe(CHILD_RD, PARENT_WR); my $pid = open(KID_TO_READ, "-|"); unless(defined($pid)) { print("Content-type: text/plain\r\n\r\n"); print "Error: CGI app returned no output - "; print "Executing $req_params{SCRIPT_FILENAME} failed !\n"; next; } if ($pid > 0) { close(CHILD_RD); print PARENT_WR $stdin_passthrough; close(PARENT_WR); while(my $s = ) { print $s; } close KID_TO_READ; waitpid($pid, 0); } else { foreach $key ( keys %req_params){ $ENV{$key} = $req_params{$key}; } # cd to the script's local directory if ($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) { chdir $1; } close(PARENT_WR); close(STDIN); #fcntl(CHILD_RD, F_DUPFD, 0); syscall(&SYS_dup2, fileno(CHILD_RD), 0); #open(STDIN, "<&CHILD_RD"); exec($req_params{SCRIPT_FILENAME}); die("exec failed"); } } else { print("Content-type: text/plain\r\n\r\n"); print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not "; print "exist or is not executable by this process.\n"; } } } === Systemd Script === [Unit] Description=Fast CGI wrapper After=network.target [Service] Type=forking TimeoutStopSec=0 User=backuppc Group=backuppc ExecStart=/usr/local/sbin/fastcgi-wrapper [Install] WantedBy=multi-user.target ==== Final Note ==== Once everything is configured you should be able to access your backuppc using user admin.\\