logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Backups-and-redundancy-at-sr.ht.md (6966B)


  1. ---
  2. date: 2019-01-13
  3. layout: post
  4. title: "Backups & redundancy at sr.ht"
  5. tags: ["sourcehut", "ops"]
  6. ---
  7. [sr.ht](https://sr.ht)[^1] is [100% open source][sr.ht-code] and I encourage
  8. people to install it on their own infrastructure, especially if they'll be
  9. sending patches upstream. However, I am equally thrilled to host sr.ht for you
  10. on the "official" instance, and most users find this useful because the
  11. maintenance burden is non-trivial. Today I'll give you an idea of what your
  12. subscription fee pays for. In this first post on ops at sr.ht, I'll talk about
  13. backups and redundancy. In future posts, I'll talk about security, high
  14. availability, automation, and more.
  15. [^1]: sr.ht is a software project hosting website, with git hosting, ticket tracking, continuous integration, mailing lists, and more. [Try it out!](https://sr.ht)
  16. [sr.ht-code]: https://git.sr.ht/~sircmpwn?search=sr.ht
  17. As sr.ht is still in the alpha phase, high availability has been on the
  18. backburner. However, data integrity has always been of paramount importance to
  19. me. The very earliest versions of sr.ht, from well before it was even trying to
  20. be a software forge, made a point to never lose a single byte of user data.
  21. Outages are okay - so long as when service is restored, everything is still
  22. there. Over time I'm working to make outages a thing of the past, too, but let's
  23. start with backups.
  24. There are several ways that sr.ht stores data:
  25. - Important data on the filesystem (e.g. bare git repositories)
  26. - Important persistent data in PostgreSQL
  27. - Unimportant ephemeral data in Redis (& caches)
  28. - Miscellaneous filesystem storage, like the operating system
  29. Some of this data is important and kept redundant (PostgreSQL, git repos), and
  30. others are unimportant and is not redundant. For example, I store a rendered
  31. Markdown cache for git.sr.ht in Redis. If the Redis cluster goes *poof*, the
  32. source Markdown is still available, so I don't bother backing up Redis. Most
  33. services run in a VM and I generally don't store important data on these - the
  34. hosts usually only have one hard drive with no backups and no redundancy. If the
  35. host dies, I have to reprovision all of those VMs.
  36. Other data is more important. Consider PostgreSQL, which contains some of the
  37. most important data for sr.ht. I have one master PostgreSQL server, a dedicated
  38. server in the space I colocate in my home town of Philadelphia. I run sr.ht on
  39. this server, but I also use it for a variety of other projects - I maintain many
  40. myself, and I volunteer as a sysadmin for more still. This box (named Remilia)
  41. has four hard drives configured in a ZRAID (ZFS). I buy these hard drives from a
  42. variety of vendors, mostly Western Digital and Seagate, and from different
  43. batches - reducing the likelihood that they'll fail around the same time. ZFS is
  44. well-known for it's excellent design, featureset and for simply keeping your
  45. data intact, and I don't trust any other filesystem with important data. I take
  46. ZFS snapshots every 15 minutes and retain them for 30 days. These snapshots are
  47. important for correcting the "oh shit, I rm'd something important" mistakes -
  48. you can mount them later and see what the filesystem looked like at the time
  49. they were taken.
  50. On top of this, the PostgreSQL server is set up with two additional important
  51. features: continuous archiving and streaming replication. Continuous archiving
  52. has PostgreSQL writing each transaction to log files on disk, which represents a
  53. re-playable history of the entire database, and allows you to restore the
  54. database to any point in time. This helps with "oh shit, I dropped an important
  55. table" mistakes. Streaming replication ships changes to an off-site standby
  56. server, in this case set up in my second colocation in San Francisco (the main
  57. backup box, which we'll talk about more shortly). This takes a near real-time
  58. backup of the database, and has the advantage of being able to quickly failover
  59. to it as the primary database during maintenance and outages (more on this
  60. during the upcoming high availability article). Soon I'll be setting up a second
  61. failover server as well, on-site.
  62. So there are multiple layers to this:
  63. - ZFS & zraid prevents disk failure from causing data loss
  64. - ZFS snapshots allows retrieving filesystem-level data from the past
  65. - Continuous archiving allows retrieving database-level data from the past
  66. - Streaming replication prevents datacenter existence failure from causing data
  67. loss
  68. Having multiple layers of data redundancy here protects sr.ht from a wide
  69. variety of failure modes, and also protects each redundant system from itself -
  70. if any of these systems fails, there's another place to get this data from.
  71. The off-site backup in San Francisco (this box is called Konpaku) has a whopping
  72. 52T of storage in two ZFS pools, named "small" (4T) and "large" (48T). The
  73. PostgreSQL standby server lives in the small pool, and [borg
  74. backups](https://www.borgbackup.org/) live in the large pool. This has the same
  75. ZFS snapshotting and retention policy as Remilia, and also has drives sourced
  76. from a variety of vendors and batches. Borg is how important filesystem-level
  77. data is backed up, for example git repositories on git.sr.ht. Borg is nice
  78. enough to compress, encrypt, and deduplicate its backups for us, which I take
  79. hourly with a cronjob on the machines which own that data. The retention policy
  80. is hourly backups stored for 48 hours, daily backups for 2 weeks, and weekly
  81. backups stored indefinitely.
  82. There are two other crucial steps in maintaining a working backup system:
  83. monitoring and testing. The old wisdom is "you don't have backups until you've
  84. tested them". The simplest monitoring comes from cron - when I provision a new
  85. box, I make sure to set `MAILTO`, make sure sendmail works, and set up a
  86. deliberately failing cron entry to ensure I hear about it when it breaks. I also
  87. set up zfs-zed to email me whenever ZFS encounters issues, which also has a test
  88. mode you should use. For testing, I periodically provision private replicas of
  89. sr.ht services from backups and make sure that they work as expected. PostgreSQL
  90. replication is fairly new to my setup, but my intention is to switch the primary
  91. and standby servers on every database upgrade for HA[^2] purposes, which
  92. conveniently also tests that each standby is up-to-date and still replicating.
  93. [^2]: High availability
  94. To many veteran sysadmins, a lot of this is basic stuff, but it took me a long
  95. time to learn how all of this worked and establish a set of best practices for
  96. myself. With the rise in popularity of managed ops like AWS and GCP, it seems
  97. like ops & sysadmin roles are becoming less common. Some of us still love the
  98. sound of a datacenter and the greater level of control you have over your
  99. services, and as a bonus my users aren't worrying about $bigcorp having access
  100. to their data.
  101. The next ops thing on my todo list is high availability, which is still
  102. in-progress on sr.ht. When it's done, expect another blog post!