Skip to content

Commit 490f28d

Browse files
committed
Added backup tool, fixed #14
1 parent 61fc97a commit 490f28d

8 files changed

Lines changed: 450 additions & 67 deletions

File tree

INSTALL.md

Lines changed: 71 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -54,73 +54,73 @@ systemctl restart php8.2-fpm
5454

5555
```bash
5656
server {
57-
listen 80;
58-
server_name %%DOMAIN%%;
59-
return 301 https://%%DOMAIN%%/request_uri/;
57+
listen 80;
58+
server_name %%DOMAIN%%;
59+
return 301 https://%%DOMAIN%%/request_uri/;
6060
}
6161

6262
server {
63-
listen 443 ssl;
64-
http2 on;
65-
ssl_certificate /etc/letsencrypt/live/%%DOMAIN%%/fullchain.pem;
66-
ssl_certificate_key /etc/letsencrypt/live/%%DOMAIN%%/privkey.pem;
67-
ssl_stapling on;
68-
ssl_stapling_verify on;
69-
70-
set $root_path '%%SOURCE_PATH%%';
71-
server_name %%DOMAIN%%;
72-
73-
index index.php;
74-
root $root_path;
75-
try_files $uri $uri/ @rewrite;
76-
sendfile off;
77-
include /etc/nginx/mime.types;
78-
79-
# Block access to sensitive files and return 404 to make it indistinguishable from a missing file
80-
location ~* .(ini|sh|inc|bak|twig|sql)$ {
81-
return 404;
82-
}
83-
84-
# Block access to hidden files except .well-known
85-
location ~ /\.(?!well-known\/) {
86-
return 404;
87-
}
88-
89-
# Disable PHP execution in /uploads
90-
location ~* /uploads/.*\.php$ {
91-
return 404;
92-
}
93-
94-
# Deny access to /data
95-
location ~* /data/ {
96-
return 404;
97-
}
98-
99-
location @rewrite {
100-
rewrite ^/page/(.*)$ /index.php?_url=/custompages/$1;
101-
rewrite ^/(.*)$ /index.php?_url=/$1;
102-
}
103-
104-
location ~ \.php {
105-
fastcgi_split_path_info ^(.+\.php)(/.+)$;
106-
107-
# fastcgi_pass need to be changed according your server setup:
108-
# phpx.x is your server setup
109-
# examples: /var/run/phpx.x-fpm.sock, /var/run/php/phpx.x-fpm.sock or /run/php/phpx.x-fpm.sock are all valid options
110-
# Or even localhost:port (Default 9000 will work fine)
111-
# Please check your server setup
112-
113-
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
114-
fastcgi_param PATH_INFO $fastcgi_path_info;
115-
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
116-
fastcgi_intercept_errors on;
117-
include fastcgi_params;
118-
}
119-
120-
location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
121-
root $root_path;
122-
expires off;
123-
}
63+
listen 443 ssl;
64+
http2 on;
65+
ssl_certificate /etc/letsencrypt/live/%%DOMAIN%%/fullchain.pem;
66+
ssl_certificate_key /etc/letsencrypt/live/%%DOMAIN%%/privkey.pem;
67+
ssl_stapling on;
68+
ssl_stapling_verify on;
69+
70+
set $root_path '%%SOURCE_PATH%%';
71+
server_name %%DOMAIN%%;
72+
73+
index index.php;
74+
root $root_path;
75+
try_files $uri $uri/ @rewrite;
76+
sendfile off;
77+
include /etc/nginx/mime.types;
78+
79+
# Block access to sensitive files and return 404 to make it indistinguishable from a missing file
80+
location ~* .(ini|sh|inc|bak|twig|sql)$ {
81+
return 404;
82+
}
83+
84+
# Block access to hidden files except .well-known
85+
location ~ /\.(?!well-known\/) {
86+
return 404;
87+
}
88+
89+
# Disable PHP execution in /uploads
90+
location ~* /uploads/.*\.php$ {
91+
return 404;
92+
}
93+
94+
# Deny access to /data
95+
location ~* /data/ {
96+
return 404;
97+
}
98+
99+
location @rewrite {
100+
rewrite ^/page/(.*)$ /index.php?_url=/custompages/$1;
101+
rewrite ^/(.*)$ /index.php?_url=/$1;
102+
}
103+
104+
location ~ \.php {
105+
fastcgi_split_path_info ^(.+\.php)(/.+)$;
106+
107+
# fastcgi_pass need to be changed according your server setup:
108+
# phpx.x is your server setup
109+
# examples: /var/run/phpx.x-fpm.sock, /var/run/php/phpx.x-fpm.sock or /run/php/phpx.x-fpm.sock are all valid options
110+
# Or even localhost:port (Default 9000 will work fine)
111+
# Please check your server setup
112+
113+
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
114+
fastcgi_param PATH_INFO $fastcgi_path_info;
115+
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
116+
fastcgi_intercept_errors on;
117+
include fastcgi_params;
118+
}
119+
120+
location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
121+
root $root_path;
122+
expires off;
123+
}
124124
}
125125
```
126126

@@ -417,4 +417,10 @@ Navigate to https://github.com/getnamingo/fossbilling-dns and follow the install
417417

418418
2. In your contact page, you will need to list all company details, including registration number and name of CEO.
419419

420-
3. Some manual tune-in is still required in various parts.
420+
3. Some manual tune-in is still required in various parts.
421+
422+
### Setup Backup
423+
424+
To ensure the safety and availability of your data in Namingo, it's crucial to set up and verify automated backups. Begin by editing the backup.json file in the automation directory, where you'll input your database details. Ensure that the details for the database are accurately entered in two specified locations within the backup.json file.
425+
426+
Additionally, check that the cronjob for PHPBU is correctly scheduled on your server `cron.php`, as this automates the backup process. You can verify this by reviewing your server's cronjob list. These steps are vital to maintain regular, secure backups of your system, safeguarding against data loss and ensuring business continuity.

automation/backup-upload.php

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
require __DIR__ . '/vendor/autoload.php';
4+
5+
require_once 'helpers.php';
6+
7+
use League\Flysystem\Filesystem;
8+
use League\Flysystem\PhpseclibV3\SftpConnectionProvider;
9+
use League\Flysystem\PhpseclibV3\SftpAdapter;
10+
use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
11+
use Spatie\FlysystemDropbox\DropboxAdapter;
12+
use Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter;
13+
use Monolog\Logger;
14+
use Monolog\Handler\StreamHandler;
15+
use League\Flysystem\AdapterInterface;
16+
17+
$logFilePath = '/var/log/backup_upload.log';
18+
$log = setupLogger($logFilePath, 'Backup_Upload');
19+
$log->info('job started.');
20+
21+
// Storage type: 'sftp', 'dropbox', or 'google_drive'
22+
$storageType = 'sftp'; // Set this to your preferred storage
23+
24+
// Setup the filesystem based on the storage type
25+
switch ($storageType) {
26+
case 'sftp':
27+
$sftpProvider = new SftpConnectionProvider(
28+
'your_sftp_host', // host
29+
'your_username', // username
30+
'your_password', // password
31+
'/path/to/my/private_key', // private key
32+
'passphrase', // passphrase
33+
22, // port
34+
true, // use agent
35+
30, // timeout
36+
10, // max tries
37+
'fingerprint-string' // host fingerprint
38+
// connectivity checker (optional)
39+
);
40+
41+
$visibilityConverter = PortableVisibilityConverter::fromArray([
42+
'file' => [
43+
'public' => 0640,
44+
'private' => 0604,
45+
],
46+
'dir' => [
47+
'public' => 0740,
48+
'private' => 7604,
49+
],
50+
]);
51+
52+
$adapter = new SftpAdapter($sftpProvider, '/upload', $visibilityConverter);
53+
break;
54+
case 'dropbox':
55+
$client = new \Spatie\Dropbox\Client('your_dropbox_access_token');
56+
$adapter = new DropboxAdapter($client);
57+
break;
58+
case 'google_drive':
59+
$client = new \Google\Client();
60+
$client->setClientId('your_client_id');
61+
$client->setClientSecret('your_client_secret');
62+
$client->refreshToken('your_refresh_token');
63+
$service = new \Google\Service\Drive($client);
64+
$adapter = new GoogleDriveAdapter($service, 'your_folder_id');
65+
break;
66+
default:
67+
$log->error("Invalid storage type");
68+
exit;
69+
}
70+
71+
$filesystem = new Filesystem($adapter);
72+
73+
// Function to upload a file with try-catch for error handling
74+
function uploadFile($filesystem, $localPath, $remotePath, $logger) {
75+
try {
76+
if (file_exists($localPath)) {
77+
$stream = fopen($localPath, 'r+');
78+
$filesystem->writeStream($remotePath, $stream);
79+
if (is_resource($stream)) {
80+
fclose($stream);
81+
}
82+
$logger->info("Uploaded: $localPath to $remotePath");
83+
} else {
84+
$logger->warning("File not found: $localPath");
85+
}
86+
} catch (Exception $e) {
87+
$logger->error("Error uploading $localPath: " . $e->getMessage());
88+
}
89+
}
90+
91+
// Current date and hour in the specified format
92+
$currentDateHour = date('Ymd-H'); // Format: YYYYMMDD-HH
93+
94+
// Directory to check
95+
$directory = '/srv/';
96+
97+
// Pattern to match files
98+
$pattern = "/^database-$currentDateHour.*\.sql\.bz2$/";
99+
$pattern2 = "/^files-$currentDateHour.*\.bz2$/";
100+
$pattern3 = "/^registrarweb-$currentDateHour.*\.bz2$/";
101+
102+
// Scan directory for matching files
103+
$files = scandir($directory);
104+
foreach ($files as $file) {
105+
if (preg_match($pattern, $file) || preg_match($pattern2, $file) || preg_match($pattern3, $file)) {
106+
$localPath = $directory . $file;
107+
$remoteFileName = basename($file);
108+
uploadFile($filesystem, $localPath, $remoteFileName, $log);
109+
}
110+
}

automation/backup.json

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"verbose": true,
3+
"logging": [
4+
{
5+
"type": "json",
6+
"target": "/var/log/backup.log"
7+
}
8+
],
9+
"backups": [
10+
{
11+
"name": "Database",
12+
"source": {
13+
"type": "mysqldump",
14+
"options": {
15+
"databases": "registrar",
16+
"user": "your_username",
17+
"password": "your_password"
18+
}
19+
},
20+
"target": {
21+
"dirname": "/srv",
22+
"filename": "database-%Y%m%d-%H%i.sql",
23+
"compress": "bzip2"
24+
},
25+
"checks": [
26+
{
27+
"type": "sizemin",
28+
"value": "10M"
29+
}
30+
],
31+
"cleanup": {
32+
"type": "Capacity",
33+
"options": {
34+
"size": "750M"
35+
}
36+
}
37+
},
38+
{
39+
"name": "Files",
40+
"source": {
41+
"type": "tar",
42+
"options": {
43+
"path": "/opt/registrar",
44+
"throttle": "5m"
45+
}
46+
},
47+
"target": {
48+
"dirname": "/srv",
49+
"filename": "files-%Y%m%d-%H%i",
50+
"compress": "bzip2"
51+
},
52+
"checks": [
53+
{
54+
"type": "sizemin",
55+
"value": "10M"
56+
}
57+
],
58+
"cleanup": {
59+
"type": "Capacity",
60+
"options": {
61+
"size": "750M"
62+
}
63+
}
64+
},
65+
{
66+
"name": "Files",
67+
"source": {
68+
"type": "tar",
69+
"options": {
70+
"path": "/var/www",
71+
"throttle": "5m"
72+
}
73+
},
74+
"target": {
75+
"dirname": "/srv",
76+
"filename": "registrarweb-%Y%m%d-%H%i",
77+
"compress": "bzip2"
78+
},
79+
"checks": [
80+
{
81+
"type": "sizemin",
82+
"value": "10M"
83+
}
84+
],
85+
"cleanup": {
86+
"type": "Capacity",
87+
"options": {
88+
"size": "750M"
89+
}
90+
}
91+
}
92+
]
93+
}

automation/composer.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
{
22
"require": {
33
"peppeocchi/php-cron-scheduler": "^4.0",
4-
"phpmailer/phpmailer": "^6.9.1"
4+
"phpmailer/phpmailer": "^6.9.1",
5+
"phpseclib/phpseclib": "^3.0",
6+
"phpbu/phpbu": "^6.0",
7+
"monolog/monolog": "^3.7",
8+
"league/flysystem": "^3.28",
9+
"league/flysystem-sftp-v3": "^3.28"
510
}
611
}

automation/cron.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
<?php
22

3+
// Configuration
4+
$cronJobConfig = [
5+
'backup' => false, // Set to true to enable
6+
];
7+
38
require __DIR__ . '/vendor/autoload.php';
49

510
use GO\Scheduler;
@@ -13,4 +18,9 @@
1318
$scheduler->php('/opt/registrar/automation/errp_dns.php')->at('0 2 * * *');
1419
$scheduler->php('/opt/registrar/automation/urs.php')->at('45 * * * *');
1520

21+
if ($cronJobConfig['backup']) {
22+
$scheduler->raw('/opt/registrar/automation/vendor/bin/phpbu --configuration=/opt/registrar/automation/backup.json')->at('15 * * * *');
23+
$scheduler->php('/opt/registrar/automation/backup-upload.php')->at('30 * * * *');
24+
}
25+
1626
$scheduler->run();

0 commit comments

Comments
 (0)