WordPress backups to a remote server

Earlier, I used a WordPress plugin to do periodic backups of the sites I’m hosting, but I came to a conclusion that it would be more reliable, flexible and fun to do the backups via a system script instead, sending the resulting backup archives to a remote server. Here’s how I ended up doing it:

First, I wanted to create a separate mariadb/mysql user with only just enough privileges to be able to make a mysqldump (using the “Principle of Least Privilege“; for the same reason the backup script is executed by an user, not by root). I chose the username ‘dumpo’ because… well. he just dumbly dumps stuff:

MariaDB [(none)]> CREATE USER 'dumpo'@'localhost' IDENTIFIED BY '<dumpopasswd>';

Then, the mysqldump user’s credentials must be stored in the ~/.my.cnf file within the backup-executing user’s home directory. Afterwards, run chmod 600 ~/.my.cnf to set the correct permissions.

  1. [mysqldump]
  2. user=dumpo
  3. password=<dumpopasswd>

The actual backup script below is executed by an user’s cronjob once a week. I added a lot of comments to the example script to explain how it works.

  1. #!/bin/bash
  3. # The device acting as a fileserver for WP backups is not always powered up,
  4. # so let's use Wake-On-LAN to make sure it is up when it is actually needed.
  5. wol <mac-address-of-fileserver>
  7. # I happen to have the same username on both the webserver and the fileserver,
  8. # that simplifies some settings.
  9. USER=<user-running-the-script>
  10. WPUSER=dumpo
  11. BFILENAME=backupwp-$(date +%d%m%Y)
  12. # I'm mailing the backup messages somewhere.
  13. MAILADR=someone@somewhere.com
  15. # Let's make a temporary working directory on the users home directory.
  16. cd /home/${USER}
  17. mkdir -p backupdb
  19. # I have three Wordpress sites on the server.
  20. # Dump the mariadb databases of those sites to the working directory.
  21. mysqldump -u ${WPUSER} SITE1 > backupdb/SITE1.sql
  22. mysqldump -u ${WPUSER} SITE2 > backupdb/SITE2.sql
  23. mysqldump -u ${WPUSER} SITE3 > backupdb/SITE3.sql
  24. mysqldump -u ${WPUSER} mysql > backupdb/MYSQL.sql
  25. echo -e "Database dump: done"
  27. # Copy the Wordpress installations to the working directory.
  28. cp -a /var/www/site1.com backupdb/
  29. cp -a /var/www/site2.com backupdb/
  30. cp -a /var/www/site3.com backupdb/
  31. echo -e "Website copy: done"
  33. # Make a tar.gz archive of the contents of the working directory.
  34. tar -czf ${BFILENAME}.tar.gz backupdb
  35. echo -e "Archive: done"
  37. # Check whether the fileserver is up and running. I'm checking the port 22
  38. # (ssh) because I'll be using rsync with ssh for upload. The loop waits for
  39. # 5 minutes for the connection, and then gives up and mails an error message.
  40. # Waiting for 5 minutes may actually be useless, because the fileserver usually
  41. # boots up within a minute, and making the backup archive already takes up some
  42. # 3-4 minutes. But just in case...
  43. CHECK=0
  44. until [[ `nmap <fileserver-ip-addr> -p 22 | grep "Host is up"` ]]
  45. do
  46.     if [ $CHECK -ge 60 ]; then
  47.         echo -e "File server unreachable, aborting!!! $(date '+%d-%m-%Y %T')" | mail -s "Backup" ${MAILADR}
  48.         exit 1
  49.     fi
  50.     sleep 5
  51.     let CHECK++
  52. done
  54. # Send the backup archive to the fileserver using rsync with ssh.
  55. rsync -e ssh ${BFILENAME}.tar.gz ${USER}@<fileserver-ip-addr>:/home/${USER}/wpbackup/
  57. # If the upload was succesful, clean up by removing the local archive and
  58. # temporary  working directory, and mail a success message; otherwise, leave
  59. # everything as it is and mail a failure message.
  60. if [[ $? == 0 ]]; then
  61.     rm ${BFILENAME}.tar.gz
  62.     rm -rf backupdb
  63.     echo -e "Wordpress and mariadb backup completed successfully at $(date '+%d-%m-%Y %T')" | mail -s "Backup" ${MAILADR}
  64. else
  65.     echo -e "Archive upload failure!!! $(date '+%d-%m-%Y %T')" | mail -s "Backup" ${MAILADR}
  66.     exit 1
  67. fi

Finally, at the fileserver end, a script – executed by the cron some time after the upload – rotates and cleans up the backups, leaving only the 4 latest backup archives:

  1. #!/bin/bash
  3. cd /home/<user>/wpbackup
  4. echo -e "Rotating Wordpress backups, removing following files:\n"
  5. ls -1t | tail -n +5 | xargs rm -v # That is 'ls dash one t'.
Posted in Linux | Tagged , , , , | Comments Off on WordPress backups to a remote server

Killing Zoom popup windows, Awesome/i3-style

During the still-ongoing Covid-19 epidemic the Zoom video conferencing app/service has been a lifeline for many, many people, including myself; I’m using Zoom several times a week. I AM very grateful to the Zoom team for making a version for Linux, too, and including Arch as an officially supported Linux distribution.

However, there’s one design ‘feature’ in Zoom which makes me grimace: the multi-window/multi-popup user interface. I firmly think that it is a bad UI design principle in all cases, but worse, it makes life very difficult for the tiling window manager users. I use Awesome window manager on the desktop and i3wm on the laptop, so you can guess where this is going…

One way to tame Zoom on these wm’s is to configure most, if not all, Zoom windows as floating, but that still leaves the annoying and unnecessary ‘informative’ popups (“John Doe has started screen sharing” and so like), which steal mouse and keyboard focus while present. I cooked up a special configuration for those popups to kill them instantly, so they never have a chance to disturb the user. (NOTE: these window rules are not perfect: due to Zoom design. they may kill windows which should be left untouched, and as a side-effect, make Zoom a ‘start-in-tray’ app, which may, or may not be desirable.)

Let’s start with Awesome. These rules go to rc.lua inside the awful.rules.rules = {}-section.

  1. -- Kill Zoom popups
  2.      { rule = { class = "zoom", instance = "zoom", name = "zoom" },
  3.        callback = function (c) 
  4.          c:kill()
  5.      end },

Then, it’s i3 time. The lines below set everything else except the main window floating. They belong to .config/i3/config

  1. for_window [class="^zoom$"] floating enable
  2. for_window [class="zoom" instance="zoom" title="zoom"] kill
  3. for_window [class="^zoom$" title="Zoom Meeting"] floating disable
Posted in Linux | Tagged , , , , , , | Comments Off on Killing Zoom popup windows, Awesome/i3-style

Server updates

This site, Dollz’n’Codez and its sister sites, Miranda and Lux Argentea, were down for some time because of an unscheduled server maintenance.

The server got some hardware updates, complete OS reinstall (still Gentoo Linux), and finally, a proper SSL support courtesy of Let’s Encrypt.

Posted in Linux | Tagged , , , | Comments Off on Server updates

Punching Pulseaudio-RTP through a firewall

As I mentioned in the previous post, I recently set up a network audio server computer using pulseaudio-rtp. Because it would have been a waste of resources to use it only for audio work, I started using it for some other services, too. For security and access control reasons I ended up installing and setting up a firewall there (UFW in my case). Of course, at that point pulseaudio-rtp stopped working…

I do not want to go through all the different setups I tried to make pulseaudio-rtp to work through a firewall, lack of proper documentation made the task quite laborous. Here’s just the working setup:

  1. On the client (i.e. the desktop), in the /etc/pulse/default.pa, set module-rtp-send port=<portofyourchoice>
  2. On the server, in the /etc/pulse/default.pa, set module-rtp-recv sap_address=
  3. In the /etc/default/ufw, set DEFAULT_FORWARD_POLICY="ACCEPT"
  4. In the firewall setup, open the <port>/udp you set up in step 1, and port 9875/udp

I found out about the undocumented port 9875 only after debugging the network traffic with tcpdump and netstat. I couldn’t find any information about that port anywhere in the pulseaudio-rtp documentation (or if it is there, it’s hidden so well that I didn’t find it).

Posted in Linux | Tagged , , , | Comments Off on Punching Pulseaudio-RTP through a firewall

M-Audio Audiophile 2496 and Pulseaudio

When I built my previous Linux workstation in 2007, I equipped it with a M-Audio Audiophile 2496 professional audio card. I was very pleased with its quality – superb sound, excellent recording capabilities, S/PDIF and MIDI in/out, and proper RCA connectors instead of the standard crappy 3,5mm jack sockets. Even my untrained ear could hear the difference in sound quality between M2496 and the motherboard’s built-in sound card. It worked excellently with both ALSA and Jack-Audio-Connection-Kit, and as the system was using Gentoo Linux, I was able to keep the system Pulseaudio-free until the end of its lifespan.

I built my current AMD Ryzen-based workstation some 2,5 years ago, and I really wanted to continue using the M2496 card somehow. However, there were two issues: first, the card uses an older PCI bus connector, which isn’t supported on modern motherboards any more (unless you use a some kind of PCI-to-PCIe adapter; not applicable in my case anyway, the water cooling takes too much space).

My solution was to buy an used Intel Atom-based Mini-ITX motherboard with a spare PCI connector, and use it with the M2496 card as an Arch Linux-based sound server. Because you cannot really avoid Pulseaudio on modern Linux desktops any more, I decided to use Pulseaudio’s RTP-based streaming solution between the desktop and the sound server.

And that brings us to the second issue: M-Audio 2496 and other ICE1712-based cards does not work with Pulseaudio out of the box. No sound, period.

There’s an open, unresolved bug report on this from more than 10 years ago… quite incomprehensible. I know that Lennart Poettering hates ICE1712-based sound cards, but this is still too much… Well, it just means that M-Audio users need to do everything the hard way, manually editing and creating configuration files.

  1. Make sure that M-Audio is set as the default sound card (usually it is set as a secondary card, check with aplay -l.): create/edit the file /etc/modprobe.d/alsa-base.conf and reboot:

    1. options snd_ice1712 index=0
    2. options snd_hda_intel index=1
  2. Add a new rule to /lib/udev/rules.d/90-pulseaudio.rules (this will be overwritten by an update, so make a backup):

    + # M-Audio Audiophile 2496
    + # ICE1712
    + ATTRS(vendor)=="0x1412", ATTRS(device)=="0x1712", ENV(PULSE_PROFILE_SET)="via-ice1712.conf"

    The vendor-string may be different on other ICE1712 cards, please check with lspci -nn.

  3. Finally, create a profile definition in /usr/share/pulseaudio/alsa-mixer/profile-sets/via-ice1712.conf

    ; Via ICE1712 multi-channel audio chipset
    ; This chipset has up to four stereo pairs of input and four stereo pairs of
    ; output, named channels 1 to 8. Also available are separate S/PDIF stereo
    ; channels (input and output), and a separate "system-out" stereo jack that
    ; supports 6-channel hardware mixing.
    ; The S/PDIF stereo channels can be controlled via the mixer for hw:0, and
    ; additionally, the 8 main outputs can be loop-routed to a separate stereo
    ; input pair, available as channels 11 and 12.
    ; Many cards available from vendors do not expose all channels from this chip
    ; to an external port, which effectively reduces the number of channels that
    ; are useful to the user. However, the ALSA driver still exposes all channels
    ; even if they are not connected.
    ; We knowingly only define a subset of the theoretically possible
    ; mapping combinations as profiles here.
    ; See default.conf for an explanation on the directives used here.
    auto-profiles = no
    [Mapping analog-mch-in]
    description = Analog Multi-Channel Main Input
    device-strings = hw:%f,0
    channel-map = aux0,aux1,front-left,front-right,aux2,aux3,aux4,aux5,aux6,aux7,aux8,aux9
    direction = input
    [Mapping analog-mch-out]
    description = Analog Multi-Channel Main Output
    device-strings = hw:%f,0
    channel-map = front-left,front-right,aux0,aux1,aux2,aux3,aux4,aux5,aux6,aux7
    direction = output
    [Mapping digital-stereo]
    description = Digital Stereo Input/Output
    device-strings = iec958:%f
    channel-map = left,right
    direction = any
    [Mapping analog-system-out]
    description = Analog Stereo System-Out
    device-strings = hw:%f,2
    channel-map = left,right
    direction = output
    [Profile output:mch]
    description = Multi-Channel Output Active (Digital Disabled)
    output-mappings = analog-mch-out analog-system-out
    input-mappings =
    priority = 90
    skip-probe = yes
    [Profile output:mch+input:mch]
    description = Multi-Channel Input/Output (Digital Disabled)
    output-mappings = analog-mch-out analog-system-out
    input-mappings = analog-mch-in
    priority = 100
    skip-probe = yes
    [Profile output:spdif]
    description = Digital Output (Multi-Channel Disabled)
    output-mappings = digital-stereo analog-system-out
    input-mappings =
    priority = 80
    skip-probe = yes
    [Profile output:spdif+input:spdif]
    description = Digital Input/Output (Multi-Channel Disabled)
    output-mappings = digital-stereo analog-system-out
    input-mappings = digital-stereo
    priority = 90
    skip-probe = yes
    [Profile output:system]
    description = System Output Only
    output-mappings = analog-system-out
    input-mappings =
    priority = 60
    skip-probe = yes
  4. Restart Pulseaudio:

    pulseaudio -k
    pulseaudio --start

The original source for the Pulseaudio fix can be found here.

Posted in Linux | Tagged , , , , | Comments Off on M-Audio Audiophile 2496 and Pulseaudio