Difference between revisions of "Tarsnap"
m (fix dbname) |
m (fix wording) |
||
(6 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | [[Category:Admin guides]] | ||
+ | {{admin_guides}} | ||
Large portions of this guide were taken from Michael W Lucas' ''[https://shop.aer.io/mwl/p/Tarsnap_Mastery_Online_Backups_for_the_Truly_Paran/9780692400203-8826?collection=Technology_Books-177660 Tarsnap Mastery]''. I highly recommend it and anything else he's written. | Large portions of this guide were taken from Michael W Lucas' ''[https://shop.aer.io/mwl/p/Tarsnap_Mastery_Online_Backups_for_the_Truly_Paran/9780692400203-8826?collection=Technology_Books-177660 Tarsnap Mastery]''. I highly recommend it and anything else he's written. | ||
= Installation = | = Installation = | ||
− | The package is called <code>tarsnap</code> on most distributions and is usually included in the official repos. After installation, generate a key and associate it with your Tarnsap account using the following command. | + | The package is called <code>tarsnap</code> on most distributions and is usually included in the official repos. If it's not, take a look at their [https://www.tarsnap.com/download.html download page]. After installation, generate a key and associate it with your Tarnsap account using the following command. |
<pre> | <pre> | ||
− | tarsnap-keygen --keyfile /root/tarsnap.key --user name@example.com --machine | + | tarsnap-keygen --keyfile /root/tarsnap.key --user name@example.com --machine HOSTNAME |
</pre> | </pre> | ||
= Configuration = | = Configuration = | ||
− | The configuration file is usually stored in <code>/etc/tarsnap.conf</code>. You may need to copy the sample configuration to the | + | The configuration file is usually stored in <code>/etc/tarsnap.conf</code>. You may need to copy the sample configuration to <code>/etc/</code> from elsewhere but it's likely already in the right place. This is what we use but make sure to look at the sample and read the manual before copying and pasting this. |
<pre> | <pre> | ||
Line 24: | Line 26: | ||
We use [https://github.com/alexjurkiewicz/acts/ ACTS] for automation. It stands for ''Another Calendar-based Tarsnap Script'' and manages backup creation and rotation. It keeps 31 daily backups, 12 monthly backups, and never deletes yearly backups; maintaining those are on you. When you feel like a specific yearly backup is no longer necessary, delete it yourself. | We use [https://github.com/alexjurkiewicz/acts/ ACTS] for automation. It stands for ''Another Calendar-based Tarsnap Script'' and manages backup creation and rotation. It keeps 31 daily backups, 12 monthly backups, and never deletes yearly backups; maintaining those are on you. When you feel like a specific yearly backup is no longer necessary, delete it yourself. | ||
− | After adding a new user to our database that has read-only access to everything, we'll | + | After adding a new user to our database that has read-only access to everything, we'll create pre- and post-backup scripts for managing database dumps, configure ACTS, then set up email alerts. |
== Database dumps == | == Database dumps == | ||
Line 36: | Line 38: | ||
=== Setting PostgreSQL up === | === Setting PostgreSQL up === | ||
− | Same as above but PostgreSQL variant; you'll have to repeat | + | Same as above but PostgreSQL variant; you'll have to repeat these statements after connecting to ''every'' database you want backed up. From what I can tell, there is no way to give a user read-only permission across ''all'' PostgreSQL databases. |
<pre> | <pre> | ||
CREATE ROLE archive WITH LOGIN ENCRYPTED PASSWORD 'CHANGEMETOSOMETHINGSECURE'; | CREATE ROLE archive WITH LOGIN ENCRYPTED PASSWORD 'CHANGEMETOSOMETHINGSECURE'; | ||
Line 42: | Line 44: | ||
GRANT USAGE ON SCHEMA public TO archive; | GRANT USAGE ON SCHEMA public TO archive; | ||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO archive; | GRANT SELECT ON ALL TABLES IN SCHEMA public TO archive; | ||
+ | GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO archive; | ||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO archive; | ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO archive; | ||
+ | ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON SEQUENCES TO archive; | ||
</pre> | </pre> | ||
Line 58: | Line 62: | ||
DAY=$(date +%Y-%m-%d) | DAY=$(date +%Y-%m-%d) | ||
− | # Pick database server, postgres or mysql | + | # Pick a database server, postgres or mysql |
DATABASE=postgres | DATABASE=postgres | ||
Line 73: | Line 77: | ||
############################# | ############################# | ||
# Set the read-only user's password | # Set the read-only user's password | ||
− | PGPASSWORD='CHANGEMETOSOMETHINGSECURETOO' | + | export PGPASSWORD='CHANGEMETOSOMETHINGSECURETOO' |
# Space-separated list of databases for backing up | # Space-separated list of databases for backing up | ||
DBNAME="dbname1 dbname2" | DBNAME="dbname1 dbname2" | ||
Line 107: | Line 111: | ||
== ACTS configuration == | == ACTS configuration == | ||
− | ACTS can be installed by simply <code>wget</code>ing <code>acts</code> and <code>acts.conf.sample</code> directly from the repo. Alternatively, you can clone the whole repository and symlink <code>acts</code> to wherever you like for easier updates then copy <code>acts.conf.sample</code> to <code>/etc/acts.conf</code>. The following is how we do it. | + | ACTS can be installed by simply <code>wget</code>ing <code>acts</code> and <code>acts.conf.sample</code> directly from [https://github.com/alexjurkiewicz/acts/ the repo]. Alternatively, you can clone the whole repository and symlink <code>acts</code> to wherever you like for easier updates then copy <code>acts.conf.sample</code> to <code>/etc/acts.conf</code>. The following is how we do it. |
<pre> | <pre> | ||
Line 115: | Line 119: | ||
</pre> | </pre> | ||
− | Make sure you reference the sample configuration file but these are the base options we use. Add additional directories to the <code>backuptargets</code> line, omitting the preceding <code>/</code>. Until you run ACTS and verify that your configuration works properly, leave <code>verbose</code> set to 1. After you're sure everything works, set it to 0. ACTS | + | Make sure you reference the sample configuration file but these are the base options we use. Add additional directories to the <code>backuptargets</code> line, omitting the preceding <code>/</code>. Until you run ACTS and verify that your configuration works properly, leave <code>verbose</code> set to 1. After you're sure everything works, set it to 0. ACTS expects the config file to be located in <code>/etc/acts.conf</code> |
<pre> | <pre> | ||
Line 133: | Line 137: | ||
</pre> | </pre> | ||
− | == Failure | + | == Failure notifications == |
− | + | We use XMPP for most of our internal communication and have a dedicated MUC for alerts. There are tools such as [https://github.com/lhost/sendxmpp sendxmpp] that allows for piping messages to arbitrary MUCs and contacts. However, that <code>sendxmpp</code> implementation isn't available in all repositories. [https://salsa.debian.org/mdosch/go-sendxmpp go-sendxmpp] is an alternative written in Go that provides pre-built binaries for a large number of platforms. | |
+ | |||
+ | Download the binary, make it executable, then move it to <code>/usr/local/bin</code>. Put the following script in <code>/usr/local/scripts/alert</code> then make it executable. It takes input from <code>stdin</code>, stores it in a variable, then uses that variable in a message template that contains the cronjob's name and the machine's hostname. All of that is stored in another variable then piped to <code>go-sendxmpp</code>. The <code>go-sendxmpp</code> invocation requires TLS, sets its name to <code>Alert</code>, then relays whatever is passed on <code>stdin</code> to the <code>example@muc.example.com</code> MUC. | ||
+ | |||
+ | <pre> | ||
+ | #!/bin/bash | ||
+ | |||
+ | STDIN=$(</dev/stdin) | ||
+ | |||
+ | MSG="$1 cronjob on $(cat /etc/hostname) just exited.\n\`\`\`\n$STDIN\n\`\`\`" | ||
+ | |||
+ | echo -e "$MSG" | /usr/local/bin/go-sendxmpp -tr 'Alert' -c example@muc.example.com | ||
+ | </pre> | ||
+ | |||
+ | Before attempting to run the script, create <code>/root/.sendxmpprc</code> with the following contents, replacing USERNAME and PASSWORD with your bot's credentials. | ||
+ | |||
+ | <pre> | ||
+ | username: USERNAME | ||
+ | password: PASSWORD | ||
+ | </pre> | ||
+ | |||
+ | With all of this in place, run the following and see if the setup works. | ||
+ | |||
+ | <pre> | ||
+ | echo 'This is a test' | /usr/local/scripts/alert Test | ||
+ | </pre> | ||
+ | |||
+ | The output should look something like this. | ||
+ | |||
+ | <pre> | ||
+ | 18/11/21 | 00:15:41 Alert: Test cronjob on hostname just exited. | ||
+ | ``` | ||
+ | This is a test | ||
+ | ``` | ||
+ | </pre> | ||
+ | |||
+ | If everything works as expected, you can now use it in cronjobs like so. | ||
+ | |||
+ | <pre> | ||
+ | @daily a command to do something 2>&1 | /usr/local/scripts/alert 'Cronjob title' | ||
+ | </pre> | ||
= Backups = | = Backups = | ||
Yes, backups for the backups are necessary. Specifically, backups of backup ''keys'' are necessary; if you lose the key, you lose your backups. There is no way around this. While saving your key in a password manager, in a text file on your PC, on someone else's PC (please don't ever do this), or even on another server are all potential solutions, it's good to have an offline copy Just In Case™. We use [https://github.com/intra2net/paperbackup paperbackup] because it's easily read by both machines (QR codes) and humans (plain text); run your key through this, print the resulting PDF, put it in a folder, put the folder in a box, and put the box somewhere very very safe. | Yes, backups for the backups are necessary. Specifically, backups of backup ''keys'' are necessary; if you lose the key, you lose your backups. There is no way around this. While saving your key in a password manager, in a text file on your PC, on someone else's PC (please don't ever do this), or even on another server are all potential solutions, it's good to have an offline copy Just In Case™. We use [https://github.com/intra2net/paperbackup paperbackup] because it's easily read by both machines (QR codes) and humans (plain text); run your key through this, print the resulting PDF, put it in a folder, put the folder in a box, and put the box somewhere very very safe. |
Latest revision as of 08:33, 18 November 2021
Large portions of this guide were taken from Michael W Lucas' Tarsnap Mastery. I highly recommend it and anything else he's written.
Contents
Installation
The package is called tarsnap
on most distributions and is usually included in the official repos. If it's not, take a look at their download page. After installation, generate a key and associate it with your Tarnsap account using the following command.
tarsnap-keygen --keyfile /root/tarsnap.key --user name@example.com --machine HOSTNAME
Configuration
The configuration file is usually stored in /etc/tarsnap.conf
. You may need to copy the sample configuration to /etc/
from elsewhere but it's likely already in the right place. This is what we use but make sure to look at the sample and read the manual before copying and pasting this.
cachedir /usr/local/tarsnap-cache keyfile /root/tarsnap.key nodump print-stats checkpoint-bytes 1G humanize-numbers
Automation
We use ACTS for automation. It stands for Another Calendar-based Tarsnap Script and manages backup creation and rotation. It keeps 31 daily backups, 12 monthly backups, and never deletes yearly backups; maintaining those are on you. When you feel like a specific yearly backup is no longer necessary, delete it yourself.
After adding a new user to our database that has read-only access to everything, we'll create pre- and post-backup scripts for managing database dumps, configure ACTS, then set up email alerts.
Database dumps
Refer to SQL Snippets for more quick commands regarding SQL databases.
Setting MySQL up
Add a new user with a complicated password and minimal permissions to all databases with the following SQL command.
grant lock tables,show view,select on *.* to 'archive'@'localhost' identified by 'CHANGEMETOSOMETHINGSECURE';
Setting PostgreSQL up
Same as above but PostgreSQL variant; you'll have to repeat these statements after connecting to every database you want backed up. From what I can tell, there is no way to give a user read-only permission across all PostgreSQL databases.
CREATE ROLE archive WITH LOGIN ENCRYPTED PASSWORD 'CHANGEMETOSOMETHINGSECURE'; \c dbname GRANT USAGE ON SCHEMA public TO archive; GRANT SELECT ON ALL TABLES IN SCHEMA public TO archive; GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO archive; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO archive; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON SEQUENCES TO archive;
Scripting the dumps
We store scripts in /usr/local/scripts
but you can put them wherever. This one is named /usr/local/scripts/pre-acts.sh
. Make sure to change the variables according to your needs.
#!/bin/sh ###################################################### # MAKE SURE TO CHANGE VALUES ACCORDING TO YOUR NEEDS # ###################################################### # Create a timestamp for dump names DAY=$(date +%Y-%m-%d) # Pick a database server, postgres or mysql DATABASE=postgres # Dump file location DUMPFILE=/root/db_dumps/$DATABASE-backup-$DAY ########################## # MYSQL-SPECIFIC OPTIONS # ########################## MYSQLPASSWORD='CHANGEMETOSOMETHINGSECURE' ############################# # POSTGRES-SPECIFIC OPTIONS # ############################# # Set the read-only user's password export PGPASSWORD='CHANGEMETOSOMETHINGSECURETOO' # Space-separated list of databases for backing up DBNAME="dbname1 dbname2" case $DATABASE in mysql) touch $DUMPFILE chown 0:0 $DUMPFILE chmod 600 $DUMPFILE mysqldump -u archive -p$MYSQLPASSWORD --all-databases > $DUMPFILE ;; postgres) for i in $DBNAME do PGDUMP=$DUMPFILE-$i touch $PGDUMP chown 0:0 $PGDUMP chmod 600 $PGDUMP pg_dump -h 127.0.0.1 -U archive -Fp -n public -O -x -d $i > $PGDUMP done ;; esac exit
This one is stored in /usr/local/scripts/post-acts.sh
. It deletes all dumps older than 5 days.
#!/bin/sh find /root/db_dumps/ -type f -mtime +5 -delete
Make sure these are marked as executable with chmod +x /path/to/script.sh
.
ACTS configuration
ACTS can be installed by simply wget
ing acts
and acts.conf.sample
directly from the repo. Alternatively, you can clone the whole repository and symlink acts
to wherever you like for easier updates then copy acts.conf.sample
to /etc/acts.conf
. The following is how we do it.
cd /root/ git clone https://github.com/alexjurkiewicz/acts/ ln -s /root/acts/acts /usr/local/scripts/acts
Make sure you reference the sample configuration file but these are the base options we use. Add additional directories to the backuptargets
line, omitting the preceding /
. Until you run ACTS and verify that your configuration works properly, leave verbose
set to 1. After you're sure everything works, set it to 0. ACTS expects the config file to be located in /etc/acts.conf
backuptargets="usr/local/scripts root/db_dumps" tarsnapbackupoptions="--one-file-system --humanize-numbers" verbose=1 prebackupscript=/usr/local/scripts/pre-acts.sh postbackupscript=/usr/local/scripts/post-acts.sh
Cronjob
This runs ACTS at 02:30 on every day of every month.
# min hour day month weekday command 30 2 * * * /usr/local/scripts/acts
Failure notifications
We use XMPP for most of our internal communication and have a dedicated MUC for alerts. There are tools such as sendxmpp that allows for piping messages to arbitrary MUCs and contacts. However, that sendxmpp
implementation isn't available in all repositories. go-sendxmpp is an alternative written in Go that provides pre-built binaries for a large number of platforms.
Download the binary, make it executable, then move it to /usr/local/bin
. Put the following script in /usr/local/scripts/alert
then make it executable. It takes input from stdin
, stores it in a variable, then uses that variable in a message template that contains the cronjob's name and the machine's hostname. All of that is stored in another variable then piped to go-sendxmpp
. The go-sendxmpp
invocation requires TLS, sets its name to Alert
, then relays whatever is passed on stdin
to the example@muc.example.com
MUC.
#!/bin/bash STDIN=$(</dev/stdin) MSG="$1 cronjob on $(cat /etc/hostname) just exited.\n\`\`\`\n$STDIN\n\`\`\`" echo -e "$MSG" | /usr/local/bin/go-sendxmpp -tr 'Alert' -c example@muc.example.com
Before attempting to run the script, create /root/.sendxmpprc
with the following contents, replacing USERNAME and PASSWORD with your bot's credentials.
username: USERNAME password: PASSWORD
With all of this in place, run the following and see if the setup works.
echo 'This is a test' | /usr/local/scripts/alert Test
The output should look something like this.
18/11/21 | 00:15:41 Alert: Test cronjob on hostname just exited. ``` This is a test ```
If everything works as expected, you can now use it in cronjobs like so.
@daily a command to do something 2>&1 | /usr/local/scripts/alert 'Cronjob title'
Backups
Yes, backups for the backups are necessary. Specifically, backups of backup keys are necessary; if you lose the key, you lose your backups. There is no way around this. While saving your key in a password manager, in a text file on your PC, on someone else's PC (please don't ever do this), or even on another server are all potential solutions, it's good to have an offline copy Just In Case™. We use paperbackup because it's easily read by both machines (QR codes) and humans (plain text); run your key through this, print the resulting PDF, put it in a folder, put the folder in a box, and put the box somewhere very very safe.