{"id":219,"date":"2024-03-05T19:21:36","date_gmt":"2024-03-06T03:21:36","guid":{"rendered":"https:\/\/blog.sacko.dev\/?p=219"},"modified":"2024-03-05T19:31:51","modified_gmt":"2024-03-06T03:31:51","slug":"how-to-create-a-full-backup-system-with-linux-scp-and-cron","status":"publish","type":"post","link":"https:\/\/blog.sacko.dev\/?p=219","title":{"rendered":"How to Create a Full Backup System with Linux scp and cron"},"content":{"rendered":"\n<p>I wanted to create a backup system using tools I already knew, such as scp. I set up a way for it to send a backup to a remote server at home with a 2nd SSH key specifically for the task.<\/p>\n\n\n\n<p>1. Generate the key on the server you&#8217;ll be backing up with <strong>ssh-keygen<\/strong>. Save the key to something like ~\/.ssh\/backup-key, and configure it how you like.<\/p>\n\n\n\n<p>2. Transfer the private key to your PC (not any of the servers). Disconnect from the server by typing <strong>exit<\/strong>, then <strong>scp <\/strong>the key to your PC. This will transfer the private key to your PC so you can copy it to the server you are backing up to.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>exit\nscp -i ~\/.ssh\/<strong>current-key<\/strong> <strong>server-user<\/strong>@<strong>server-to-backup.domain<\/strong>:\/home\/<strong>server-user<\/strong>\/.ssh\/<strong>backup-key<\/strong>  ~\/.ssh\/<strong>backup-key<\/strong><\/code><\/pre>\n\n\n\n<p>3. Transfer the private key to the server you are backing up to. There&#8217;s a few ways to do this, but I used this method since I already had authentication set up with a different SSH key. Replace <strong>backup-key<\/strong> with your new key if you used a different name, and replace <strong>current-priv-key<\/strong> with your current working key.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>scp -i ~\/.ssh\/<strong>current-priv-key<\/strong> ~\/.ssh\/<strong>backup-key<\/strong> <strong>bkup-user<\/strong>@<strong>the-backup-server.domain<\/strong>:\/home\/<strong>bkup-user<\/strong>\/.ssh\/backup-key<\/code><\/pre>\n\n\n\n<p>4. Connect to the server you are backing up to. Create the backup folder <strong>\/home\/bkup-user\/backup<\/strong>, then a folder for the server you are backing up, such as <strong>\/home\/bkup-user\/backup\/server-name<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># ssh into the backup server before doing this, and run it there\nmkdir \/home\/<strong>bkup-user<\/strong>\/backup\nmkdir \/home\/<strong>bkup-user<\/strong>\/backup\/<strong>server-name<\/strong><\/code><\/pre>\n\n\n\n<p>5. Create a script that we will use for crontab to run. Use <strong>nano <\/strong>to open it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nano \/home\/<strong>bkup-user<\/strong>\/<strong>backup-script.sh<\/strong><\/code><\/pre>\n\n\n\n<p>6. Copy this script, and change the parts in bold as needed. We will be making a couple scripts on the backup server itself as well after this.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#! \/bin\/bash\n# runs scripts on the server that backs up databases and creates a tar file with all the files needed to be backed up\nssh -i .ssh\/<strong>backup-key<\/strong> <strong>server-user<\/strong>@<strong>server-to-backup.domain<\/strong> \".\/backup.sh\"\n# once above command runs, it is disconnected\n# back on the backup server, downloads temp directory to the backup server\nscp -r -i .ssh\/<strong>backup-key<\/strong> <strong>server-user<\/strong>@<strong>server-to-backup.domain<\/strong>:\/home\/<strong>server-user<\/strong>\/temp \/home\/<strong>bkup-user<\/strong>\/backup\/<strong>server-name<\/strong>\n# everything is downloaded to \/temp; this will move it down a directory\nmv \/home\/<strong>bkup-user<\/strong>\/backup\/<strong>server-name<\/strong>\/temp\/* \/home\/<strong>bkup-user<\/strong>\/backup\/server-name\n# removes the temp folder\nrm -r \/home\/<strong>bkup-user<\/strong>\/backup\/<strong>server-name<\/strong>\/<strong>temp<\/strong>\n# deletes all files older than 30 days\nfind \/home\/<strong>bkup-user<\/strong>\/backup\/<strong>server-name<\/strong> -type f -mtime +30 -delete\n# goes back into the remote server and deletes the backed up file\nssh -i .ssh\/<strong>backup-key<\/strong> <strong>server-user<\/strong>@<strong>server-to-backup.domain<\/strong> \".\/bkup_deltemp.sh\"<\/code><\/pre>\n\n\n\n<p>7. Give the script executable permissions with <strong>chmod<\/strong>. Then open the <strong>crontab <\/strong>editor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod +x \/home\/<strong>bkup-user<\/strong>\/<strong>backup-script.sh<\/strong>\ncrontab -e<\/code><\/pre>\n\n\n\n<p>8. Add this line to crontab. This will run the script daily at 12am. Then exit crontab with ctrl+x and save the settings.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>0 0 * * * \/home\/<strong>bkup-user<\/strong>\/<strong>backup-script.sh<\/strong><\/code><\/pre>\n\n\n\n<p>9. Open up <strong>visudo <\/strong>to give the script sudo permissions.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo visudo<\/code><\/pre>\n\n\n\n<p>10. Add this line to the sudoers file that opened, then ctrl+x and save the configuration.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>bkup-user<\/strong> ALL=(ALL) NOPASSWD:\/home\/<strong>bkup-user<\/strong>\/<strong>backup-script.sh<\/strong><\/code><\/pre>\n\n\n\n<p>11. Disconnect from the backup server, then connect with <strong>ssh <\/strong>to the <strong>server you are backing up<\/strong>. Create a temp folder.<\/p>\n\n\n\n<p># ssh into the server you are backing up before doing this, and run it there<br>mkdir \/home\/<strong>server-user<\/strong>\/temp<\/p>\n\n\n\n<p>12. Open up a new script with nano called backup.sh, then give it this code and save it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#! \/bin\/bash\ntar -czvf \"\/home\/<strong>server-user<\/strong>\/temp\/<strong>server-name<\/strong>-$(date +\"%d-%m-%Y\").tar.gz\" -T backup-list.txt<\/code><\/pre>\n\n\n\n<p>13. Create another script with nano for deleting the temp contents once the backup is completed. Name it bkup_deltemp.sh and give it this code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#! \/bin\/bash\nrm \/home\/<strong>server-user<\/strong>\/temp\/*<\/code><\/pre>\n\n\n\n<p>14. Create a text file with nano that you will use to set up the directories and files you want to backup. Here is an example text file I use to back up my web server:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/<strong>server-user<\/strong>\/backup-list.txt\n\/home\/<strong>server-user<\/strong>\/bkup_script.sh\n\/home\/<strong>server-user<\/strong>\/bkup_deltemp.sh\n\/etc\/systemd\/system\/website-1.service\n\/etc\/systemd\/system\/website-2.service\n\/var\/www\n\/etc\/nginx\/sites-available\n\/etc\/nginx\/sites-enabled<\/code><\/pre>\n\n\n\n<p>15. The back up should now be set up. You can test this by logging into the backup server and running the backup script, then checking the ~\/backup\/server-name folder for a .tar.gz file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/backup-script.sh\ncd ~\/backup\/<strong>server-name<\/strong><\/code><\/pre>\n\n\n\n<p>This does not include a mysql database backup, as I did not want to add more complexity to this post. If you have a mysql database backup already configured, you can add it to the backup-list.txt.<\/p>\n\n\n\n<p>Otherwise, you can look into creating a separate script to backup mysql, use a cron job on the server to run it an hour before (0 23 * * *), and include the mysql backup files into the backup-list.txt. I used this script from github: <a href=\"https:\/\/gist.github.com\/zertrin\/5883555#file-mysqlbackup-sh-L8\">GitHub Script<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to create a backup system using tools I already knew, such as scp. I set up a way for it to send a backup to a remote server at home with a 2nd SSH key specifically for the task. 1. Generate the key on the server you&#8217;ll be backing up with ssh-keygen. Save <a href=\"https:\/\/blog.sacko.dev\/?p=219\" class=\"more-link\">&#8230;<span class=\"screen-reader-text\">  How to Create a Full Backup System with Linux scp and cron<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=\/wp\/v2\/posts\/219"}],"collection":[{"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=219"}],"version-history":[{"count":6,"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=\/wp\/v2\/posts\/219\/revisions"}],"predecessor-version":[{"id":226,"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=\/wp\/v2\/posts\/219\/revisions\/226"}],"wp:attachment":[{"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.sacko.dev\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}