diff --git a/README.md b/README.md
index f5b384d..3722f82 100644
--- a/README.md
+++ b/README.md
@@ -78,6 +78,14 @@ Create a superuser account
```
+### Repository Quota Updates
+
+The repository quotas in the UI are updated after each backup.
+To update the quota during an operation the `update_used_quota` management command can be executed on a regular basis.
+
+There are example configs for systemd-timers in `contrib/communitybackup-quota-update.service` and `contrib/communitybackup-quota-update.timer`. Adjust the paths and the timers to your needs.
+
+
## Custom pages
Some pages are specific to your installation. E.g. an imprint.
@@ -134,3 +142,37 @@ Django debug setting.
### MARKDOWN_PAGE_DIR
`MARKDOWN_PAGE_DIR` is the directory where customized markdown files are put. This directory is required.
+
+### BACKUP_MANAGE_PY
+
+`BACKUP_MANAGE_PY` is the command to run the `manage.py` file, including e.g. a Python interpreter, venv, etc. This must be a `pathlib.Path`
+
+### ADDITIONAL_FOOTER_NAV_ITEMS
+
+`ADDITIONAL_FOOTER_NAV_ITEMS` allows you to add additional links to the footer. This is a `list[str]`. Each item gets rendered as is into a `
`. So usually you want to continue the proper Bootstrap styling in the lst. E.g.:
+
+```python
+ADDITIONAL_FOOTER_NAV_ITEMS = [""" str:
- return f"{settings.BACKUP_USER}@{settings.BACKUP_REPO_HOST}:{self.user.pk}/{self.pk}"
+ return f"ssh://{settings.BACKUP_USER}@{settings.BACKUP_REPO_HOST}/./{self.user.pk}/{self.pk}"
def save(self, *args, **kwargs):
@@ -95,6 +99,21 @@ class BorgRepository(models.Model):
return output
+ def refresh_quota(self):
+ hints_files = self.path.glob("hints.*")
+
+ try:
+ hint = next(hints_files)
+ data = hint.open(mode="rb").read()
+
+ unpacked = msgpack.unpackb(data, strict_map_key=False, raw=True)
+ quota_used = unpacked[b"storage_quota_use"]
+
+ self.used_quota = int(quota_used / 10**9)
+ except StopIteration:
+ # No hints file found, therefore the repo is probably not initialized
+ self.used_quota = -1
+
class Voucher(models.Model):
used = models.BooleanField(default=False)
diff --git a/community_backup/webui/templates/base.html b/community_backup/webui/templates/base.html
index f030569..b418e2b 100644
--- a/community_backup/webui/templates/base.html
+++ b/community_backup/webui/templates/base.html
@@ -67,6 +67,17 @@
+ {% if ADDITIONAL_FOOTER_NAV_ITEMS %}
+
+
+ {% for item in ADDITIONAL_FOOTER_NAV_ITEMS %}
+ -
+ {{item|safe}}
+
+ {% endfor %}
+
+
+ {% endif %}
diff --git a/community_backup/webui/templates/borg_list.html b/community_backup/webui/templates/borg_list.html
index cd508d4..2f6e7c7 100644
--- a/community_backup/webui/templates/borg_list.html
+++ b/community_backup/webui/templates/borg_list.html
@@ -18,14 +18,16 @@
Name |
Key |
Repo-URL |
+ Quota (used/total) |
|
{% for repo in object_list %}
| {{ repo.name }} |
- {{ repo.truncated_key }} |
- {{ repo.repo_url}} |
+ {{ repo.truncated_key }} |
+ {{ repo.repo_url }} |
+ {% if repo.used_quota < 0 %}not initialized{% else %}{{ repo.used_quota }}/{{ repo.quota }} GB{% endif %} |
Edit
Delete |
@@ -33,6 +35,21 @@
+{% if BORG_SERVER_PUBKEYS %}
+
+
+
+ {% for key, fingerprint in BORG_SERVER_PUBKEYS %}
+ -
+
{{ key }}
+ {{ fingerprint }}
+
+ {% endfor %}
+
+
+{% endif %}
diff --git a/pyproject.toml b/pyproject.toml
index 9e552ec..2412b09 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "community_backup"
-version = "0.7"
+version = "0.12"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
@@ -10,4 +10,5 @@ dependencies = [
"django-crispy-forms>=2.6",
"gunicorn>=25.3.0",
"markdown2>=2.5.5",
+ "msgpack>=1.1.2",
]