Updating to include systemd timers
Better Makefile layout Improving pytest
This commit is contained in:
parent
49f9f6d315
commit
3b49a6c49e
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ nodeslist
|
|||||||
*.tar.xz
|
*.tar.xz
|
||||||
pkg/
|
pkg/
|
||||||
src/
|
src/
|
||||||
|
**/__pycache__
|
||||||
|
77
Makefile
77
Makefile
@ -1,76 +1,25 @@
|
|||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
BACKUPDIR := /usr/local/backup
|
BACKUPDIR := /usr/local/backup
|
||||||
|
|
||||||
client: user aether.bash
|
|
||||||
cp aether.bash /home/aether/aether.bash
|
|
||||||
/home/aether/aether.bash
|
|
||||||
sudo -u aether crontab -l > /tmp/cronie
|
|
||||||
grep aether.bash /tmp/cronie || echo '0 1 * * * /home/aether/aether.bash &>> /var/log/aether.log' >> /tmp/cronie
|
|
||||||
sudo -u aether crontab /tmp/cronie
|
|
||||||
rm /tmp/cronie
|
|
||||||
touch /var/log/aether.log
|
|
||||||
chown aether:aether /var/log/aether.log
|
|
||||||
make checkperm
|
|
||||||
|
|
||||||
compile:
|
compile:
|
||||||
@echo Nothing to do
|
@echo Nothing to do
|
||||||
|
|
||||||
install: compile
|
install: compile
|
||||||
@echo You must specify client or server in a call to make.
|
mkdir -p ${pkgdir}/usr/local/sbin
|
||||||
|
mkdir -p ${pkgdir}/usr/local/etc
|
||||||
server: keys scripts user ./aether-gen.bash ./aether.pub ./server-backup
|
install -m 0750 -o aether aether.bash ${pkgdir}/usr/local/sbin
|
||||||
bash ./aether-gen.bash
|
install -m 0750 -o root -g root aether-gen.bash ${pkgdir}/usr/local/sbin
|
||||||
cp ./aether.pub /home/aether/.ssh/authorized_keys
|
install -m 0750 -o root -g root remote-backup ${pkgdir}/usr/local/sbin
|
||||||
cp ./aether-gen.bash /root/bin/aether-gen.bash
|
install -m 0750 -o aether -d ${pkgdir}/usr/local/etc/Aether
|
||||||
mkdir -p /usr/local/etc/Aether/backup-entries
|
install -m 0750 -o aether -d ${pkgdir}/usr/local/etc/Aether/backup-entries
|
||||||
touch /usr/local/etc/Aether/nodeslist
|
mkdir -p ${pkgdir}/usr/lib/systemd/system
|
||||||
mkdir -p ${BACKUPDIR};
|
for i in *.service *.timer; do install -m 0640 -o root -g root "$$i" ${pkgdir}/usr/lib/systemd/system; done
|
||||||
make checkperm
|
|
||||||
@echo You have the files. Add aether-gen.bash and server-backup to root\'s crontab.
|
|
||||||
@echo Mark services to be backed up by adding a file from examples/ to /usr/local/etc/Aether/backup-entries
|
|
||||||
@echo Track client nodes in /usr/local/etc/Aether/nodeslist
|
|
||||||
|
|
||||||
user: aether make-user.bash
|
|
||||||
/bin/bash ./make-user.bash
|
|
||||||
|
|
||||||
node-command:
|
|
||||||
@echo USE THE FOLLOWING COMMANDS TO SET UP A NODE.
|
|
||||||
@echo -ne 'git clone https://aninix.net/foundation/Aether;'
|
|
||||||
@echo
|
|
||||||
@echo -ne 'cd Aether; cat > aether # Paste the private key'
|
|
||||||
@echo
|
|
||||||
@echo -ne 'make client'
|
|
||||||
@echo
|
|
||||||
@echo MAKE SURE TO ADD THE NODE TO /usr/local/etc/Aether/nodes.list
|
|
||||||
|
|
||||||
keys:
|
|
||||||
if [ ! -f ./aether ]; then ssh-keygen -t rsa -P "" -f aether; fi
|
|
||||||
|
|
||||||
scripts: ./server-backup ./remote-backup
|
|
||||||
cp ./server-backup /root/bin
|
|
||||||
cp ./remote-backup /root/bin
|
|
||||||
make checkperm
|
|
||||||
|
|
||||||
reverse:
|
|
||||||
if [ -f /root/bin/server-backup ]; then cp /root/bin/server-backup .; fi
|
|
||||||
if [ -f /root/bin/remote-backup ]; then cp /root/bin/remote-backup .; fi
|
|
||||||
if [ -f /root/bin/aether-gen.bash ]; then cp /root/bin/aether-gen.bash .; fi
|
|
||||||
if [ -f /home/aether/aether.bash ]; then cp /home/aether/aether.bash .; fi
|
|
||||||
|
|
||||||
diff:
|
|
||||||
if [ -f /root/bin/server-backup ]; then diff ./server-backup /root/bin/server-backup; fi
|
|
||||||
if [ -f /root/bin/remote-backup ]; then diff ./remote-backup /root/bin/remote-backup; fi
|
|
||||||
if [ -f /root/bin/aether-gen.bash ]; then diff ./aether-gen.bash /root/bin/aether-gen.bash; fi
|
|
||||||
if [ -f /home/aether/aether.bash ]; then diff ./aether.bash /home/aether/aether.bash; fi
|
|
||||||
|
|
||||||
checkperm:
|
checkperm:
|
||||||
id aether;
|
for i in ${pkgdir}/usr/local/sbin/aether.bash ${pkgdir}/usr/local/sbin/aether-gen.bash ${pkgdir}/usr/local/sbin/remote-backup ${pkgdir}/usr/local/etc/Aether; do chmod 0750 "$$i"; done
|
||||||
if [ -d /home/aether ]; then chmod 0600 /home/aether/.ssh/authorized_keys; chmod 0700 /home/aether/.ssh /home/aether; chown -R aether:aether /home/aether; fi
|
for i in ${pkgdir}/usr/local/sbin/aether.bash ${pkgdir}/usr/local/sbin/aether-gen.bash ${pkgdir}/usr/local/sbin/remote-backup ${pkgdir}/usr/local/etc/Aether; do chown root: "$$i"; done
|
||||||
if [ -f /root/bin/remote-backup ]; then chmod 0700 /root/bin/remote-backup; chown root:root /root/bin/remote-backup; fi
|
chown aether: ${pkgdir}/usr/local/sbin/aether.bash
|
||||||
if [ -f /root/bin/server-backup ]; then chmod 0700 /root/bin/server-backup; chown root:root /root/bin/server-backup; fi
|
for i in *.service *.timer; do chown root: ${pkgdir}/usr/lib/systemd/system; chmod 0640 ${pkgdir}/usr/lib/systemd/system; done
|
||||||
if [ -d /usr/local/etc/Aether ]; then chmod -R 0700 /usr/local/etc/Aether; chown -R aether:aether /usr/local/etc/Aether; fi
|
|
||||||
if [ -d ${BACKUPDIR} ]; then chmod 0770 ${BACKUPDIR}; chown postgres:root ${BACKUPDIR}; fi
|
|
||||||
if [ -f /var/log/aether.log ]; then chown aether:aether /var/log/aether.log; chmod 0750 /var/log/aether.log; fi
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@bash -c 'printf "This will irreversibly destroy all backups. Confirm? [YES/no] " ; read answer; [ "$$answer" == "YES" ] && exit 0; exit 1'
|
@bash -c 'printf "This will irreversibly destroy all backups. Confirm? [YES/no] " ; read answer; [ "$$answer" == "YES" ] && exit 0; exit 1'
|
||||||
|
2
PKGBUILD
2
PKGBUILD
@ -19,7 +19,7 @@ conflicts=()
|
|||||||
replaces=("${pkgname,,}", "aninix-${pkgname,,}")
|
replaces=("${pkgname,,}", "aninix-${pkgname,,}")
|
||||||
backup=()
|
backup=()
|
||||||
options=()
|
options=()
|
||||||
install=
|
install=installscript
|
||||||
changelog=
|
changelog=
|
||||||
source=()
|
source=()
|
||||||
noextract=()
|
noextract=()
|
||||||
|
15
README.md
15
README.md
@ -10,20 +10,27 @@ You have two options to install this project:
|
|||||||
* Arch Linux and related distros: Run `makepkg -sri`
|
* Arch Linux and related distros: Run `makepkg -sri`
|
||||||
* Other operating systems: Run `make install`
|
* Other operating systems: Run `make install`
|
||||||
|
|
||||||
# Initial setup
|
## Initial setup
|
||||||
To create the aether and aether.pub files, run "make keys". This should not be repeated.
|
To create the aether and aether.pub files, run "make keys". This should not be repeated.
|
||||||
|
|
||||||
# Adding backup configurations
|
## Adding backup configurations
|
||||||
Individual projects wanting to be backed up by the Aether system should add a file to their package into `/usr/local/etc/Aether/backups/`.
|
Individual projects wanting to be backed up by the Aether system should add a file to their package into `/usr/local/etc/Aether/backups/`.
|
||||||
|
|
||||||
|
## Tracking Nodes
|
||||||
|
A SIEM filter should be set up to search for successful logins of the `aether` user.
|
||||||
|
|
||||||
# Relevant Files and Software
|
# Relevant Files and Software
|
||||||
Aether installs a script for rsync-based remote backups. We implement this policy through the two 4TB hard-drives, at least one of which is always off-site, that can be plugged into the [Maat](/Wiki/Hosts/Maat.md) hotswap bay along with a virtual machine that mounts the ArchLinux iso and the drive in the bay.
|
Aether installs a script for rsync-based remote backups. We implement this policy through the two 8TB hard-drives, at least one of which is always off-site, that can be plugged into a hotswap bay of a hypervisor along with a virtual machine that mounts the ArchLinux iso and the drive. Admins use the included ssh daemon in the iso to present the drive as a backup target,
|
||||||
|
|
||||||
|
An additional backup is the generated `/home/aether/aether.enc` file. This is a more targeted backup of databases and file indexes.
|
||||||
|
|
||||||
|
Keep in mind that all of [AniNIX/Foundation](https://foundation.aninix.net) is naturally a backup solution -- so long as anyone has a clone of the repo, the data survives.
|
||||||
|
|
||||||
# Available Clients
|
# Available Clients
|
||||||
The only client is direct server access on one of the client nodes.
|
The only client is direct server access on one of the client nodes.
|
||||||
|
|
||||||
# Equivalents or Competition
|
# Equivalents or Competition
|
||||||
Equivalent services are DropBox, Google Drive, or Barracuda.
|
Equivalent services are DropBox, Google Drive, iCloud, or OneDrive.
|
||||||
|
|
||||||
# Notes
|
# Notes
|
||||||
Those deploying Aether should maintain a nodeslist file that only root can read.
|
Those deploying Aether should maintain a nodeslist file that only root can read.
|
||||||
|
@ -1,31 +1,29 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
export LOGFILE="/var/log/aether-gen.log"
|
# File: aether-gen.bash
|
||||||
|
#
|
||||||
|
# Description: This file generates the backup in an encrypted format.
|
||||||
|
#
|
||||||
|
# Package: AniNIX/HelloWorld
|
||||||
|
# Copyright: WTFPL
|
||||||
|
#
|
||||||
|
# Author: DarkFeather <ircs://aninix.net:6697/DarkFeather>
|
||||||
|
|
||||||
export BACKUPDIR="/usr/local/backup"
|
export BACKUPDIR="/usr/local/backup"
|
||||||
export BACKUPCMD="rsync -avzl --delete-after";
|
export BACKUPCMD="rsync -avzl --delete-after";
|
||||||
|
|
||||||
date >> "$LOGFILE"
|
|
||||||
chown root:root "$BACKUPDIR"
|
chown root:root "$BACKUPDIR"
|
||||||
chmod 0770 "$BACKUPDIR"
|
chmod 0770 "$BACKUPDIR"
|
||||||
|
|
||||||
for i in `find /usr/local/etc/Aether/backup-entries/ -type f`; do
|
for i in `find /usr/local/etc/Aether/backup-entries/ -type f`; do
|
||||||
bash "${i}" &>> "$LOGFILE"
|
bash "${i}"
|
||||||
done
|
done
|
||||||
|
|
||||||
date > "$BACKUPDIR"/lastbackup.date
|
date > "$BACKUPDIR"/lastbackup.date
|
||||||
|
|
||||||
cd /home/aether
|
cd /home/aether
|
||||||
|
|
||||||
echo Creating and compressing archive...
|
echo Creating and encrypting archive...
|
||||||
tar cvf aether.tar /usr/local/backup
|
tar cvzf - /usr/local/backup | openssl enc -aes256 -pass file:/usr/local/etc/Aether/pass.txt -in aether.tar.gz -out aether.enc
|
||||||
gzip -f aether.tar
|
|
||||||
|
|
||||||
echo Encrypting archive
|
|
||||||
openssl enc -aes256 -pass file:/usr/local/etc/Aether/pass.txt -in aether.tar.gz -out aether.enc
|
|
||||||
rm aether.tar.gz
|
|
||||||
|
|
||||||
echo Created aether archive.
|
echo Created aether archive.
|
||||||
|
|
||||||
date >> "$LOGFILE"
|
|
||||||
echo >> "$LOGFILE"
|
|
||||||
|
11
aether-gen.service
Normal file
11
aether-gen.service
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=AniNIX/Aether | Generation
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Nice=19
|
||||||
|
IOSchedulingClass=best-effort
|
||||||
|
IOSchedulingPriority=7
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/sbin/aether-gen.bash
|
||||||
|
|
||||||
|
#EOF
|
11
aether-gen.timer
Normal file
11
aether-gen.timer
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=AniNIX/Aether | Generation
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=01:00
|
||||||
|
Persistent=false
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
|
||||||
|
#EOF
|
12
aether.service
Normal file
12
aether.service
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=AniNIX/Aether | Pull-back
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Nice=19
|
||||||
|
IOSchedulingClass=best-effort
|
||||||
|
IOSchedulingPriority=7
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/sbin/aether
|
||||||
|
User=aether
|
||||||
|
|
||||||
|
#EOF
|
11
aether.timer
Normal file
11
aether.timer
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=AniNIX/Aether | Pull-back
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=05:00
|
||||||
|
Persistent=false
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
|
||||||
|
#EOF
|
9
installscript
Normal file
9
installscript
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pre_install() {
|
||||||
|
groupadd aether &>/dev/null
|
||||||
|
useradd -g aether -d /srv/aether -s /bin/false aether &> /dev/null
|
||||||
|
chown -R aether:aether /srv/aether &> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
pre_remove() {
|
||||||
|
getent passwd aether &>/dev/null && userdel aether &> /dev/null
|
||||||
|
}
|
@ -1,17 +1,44 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# File: HelloWorld.bash
|
||||||
|
#
|
||||||
|
# Description: This file exemplifies printing 'Hello world!' in bash.
|
||||||
|
#
|
||||||
|
# Package: AniNIX/HelloWorld
|
||||||
|
# Copyright: WTFPL
|
||||||
|
#
|
||||||
|
# Author: DarkFeather <ircs://aninix.net:6697/DarkFeather>
|
||||||
|
|
||||||
|
# Should only be done as root.
|
||||||
if [ "$(whoami)" != "root" ]; then
|
if [ "$(whoami)" != "root" ]; then
|
||||||
echo Needs to be run as root.
|
echo Needs to be run as root.
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (ping -c 4 "$1" | grep -c ' 0% packet loss,'); then
|
# Default the host to the Aether host in whatever domain this host lives in.
|
||||||
printf "Are you sure you want to back everything up to %s?\nIs the root password set and all storage mounted?\nDo you have time for this backup to complete?\nEnter YES in all capitals to continue..." "$1"
|
host="$1"
|
||||||
|
if [ -z "$host" ]; then
|
||||||
|
host=Aether
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default the path to /
|
||||||
|
path="$2"
|
||||||
|
if [ -z "$path" ]; then
|
||||||
|
path='/'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to contract the host
|
||||||
|
if (nmap --open -p 22 "$host" | grep -E '22/tcp\s+open' &>/dev/null); then
|
||||||
|
|
||||||
|
# Confirm with the user
|
||||||
|
printf "Are you sure you want to back everything up to %s?\n* Is the root password set and backup volume mounted on '/mnt'?\n* Do you have time for this backup to complete?\n* Does \`ssh-keyscan -D localhost\` on the server match this? `ssh-keyscan -D "$host" 2>/dev/null | grep 4\ 2`\nEnter YES in all capitals to continue..." "$host"
|
||||||
|
|
||||||
read answer
|
read answer
|
||||||
if [ "$answer" != "YES" ]; then
|
if [ "$answer" != "YES" ]; then
|
||||||
echo User did not confirm.
|
echo User did not confirm.
|
||||||
exit 1;
|
exit 1;
|
||||||
else
|
else
|
||||||
rsync -aAXv --delete --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / root@"$1":/mnt/
|
rsync -aAXv --delete --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} "$path" root@"$host":/mnt"$path"
|
||||||
status="$?"
|
status="$?"
|
||||||
echo rsync exited with status $status
|
echo rsync exited with status $status
|
||||||
exit $status
|
exit $status
|
||||||
|
@ -5,7 +5,7 @@ import subprocess
|
|||||||
# TODO Still need to devise a testing strategy (https://foundation.aninix.net/AniNIX/Aether/issues/1)
|
# TODO Still need to devise a testing strategy (https://foundation.aninix.net/AniNIX/Aether/issues/1)
|
||||||
def test_aether():
|
def test_aether():
|
||||||
print(os.getcwd())
|
print(os.getcwd())
|
||||||
fh = os.popen("echo bye | sftp -o IdentityFile=./aether aether@aninix.net", mode='r', buffering=-1)
|
fh = os.popen("echo bye | timeout 3 sftp -o IdentityFile=./aether aether@aninix.net", mode='r', buffering=-1)
|
||||||
output = fh.read()
|
output = fh.read()
|
||||||
retcode = fh.close()
|
retcode = fh.close()
|
||||||
assert retcode == None and CheckOutput(output)
|
assert retcode == None
|
||||||
|
Loading…
Reference in New Issue
Block a user