BackupPC server

Package installation

apt-get install --no-install-recommends apache2 ssl-cert backuppc libfile-rsyncp-perl

The backuppc package in Precise triggers some Perl warning:

 * Starting backuppc...
Use of qw(...) as parentheses is deprecated at /usr/share/backuppc/lib/BackupPC/Storage/Text.pm line 302.
Use of qw(...) as parentheses is deprecated at /usr/share/backuppc/lib/BackupPC/Lib.pm line 1425.

Until LP #1119628 is addressed, you can simply run this sed command to fix the warnings:

sed -i 's/\(^[[:space:]]\+foreach my \$param\) \(qw(BackupFilesOnly BackupFilesExclude)\) {$/\1 (\2) {/' /usr/share/backuppc/lib/BackupPC/Lib.pm /usr/share/backuppc/lib/BackupPC/Storage/Text.pm
or apply the following patches:
  • Text.pm.patch
  • Lib.pm.patch
  • Configuration

    Apache

    Since this service is rarely accessed via HTTP/HTTPS it is best to have the Web server offline and start it when needed:

    update-rc.d -f apache2 remove
    

    Optionally, you can remove some unused modules but be careful if there are other vhosts on your server:

    a2dismod access_compat authz_groupfile autoindex autoindex cgid deflate env filter negotiation status > /dev/null
    

    It is also desirable to only access the service via HTTPS to avoid transmitting credentials in the clear:

    a2dissite 000-default
    a2ensite default-ssl
    a2enmod ssl
    
    # Force SSL
    sed -i 's/^\([[:space:]]*\)#SSLRequireSSL/\1SSLRequireSSL/' /etc/backuppc/apache.conf
    
    # Restrict access to VPN IPs only
    sed -i 's/\(Allow from all\)/#\1\n\t# Only allow VPN\n\tRequire ip 172.31.0.0\/16\n\tRequire ip 2607:f2c0:f00e:794c::\/64/' /etc/backuppc/apache.conf
    
    # Correct a packaging issue
    ln -s /etc/backuppc/apache.conf /etc/apache2/conf-enabled/backuppc.conf
    
    apache2ctl -S && service apache2 restart
    

    BackupPC

    Adding a client

    # SSH
    mkdir -m 0700 ~backup/.ssh
    cat << EOF >> ~backup/.ssh/authorized_keys
    command="/usr/local/bin/backuppc-wrapper",from="172.24.30.64,2607:f2c0:f00e:794a::64",no-agent-forwarding,no-port-forwarding,no-user-rc,no-X11-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5gjBiK5uXBrg+pzGmKLrIIYdjUhP2SVcjaLb6u/fD9czM7tnshUYQfTF7YZkDRQ5oHIlvekJg8vxGeTXnXub/5jVYdbGaTD8vFpuZg+a8egzaamLGSTwlAJka3otgHtekyaroztkxKhfOTou0c0nYcgI7kTUwQIFWe7/bBoCNy+7azGL8bHenVG6YWuuvFwe1nOpUzgPLeYuN3fcrvJP5r2nHPu7wOHsjerhO/tbaRoPOy5ffLhlfAof+tqunpgccWHCy6YnXMCAWrsg+Hn29IMIQhk99tHmYmkzBHBjTdVk4YQT012zCi/LbBk5rF0rUKrRdsluj4rzq0jEGBlWvJhza+Lkz6Q0ynw07K6E5pBgsYSk85tkiPbf0UK5WVvOKhI3znzN1Dp9P4TO1q5JXGFkEBUeyafArMUBcU7//GIKMQrTH9MQIjPVJ/YPq3/QLujXPSEjuSuM8Jz/tQ6yx1pccHgypB9mtfUDARVBCINDdqyuQKV+MpUBqny9tpZYbWJiwi/cYkDTNpNPazd8QLjRep/QKN/wj62e5yQ1SpQMxmTYxPYURBSythUIowtOvZx+1hkrzSD69RBslQCBamEq06bSwNwHsTBJFBkTHhlwc/Fyab8xEULhtPGsqNNpp7TTDw9GDaIXO7NZE3TNWdt/WJh2qDLMzKxMq7hBYrw== bck BackupPC
    EOF
    chown backup: -R ~backup/.ssh
    
    # Delete old key
    sed -i '/^command=.*Ocelot BackupPC$/d' ~backup/.ssh/authorized_keys
    
    # Sudo
    cat << "EOF" > /etc/sudoers.d/backuppc
    # read only access authorized
    backup ALL = (root) NOPASSWD: /usr/bin/rsync --server --sender -* . /*
    EOF
    chmod 0440 /etc/sudoers.d/backuppc
    
    # Limits
    printf "backup\t-\tpriority\t10\n" > /etc/security/limits.d/backup.conf
    
    # BackupPC wrapper
    cat << "EOF" > /usr/local/bin/backuppc-wrapper
    #!/bin/sh
    
    # Explicitly set the PATH to that of ENV_SUPATH in /etc/login.defs and unset
    # various other variables. For details, see:
    # https://wiki.ubuntu.com/SecurityTeam/AppArmorPolicyReview#Execute_rules
    export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    export ENV=
    export CDPATH=
    
    LOGGER="/usr/bin/logger"
    RSYNC="/usr/bin/rsync"
    SUDO="/usr/bin/sudo"
    KILL="/bin/kill"
    LOGGER_CALL="$LOGGER -t $(basename $0)"
    
    illegal_command() {
      # Do not log SSH_ORIGINAL_COMMAND for security reasons
      $LOGGER_CALL "illegal command denied"
      # Default deny
      $KILL -9 $PPID
      exit 0
    }
    
    check_rsync_command() {
      if [ "$#" -lt 6 ]; then
        # not in the form of /usr/bin/rsync --server --sender -* . /*
        illegal_command
      fi
    
      if [ "$1" != "rsync" ] && [ "$1" != "$RSYNC" ]; then
        # not invoking rsync
        illegal_command
      else
        # Remove the 1st arg with later replace it with the
        # fully qualified path to rsync
        shift
      fi
    
      if [ "$1" != "--server" ] && [ "$2" != "--sender" ]; then
        # not read only
        illegal_command
      fi
    
      # Use an exclude list if one is available
      if [ -r "${HOME}/exclude.list" ]; then
        EXCLUDE="--filter=\"merge,-/ ${HOME}/exclude.list\""
      else
        EXCLUDE=""
      fi
    
      $LOGGER_CALL "transfer start"
      # Remove first 2 known args and pass any exclude file
      shift 2
      eval $SUDO $RSYNC --server --sender "$EXCLUDE" "$@"
      $LOGGER_CALL "transfer stop"
    }
    
    if [ -z "$SSH_ORIGINAL_COMMAND" ]; then
      illegal_command
    fi
    
    case "$SSH_ORIGINAL_COMMAND" in
      *\&*)
        illegal_command
        ;;
      *\(*)
        illegal_command
        ;;
      *\{*)
        illegal_command
        ;;
      *\;*)
        illegal_command
        ;;
      *\>*)
        illegal_command
        ;;
      *\`*)
        illegal_command
        ;;
      *\|*)
        illegal_command
        ;;
      $RSYNC\ --server\ --sender\ -*\ .\ /*)
        # short path to rsync binary
        check_rsync_command $SSH_ORIGINAL_COMMAND
        ;;
      rsync\ --server\ --sender\ -*\ .\ /*)
        # short path to rsync binary
        check_rsync_command $SSH_ORIGINAL_COMMAND
        ;;
      *)
        illegal_command
        ;;
    esac
    EOF
    chmod 0755 /usr/local/bin/backuppc-wrapper