borgitory 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. borgitory-2.2.0/.gitignore +237 -0
  2. borgitory-2.2.0/LICENSE +21 -0
  3. borgitory-2.2.0/PKG-INFO +441 -0
  4. borgitory-2.2.0/README.md +368 -0
  5. borgitory-2.2.0/pyproject.toml +224 -0
  6. borgitory-2.2.0/src/borgitory/__init__.py +0 -0
  7. borgitory-2.2.0/src/borgitory/alembic/README +1 -0
  8. borgitory-2.2.0/src/borgitory/alembic/env.py +109 -0
  9. borgitory-2.2.0/src/borgitory/alembic/script.py.mako +28 -0
  10. borgitory-2.2.0/src/borgitory/alembic/versions/d930de046be6_migrate_cloud_sync_configs_to_json_.py +131 -0
  11. borgitory-2.2.0/src/borgitory/alembic.ini +147 -0
  12. borgitory-2.2.0/src/borgitory/api/__init__.py +0 -0
  13. borgitory-2.2.0/src/borgitory/api/auth.py +236 -0
  14. borgitory-2.2.0/src/borgitory/api/backups.py +53 -0
  15. borgitory-2.2.0/src/borgitory/api/cleanup.py +257 -0
  16. borgitory-2.2.0/src/borgitory/api/cloud_sync.py +558 -0
  17. borgitory-2.2.0/src/borgitory/api/debug.py +42 -0
  18. borgitory-2.2.0/src/borgitory/api/jobs.py +421 -0
  19. borgitory-2.2.0/src/borgitory/api/notifications.py +326 -0
  20. borgitory-2.2.0/src/borgitory/api/repositories.py +694 -0
  21. borgitory-2.2.0/src/borgitory/api/repository_check_configs.py +340 -0
  22. borgitory-2.2.0/src/borgitory/api/repository_stats.py +175 -0
  23. borgitory-2.2.0/src/borgitory/api/schedules.py +330 -0
  24. borgitory-2.2.0/src/borgitory/api/shared.py +32 -0
  25. borgitory-2.2.0/src/borgitory/api/tabs.py +176 -0
  26. borgitory-2.2.0/src/borgitory/cli.py +165 -0
  27. borgitory-2.2.0/src/borgitory/config.py +18 -0
  28. borgitory-2.2.0/src/borgitory/dependencies.py +552 -0
  29. borgitory-2.2.0/src/borgitory/main.py +276 -0
  30. borgitory-2.2.0/src/borgitory/models/__init__.py +0 -0
  31. borgitory-2.2.0/src/borgitory/models/database.py +453 -0
  32. borgitory-2.2.0/src/borgitory/models/enums.py +47 -0
  33. borgitory-2.2.0/src/borgitory/models/repository_dtos.py +216 -0
  34. borgitory-2.2.0/src/borgitory/models/schemas.py +791 -0
  35. borgitory-2.2.0/src/borgitory/py.typed +1 -0
  36. borgitory-2.2.0/src/borgitory/services/__init__.py +0 -0
  37. borgitory-2.2.0/src/borgitory/services/archives/archive_manager.py +365 -0
  38. borgitory-2.2.0/src/borgitory/services/archives/archive_mount_manager.py +398 -0
  39. borgitory-2.2.0/src/borgitory/services/backups/backup_executor.py +514 -0
  40. borgitory-2.2.0/src/borgitory/services/backups/backup_service.py +441 -0
  41. borgitory-2.2.0/src/borgitory/services/borg_command_builder.py +362 -0
  42. borgitory-2.2.0/src/borgitory/services/borg_service.py +747 -0
  43. borgitory-2.2.0/src/borgitory/services/cleanup_service.py +260 -0
  44. borgitory-2.2.0/src/borgitory/services/cloud_providers/__init__.py +57 -0
  45. borgitory-2.2.0/src/borgitory/services/cloud_providers/config_service.py +126 -0
  46. borgitory-2.2.0/src/borgitory/services/cloud_providers/orchestration.py +226 -0
  47. borgitory-2.2.0/src/borgitory/services/cloud_providers/registry.py +391 -0
  48. borgitory-2.2.0/src/borgitory/services/cloud_providers/registry_factory.py +117 -0
  49. borgitory-2.2.0/src/borgitory/services/cloud_providers/service.py +300 -0
  50. borgitory-2.2.0/src/borgitory/services/cloud_providers/storage/__init__.py +45 -0
  51. borgitory-2.2.0/src/borgitory/services/cloud_providers/storage/base.py +98 -0
  52. borgitory-2.2.0/src/borgitory/services/cloud_providers/storage/s3_storage.py +275 -0
  53. borgitory-2.2.0/src/borgitory/services/cloud_providers/storage/sftp_storage.py +267 -0
  54. borgitory-2.2.0/src/borgitory/services/cloud_providers/storage/smb_storage.py +320 -0
  55. borgitory-2.2.0/src/borgitory/services/cloud_providers/types.py +109 -0
  56. borgitory-2.2.0/src/borgitory/services/cloud_sync_service.py +355 -0
  57. borgitory-2.2.0/src/borgitory/services/configuration_service.py +87 -0
  58. borgitory-2.2.0/src/borgitory/services/cron_description_service.py +65 -0
  59. borgitory-2.2.0/src/borgitory/services/debug_service.py +394 -0
  60. borgitory-2.2.0/src/borgitory/services/jobs/broadcaster/event_type.py +19 -0
  61. borgitory-2.2.0/src/borgitory/services/jobs/broadcaster/job_event.py +67 -0
  62. borgitory-2.2.0/src/borgitory/services/jobs/broadcaster/job_event_broadcaster.py +303 -0
  63. borgitory-2.2.0/src/borgitory/services/jobs/job_database_manager.py +360 -0
  64. borgitory-2.2.0/src/borgitory/services/jobs/job_executor.py +587 -0
  65. borgitory-2.2.0/src/borgitory/services/jobs/job_manager.py +1884 -0
  66. borgitory-2.2.0/src/borgitory/services/jobs/job_output_manager.py +242 -0
  67. borgitory-2.2.0/src/borgitory/services/jobs/job_queue_manager.py +391 -0
  68. borgitory-2.2.0/src/borgitory/services/jobs/job_render_service.py +566 -0
  69. borgitory-2.2.0/src/borgitory/services/jobs/job_service.py +376 -0
  70. borgitory-2.2.0/src/borgitory/services/jobs/job_stream_service.py +442 -0
  71. borgitory-2.2.0/src/borgitory/services/notifications/notification_config_service.py +235 -0
  72. borgitory-2.2.0/src/borgitory/services/notifications/pushover_service.py +212 -0
  73. borgitory-2.2.0/src/borgitory/services/rclone_service.py +1268 -0
  74. borgitory-2.2.0/src/borgitory/services/recovery_service.py +163 -0
  75. borgitory-2.2.0/src/borgitory/services/repositories/repository_check_config_service.py +231 -0
  76. borgitory-2.2.0/src/borgitory/services/repositories/repository_parser.py +543 -0
  77. borgitory-2.2.0/src/borgitory/services/repositories/repository_service.py +592 -0
  78. borgitory-2.2.0/src/borgitory/services/repositories/repository_stats_service.py +644 -0
  79. borgitory-2.2.0/src/borgitory/services/scheduling/schedule_service.py +285 -0
  80. borgitory-2.2.0/src/borgitory/services/scheduling/scheduler_service.py +316 -0
  81. borgitory-2.2.0/src/borgitory/services/simple_command_runner.py +137 -0
  82. borgitory-2.2.0/src/borgitory/services/task_definition_builder.py +347 -0
  83. borgitory-2.2.0/src/borgitory/services/upcoming_backups_service.py +98 -0
  84. borgitory-2.2.0/src/borgitory/services/volumes/file_system_interface.py +26 -0
  85. borgitory-2.2.0/src/borgitory/services/volumes/os_file_system.py +23 -0
  86. borgitory-2.2.0/src/borgitory/services/volumes/volume_service.py +64 -0
  87. borgitory-2.2.0/src/borgitory/static/css/modern-components.css +284 -0
  88. borgitory-2.2.0/src/borgitory/static/favicon/android-chrome-192x192.png +0 -0
  89. borgitory-2.2.0/src/borgitory/static/favicon/android-chrome-512x512.png +0 -0
  90. borgitory-2.2.0/src/borgitory/static/favicon/apple-touch-icon.png +0 -0
  91. borgitory-2.2.0/src/borgitory/static/favicon/favicon-16x16.png +0 -0
  92. borgitory-2.2.0/src/borgitory/static/favicon/favicon-32x32.png +0 -0
  93. borgitory-2.2.0/src/borgitory/static/favicon/favicon.ico +0 -0
  94. borgitory-2.2.0/src/borgitory/static/favicon/site.webmanifest +19 -0
  95. borgitory-2.2.0/src/borgitory/static/js/app.js +259 -0
  96. borgitory-2.2.0/src/borgitory/static/js/components/jobs.js +61 -0
  97. borgitory-2.2.0/src/borgitory/static/js/components/navigation.js +43 -0
  98. borgitory-2.2.0/src/borgitory/templates/base.html +241 -0
  99. borgitory-2.2.0/src/borgitory/templates/index.html +47 -0
  100. borgitory-2.2.0/src/borgitory/templates/login.html +188 -0
  101. borgitory-2.2.0/src/borgitory/templates/partials/archives/contents_modal.html +28 -0
  102. borgitory-2.2.0/src/borgitory/templates/partials/archives/directory_contents.html +119 -0
  103. borgitory-2.2.0/src/borgitory/templates/partials/archives/directory_loading_state.html +12 -0
  104. borgitory-2.2.0/src/borgitory/templates/partials/archives/directory_loading_with_trigger.html +15 -0
  105. borgitory-2.2.0/src/borgitory/templates/partials/archives/empty_state.html +6 -0
  106. borgitory-2.2.0/src/borgitory/templates/partials/archives/error_message.html +11 -0
  107. borgitory-2.2.0/src/borgitory/templates/partials/archives/list_content.html +61 -0
  108. borgitory-2.2.0/src/borgitory/templates/partials/archives/loading_state.html +10 -0
  109. borgitory-2.2.0/src/borgitory/templates/partials/archives/loading_with_trigger.html +13 -0
  110. borgitory-2.2.0/src/borgitory/templates/partials/archives/repository_selector.html +32 -0
  111. borgitory-2.2.0/src/borgitory/templates/partials/archives/tab.html +29 -0
  112. borgitory-2.2.0/src/borgitory/templates/partials/auth/login_error.html +6 -0
  113. borgitory-2.2.0/src/borgitory/templates/partials/auth/login_form_active.html +58 -0
  114. borgitory-2.2.0/src/borgitory/templates/partials/auth/login_success.html +13 -0
  115. borgitory-2.2.0/src/borgitory/templates/partials/auth/register_error.html +6 -0
  116. borgitory-2.2.0/src/borgitory/templates/partials/auth/register_form_active.html +56 -0
  117. borgitory-2.2.0/src/borgitory/templates/partials/auth/register_success.html +10 -0
  118. borgitory-2.2.0/src/borgitory/templates/partials/backups/manual_form.html +87 -0
  119. borgitory-2.2.0/src/borgitory/templates/partials/backups/operations.html +10 -0
  120. borgitory-2.2.0/src/borgitory/templates/partials/backups/tab.html +19 -0
  121. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/action_error.html +6 -0
  122. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/action_success.html +6 -0
  123. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/add_form.html +42 -0
  124. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/config_list_content.html +70 -0
  125. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/create_error.html +6 -0
  126. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/create_success.html +13 -0
  127. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/edit_form.html +55 -0
  128. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/list.html +10 -0
  129. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/provider_fields.html +14 -0
  130. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/providers/s3_fields.html +32 -0
  131. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/providers/s3_fields_edit.html +32 -0
  132. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/providers/sftp_fields.html +38 -0
  133. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/providers/sftp_fields_edit.html +39 -0
  134. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/providers/smb_fields.html +74 -0
  135. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/providers/smb_fields_edit.html +74 -0
  136. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/tab.html +13 -0
  137. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/test_error.html +6 -0
  138. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/test_success.html +6 -0
  139. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/test_warning.html +6 -0
  140. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/update_error.html +6 -0
  141. borgitory-2.2.0/src/borgitory/templates/partials/cloud_sync/update_success.html +13 -0
  142. borgitory-2.2.0/src/borgitory/templates/partials/common/error_message.html +2 -0
  143. borgitory-2.2.0/src/borgitory/templates/partials/debug/debug_panel.html +291 -0
  144. borgitory-2.2.0/src/borgitory/templates/partials/debug/tab.html +44 -0
  145. borgitory-2.2.0/src/borgitory/templates/partials/jobs/backup_error.html +6 -0
  146. borgitory-2.2.0/src/borgitory/templates/partials/jobs/backup_success.html +14 -0
  147. borgitory-2.2.0/src/borgitory/templates/partials/jobs/current_jobs_list.html +23 -0
  148. borgitory-2.2.0/src/borgitory/templates/partials/jobs/empty_state.html +4 -0
  149. borgitory-2.2.0/src/borgitory/templates/partials/jobs/error_state.html +4 -0
  150. borgitory-2.2.0/src/borgitory/templates/partials/jobs/job_details_static.html +33 -0
  151. borgitory-2.2.0/src/borgitory/templates/partials/jobs/job_details_streaming.html +45 -0
  152. borgitory-2.2.0/src/borgitory/templates/partials/jobs/job_item.html +45 -0
  153. borgitory-2.2.0/src/borgitory/templates/partials/jobs/tab.html +12 -0
  154. borgitory-2.2.0/src/borgitory/templates/partials/jobs/task_item_static.html +76 -0
  155. borgitory-2.2.0/src/borgitory/templates/partials/jobs/task_item_streaming.html +106 -0
  156. borgitory-2.2.0/src/borgitory/templates/partials/navigation.html +29 -0
  157. borgitory-2.2.0/src/borgitory/templates/partials/navigation_nav.html +166 -0
  158. borgitory-2.2.0/src/borgitory/templates/partials/notifications/action_error.html +6 -0
  159. borgitory-2.2.0/src/borgitory/templates/partials/notifications/action_success.html +6 -0
  160. borgitory-2.2.0/src/borgitory/templates/partials/notifications/add_form.html +49 -0
  161. borgitory-2.2.0/src/borgitory/templates/partials/notifications/config_list_content.html +67 -0
  162. borgitory-2.2.0/src/borgitory/templates/partials/notifications/create_error.html +6 -0
  163. borgitory-2.2.0/src/borgitory/templates/partials/notifications/create_success.html +13 -0
  164. borgitory-2.2.0/src/borgitory/templates/partials/notifications/edit_form.html +58 -0
  165. borgitory-2.2.0/src/borgitory/templates/partials/notifications/list.html +10 -0
  166. borgitory-2.2.0/src/borgitory/templates/partials/notifications/tab.html +19 -0
  167. borgitory-2.2.0/src/borgitory/templates/partials/notifications/test_error.html +6 -0
  168. borgitory-2.2.0/src/borgitory/templates/partials/notifications/test_success.html +6 -0
  169. borgitory-2.2.0/src/borgitory/templates/partials/notifications/update_error.html +15 -0
  170. borgitory-2.2.0/src/borgitory/templates/partials/notifications/update_success.html +15 -0
  171. borgitory-2.2.0/src/borgitory/templates/partials/prune/action_error.html +6 -0
  172. borgitory-2.2.0/src/borgitory/templates/partials/prune/action_success.html +6 -0
  173. borgitory-2.2.0/src/borgitory/templates/partials/prune/config_form.html +95 -0
  174. borgitory-2.2.0/src/borgitory/templates/partials/prune/config_form_error.html +134 -0
  175. borgitory-2.2.0/src/borgitory/templates/partials/prune/config_form_success.html +118 -0
  176. borgitory-2.2.0/src/borgitory/templates/partials/prune/config_list_content.html +57 -0
  177. borgitory-2.2.0/src/borgitory/templates/partials/prune/create_error.html +6 -0
  178. borgitory-2.2.0/src/borgitory/templates/partials/prune/create_form.html +37 -0
  179. borgitory-2.2.0/src/borgitory/templates/partials/prune/create_success.html +13 -0
  180. borgitory-2.2.0/src/borgitory/templates/partials/prune/delete_error.html +6 -0
  181. borgitory-2.2.0/src/borgitory/templates/partials/prune/delete_success.html +13 -0
  182. borgitory-2.2.0/src/borgitory/templates/partials/prune/edit_form.html +47 -0
  183. borgitory-2.2.0/src/borgitory/templates/partials/prune/policies.html +21 -0
  184. borgitory-2.2.0/src/borgitory/templates/partials/prune/prune_error.html +11 -0
  185. borgitory-2.2.0/src/borgitory/templates/partials/prune/prune_success.html +6 -0
  186. borgitory-2.2.0/src/borgitory/templates/partials/prune/strategy_fields.html +29 -0
  187. borgitory-2.2.0/src/borgitory/templates/partials/prune/tab.html +19 -0
  188. borgitory-2.2.0/src/borgitory/templates/partials/prune/update_error.html +6 -0
  189. borgitory-2.2.0/src/borgitory/templates/partials/prune/update_success.html +13 -0
  190. borgitory-2.2.0/src/borgitory/templates/partials/repositories/delete_success.html +13 -0
  191. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_create.html +46 -0
  192. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_create_error.html +6 -0
  193. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_create_success.html +13 -0
  194. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_import.html +97 -0
  195. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_import_error.html +6 -0
  196. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_import_inner.html +93 -0
  197. borgitory-2.2.0/src/borgitory/templates/partials/repositories/form_import_success.html +20 -0
  198. borgitory-2.2.0/src/borgitory/templates/partials/repositories/import_form_clear.html +1 -0
  199. borgitory-2.2.0/src/borgitory/templates/partials/repositories/import_form_dynamic.html +76 -0
  200. borgitory-2.2.0/src/borgitory/templates/partials/repositories/import_form_loading.html +16 -0
  201. borgitory-2.2.0/src/borgitory/templates/partials/repositories/import_form_simple.html +55 -0
  202. borgitory-2.2.0/src/borgitory/templates/partials/repositories/list.html +10 -0
  203. borgitory-2.2.0/src/borgitory/templates/partials/repositories/list_content.html +39 -0
  204. borgitory-2.2.0/src/borgitory/templates/partials/repositories/scan_results.html +23 -0
  205. borgitory-2.2.0/src/borgitory/templates/partials/repositories/tab.html +35 -0
  206. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/action_error.html +6 -0
  207. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/action_success.html +6 -0
  208. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/check_error.html +11 -0
  209. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/check_success.html +6 -0
  210. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/config_list_content.html +66 -0
  211. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/create_error.html +6 -0
  212. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/create_form.html +105 -0
  213. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/create_success.html +13 -0
  214. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/custom_options.html +31 -0
  215. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/delete_error.html +6 -0
  216. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/delete_success.html +13 -0
  217. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/dynamic_options.html +73 -0
  218. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/edit_form.html +119 -0
  219. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/form.html +67 -0
  220. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/tab.html +59 -0
  221. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/update_error.html +6 -0
  222. borgitory-2.2.0/src/borgitory/templates/partials/repository_check/update_success.html +13 -0
  223. borgitory-2.2.0/src/borgitory/templates/partials/repository_stats/stats_panel.html +134 -0
  224. borgitory-2.2.0/src/borgitory/templates/partials/schedules/create_error.html +6 -0
  225. borgitory-2.2.0/src/borgitory/templates/partials/schedules/create_form.html +99 -0
  226. borgitory-2.2.0/src/borgitory/templates/partials/schedules/create_success.html +33 -0
  227. borgitory-2.2.0/src/borgitory/templates/partials/schedules/cron_description.html +10 -0
  228. borgitory-2.2.0/src/borgitory/templates/partials/schedules/cron_expression_form.html +31 -0
  229. borgitory-2.2.0/src/borgitory/templates/partials/schedules/delete_error.html +6 -0
  230. borgitory-2.2.0/src/borgitory/templates/partials/schedules/delete_success.html +13 -0
  231. borgitory-2.2.0/src/borgitory/templates/partials/schedules/edit_form.html +118 -0
  232. borgitory-2.2.0/src/borgitory/templates/partials/schedules/list.html +14 -0
  233. borgitory-2.2.0/src/borgitory/templates/partials/schedules/schedule_list_content.html +63 -0
  234. borgitory-2.2.0/src/borgitory/templates/partials/schedules/tab.html +23 -0
  235. borgitory-2.2.0/src/borgitory/templates/partials/schedules/upcoming.html +15 -0
  236. borgitory-2.2.0/src/borgitory/templates/partials/schedules/upcoming_backups_content.html +20 -0
  237. borgitory-2.2.0/src/borgitory/templates/partials/schedules/update_error.html +6 -0
  238. borgitory-2.2.0/src/borgitory/templates/partials/schedules/update_success.html +13 -0
  239. borgitory-2.2.0/src/borgitory/templates/partials/shared/notification.html +109 -0
  240. borgitory-2.2.0/src/borgitory/templates/partials/shared/path_autocomplete.html +30 -0
  241. borgitory-2.2.0/src/borgitory/templates/partials/shared/path_autocomplete_dropdown.html +42 -0
  242. borgitory-2.2.0/src/borgitory/templates/partials/statistics/empty_state.html +9 -0
  243. borgitory-2.2.0/src/borgitory/templates/partials/statistics/loading_state.html +51 -0
  244. borgitory-2.2.0/src/borgitory/templates/partials/statistics/repository_selector.html +22 -0
  245. borgitory-2.2.0/src/borgitory/templates/partials/statistics/tab.html +34 -0
  246. borgitory-2.2.0/src/borgitory/utils/__init__.py +1 -0
  247. borgitory-2.2.0/src/borgitory/utils/db_session.py +37 -0
  248. borgitory-2.2.0/src/borgitory/utils/migrations.py +66 -0
  249. borgitory-2.2.0/src/borgitory/utils/path_prefix.py +99 -0
  250. borgitory-2.2.0/src/borgitory/utils/secure_path.py +440 -0
  251. borgitory-2.2.0/src/borgitory/utils/security.py +239 -0
  252. borgitory-2.2.0/src/borgitory/utils/template_paths.py +113 -0
  253. borgitory-2.2.0/src/borgitory/utils/template_responses.py +166 -0
  254. borgitory-2.2.0/tests/__init__.py +1 -0
  255. borgitory-2.2.0/tests/archives/test_archive_browser_htmx.py +623 -0
  256. borgitory-2.2.0/tests/archives/test_archive_manager.py +575 -0
  257. borgitory-2.2.0/tests/archives/test_archive_mount_manager.py +781 -0
  258. borgitory-2.2.0/tests/auth/test_auth_htmx.py +134 -0
  259. borgitory-2.2.0/tests/auth/test_auth_redirect_flow.py +97 -0
  260. borgitory-2.2.0/tests/auth/test_main_login_page.py +167 -0
  261. borgitory-2.2.0/tests/backups/test_backup_executor.py +912 -0
  262. borgitory-2.2.0/tests/backups/test_backup_service.py +921 -0
  263. borgitory-2.2.0/tests/borg/test_borg_command_builder.py +588 -0
  264. borgitory-2.2.0/tests/borg/test_borg_service.py +999 -0
  265. borgitory-2.2.0/tests/borg/test_borg_service_core.py +395 -0
  266. borgitory-2.2.0/tests/cloud_providers/__init__.py +1 -0
  267. borgitory-2.2.0/tests/cloud_providers/test_config_service.py +449 -0
  268. borgitory-2.2.0/tests/cloud_providers/test_display_details.py +203 -0
  269. borgitory-2.2.0/tests/cloud_providers/test_job_executor.py +516 -0
  270. borgitory-2.2.0/tests/cloud_providers/test_orchestration.py +565 -0
  271. borgitory-2.2.0/tests/cloud_providers/test_provider_validation.py +256 -0
  272. borgitory-2.2.0/tests/cloud_providers/test_rclone_integration.py +441 -0
  273. borgitory-2.2.0/tests/cloud_providers/test_registry.py +326 -0
  274. borgitory-2.2.0/tests/cloud_providers/test_registry_integration.py +302 -0
  275. borgitory-2.2.0/tests/cloud_providers/test_schema_validation.py +260 -0
  276. borgitory-2.2.0/tests/cloud_providers/test_service.py +829 -0
  277. borgitory-2.2.0/tests/cloud_providers/test_smb_storage.py +365 -0
  278. borgitory-2.2.0/tests/cloud_providers/test_storage.py +720 -0
  279. borgitory-2.2.0/tests/cloud_providers/test_types.py +301 -0
  280. borgitory-2.2.0/tests/cloud_sync/test_cloud_sync_api.py +342 -0
  281. borgitory-2.2.0/tests/cloud_sync/test_cloud_sync_service.py +488 -0
  282. borgitory-2.2.0/tests/conftest.py +242 -0
  283. borgitory-2.2.0/tests/fixtures/__init__.py +5 -0
  284. borgitory-2.2.0/tests/fixtures/job_fixtures.py +259 -0
  285. borgitory-2.2.0/tests/fixtures/registry_fixtures.py +151 -0
  286. borgitory-2.2.0/tests/jobs/test_job_database_manager.py +421 -0
  287. borgitory-2.2.0/tests/jobs/test_job_event_broadcaster.py +257 -0
  288. borgitory-2.2.0/tests/jobs/test_job_executor.py +204 -0
  289. borgitory-2.2.0/tests/jobs/test_job_executor_cloud_sync_integration.py +600 -0
  290. borgitory-2.2.0/tests/jobs/test_job_executor_comprehensive.py +632 -0
  291. borgitory-2.2.0/tests/jobs/test_job_manager.py +456 -0
  292. borgitory-2.2.0/tests/jobs/test_job_manager_comprehensive.py +1026 -0
  293. borgitory-2.2.0/tests/jobs/test_job_output_manager.py +245 -0
  294. borgitory-2.2.0/tests/jobs/test_job_render_service.py +992 -0
  295. borgitory-2.2.0/tests/jobs/test_job_service.py +469 -0
  296. borgitory-2.2.0/tests/jobs/test_job_stream_service.py +533 -0
  297. borgitory-2.2.0/tests/jobs/test_jobs_api_sse.py +51 -0
  298. borgitory-2.2.0/tests/notifications/test_notification_config_service.py +442 -0
  299. borgitory-2.2.0/tests/notifications/test_notification_configs_api.py +560 -0
  300. borgitory-2.2.0/tests/notifications/test_pushover_service.py +421 -0
  301. borgitory-2.2.0/tests/repositories/test_repositories_api.py +1584 -0
  302. borgitory-2.2.0/tests/repositories/test_repository_check_config_service.py +412 -0
  303. borgitory-2.2.0/tests/repositories/test_repository_check_configs_api.py +567 -0
  304. borgitory-2.2.0/tests/repositories/test_repository_parser.py +1328 -0
  305. borgitory-2.2.0/tests/repositories/test_repository_service.py +335 -0
  306. borgitory-2.2.0/tests/repositories/test_repository_stats_service.py +460 -0
  307. borgitory-2.2.0/tests/schedules/test_cron_description_api.py +239 -0
  308. borgitory-2.2.0/tests/schedules/test_cron_description_htmx_api.py +265 -0
  309. borgitory-2.2.0/tests/schedules/test_schedule_creation_api.py +380 -0
  310. borgitory-2.2.0/tests/schedules/test_schedule_service.py +518 -0
  311. borgitory-2.2.0/tests/schedules/test_schedule_validation_service.py +319 -0
  312. borgitory-2.2.0/tests/schedules/test_scheduler_service.py +301 -0
  313. borgitory-2.2.0/tests/schedules/test_schedules_api.py +502 -0
  314. borgitory-2.2.0/tests/test_backups_api.py +347 -0
  315. borgitory-2.2.0/tests/test_basic.py +23 -0
  316. borgitory-2.2.0/tests/test_cleanup_api.py +464 -0
  317. borgitory-2.2.0/tests/test_cleanup_service.py +416 -0
  318. borgitory-2.2.0/tests/test_cron_description_service.py +136 -0
  319. borgitory-2.2.0/tests/test_database_models.py +519 -0
  320. borgitory-2.2.0/tests/test_debug_service.py +428 -0
  321. borgitory-2.2.0/tests/test_dependencies.py +216 -0
  322. borgitory-2.2.0/tests/test_jobs_api.py +886 -0
  323. borgitory-2.2.0/tests/test_path_prefix_utils.py +193 -0
  324. borgitory-2.2.0/tests/test_progress_streaming.py +321 -0
  325. borgitory-2.2.0/tests/test_rclone_service.py +1257 -0
  326. borgitory-2.2.0/tests/test_recovery_service.py +434 -0
  327. borgitory-2.2.0/tests/test_secure_path_comprehensive.py +681 -0
  328. borgitory-2.2.0/tests/test_security.py +826 -0
  329. borgitory-2.2.0/tests/test_simple_command_runner.py +286 -0
  330. borgitory-2.2.0/tests/test_streaming_edge_cases.py +339 -0
  331. borgitory-2.2.0/tests/test_streaming_fixes.py +341 -0
  332. borgitory-2.2.0/tests/test_tabs_api.py +304 -0
  333. borgitory-2.2.0/tests/test_task_definition_builder.py +479 -0
  334. borgitory-2.2.0/tests/test_volume_service.py +178 -0
@@ -0,0 +1,237 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+ #poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ #pdm.lock
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # SageMath parsed files
135
+ *.sage.py
136
+
137
+ # Environments
138
+ .env
139
+ .envrc
140
+ .venv
141
+ env/
142
+ venv/
143
+ ENV/
144
+ env.bak/
145
+ venv.bak/
146
+
147
+ # Spyder project settings
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope project settings
152
+ .ropeproject
153
+
154
+ # mkdocs documentation
155
+ /site
156
+
157
+ # mypy
158
+ .mypy_cache/
159
+ .dmypy.json
160
+ dmypy.json
161
+
162
+ # Pyre type checker
163
+ .pyre/
164
+
165
+ # pytype static type analyzer
166
+ .pytype/
167
+
168
+ # Cython debug symbols
169
+ cython_debug/
170
+
171
+ # PyCharm
172
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
175
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
+ #.idea/
177
+
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ # .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
208
+
209
+ # Project specific ignores
210
+ backup-sources/
211
+ borg-repos/
212
+ .claude/
213
+ data/
214
+ local-data/**
215
+ *.db
216
+ *.sqlite
217
+ *.sqlite3
218
+
219
+ # Docker
220
+ .dockerignore
221
+
222
+ # Local configuration
223
+ .env.local
224
+ .env.production
225
+
226
+ # Runtime files
227
+ *.pid
228
+ *.log
229
+
230
+ # OS generated files
231
+ .DS_Store
232
+ .DS_Store?
233
+ ._*
234
+ .Spotlight-V100
235
+ .Trashes
236
+ ehthumbs.db
237
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Matt LaPaglia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,441 @@
1
+ Metadata-Version: 2.4
2
+ Name: borgitory
3
+ Version: 2.2.0
4
+ Summary: A comprehensive web-based management interface for BorgBackup repositories with real-time monitoring, automated scheduling, and cloud synchronization capabilities.
5
+ Project-URL: Homepage, https://github.com/mlapaglia/Borgitory
6
+ Project-URL: Repository, https://github.com/mlapaglia/Borgitory
7
+ Project-URL: Issues, https://github.com/mlapaglia/Borgitory/issues
8
+ Author-email: mlapaglia <mlapaglia@users.noreply.github.com>
9
+ License: MIT License
10
+
11
+ Copyright (c) 2025 Matt LaPaglia
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: archive-management,backup,borgbackup,cloud-sync,scheduling,web-interface
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Intended Audience :: System Administrators
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: OS Independent
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Topic :: System :: Archiving :: Backup
41
+ Classifier: Topic :: System :: Systems Administration
42
+ Requires-Python: >=3.11
43
+ Requires-Dist: aiofiles>=24.1.0
44
+ Requires-Dist: aiohttp>=3.9.0
45
+ Requires-Dist: alembic>=1.16.5
46
+ Requires-Dist: apscheduler>=3.10.4
47
+ Requires-Dist: bcrypt<5.0.0,>=4.0.0
48
+ Requires-Dist: cron-descriptor>=2.0.5
49
+ Requires-Dist: cryptography>=45.0.0
50
+ Requires-Dist: docker>=7.1.0
51
+ Requires-Dist: fastapi>=0.115.0
52
+ Requires-Dist: jinja2>=3.1.4
53
+ Requires-Dist: passlib[bcrypt]>=1.7.4
54
+ Requires-Dist: pydantic>=2.9.0
55
+ Requires-Dist: pyfuse3>=3.4.0; sys_platform != 'win32'
56
+ Requires-Dist: python-dotenv>=1.0.1
57
+ Requires-Dist: python-multipart>=0.0.12
58
+ Requires-Dist: sqlalchemy>=2.0.35
59
+ Requires-Dist: sse-starlette>=2.1.3
60
+ Requires-Dist: uvicorn[standard]>=0.30.0
61
+ Provides-Extra: dev
62
+ Requires-Dist: httpx>=0.25.0; extra == 'dev'
63
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
64
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
65
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
66
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
67
+ Requires-Dist: ruff>=0.12.11; extra == 'dev'
68
+ Requires-Dist: sqlalchemy[mypy]>=2.0.35; extra == 'dev'
69
+ Requires-Dist: types-aiofiles>=23.2.0.20240106; extra == 'dev'
70
+ Requires-Dist: types-passlib>=1.7.7.20240327; extra == 'dev'
71
+ Requires-Dist: types-python-dateutil>=2.8.19.20240106; extra == 'dev'
72
+ Description-Content-Type: text/markdown
73
+
74
+ # Borgitory
75
+
76
+ [![codecov](https://codecov.io/gh/mlapaglia/Borgitory/graph/badge.svg?token=3XFFTWSKTB)](https://codecov.io/gh/mlapaglia/Borgitory)
77
+ [![build](https://img.shields.io/github/actions/workflow/status/mlapaglia/borgitory/release.yml)](https://github.com/mlapaglia/Borgitory/actions/workflows/release.yml)
78
+ [![sponsors](https://img.shields.io/github/sponsors/mlapaglia)](https://github.com/sponsors/mlapaglia)
79
+ [![sponsors](https://img.shields.io/docker/pulls/mlapaglia/borgitory)](https://hub.docker.com/r/mlapaglia/borgitory)
80
+
81
+ <img alt="borgitory logo" src="./assets/logo.png" width="400">
82
+
83
+ A comprehensive web-based management interface for BorgBackup repositories with real-time monitoring, automated scheduling, and cloud synchronization capabilities.
84
+
85
+ ## Features
86
+
87
+ ### Core Functionality
88
+
89
+ - **Repository Management**: Add, configure, and manage multiple Borg repositories
90
+ - **Manual Backups**: Create backups on-demand with configurable compression and source paths
91
+ - **Real-time Progress**: Monitor backup progress with live updates
92
+ - **Archive Browser**: Interactive directory-based archive exploration with file downloads
93
+ - **Job History**: Track all backup operations with detailed logs and expandable task views
94
+
95
+ - **Automated Scheduling**: Set up cron-based backup schedules with integrated cleanup and notifications
96
+ - **Archive Pruning**: Configure automated pruning policies with simple or advanced retention strategies
97
+ - **Cloud Sync**: Synchronize repositories to S3-compatible storage using Rclone
98
+ - **Push Notifications**: Pushover integration for job completion alerts
99
+ - **User Authentication**: Secure username/password authentication
100
+ - **Template System**: Modern Jinja2-based UI with reusable components
101
+ - **Mobile Responsive**: HTMX + Alpine.js + Tailwind CSS interface
102
+
103
+ ## Quick Start
104
+
105
+ ### Prerequisites
106
+
107
+ - **Docker Installation (Recommended)**: Docker with Docker Compose for containerized deployment
108
+ - **PyPI Installation**: Python 3.11+ for direct installation from PyPI
109
+
110
+ ### Installation
111
+
112
+ #### Option 1: PyPI Installation (New!)
113
+
114
+ Install Borgitory directly from PyPI:
115
+
116
+ ```bash
117
+ # Install stable release from PyPI
118
+ pip install borgitory
119
+
120
+ # Or install pre-release from TestPyPI (for testing new features)
121
+ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ borgitory
122
+
123
+ # Start the server
124
+ borgitory serve
125
+
126
+ # Or run with custom settings
127
+ borgitory serve --host 0.0.0.0 --port 8000
128
+ ```
129
+
130
+ **PyPI Installation Requirements:**
131
+
132
+ - Python 3.11 or higher
133
+ - BorgBackup installed and available in PATH
134
+ - Rclone (optional, for cloud sync features)
135
+
136
+ **Note**: Pre-release versions are published to [TestPyPI](https://test.pypi.org/project/borgitory/) for testing before stable release.
137
+
138
+ #### Option 2: Docker Installation
139
+
140
+ 1. **Pull and run the Docker image**
141
+
142
+ ```bash
143
+ # Using Docker directly
144
+ docker run -d \
145
+ -p 8000:8000 \
146
+ -v ./data:/app/data \
147
+ -v /path/to/backup/sources:/mnt/backup/sources:ro \
148
+ -v /path/to/borg/repos:/mnt/repos \
149
+ --cap-add SYS_ADMIN \
150
+ --device /dev/fuse \
151
+ --name borgitory \
152
+ mlapaglia/borgitory:latest
153
+ ```
154
+
155
+ **Or using Docker Compose** (create a `docker-compose.yml`):
156
+
157
+ ```yaml
158
+ version: '3.8'
159
+ services:
160
+ borgitory:
161
+ image: mlapaglia/borgitory:latest
162
+ ports:
163
+ - "8000:8000"
164
+ volumes:
165
+ - ./data:/app/data
166
+ - /path/to/backup/sources:/mnt/backup/sources:ro
167
+ - /path/to/borg/repos:/mnt/repos
168
+ cap_add:
169
+ - SYS_ADMIN
170
+ devices:
171
+ - /dev/fuse
172
+ restart: unless-stopped
173
+ ```
174
+
175
+ ```bash
176
+ docker-compose up -d
177
+ ```
178
+
179
+ 2. **Access the web interface**
180
+ - Open <http://localhost:8000> in your browser
181
+ - Create your first admin account on initial setup
182
+
183
+ **Docker Hub**: Available at [mlapaglia/borgitory](https://hub.docker.com/r/mlapaglia/borgitory)
184
+
185
+ ### Docker Volumes
186
+
187
+ ```yaml
188
+ volumes:
189
+ - ./data:/app/data # Persistent application data (required)
190
+ - /path/to/backup/sources:/mnt/backup/sources:ro # Source directories to backup (read-only)
191
+ - /path/to/borg/repos:/mnt/repos # Borg repository storage (read-write)
192
+ - /additional/source:/mnt/additional:ro # Additional source directories as needed
193
+ - /another/repo/location:/mnt/alt-repos # Additional repository locations as needed
194
+ ```
195
+
196
+ **Volume Strategy:**
197
+
198
+ - **Important**: All volumes must be mounted under `/mnt/` to be visible in the application
199
+ - Mount as many volumes as necessary to access all your backup sources and repository locations
200
+ - Source directories can be mounted read-only (`:ro`) for safety
201
+ - Repository directories need read-write access for Borg operations
202
+ - Each volume can be mapped to any convenient path under `/mnt/` inside the container
203
+ - Supports distributed setups where repositories and sources are in different locations
204
+
205
+ ## Usage
206
+
207
+ ### 1. Repository Setup
208
+
209
+ 1. Navigate to the main dashboard
210
+ 2. Add a new repository:
211
+ - **Name**: Friendly identifier
212
+ - **Path**: Repository location (local or remote)
213
+ - **Passphrase**: Encryption password
214
+ 3. The system will validate the repository connection
215
+
216
+ ### 2. Creating Backups
217
+
218
+ **Manual Backup:**
219
+
220
+ 1. Select repository from dropdown
221
+ 2. Configure source path and compression
222
+ 3. Click "Start Backup"
223
+ 4. Monitor progress in real-time
224
+
225
+ **Scheduled Backup:**
226
+
227
+ 1. Go to Schedules section
228
+ 2. Create new schedule with cron expression
229
+ 3. Enable/disable schedules as needed
230
+
231
+ ### 3. Archive Pruning
232
+
233
+ 1. Create pruning policies:
234
+ - **Simple Strategy**: Keep archives within X days
235
+ - **Advanced Strategy**: Granular retention (daily/weekly/monthly/yearly)
236
+ 2. Configure options:
237
+ - Show detailed prune lists
238
+ - Display space savings statistics
239
+ - Force prune execution
240
+ 3. Attach policies to schedules or manual backups
241
+
242
+ ### 4. Archive Browsing
243
+
244
+ **Exploring Archives:**
245
+
246
+ 1. Click "View Contents" on any archive to open the browser
247
+ 2. Navigate through directories by clicking folder names
248
+ 3. View file details including size and modification dates
249
+ 4. Real-time directory exploration using FUSE-mounted archive filesystems
250
+
251
+ **Downloading Files:**
252
+
253
+ 1. Click the download button (⬇) next to any file
254
+ 2. Files stream directly from the mounted archive without temporary storage
255
+ 3. Works efficiently with large files and slow connections
256
+ 4. Multiple downloads can run simultaneously
257
+ 5. Uses FUSE mounting for fast, direct file access
258
+
259
+ **Requirements:**
260
+
261
+ - Docker container must run with `--cap-add SYS_ADMIN` and `--device /dev/fuse`
262
+ - Without FUSE support, archive browsing will be disabled
263
+
264
+ ### 5. Cloud Sync
265
+
266
+ 1. Configure S3 remote:
267
+ - Access Key ID and Secret
268
+ 2. Test connection
269
+ 3. Set up automatic sync after backups or manual sync
270
+
271
+ ### 6. Push Notifications
272
+
273
+ 1. Configure Pushover notifications:
274
+ - User Key and API Token
275
+ 2. Choose notification triggers:
276
+ - Success, failure, or both
277
+ 3. Attach to schedules for automated alerts
278
+
279
+ ## API Documentation
280
+
281
+ The application provides a RESTful API with automatic OpenAPI documentation:
282
+
283
+ - **Swagger UI**: <http://localhost:8000/docs>
284
+ - **ReDoc**: <http://localhost:8000/redoc>
285
+
286
+ ## Deployment
287
+
288
+ ### Docker Compose (Recommended)
289
+
290
+ ```bash
291
+ # Production deployment
292
+ docker-compose -f docker-compose.yml up -d
293
+ ```
294
+
295
+ ### Manual Docker
296
+
297
+ ```bash
298
+ # Build image
299
+ docker build -t borgitory .
300
+
301
+ # Run container with FUSE support for archive browsing
302
+ docker run -d \
303
+ -p 8000:8000 \
304
+ -v ./data:/app/data \
305
+ -v /path/to/backup/sources:/mnt/backup/sources:ro \
306
+ -v /path/to/borg/repos:/mnt/repos \
307
+ --cap-add SYS_ADMIN \
308
+ --device /dev/fuse \
309
+ --name borgitory \
310
+ borgitory
311
+ ```
312
+
313
+ **Required Docker Parameters:**
314
+
315
+ - `--cap-add SYS_ADMIN`: Required for FUSE filesystem mounting to enable archive browsing
316
+ - `--device /dev/fuse`: Provides access to FUSE device for archive file system mounting
317
+
318
+ **FUSE Requirements:**
319
+
320
+ - FUSE mounting enables the interactive archive browser feature
321
+ - Allows real-time exploration of backup archives without extraction
322
+ - Supports direct file downloads from mounted archive filesystems
323
+ - Without FUSE support, archive browsing will be disabled
324
+
325
+ ## Project Dependencies
326
+
327
+ This project uses modern Python packaging standards with all dependencies defined in `pyproject.toml`:
328
+
329
+ > Install with `pip install -e .[dev]` to include development tools.
330
+
331
+ ## Architecture
332
+
333
+ ### Backend Stack
334
+
335
+ - **FastAPI**: Modern Python web framework with automatic OpenAPI docs
336
+ - **SQLite**: Lightweight database for configuration and job history
337
+ - **APScheduler**: Advanced job scheduling and cron support
338
+ - **Jinja2**: Powerful template engine for dynamic HTML generation
339
+ - **Passlib**: Secure password hashing and verification
340
+ - **Pushover**: Push notification service integration
341
+
342
+ ### Frontend Stack
343
+
344
+ - **HTMX**: Dynamic HTML updates without JavaScript frameworks
345
+ - **Alpine.js**: Lightweight JavaScript reactivity
346
+ - **Tailwind CSS**: Utility-first styling with responsive design
347
+ - **Server-Sent Events**: Real-time progress updates and live job monitoring
348
+
349
+ ### Job Management System
350
+
351
+ - **Real-time Monitoring**: Live job output streaming with expandable task details
352
+ - **Progress Tracking**: Detailed progress indicators for each job stage
353
+ - **Job History**: Persistent storage of job results with searchable history
354
+ - **Task Management**: Individual task tracking within jobs
355
+
356
+ ### Security Features
357
+
358
+ - Username/password authentication with bcrypt hashing
359
+ - Secure session management
360
+ - Encrypted credential storage (Fernet)
361
+
362
+ ## Troubleshooting
363
+
364
+ ### Logs
365
+
366
+ ```bash
367
+ # View application logs
368
+ docker-compose logs -f borgitory
369
+
370
+ # Check specific container logs
371
+ docker logs <container-id>
372
+ ```
373
+
374
+ ## Contributing
375
+
376
+ 1. Fork the repository
377
+ 2. Create feature branch (`git checkout -b feature/amazing-feature`)
378
+ 3. Run lint (`python lint.py all`)
379
+ 4. Run tests (`pytest`)
380
+ 5. Commit changes (`git commit -m 'Add amazing feature'`)
381
+ 6. Push to branch (`git push origin feature/amazing-feature`)
382
+ 7. Open Pull Request
383
+
384
+ ### Adding additional cloud destinations
385
+
386
+ - Refer to [CLOUD_PROVIDERS.md](https://github.com/mlapaglia/borgitory/blob/main/CLOUD_PROVIDERS.md) for adding additional cloud destinations.
387
+
388
+ ### Development Setup
389
+
390
+ 1. **Set up Python virtual environment**
391
+
392
+ ```bash
393
+ # Create virtual environment
394
+ python -m venv .env_borg
395
+
396
+ # Activate virtual environment
397
+ # On Windows:
398
+ .env_borg\Scripts\activate
399
+ # On macOS/Linux:
400
+ source .env_borg/bin/activate
401
+ ```
402
+
403
+ 2. **Install Python dependencies**
404
+
405
+ ```bash
406
+ # Install runtime dependencies only
407
+ pip install -e .
408
+
409
+ # Install with development dependencies (testing, linting, etc.)
410
+ pip install -e .[dev]
411
+
412
+ # Or install stable release from PyPI for testing
413
+ pip install borgitory
414
+
415
+ # Or install pre-release from TestPyPI for testing new features
416
+ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ borgitory
417
+ ```
418
+
419
+ > **Note**: This project uses modern Python packaging with `pyproject.toml` following PEP 518 standards and is available on PyPI. All dependencies and project metadata are defined in a single configuration file.
420
+
421
+ 3. **Install Rclone** (for cloud sync)
422
+
423
+ ```bash
424
+ # On Ubuntu/Debian
425
+ curl https://rclone.org/install.sh | sudo bash
426
+
427
+ # On macOS
428
+ brew install rclone
429
+ ```
430
+
431
+ 4. **Run development server**
432
+
433
+ ```bash
434
+ python run.py
435
+ ```
436
+
437
+ 5. **Run tests**
438
+
439
+ ```bash
440
+ pytest
441
+ ```