Own Remote Backup Server

As a Proof of Concept (PoC) for your own Backup Server we provide some “code snippets” and config-files to help you getting started.

The PoC was setup on:

  • Debian 11
  • PHP 7.4
  • Apache 2.4
    • with activated REWRITE
    • with activated SSL
    • with activated PHP

Since the protocol https is “hard coded” on the configuration page “COMtrexx Backup site”, you need to serve a https-server.

All filenames are relative to /etc/apache2/.

In default configuration it is well prepared.

You can use vHosts. You do not need to use special vHosts; we do :-)

sites-enabled/000-default.conf

You can disable it using a2dissite 000-default.conf

sites-enabled/default-ssl.conf

You can disable it using a2dissite default-ssl.conf

sites-available/my.backup.auerswald.de.conf

Sure, this fqdn is “our” you should create your own.

You can devide the configuration in 2 files and include one to the other.

my.backup.auerswald.de.conf
<VirtualHost *:443>
    Include /etc/apache2/sites-available/my.backup.auerswald.de
    SSLEngine on
    SSLCertificateFile    /var/www/my.backup.auerswald.de/ssl/my.backup.auerswald.de.pem
    SSLCertificateKeyFile /var/www/my.backup.auerswald.de/ssl/my.backup.auerswald.de.key
</VirtualHost>

Which will include the following file:

sites-available/my.backup.auerswald.de

my.backup.auerswald.de
    ServerName my.backup.auerswald.de
    DocumentRoot /var/www/my.backup.auerswald.de/www/
 
    RewriteEngine on
 
    <Directory "/var/www/my.backup.auerswald.de/www">
 
	RewriteCond %{REQUEST_METHOD} =PUT
	RewriteRule ^api/v1/backup /var/www/my.backup.auerswald.de/www/__api__/v1/backup/put.php [QSA,END]
 
        RewriteCond %{REQUEST_METHOD} =PUT
        RewriteRule ^api/backup /var/www/my.backup.auerswald.de/www/__api__/v1/backup/put.php [QSA,END]
 
	RewriteCond %{REQUEST_METHOD} =DELETE
	RewriteRule ^api/v1/backup/?([0-9-_]{32})? /var/www/my.backup.auerswald.de/www/__api__/v1/backup/delete.php?file=$1 [QSA,END]
 
        RewriteCond %{REQUEST_METHOD} =DELETE
        RewriteRule ^api/backup/?([0-9-_]{32})? /var/www/my.backup.auerswald.de/www/__api__/v1/backup/delete.php?file=$1 [QSA,END]
 
        RewriteCond %{REQUEST_METHOD} =GET
        RewriteRule ^api/v1/backup/?([0-9-_]{32})? /var/www/my.backup.auerswald.de/www/__api__/v1/backup/get.php?file=$1 [QSA,END]
 
        RewriteCond %{REQUEST_METHOD} =GET
        RewriteRule ^api/backup/?([0-9-_]{32})? /var/www/my.backup.auerswald.de/www/__api__/v1/backup/get.php?file=$1 [QSA,END]
 
	RewriteCond %{REQUEST_METHOD} =GET
	RewriteRule ^api/v1/system/info /var/www/my.backup.auerswald.de/www/__api__/v1/system/info/info.get.php [END]
 
        RewriteCond %{REQUEST_METHOD} =GET
        RewriteRule ^api/system/info    /var/www/my.backup.auerswald.de/www/__api__/v1/system/info/info.get.php [END]
    </Directory>

Do not forget to create a certificate and a private key.

You must enable it using a2ensite my.backup.auerswald.de.conf

As you see the DocumentRoot is set to DocumentRoot /var/www/my.backup.auerswald.de/www/ you need to create this directory or adapt the config.

Here you need some files … all filenames are relative to the DocumentRoot.

Your Webserver need rights to read here.

/__api__/v1/backup/delete.php

delete.php
<?php
 
// erwartete Parameter: list, latest
$DELETE_FILE=$_GET['file'];
 
require('include_common.php');
 
// Dirname & Filename
$dirname = getDirectoryName();
$filename=$dirname.$DELETE_FILE;
 
unlink($filename);
 
?>

/__api__/v1/backup/get.php

get.php
<?php
 
require('include_common.php');
 
// Dirname & Filename
$dirname = getDirectoryName();
 
if (isset($_GET['file']) && strlen($_GET['file'])) {
	$filename = $dirname . $_GET['file'];
	// echo '-> file "'. $filename . '" (' . strlen($_GET['file']) . ')';
	if (file_exists($filename)) {
	    header('Content-Description: File Transfer');
	    header('Content-Type: application/octet-stream');
	    header('Content-Disposition: attachment; filename="'.basename($filename).'"');
	    header('Expires: 0');
	    header('Cache-Control: must-revalidate');
	    header('Pragma: public');
	    header('Content-Length: ' . filesize($filename));
	    readfile($filename);
	    http_response_code(200);
	} else {
        // echo '404';	
		http_response_code(404);
	}
	exit;
} else {
 
	$files=scanDirForFiles($dirname);
 
	if (DEBUG) 
	{
		echo "Scanned, start: \n";
		var_dump ($files);
		echo "Scanned, end: \n";
	}
 
 
	echo json_encode ($files) . "\n";
}
 
?>

/__api__/v1/backup/include_common.php

Do NOT change the name of the FILE which contains the backup. COMtrexx will parse all files (using GET method without supplying a filename to download) on the webserver and accepts files only with this “filename-schema”:

date("Y-m-d__H-i-s", $now)

.

include_common.php
<?php
 
define('TEST',  false );
define('DEBUG', false );
 
define ('DATA_DIR', '../../../data/');
 
function getDateForFileName() {
	// create date and time as string
	$now = time();
	$formatedDate = date('Y-m-d__H-i-s', $now);
	$filename = $formatedDate.'__'.$now;
	if (DEBUG) {
		echo "Filename: $filename <br />\n";
	}
	return $filename;
}
 
 
function getDirectoryName() {
	$dirName = DATA_DIR . '/mypbxbackup/' .  $subdir . '/';
	if (DEBUG) {
		echo "Directory: $dirName <br />\n";
	}	
	return $dirName;
}
 
function scanDirForFiles($dirname)
{
        $directory = scandir($dirname,  SCANDIR_SORT_DESCENDING);
        $files = array();
        foreach ($directory as $file) {
            if ($file[0] !== '.' && is_file($dirname . $file)) {
 
                    $files[] = $file;
            }
        }
        return ($files);
}
 
?>

/__api__/v1/backup/put.php

put.php
<?php
 
require('include_common.php');
 
// Dirname & Filename
$dirname = getDirectoryName();
$filename = $dirname . getDateForFileName(); 
 
try {
	mkdir ($dirname, 0777, true);
	$fp = fopen( $filename, "w");
 
	// read file / PUT from stdin Stream in 1k blocks and write to file
	// https://www.php.net/manual/de/features.file-upload.put-method.php
	$putdata = fopen("php://input", "r");   
	while ($data = fread($putdata, 1024)) {
		fwrite($fp, $data);
	}
 
	// close stream / file
	fclose($putdata);
	fclose($fp);
} catch (Exception $e) {
    echo '', $e->getMessage(), "\n";
}
?>

/__api__/v1/system/info/info.get.php

info.get.php
<?php
 
$info = new stdClass();
$info->status = 200;
$info->text = 'Server running';
 
echo json_encode($info);
 
?>

Here you need a directory … all filenames are relative to the DocumentRoot.

data/mypbxbackup

Your Webserver needs rights to write/delete/read/mkdir here.

  • en/products/comtrexx/developer/remotebackup/ownserver.txt
  • Last modified: 31.01.2023 19:42
  • by kubiak