Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| omv8:omv8_plugins:borgbackup [2025/12/22 05:11] – created chente | omv8:omv8_plugins:borgbackup [2025/12/28 15:22] (current) – [Create a ARCHIVE] chente | ||
|---|---|---|---|
| Line 9: | Line 9: | ||
| \\ | \\ | ||
| - | === Note === | + | ===== Summary ===== |
| - | This plugin | + | * The **openmediavault-borgbackup** |
| + | * Currently, the plugin allows configuring both local and remote backups. | ||
| - | The documentation for OMV8 is still being written. | + | ---- |
| - | For now, you can use the documentation written for OMV7. The changes for the OMV8 version are not significant. | + | === Third-Party Software Note === |
| - | Go to -> [[omv7: | + | [[https:// |
| + | This OMV plugin uses BorgBackup, a third-party software. For detailed information and support, see the project webpage | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === What is BorgBackup? === | ||
| + | |||
| + | Quote: | ||
| + | |||
| + | //" | ||
| + | |||
| + | //The main goal of Borg is to provide an efficient and secure way to backup data. The data deduplication technique used makes Borg suitable for daily backups since only changes are stored. The authenticated encryption technique makes it suitable for backups to not fully trusted targets."// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === How does BorgBackup work? === | ||
| + | |||
| + | **Backup** | ||
| + | |||
| + | The basic operation consists of: | ||
| + | * Creating a **REPOSITORY** and initializing it to receive one or more backups. Each backup is stored in an **ARCHIVE**. | ||
| + | * Running a backup of one or more files or folders packed into an **ARCHIVE** within the **REPOSITORY**. | ||
| + | |||
| + | The result is a folder that Borg calls **REPOSITORY** containing one or more **ARCHIVES**. Each **ARCHIVE** contains a backup. Borg automatically deduplicates data: if **ARCHIVE_1** has files that also exist in **ARCHIVE_2**, | ||
| + | |||
| + | Borg itself does not automate backups; this is handled by the **openmediavault-borgbackup** plugin. Using the plugin GUI, you create an **ARCHIVE** and give it a name (**ARCHIVE_NAME**), | ||
| + | |||
| + | Detailed backup configuration procedures using the plugin are provided at the end of this document. | ||
| + | |||
| + | **Restore** | ||
| + | |||
| + | There are two ways to restore backups: | ||
| + | * If you know the file location, restore it directly. The plugin GUI allows specifying the path. | ||
| + | * If you do not know the exact file or version, inspect the backup contents. Borg can mount an **ARCHIVE** as a filesystem, allowing inspection via CLI or file explorers (e.g., WinSCP) and copy files elsewhere. Once restored, unmount the folder. | ||
| + | |||
| + | < | ||
| + | Beginners Info | ||
| + | </ | ||
| + | Key phrase to remember:< | ||
| + | < | ||
| + | Always test the restoration process. | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Index === | ||
| + | |||
| + | * [[omv8: | ||
| + | * [[omv8: | ||
| + | * [[omv8: | ||
| + | * [[omv8: | ||
| + | * [[omv8: | ||
| + | * [[omv8: | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Prerequisites ===== | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Installation ===== | ||
| + | |||
| + | In OMV8 GUI: | ||
| + | Under **SYSTEM → Plugins**, locate **openmediavault-borgbackup 8.X** and click **Install**. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Repos tab ===== | ||
| + | |||
| + | In this tab we can both create and manage Borg // | ||
| + | \\ | ||
| + | |||
| + | |||
| + | < | ||
| + | \\ | ||
| + | {{ : | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Create === | ||
| + | |||
| + | {{ : | ||
| + | Allows you to create and initialize a Borg // | ||
| + | |||
| + | * NAME: Defines the name of the // | ||
| + | * TYPE: Choose whether you are creating a local or remote // | ||
| + | * LOCAL: For repositories located on the same server. | ||
| + | * SHARED FOLDER: Choose a shared folder to store the // | ||
| + | * REMOTE: For repositories located on a remote server. | ||
| + | * REMOTE PATH: Defines the path to the // | ||
| + | * PASSPHRASE: Defines a password to access the // | ||
| + | * ENCRYPTION. Check this box if you want the // | ||
| + | * SKIP INIT. If you are trying to import an already created // | ||
| + | * STORAGE QUOTA: Set the maximum capacity of the repository. 5G, 1.5T as examples. Leave blank for no quota. | ||
| + | * Press the SAVE button. You will return to the REPOS form where a line should appear with the values of your new // | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Change location === | ||
| + | |||
| + | Allows you to change the location of a // | ||
| + | |||
| + | < | ||
| + | Warning | ||
| + | </ | ||
| + | Before changing the location of a // | ||
| + | </ | ||
| + | |||
| + | * TYPE | ||
| + | * LOCAL: Select LOCAL if you want to move the // | ||
| + | * SHARED FOLDER: Select the shared folder where you are going to move the // | ||
| + | * REMOTE: Select REMOTE if you want to move the // | ||
| + | * REMOTE PATH: Defines the path to the // | ||
| + | * Press the CHANGE button to apply the changes. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Change quota === | ||
| + | |||
| + | Allows you to change the quota of a // | ||
| + | |||
| + | * TYPE | ||
| + | * NAME: Specifies the name of the repository for which you want to change the quota. | ||
| + | * CURRENT QUOTA: Current quota value. | ||
| + | * NEW QUOTA: Desired quota value. | ||
| + | * Press CHANGE to apply changes. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | |||
| + | === Remove === | ||
| + | |||
| + | Allows you to delete a // | ||
| + | |||
| + | < | ||
| + | | ||
| + | </ | ||
| + | Deleting the repository will not delete the folder or its contents in the file system.< | ||
| + | If there are ARCHIVES configured in this REPOSITORY the FILES will be removed from the plugin configuration but the files in the server file system will not be removed. | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Delete+files === | ||
| + | |||
| + | Allows you to delete a // | ||
| + | * In order to delete a // | ||
| + | * After deleting the // | ||
| + | |||
| + | < | ||
| + | | ||
| + | </ | ||
| + | When you delete an entire repository, the security information and local cache for it (if any) are also deleted. | ||
| + | </ | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Change passphrase === | ||
| + | |||
| + | Allows you to change the password for accessing the // | ||
| + | * PASSPHRASE: Enter the new password. Do not use spaces or special symbols, they may not be interpreted correctly and create conflicts. | ||
| + | * Press the CHANGE button and apply the changes. | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Check === | ||
| + | |||
| + | Allows you to check the consistency of a // | ||
| + | |||
| + | < | ||
| + | | ||
| + | </ | ||
| + | The check command verifies the consistency of a repository and its archives. It consists of two major steps:< | ||
| + | 1. Checking the consistency of the repository itself. This includes checking the segment magic headers, and both the metadata and data of all objects in the segments. The read data is checked by size and CRC. Bit rot and other types of accidental damage can be detected this way. When checking a remote repository, please note that the checks run on the server and do not cause significant network traffic.< | ||
| + | 2. Checking consistency and correctness of the archive metadata and optionally archive data (requires --verify-data). This includes ensuring that the repository manifest exists, the archive metadata chunk is present, and that all chunks referencing files (items) in the archive exist. This requires reading archive and file metadata, but not data. To cryptographically verify the file (content) data integrity pass --verify-data, | ||
| + | </ | ||
| + | |||
| + | If it is a remote // | ||
| + | |||
| + | * ALL: '' | ||
| + | * REPOS ONLY: '' | ||
| + | * ARCHIVES ONLY: '' | ||
| + | * VERIFY: '' | ||
| + | |||
| + | < | ||
| + | Warning | ||
| + | </ | ||
| + | Do not confuse data integrity of an ARCHIVE in a REPOSITORY with data integrity of the backup source (your file system on the server where the data from which the backup is made is stored).< | ||
| + | < | ||
| + | If you need to ensure the integrity of files on your file system, you should use other means, such as a COW file system such as ZFS or BTRFS or a parity checking system such as SnapRaid. < | ||
| + | </ | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Export === | ||
| + | |||
| + | Allows you to create a tar-compressed file that contains all the files in the // | ||
| + | * ARCHIVE: Select a //ARCHIVE// to export from the list of existing // | ||
| + | * SHARED FOLDER: Select a shared folder where to place the export // | ||
| + | * Press the EXPORT button to execute the export. | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Extract === | ||
| + | |||
| + | Allows you to extract all files from an //ARCHIVE// to a shared folder. Select a // | ||
| + | * ARCHIVE: Select a //ARCHIVE// to extract from those existing in the // | ||
| + | * ORIGINAL LOCATION: Activate this button if you want to extract all the contents of the //ARCHIVE// to its original location. | ||
| + | * SHARED FOLDER: If you do not press the previous button, you must choose a shared folder as the extraction destination. In this shared folder the tree of existing folders within the //ARCHIVE// will be reproduced and all existing files will be extracted in their corresponding position. | ||
| + | * Press the EXTRACT button to start execution. | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === List === | ||
| + | |||
| + | Allows you to list existing // | ||
| + | * A code box will be displayed with the list of // | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Compact === | ||
| + | |||
| + | Allows you to compact a // | ||
| + | * A code box will open showing the compaction result. | ||
| + | |||
| + | < | ||
| + | | ||
| + | </ | ||
| + | Borg does not automatically compact segments in the // | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Info === | ||
| + | |||
| + | Allows you to view detailed information about a // | ||
| + | * A code box will open showing the information of the selected // | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Download repo keyfile === | ||
| + | |||
| + | Allows you to download the encryption key of a // | ||
| + | * The file with the key will be downloaded to your browser. | ||
| + | |||
| + | < | ||
| + | | ||
| + | </ | ||
| + | Accessing an encrypted repository requires the repository' | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Mount === | ||
| + | |||
| + | Allows you to mount all the // | ||
| + | * SHARED FOLDER: Select a shared folder in which to mount the // | ||
| + | * VERSIONS: If you activate this button, a montage will be made so that a subfolder will be created for each file that will contain the different versions of that file. This assembly procedure is experimental, | ||
| + | * Press the MOUNT button to mount. **Remember to umount** it when you are done. | ||
| + | |||
| + | < | ||
| + | | ||
| + | </ | ||
| + | The plugin does not apply any permissions arguments to this command, so all files and folders will have their original permissions. | ||
| + | </ | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Umount === | ||
| + | |||
| + | Allows you to unmount a previously mounted // | ||
| + | * The // | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Docs === | ||
| + | |||
| + | Shows a link to the official Borgbackup documentation and another link to this document on the omv-extras wiki. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Archives tab ===== | ||
| + | |||
| + | In this tab we can manage // | ||
| + | |||
| + | By generating a //ARCHIVE// in the plugin we define what the backup sources are and at the same time we define a schedule to execute the backups as well as the retention policy for the backup versions. In each execution of a backup the plugin will generate a new //ARCHIVE// and add a suffix to it with the date and time of its creation. | ||
| + | \\ | ||
| + | |||
| + | < | ||
| + | \\ | ||
| + | {{ : | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Create === | ||
| + | |||
| + | {{ : | ||
| + | Allows you to create a // | ||
| + | * ENABLE: Determines whether this schedule will run automatically or not. | ||
| + | * NAME/ | ||
| + | * REPO: Choose one of the repositories created with the plugin to store backups of this // | ||
| + | * COMPRESSION TYPE: Optional. You can choose whether or not you want to compress the backups and the type of compression. | ||
| + | * COMPRESSION RATIO: The compression ratio applied if you have chosen to compress. From 0 for lower compression and higher speed to 9 for higher compression and lower speed. | ||
| + | * ONE FILESYSTEM ONLY: Enable this to exclude the contents of other mounted file systems. | ||
| + | * NO ATIME: Enable this to exclude the last access time of each file. | ||
| + | * INCLUDES: Write the absolute paths of the folders or files that you want to include in the backup. If you establish more than one route you must separate them with a comma. If a path contains spaces, enclose it in quotes. | ||
| + | * EXCLUDES: Optional, you can write paths to exclude from the backup. | ||
| + | * RETENTION PERIODS: -> RETAIN HOURLY, RETAIN DAILY, RETAIN WEEKLY, RETAIN MONTHLY, RETAIN YEARLY. These are the retention periods for backups that at the same time establish the backup execution schedule: | ||
| + | * Backups will be executed regularly according to the first value other than 0, that is, if you want to make a backup every day, set the hourly value equal to 0 and the daily value with a value other than 0. | ||
| + | * The value established in each field will determine how many versions are maintained during that period; the oldest versions that exceed that total will be deleted after the next backup is executed. | ||
| + | * RATE LIMIT: Optional. This value will limit the upload bandwidth. Set a value (in KB/s) if you need it to not saturate the bandwidth of a remote server. Set the value 0 for unlimited speed. | ||
| + | * LIST: Activating this button will generate a list of backup files and directories on each run. | ||
| + | * EMAIL: Activating this option will cause you to receive an email with the result of each backup. If you do not activate it, you will receive an email only in case an error occurs. To receive emails you must previously configure notifications in the OMV GUI. | ||
| + | * PRE-SCRIPT: Allows you to run a script before executing the backup. To do this you must define the absolute path where the script is located. | ||
| + | * POST-SCRIPT: | ||
| + | * Press the SAVE button to apply the changes. A line will appear in the form with the name of the //ARCHIVE// you just created. | ||
| + | |||
| + | The '' | ||
| + | |||
| + | '' | ||
| + | |||
| + | '' | ||
| + | |||
| + | Example: setting the starting hour to 4 would mean the following: | ||
| + | * yearly jobs start on January 1 at 4 | ||
| + | * monthly jobs start on the first day of the month at 4:30 (4 + 30 mins) | ||
| + | * weekly jobs start on Mondays at 5 (4 + 1 hour) | ||
| + | * daily jobs start at 5:30 (4 + 1 hour + 30 mins) | ||
| + | * hourly start at 5 mins after the hour every hour | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Edit === | ||
| + | |||
| + | Allows you to edit a // | ||
| + | * A dialog box will open with all the //ARCHIVE// settings and you can edit them. | ||
| + | * Press SAVE to apply changes. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Delete === | ||
| + | |||
| + | Allows you to delete a // | ||
| + | * The selected programming //ARCHIVE// will be deleted and all existing backups of this //ARCHIVE// in the // | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Info === | ||
| + | |||
| + | Allows you to list information about all backups executed with the selected // | ||
| + | * A code box will open showing the list of execution information for each backup. | ||
| + | |||
| + | Link to official documentation -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Dry run === | ||
| + | |||
| + | This allows you to run a backup to see the result without making any changes. Select a ARCHIVE and press **DRY RUN**. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Run === | ||
| + | |||
| + | Allows you to manually run a backup from the existing schedule to a // | ||
| + | * A code box will open showing the backup execution command. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Docs === | ||
| + | |||
| + | Shows a link to the official Borgbackup documentation and another link to this document on the omv-extras wiki. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Environment Variables tab ===== | ||
| + | |||
| + | Borg uses some environment variables for automation, check the official documentation to find out what they are: [[https:// | ||
| + | |||
| + | This tab allows you to customize those Borg environment variables. | ||
| + | |||
| + | \\ | ||
| + | |||
| + | < | ||
| + | \\ | ||
| + | {{ : | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Create === | ||
| + | |||
| + | Allows you to add a Borg environment variable. Press the CREATE button, a dialog box will open with the following fields: | ||
| + | * NAME: The name of the Borg environment variable you want to customize. | ||
| + | * VALUE: The value of the Borg environment variable. | ||
| + | * REPO: The // | ||
| + | * Press the SAVE button to apply the changes. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Edit === | ||
| + | |||
| + | Allows you to edit a Borg environment variable already created in the plugin. Select an environment variable in the form and press the EDIT button, a dialog box will open allowing you to edit the values of the selected environment variable. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Delete === | ||
| + | |||
| + | Allows you to delete a Borg environment variable already created in the plugin. Select an environment variable in the form and press the DELETE button, confirm the deletion and apply the changes to delete it. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Local backup configuration procedure ===== | ||
| + | |||
| + | Below is a simple example with the necessary steps to configure a backup and store it on the same server. The requirements for this backup are: | ||
| + | * We want to make a backup of the contents of the users Mary and Peter' | ||
| + | * We want to be able to restore at any time versions of the last 8 hours of Mary's folder, daily versions of the last week, weekly versions of the last month and monthly versions of the last year. In Peter' | ||
| + | * We want to store the backup on a disk that we have installed on our server dedicated to backups. | ||
| + | * We want the backup to be compressed and encrypted. | ||
| + | |||
| + | In our server environment we have: | ||
| + | * The absolute path of the mary folder is ''/ | ||
| + | * The absolute path of the peter folder is ''/ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Create a local REPOSITORY === | ||
| + | |||
| + | {{ : | ||
| + | The first step is to create the // | ||
| + | * NAME: '' | ||
| + | * TYPE: Local | ||
| + | * SHARED FOLDER: | ||
| + | * We create a shared folder in STORAGE > SHARED FOLDERS with the name '' | ||
| + | * We select the shared folder '' | ||
| + | * PASSPHRASE: '' | ||
| + | * ENCRYPTION: We activate this button so that the // | ||
| + | * SKIP INIT: We deactivate this button since we are creating a new // | ||
| + | * We press the SAVE button and apply the changes. | ||
| + | |||
| + | The // | ||
| + | |||
| + | To access this // | ||
| + | * We select the newly created // | ||
| + | |||
| + | Our browser should have received a file with the encryption key from the // | ||
| + | |||
| + | ---- | ||
| + | |||
| + | === Create a ARCHIVE === | ||
| + | |||
| + | {{ : | ||
| + | The second step is to create a // | ||
| + | |||
| + | We start with the //ARCHIVE// in the mary folder. In the SERVICES > BORGBACKUP > REPOS tab, press the CREATE button and establish the following configuration: | ||
| + | * ENABLE: We activate this button so that the programming is active. | ||
| + | * NAME/ | ||
| + | * REPO: We select the // | ||
| + | * COMPRESSION TYPE: '' | ||
| + | * COMPRESSION RATIO: '' | ||
| + | * ONE FILESYSTEM ONLY: We activate this button since we only want to backup a folder in a single file system. | ||
| + | * NO ATIME: We activate this button to avoid backing up versions with different access times. | ||
| + | * INCLUDES: ''/ | ||
| + | * EXCLUDES: (We leave it blank, we don't want to exclude anything from the mary folder) | ||
| + | * RETAIN HOURLY: '' | ||
| + | * RETAIN DAILY: '' | ||
| + | * RETAIN WEEKLY: '' | ||
| + | * RETAIN MONTHLY: '' | ||
| + | * RETAIN YEARLY: '' | ||
| + | * RATE LIMIT: '' | ||
| + | * LIST: We activate this button to have a list of backup files and directories in each execution. | ||
| + | * EMAIL: We deactivate this button, this way we will only receive an email if there is an error during the execution of a backup. | ||
| + | * PRE-SCRIPT: (we leave it blank, we do not need to run any script before the backup) | ||
| + | * POST-SCRIPT: | ||
| + | * We press the SAVE button and apply changes. | ||
| + | |||
| + | At this moment, a line will appear in the form with the name mary corresponding to the //ARCHIVE// that we just created. If we press the RUN button we can check its execution when making the first backup. | ||
| + | |||
| + | The next step would be to create another //ARCHIVE// for the peter folder. We repeat the steps but in this case we change the location of the folder: | ||
| + | * INCLUDES: ''/ | ||
| + | |||
| + | and we also change the programming: | ||
| + | * RETAIN HOURLY: '' | ||
| + | * RETAIN DAILY: '' | ||
| + | * RETAIN WEEKLY: '' | ||
| + | * RETAIN MONTHLY: '' | ||
| + | * RETAIN YEARLY: '' | ||
| + | |||
| + | {{:omv7: | ||
| + | The rest of the values will be the same as those we established in the mary // | ||
| + | |||
| + | At any time we can mount the // | ||
| + | |||
| + | To see the versions of the backups generated so far, select the // | ||
| + | \\ | ||
| + | \\ | ||
| + | \\ | ||
| + | ---- | ||
| + | |||
| + | ===== Remote backup configuration procedure ===== | ||
| + | |||
| + | [[https:// | ||
| + | In the guides section of the Openmediavault forum there is an excellent guide to performing remote backups masterfully written by forum member '' | ||
| + | |||
| + | Borg requires SSH connections to access remote repositories. These links may be useful to you: | ||
| + | |||
| + | --> [[https:// | ||
| + | |||
| + | --> [[https:// | ||
| + | |||
| + | --> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Source Code ===== | ||
| + | |||
| + | -> [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== A Closing Note ===== | ||
| + | |||
| + | We, who support the openmediavault project, hope you've found this guide to be useful and that you'll find your openmediavault server to be efficient, easy to use, and enjoyable.\\ | ||
| + | \\ | ||
| + | If you found this plugin guide to be helpful, please consider a modest donation to support the hosting costs of this server.\\ | ||
| + | \\ | ||
| + | **OMV-Extras.org** | ||
| + | \\ | ||
| + | < | ||
| + | <form action=" | ||
| + | <input type=" | ||
| + | <input type=" | ||
| + | <input type=" | ||
| + | <img alt="" | ||
| + | </ | ||
| + | </ | ||
| + | \\ | ||
| + | \\ | ||
| + | **Venmo: ryecoaaron** \\ | ||