This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
centos_nginx_backuppc4.x [2018/02/15 17:42] k2patel |
centos_nginx_backuppc4.x [2020/08/10 02:35] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== CentOS / Fedora + Nginx + Backuppc ====== | + | ====== CentOS / RHEL7 / Fedora + Nginx + Backuppc ====== |
This combination gave me no documentation online, Recently Backuppc is available as SCGI Script version.\\ | This combination gave me no documentation online, Recently Backuppc is available as SCGI Script version.\\ | ||
Line 7: | Line 7: | ||
Once you install the package you should be good to go, configuration and all needed files are in place. | Once you install the package you should be good to go, configuration and all needed files are in place. | ||
+ | |||
+ | ==== Installation ==== | ||
<code bash | Needed Packages> | <code bash | Needed Packages> | ||
Line 20: | Line 22: | ||
==== Configuration ==== | ==== Configuration ==== | ||
+ | |||
+ | === In configuration i've only changed few of the options to make it work under browser. === | ||
+ | |||
+ | |||
+ | <code diff| /etc/BackupPC/config.pl> | ||
+ | --- 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 | ||
+ | </code> | ||
+ | |||
+ | === Nginx Configuration === | ||
+ | <code bash | /etc/nginx/nginx.conf> | ||
+ | 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; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Required Third party scripts ==== | ||
+ | <code perl | /usr/local/sbin/fastcgi-wrapper | http://nginxlibrary.com/downloads/perl-fcgi/fastcgi-wrapper> | ||
+ | #!/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 = <KID_TO_READ>) { 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"; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === Systemd Script === | ||
+ | <code bash | /etc/systemd/system/fcgiwrapper.service> | ||
+ | [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 | ||
+ | </code> | ||
+ | |||
+ | ==== Final Note ==== | ||
+ | Once everything is configured you should be able to access your backuppc using user admin.\\ | ||
+ | |||