Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mailinabox
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
mailinabox
Commits
89730bd6
Commit
89730bd6
authored
Jun 03, 2014
by
Joshua Tauberer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new backup script, see #11
parent
51dd2ed7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
141 additions
and
6 deletions
+141
-6
backup.py
management/backup.py
+54
-0
daemon.py
management/daemon.py
+3
-5
utils.py
management/utils.py
+77
-0
management.sh
setup/management.sh
+7
-1
No files found.
management/backup.py
0 → 100755
View file @
89730bd6
#!/usr/bin/python3
# This script performs a backup of all user data:
# 1) System services are stopped while a copy of user data is made.
# 2) An incremental backup is made using rdiff-backup into the
# directory STORAGE_ROOT/backup/rdiff-history. This directory
# will contain the latest files plus a complete history for
# all prior backups.
# 3) The stopped services are restarted.
# 4) The backup directory is compressed into a single file using tar.
# 5) That file is encrypted with a long password stored in backup/secret_key.txt.
import
os
,
os
.
path
,
subprocess
from
utils
import
exclusive_process
,
load_environment
env
=
load_environment
()
exclusive_process
(
"backup"
)
# Ensure the backup directory exists.
backup_dir
=
os
.
path
.
join
(
env
[
"STORAGE_ROOT"
],
'backup'
)
rdiff_backup_dir
=
os
.
path
.
join
(
backup_dir
,
'rdiff-history'
)
os
.
makedirs
(
backup_dir
,
exist_ok
=
True
)
# Stop services.
subprocess
.
check_call
([
"service"
,
"dovecot"
,
"stop"
])
subprocess
.
check_call
([
"service"
,
"postfix"
,
"stop"
])
# Update the backup directory which stores increments.
try
:
subprocess
.
check_call
([
"rdiff-backup"
,
"--exclude"
,
backup_dir
,
env
[
"STORAGE_ROOT"
],
rdiff_backup_dir
])
except
subprocess
.
CalledProcessError
:
pass
# Start services.
subprocess
.
check_call
([
"service"
,
"dovecot"
,
"start"
])
subprocess
.
check_call
([
"service"
,
"postfix"
,
"start"
])
# Tar the rdiff-backup directory into a single file encrypted using the backup private key.
os
.
system
(
"tar -zcC
%
s . | openssl enc -aes-256-cbc -a -salt -in /dev/stdin -out
%
s -pass file:
%
s"
%
(
rdiff_backup_dir
,
os
.
path
.
join
(
backup_dir
,
"latest.tgz.enc"
),
os
.
path
.
join
(
backup_dir
,
"secret_key.txt"
),
))
# The backup can be decrypted with:
# openssl enc -d -aes-256-cbc -a -in latest.tgz.enc -out /dev/stdout -pass file:secret_key.txt | tar -z
management/daemon.py
View file @
89730bd6
...
@@ -5,13 +5,11 @@ import os, os.path
...
@@ -5,13 +5,11 @@ import os, os.path
from
flask
import
Flask
,
request
,
render_template
from
flask
import
Flask
,
request
,
render_template
app
=
Flask
(
__name__
)
app
=
Flask
(
__name__
)
# Load settings from /etc/mailinabox.conf.
import
utils
env
=
{
}
for
line
in
open
(
"/etc/mailinabox.conf"
):
env
.
setdefault
(
*
line
.
strip
()
.
split
(
"="
,
1
))
env
[
"CONF_DIR"
]
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"../conf"
)
from
mailconfig
import
get_mail_users
,
add_mail_user
,
set_mail_password
,
remove_mail_user
,
get_mail_aliases
,
get_mail_domains
,
add_mail_alias
,
remove_mail_alias
from
mailconfig
import
get_mail_users
,
add_mail_user
,
set_mail_password
,
remove_mail_user
,
get_mail_aliases
,
get_mail_domains
,
add_mail_alias
,
remove_mail_alias
env
=
utils
.
load_environment
()
@
app
.
route
(
'/'
)
@
app
.
route
(
'/'
)
def
index
():
def
index
():
return
render_template
(
'index.html'
)
return
render_template
(
'index.html'
)
...
...
management/utils.py
0 → 100644
View file @
89730bd6
def
load_environment
():
# Load settings from /etc/mailinabox.conf.
import
os.path
env
=
{
}
for
line
in
open
(
"/etc/mailinabox.conf"
):
env
.
setdefault
(
*
line
.
strip
()
.
split
(
"="
,
1
))
env
[
"CONF_DIR"
]
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"../conf"
)
return
env
def
exclusive_process
(
name
):
# Ensure that a process named `name` does not execute multiple
# times concurrently.
import
os
,
sys
,
atexit
pidfile
=
'/var/run/mailinabox-
%
s.pid'
%
name
mypid
=
os
.
getpid
()
# Attempt to get a lock on ourself so that the concurrency check
# itself is not executed in parallel.
with
open
(
__file__
,
'r+'
)
as
flock
:
# Try to get a lock. This blocks until a lock is acquired. The
# lock is held until the flock file is closed at the end of the
# with block.
os
.
lockf
(
flock
.
fileno
(),
os
.
F_LOCK
,
0
)
# While we have a lock, look at the pid file. First attempt
# to write our pid to a pidfile if no file already exists there.
try
:
with
open
(
pidfile
,
'x'
)
as
f
:
# Successfully opened a new file. Since the file is new
# there is no concurrent process. Write our pid.
f
.
write
(
str
(
mypid
))
atexit
.
register
(
clear_my_pid
,
pidfile
)
return
except
FileExistsError
:
# The pid file already exixts, but it may contain a stale
# pid of a terminated process.
with
open
(
pidfile
,
'r+'
)
as
f
:
# Read the pid in the file.
existing_pid
=
None
try
:
existing_pid
=
int
(
f
.
read
()
.
strip
())
except
ValueError
:
pass
# No valid integer in the file.
# Check if the pid in it is valid.
if
existing_pid
:
if
is_pid_valid
(
existing_pid
):
print
(
"Another
%
s is already running (pid
%
d)."
%
(
name
,
existing_pid
),
file
=
sys
.
stderr
)
sys
.
exit
(
1
)
# Write our pid.
f
.
seek
(
0
)
f
.
write
(
str
(
mypid
))
f
.
truncate
()
atexit
.
register
(
clear_my_pid
,
pidfile
)
def
clear_my_pid
(
pidfile
):
import
os
os
.
unlink
(
pidfile
)
def
is_pid_valid
(
pid
):
"""Checks whether a pid is a valid process ID of a currently running process."""
# adapted from http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
import
os
,
errno
if
pid
<=
0
:
raise
ValueError
(
'Invalid PID.'
)
try
:
os
.
kill
(
pid
,
0
)
except
OSError
as
err
:
if
err
.
errno
==
errno
.
ESRCH
:
# No such process
return
False
elif
err
.
errno
==
errno
.
EPERM
:
# Not permitted to send signal
return
True
else
:
# EINVAL
raise
else
:
return
True
\ No newline at end of file
setup/management.sh
View file @
89730bd6
...
@@ -2,7 +2,13 @@
...
@@ -2,7 +2,13 @@
source
setup/functions.sh
source
setup/functions.sh
apt_install python3-flask links
apt_install python3-flask links rdiff-backup
# Create a backup directory and a random key for encrypting backups.
mkdir
-p
$STORAGE_ROOT
/backup
if
[
!
-f
$STORAGE_ROOT
/backup/secret_key.txt
]
;
then
openssl rand
-base64
2048
>
$STORAGE_ROOT
/backup/secret_key.txt
fi
# Link the management server daemon into a well known location.
# Link the management server daemon into a well known location.
rm
-f
/usr/bin/mailinabox-daemon
rm
-f
/usr/bin/mailinabox-daemon
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment