forked from borgmatic-collective/borgmatic
Split out example configuration into different pages of reference documentation (#942).
This commit is contained in:
parent
5e6ceea7e2
commit
efc4316a45
30 changed files with 488 additions and 143 deletions
|
|
@ -19,26 +19,33 @@ def run_generate(generate_arguments, global_arguments):
|
|||
dry_run_label = ' (dry run; not actually writing anything)' if global_arguments.dry_run else ''
|
||||
|
||||
logger.answer(
|
||||
f'Generating a configuration file at: {generate_arguments.destination_filename}{dry_run_label}',
|
||||
f'Generating configuration files within: {generate_arguments.destination_path}{dry_run_label}'
|
||||
if generate_arguments.split
|
||||
else f'Generating a configuration file at: {generate_arguments.destination_path}{dry_run_label}'
|
||||
)
|
||||
|
||||
borgmatic.config.generate.generate_sample_configuration(
|
||||
global_arguments.dry_run,
|
||||
generate_arguments.source_filename,
|
||||
generate_arguments.destination_filename,
|
||||
generate_arguments.destination_path,
|
||||
borgmatic.config.validate.schema_filename(),
|
||||
overwrite=generate_arguments.overwrite,
|
||||
split=generate_arguments.split,
|
||||
)
|
||||
|
||||
if generate_arguments.source_filename:
|
||||
logger.answer(
|
||||
f'''
|
||||
Merged in the contents of configuration file at: {generate_arguments.source_filename}
|
||||
To review the changes made, run:
|
||||
|
||||
diff --unified {generate_arguments.source_filename} {generate_arguments.destination_filename}''',
|
||||
Merged in the contents of configuration file at: {generate_arguments.source_filename}'''
|
||||
)
|
||||
|
||||
if not generate_arguments.split:
|
||||
logger.answer(
|
||||
'''To review the changes made, run:
|
||||
|
||||
diff --unified {generate_arguments.source_filename} {generate_arguments.destination_path}''',
|
||||
)
|
||||
|
||||
logger.answer(
|
||||
'''
|
||||
This includes all available configuration options with example values, the few
|
||||
|
|
|
|||
|
|
@ -1213,9 +1213,9 @@ def make_parsers(schema, unparsed_arguments): # noqa: PLR0915
|
|||
config_generate_group.add_argument(
|
||||
'-d',
|
||||
'--destination',
|
||||
dest='destination_filename',
|
||||
dest='destination_path',
|
||||
default=config_paths[0],
|
||||
help=f'Destination configuration file, default: {unexpanded_config_paths[0]}',
|
||||
help=f'Destination configuration file (or directory if using --split), default: {unexpanded_config_paths[0]}',
|
||||
)
|
||||
config_generate_group.add_argument(
|
||||
'--overwrite',
|
||||
|
|
@ -1223,6 +1223,11 @@ def make_parsers(schema, unparsed_arguments): # noqa: PLR0915
|
|||
action='store_true',
|
||||
help='Whether to overwrite any existing destination file, defaults to false',
|
||||
)
|
||||
config_generate_group.add_argument(
|
||||
'--split',
|
||||
action='store_true',
|
||||
help='Assuming the destination is a directory instead of a file, split the configuration into separate files within it, one per option, useful for documentation',
|
||||
)
|
||||
config_generate_group.add_argument(
|
||||
'-h',
|
||||
'--help',
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ def comment_out_line(line):
|
|||
return '# '.join((indent_spaces, line[count_indent_spaces:]))
|
||||
|
||||
|
||||
def comment_out_optional_configuration(rendered_config):
|
||||
def transform_optional_configuration(rendered_config, comment_out=True):
|
||||
'''
|
||||
Post-process a rendered configuration string to comment out optional key/values, as determined
|
||||
by a sentinel in the comment before each key.
|
||||
|
|
@ -117,6 +117,9 @@ def comment_out_optional_configuration(rendered_config):
|
|||
|
||||
Ideally ruamel.yaml would support commenting out keys during configuration generation, but it's
|
||||
not terribly easy to accomplish that way.
|
||||
|
||||
If comment_out is False, then just strip the comment sentinel without actually commenting
|
||||
anything out.
|
||||
'''
|
||||
lines = []
|
||||
optional = False
|
||||
|
|
@ -129,6 +132,9 @@ def comment_out_optional_configuration(rendered_config):
|
|||
# Upon encountering an optional configuration option, comment out lines until the next blank
|
||||
# line.
|
||||
if line.strip().startswith(f'# {COMMENTED_OUT_SENTINEL}'):
|
||||
if comment_out is False:
|
||||
continue
|
||||
|
||||
optional = True
|
||||
indent_characters_at_sentinel = indent_characters
|
||||
continue
|
||||
|
|
@ -313,16 +319,18 @@ def merge_source_configuration_into_destination(destination_config, source_confi
|
|||
def generate_sample_configuration(
|
||||
dry_run,
|
||||
source_filename,
|
||||
destination_filename,
|
||||
destination_path,
|
||||
schema_filename,
|
||||
overwrite=False,
|
||||
split=False,
|
||||
):
|
||||
'''
|
||||
Given an optional source configuration filename, and a required destination configuration
|
||||
filename, the path to a schema filename in a YAML rendition of the JSON Schema format, and
|
||||
whether to overwrite a destination file, write out a sample configuration file based on that
|
||||
schema. If a source filename is provided, merge the parsed contents of that configuration into
|
||||
the generated configuration.
|
||||
Given an optional source configuration filename, a required destination configuration path, the
|
||||
path to a schema filename in a YAML rendition of the JSON Schema format, whether to overwrite a
|
||||
destination file, and whether to split the configuration into multiple files (one per option) in
|
||||
the assumed destination directory, write out sample configuration file(s) based on that schema.
|
||||
If a source filename is provided, merge the parsed contents of that configuration into the
|
||||
generated configuration.
|
||||
'''
|
||||
schema = ruamel.yaml.YAML(typ='safe').load(open(schema_filename, encoding='utf-8'))
|
||||
source_config = None
|
||||
|
|
@ -345,8 +353,31 @@ def generate_sample_configuration(
|
|||
if dry_run:
|
||||
return
|
||||
|
||||
if split:
|
||||
if os.path.exists(destination_path) and not os.path.isdir(destination_path):
|
||||
raise ValueError('With the --split flag, the destination path must be a directory')
|
||||
|
||||
os.makedirs(destination_path, exist_ok=True)
|
||||
|
||||
for option_name, option_config in destination_config.items():
|
||||
write_configuration(
|
||||
os.path.join(destination_path, f'{option_name}.yaml'),
|
||||
transform_optional_configuration(
|
||||
render_configuration({option_name: option_config}),
|
||||
comment_out=False,
|
||||
),
|
||||
overwrite=overwrite,
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
if os.path.exists(destination_path) and not os.path.isfile(destination_path):
|
||||
raise ValueError('Without the --split flag, the destination path must be a file')
|
||||
|
||||
write_configuration(
|
||||
destination_filename,
|
||||
comment_out_optional_configuration(render_configuration(destination_config)),
|
||||
destination_path,
|
||||
transform_optional_configuration(
|
||||
render_configuration(destination_config), comment_out=True
|
||||
),
|
||||
overwrite=overwrite,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2139,17 +2139,17 @@ properties:
|
|||
type: string
|
||||
description: |
|
||||
The message body to publish.
|
||||
example: Your backups have failed.
|
||||
example: Your backups have started.
|
||||
priority:
|
||||
type: string
|
||||
description: |
|
||||
The priority to set.
|
||||
example: urgent
|
||||
example: min
|
||||
tags:
|
||||
type: string
|
||||
description: |
|
||||
Tags to attach to the message.
|
||||
example: incoming_envelope
|
||||
example: borgmatic
|
||||
finish:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
|
@ -2163,17 +2163,17 @@ properties:
|
|||
type: string
|
||||
description: |
|
||||
The message body to publish.
|
||||
example: Your backups have failed.
|
||||
example: Your backups have finished.
|
||||
priority:
|
||||
type: string
|
||||
description: |
|
||||
The priority to set.
|
||||
example: urgent
|
||||
example: min
|
||||
tags:
|
||||
type: string
|
||||
description: |
|
||||
Tags to attach to the message.
|
||||
example: incoming_envelope
|
||||
example: borgmatic,+1
|
||||
fail:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
|
@ -2192,12 +2192,12 @@ properties:
|
|||
type: string
|
||||
description: |
|
||||
The priority to set.
|
||||
example: urgent
|
||||
example: max
|
||||
tags:
|
||||
type: string
|
||||
description: |
|
||||
Tags to attach to the message.
|
||||
example: incoming_envelope
|
||||
example: borgmatic,-1,skull
|
||||
states:
|
||||
type: array
|
||||
items:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ FROM docker.io/alpine:3.20.1 AS borgmatic
|
|||
|
||||
COPY . /app
|
||||
RUN apk add --no-cache py3-pip py3-ruamel.yaml py3-ruamel.yaml.clib
|
||||
RUN pip install --break-system-packages --no-cache /app && borgmatic config generate && chmod +r /etc/borgmatic/config.yaml
|
||||
RUN pip install --break-system-packages --no-cache /app && borgmatic config generate && borgmatic config generate --destination /etc/borgmatic --split && chmod +r /etc/borgmatic/*.yaml
|
||||
RUN borgmatic --help > /command-line.txt \
|
||||
&& for action in repo-create transfer create prune compact check delete extract config "config bootstrap" "config generate" "config validate" export-tar mount umount repo-delete restore repo-list list repo-info info break-lock "key export" "key import" "key change-passphrase" recreate borg; do \
|
||||
echo -e "\n--------------------------------------------------------------------------------\n" >> /command-line.txt \
|
||||
|
|
@ -23,7 +23,7 @@ RUN npm install @11ty/eleventy \
|
|||
markdown-it \
|
||||
markdown-it-anchor \
|
||||
markdown-it-replace-link
|
||||
COPY --from=borgmatic /etc/borgmatic/config.yaml /source/docs/_includes/borgmatic/config.yaml
|
||||
COPY --from=borgmatic /etc/borgmatic/* /source/docs/_includes/borgmatic/
|
||||
COPY --from=borgmatic /command-line.txt /source/docs/_includes/borgmatic/command-line.txt
|
||||
COPY --from=borgmatic /contributors.html /source/docs/_includes/borgmatic/contributors.html
|
||||
COPY . /source
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
{% if page.url != '/' %}<h3><a href="https://torsion.org/borgmatic/">borgmatic</a></h3>{% endif %}
|
||||
<div class="container" id="breadcrumb">
|
||||
{% set breadcrumb = collections.all | eleventyNavigationBreadcrumb(eleventyNavigation.key, {allowMissing: true}) %}
|
||||
{{ breadcrumb | eleventyNavigationToHtml | safe }}
|
||||
{# The replace() is a work-around for https://github.com/11ty/eleventy-navigation/issues/56 #}
|
||||
{{ breadcrumb | eleventyNavigationToHtml | replace('href="/reference/', 'href="/borgmatic/reference/') | safe }}
|
||||
</div>
|
||||
<h1 class="elv-hed">{{ title | safe }}</h1>
|
||||
{% if page.url == '/' %}<h3>It's your data. Keep it that way.</h3>{% endif %}
|
||||
|
|
|
|||
|
|
@ -23,14 +23,13 @@ services:
|
|||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.borgmatic-docs.rule=PathPrefix(`/borgmatic`)"
|
||||
# - "traefik.http.routers.borgmatic-docs.middlewares=borgmatic-trailing-slash-redirectregex,borgmatic-docs-redirectregex,borgmatic-stripprefix"
|
||||
- "traefik.http.routers.borgmatic-docs.middlewares=borgmatic-trailing-slash-redirectregex,borgmatic-stripprefix"
|
||||
- "traefik.http.routers.borgmatic-docs.middlewares=borgmatic-trailing-slash-redirectregex,borgmatic-docs-redirectregex,borgmatic-stripprefix"
|
||||
- "traefik.http.middlewares.borgmatic-trailing-slash-redirectregex.redirectregex.regex=^(.*)/borgmatic$$"
|
||||
- "traefik.http.middlewares.borgmatic-trailing-slash-redirectregex.redirectregex.replacement=$${1}/borgmatic/"
|
||||
- "traefik.http.middlewares.borgmatic-trailing-slash-redirectregex.redirectregex.permanent=true"
|
||||
# - "traefik.http.middlewares.borgmatic-docs-redirectregex.redirectregex.regex=^(.*)/borgmatic/docs/(.*)$$"
|
||||
# - "traefik.http.middlewares.borgmatic-docs-redirectregex.redirectregex.replacement=$${1}/borgmatic/$${2}"
|
||||
# - "traefik.http.middlewares.borgmatic-docs-redirectregex.redirectregex.permanent=true"
|
||||
- "traefik.http.middlewares.borgmatic-docs-redirectregex.redirectregex.regex=^(.*)/borgmatic/docs/(.*)$$"
|
||||
- "traefik.http.middlewares.borgmatic-docs-redirectregex.redirectregex.replacement=$${1}/borgmatic/$${2}"
|
||||
- "traefik.http.middlewares.borgmatic-docs-redirectregex.redirectregex.permanent=true"
|
||||
- "traefik.http.middlewares.borgmatic-stripprefix.stripprefix.prefixes=/borgmatic"
|
||||
- "traefik.http.routers.borgmatic-docs.entrypoints=web"
|
||||
build:
|
||||
|
|
|
|||
|
|
@ -27,33 +27,6 @@ mysql_databases:
|
|||
these and other database options in the `hooks:` section of your
|
||||
configuration.
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.5.22</span> You can
|
||||
also dump MongoDB databases. For example:
|
||||
|
||||
```yaml
|
||||
mongodb_databases:
|
||||
- name: messages
|
||||
```
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.7.9</span>
|
||||
Additionally, you can dump SQLite databases. For example:
|
||||
|
||||
```yaml
|
||||
sqlite_databases:
|
||||
- name: mydb
|
||||
path: /var/lib/sqlite3/mydb.sqlite
|
||||
```
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.8.2</span> If you're
|
||||
using MariaDB, use the MariaDB database hook instead of `mysql_databases:` as
|
||||
the MariaDB hook calls native MariaDB commands instead of the deprecated MySQL
|
||||
ones. For instance:
|
||||
|
||||
```yaml
|
||||
mariadb_databases:
|
||||
- name: comments
|
||||
```
|
||||
|
||||
As part of each backup, borgmatic streams a database dump for each configured
|
||||
database directly to Borg, so it's included in the backup without consuming
|
||||
additional disk space. (The exceptions are the PostgreSQL/MongoDB `directory`
|
||||
|
|
@ -107,47 +80,17 @@ sqlite_databases:
|
|||
path: /var/lib/sqlite3/mydb.sqlite
|
||||
```
|
||||
|
||||
See your [borgmatic configuration
|
||||
file](https://torsion.org/borgmatic/reference/configuration/) for
|
||||
additional customization of the options passed to database commands (when
|
||||
listing databases, restoring databases, etc.).
|
||||
See the [data sources
|
||||
documentation](https://torsion.org/borgmatic/reference/configuration/data-sources/)
|
||||
for details on additional options, including customizing the flags passed to
|
||||
database commands when listing databases, restoring databases, etc.
|
||||
|
||||
<a id="runtime-directory"></a>
|
||||
|
||||
### Runtime directory
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.9.0</span> To support
|
||||
streaming database dumps to Borg, borgmatic uses a runtime directory for
|
||||
temporary file storage, probing the following locations (in order) to find it:
|
||||
|
||||
1. The `user_runtime_directory` borgmatic configuration option.
|
||||
2. The `XDG_RUNTIME_DIR` environment variable, usually `/run/user/$UID`
|
||||
(where `$UID` is the current user's ID), automatically set by PAM on Linux
|
||||
for a user with a session.
|
||||
3. <span class="minilink minilink-addedin">New in version 1.9.2</span>The
|
||||
`RUNTIME_DIRECTORY` environment variable, set by systemd if
|
||||
`RuntimeDirectory=borgmatic` is added to borgmatic's systemd service file.
|
||||
4. <span class="minilink minilink-addedin">New in version 1.9.1</span>The
|
||||
`TMPDIR` environment variable, set on macOS for a user with a session,
|
||||
among other operating systems.
|
||||
5. <span class="minilink minilink-addedin">New in version 1.9.1</span>The
|
||||
`TEMP` environment variable, set on various systems.
|
||||
6. <span class="minilink minilink-addedin">New in version 1.9.2</span>
|
||||
Hard-coded `/tmp`. <span class="minilink minilink-addedin">Prior to
|
||||
version 1.9.2</span>This was instead hard-coded to `/run/user/$UID`.
|
||||
|
||||
You can see the runtime directory path that borgmatic selects by running with
|
||||
`--verbosity 2` and looking for "Using runtime directory" in the output.
|
||||
|
||||
Regardless of the runtime directory selected, borgmatic stores its files
|
||||
within a `borgmatic` subdirectory of the runtime directory. Additionally, in
|
||||
the case of `TMPDIR`, `TEMP`, and the hard-coded `/tmp`, borgmatic creates a
|
||||
randomly named subdirectory in an effort to reduce path collisions in shared
|
||||
system temporary directories.
|
||||
|
||||
<span class="minilink minilink-addedin">Prior to version 1.9.0</span>
|
||||
borgmatic created temporary streaming database dumps within the `~/.borgmatic`
|
||||
directory by default. At that time, the path was configurable by the
|
||||
`borgmatic_source_directory` configuration option (now deprecated).
|
||||
To support streaming database dumps to Borg, borgmatic uses a runtime directory
|
||||
for temporary file storage. See the [runtime directory
|
||||
documentation](https://torsion.org/borgmatic/reference/configuration/runtime-directory/)
|
||||
for details.
|
||||
|
||||
|
||||
### All databases
|
||||
|
|
@ -412,8 +355,6 @@ most up-to-date files and therefore the latest timestamp, run a command like:
|
|||
borgmatic restore --archive host-2023-01-02T04:06:07.080910
|
||||
```
|
||||
|
||||
(No borgmatic `restore` action? Upgrade borgmatic!)
|
||||
|
||||
Or you can simplify this to:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ and therefore the latest timestamp, run a command like:
|
|||
borgmatic extract --archive host-2023-01-02T04:06:07.080910
|
||||
```
|
||||
|
||||
(No borgmatic `extract` action? Upgrade borgmatic!)
|
||||
|
||||
Or simplify this to:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Container secerts
|
||||
title: Container secrets
|
||||
eleventyNavigation:
|
||||
key: • Container
|
||||
parent: 🔒 Credentials
|
||||
|
|
|
|||
10
docs/reference/configuration/data-sources/btrfs.md
Normal file
10
docs/reference/configuration/data-sources/btrfs.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: Btrfs
|
||||
eleventyNavigation:
|
||||
key: • Btrfs
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/btrfs.yaml %}
|
||||
```
|
||||
27
docs/reference/configuration/data-sources/index.md
Normal file
27
docs/reference/configuration/data-sources/index.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
title: Data sources
|
||||
eleventyNavigation:
|
||||
key: 🗄️ Data sources
|
||||
parent: ⚙️ Configuration
|
||||
---
|
||||
Data sources are built-in borgmatic integrations that, instead of backing up
|
||||
plain filesystem data, can pull data directly from database servers and
|
||||
filesystem snapshots.
|
||||
|
||||
In the case of supported database systems, borgmatic dumps your configured
|
||||
databases, streaming them directly to Borg when creating a backup. Here are the
|
||||
supported databases and how to configure their borgmatic integrations:
|
||||
|
||||
* [MariaDB](https://torsion.org/borgmatic/reference/configuration/data-sources/mariadb/)
|
||||
* [MongoDB](https://torsion.org/borgmatic/reference/configuration/data-sources/mongodb/)
|
||||
* [MySQL](https://torsion.org/borgmatic/reference/configuration/data-sources/mysql/)
|
||||
* [PostgreSQL](https://torsion.org/borgmatic/reference/configuration/data-sources/postgresql/)
|
||||
* [SQLite](https://torsion.org/borgmatic/reference/configuration/data-sources/sqlite/)
|
||||
|
||||
For supported filesystems, borgmatic takes on-demand snapshots of configured
|
||||
source directories and feeds them to Borg. Here are the supported filesystems /
|
||||
volume managers and how to configure their borgmatic integrations:
|
||||
|
||||
* [Btrfs](https://torsion.org/borgmatic/reference/configuration/data-sources/btrfs/)
|
||||
* [LVM](https://torsion.org/borgmatic/reference/configuration/data-sources/lvm/)
|
||||
* [ZFS](https://torsion.org/borgmatic/reference/configuration/data-sources/zfs/)
|
||||
10
docs/reference/configuration/data-sources/lvm.md
Normal file
10
docs/reference/configuration/data-sources/lvm.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: LVM
|
||||
eleventyNavigation:
|
||||
key: • LVM
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/lvm.yaml %}
|
||||
```
|
||||
23
docs/reference/configuration/data-sources/mariadb.md
Normal file
23
docs/reference/configuration/data-sources/mariadb.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
title: MariaDB
|
||||
eleventyNavigation:
|
||||
key: • MariaDB
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.8.2</span> To backup
|
||||
MariaDB with borgmatic, use the `mariadb_databases:` hook instead of
|
||||
`mysql_databases:` as the MariaDB hook calls native MariaDB commands instead of
|
||||
the deprecated MySQL ones. For instance:
|
||||
|
||||
```yaml
|
||||
mariadb_databases:
|
||||
- name: comments
|
||||
```
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/mariadb_databases.yaml %}
|
||||
```
|
||||
21
docs/reference/configuration/data-sources/mongodb.md
Normal file
21
docs/reference/configuration/data-sources/mongodb.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: MongoDB
|
||||
eleventyNavigation:
|
||||
key: • MongoDB
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.5.22</span> To backup
|
||||
MongoDB with borgmatic, use the `mongodb_databases:` hook. For example:
|
||||
|
||||
```yaml
|
||||
mongodb_databases:
|
||||
- name: messages
|
||||
```
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/mongodb_databases.yaml %}
|
||||
```
|
||||
21
docs/reference/configuration/data-sources/mysql.md
Normal file
21
docs/reference/configuration/data-sources/mysql.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: MySQL
|
||||
eleventyNavigation:
|
||||
key: • MySQL
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.4.9</span> To backup
|
||||
MySQL with borgmatic, use the `mysql_databases:` hook. For instance:
|
||||
|
||||
```yaml
|
||||
mysql_databases:
|
||||
- name: posts
|
||||
```
|
||||
|
||||
|
||||
## Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/mysql_databases.yaml %}
|
||||
```
|
||||
21
docs/reference/configuration/data-sources/postgresql.md
Normal file
21
docs/reference/configuration/data-sources/postgresql.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: PostgreSQL
|
||||
eleventyNavigation:
|
||||
key: • PostgreSQL
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 1.4.0</span> To backup
|
||||
PostgreSQL with borgmatic, use the `postgresql_databases:` hook. For instance:
|
||||
|
||||
```yaml
|
||||
postgresql_databases:
|
||||
- name: users
|
||||
```
|
||||
|
||||
|
||||
## Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/postgresql_databases.yaml %}
|
||||
```
|
||||
22
docs/reference/configuration/data-sources/sqlite.md
Normal file
22
docs/reference/configuration/data-sources/sqlite.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
title: SQLite
|
||||
eleventyNavigation:
|
||||
key: • SQLite
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
<span class="minilink minilink-addedin">New in version 1.7.9</span> To backup
|
||||
SQLite with borgmatic, use the `sqlite_databases:` hook. For example:
|
||||
|
||||
|
||||
```yaml
|
||||
sqlite_databases:
|
||||
- name: mydb
|
||||
path: /var/lib/sqlite3/mydb.sqlite
|
||||
```
|
||||
|
||||
|
||||
## Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/sqlite_databases.yaml %}
|
||||
```
|
||||
10
docs/reference/configuration/data-sources/zfs.md
Normal file
10
docs/reference/configuration/data-sources/zfs.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: ZFS
|
||||
eleventyNavigation:
|
||||
key: • ZFS
|
||||
parent: 🗄️ Data sources
|
||||
---
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/zfs.yaml %}
|
||||
```
|
||||
|
|
@ -104,3 +104,10 @@ This may be necessary for some services that reject large requests.
|
|||
See the [configuration
|
||||
reference](https://torsion.org/borgmatic/reference/configuration/) for
|
||||
details.
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/apprise.yaml %}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -48,3 +48,10 @@ defaults for these flags in your borgmatic configuration via the
|
|||
You can configure Healthchecks to notify you by a [variety of
|
||||
mechanisms](https://healthchecks.io/#welcome-integrations) when backups fail
|
||||
or it doesn't hear from borgmatic for a certain period of time.
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/healthchecks.yaml %}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@ to issues. The `states` list can override this. Each state can have its own
|
|||
custom messages, priorities and tags or, if none are provided, will use the
|
||||
default.
|
||||
|
||||
An example configuration is shown here with all the available options,
|
||||
including [priorities](https://ntfy.sh/docs/publish/#message-priority) and
|
||||
[tags](https://ntfy.sh/docs/publish/#tags-emojis):
|
||||
Here's a basic configuration that notifies on failure:
|
||||
|
||||
```yaml
|
||||
ntfy:
|
||||
|
|
@ -28,24 +26,12 @@ ntfy:
|
|||
username: myuser
|
||||
password: secret
|
||||
|
||||
start:
|
||||
title: A borgmatic backup started
|
||||
message: Watch this space...
|
||||
tags: borgmatic
|
||||
priority: min
|
||||
finish:
|
||||
title: A borgmatic backup completed successfully
|
||||
message: Nice!
|
||||
tags: borgmatic,+1
|
||||
priority: min
|
||||
fail:
|
||||
title: A borgmatic backup failed
|
||||
message: You should probably fix it
|
||||
tags: borgmatic,-1,skull
|
||||
priority: max
|
||||
states:
|
||||
- start
|
||||
- finish
|
||||
- fail
|
||||
```
|
||||
|
||||
|
|
@ -62,3 +48,14 @@ ntfy:
|
|||
server: https://ntfy.my-domain.com
|
||||
access_token: tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2
|
||||
````
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
Here's an example configuration with all the available options,
|
||||
including [priorities](https://ntfy.sh/docs/publish/#message-priority) and
|
||||
[tags](https://ntfy.sh/docs/publish/#tags-emojis):
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/ntfy.yaml %}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -65,5 +65,3 @@ pagerduty:
|
|||
integration_key: a177cad45bd374409f78906a810a3074
|
||||
send_logs: false
|
||||
```
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,3 +52,11 @@ pushover:
|
|||
expire: 600 # Used only for priority 2. Default is 600 seconds.
|
||||
retry: 30 # Used only for priority 2. Default is 30 seconds.
|
||||
device: "pixel8"
|
||||
```
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/pushover.yaml %}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ displayed
|
|||
environment variable into borgmatic's Sentry `data_source_name_url`
|
||||
configuration option. For example:
|
||||
|
||||
```
|
||||
```yaml
|
||||
sentry:
|
||||
data_source_name_url: https://5f80ec@o294220.ingest.us.sentry.io/203069
|
||||
monitor_slug: mymonitor
|
||||
|
|
@ -32,7 +32,7 @@ finishes, or fails, but only when any of the `create`, `prune`, `compact`, or
|
|||
behavior with the `states` configuration option. For instance, to only ping
|
||||
Sentry on failure:
|
||||
|
||||
```
|
||||
```yaml
|
||||
sentry:
|
||||
data_source_name_url: https://5f80ec@o294220.ingest.us.sentry.io/203069
|
||||
monitor_slug: mymonitor
|
||||
|
|
|
|||
|
|
@ -57,3 +57,10 @@ Heartbeat Retry = 360 # = 10 minutes
|
|||
# is sent each time.
|
||||
Resend Notification every X times = 1
|
||||
```
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/uptime_kuma.yaml %}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ states will trigger the hook. The value defined in the configuration of each
|
|||
state is used to populate the data of the configured Zabbix item. If none are
|
||||
provided, it defaults to a lower-case string of the state.
|
||||
|
||||
An example configuration is shown here with all the available options.
|
||||
Here's an example configuration:
|
||||
|
||||
```yaml
|
||||
zabbix:
|
||||
|
|
@ -24,21 +24,13 @@ zabbix:
|
|||
|
||||
username: myuser
|
||||
password: secret
|
||||
api_key: b2ecba64d8beb47fc161ae48b164cfd7104a79e8e48e6074ef5b141d8a0aeeca
|
||||
|
||||
host: "borg-server"
|
||||
key: borg.status
|
||||
itemid: 55105
|
||||
|
||||
start:
|
||||
value: "STARTED"
|
||||
finish:
|
||||
value: "OK"
|
||||
fail:
|
||||
value: "ERROR"
|
||||
states:
|
||||
- start
|
||||
- finish
|
||||
- fail
|
||||
```
|
||||
|
||||
|
|
@ -69,3 +61,10 @@ is used.
|
|||
|
||||
Keep in mind that `host` refers to the "Host name" on the Zabbix server and not
|
||||
the "Visual name".
|
||||
|
||||
|
||||
### Full configuration
|
||||
|
||||
```yaml
|
||||
{% include borgmatic/zabbix.yaml %}
|
||||
```
|
||||
|
|
|
|||
41
docs/reference/configuration/runtime-directory.md
Normal file
41
docs/reference/configuration/runtime-directory.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
title: Runtime directory
|
||||
eleventyNavigation:
|
||||
key: 📁 Runtime directory
|
||||
parent: ⚙️ Configuration
|
||||
---
|
||||
<span class="minilink minilink-addedin">New in version 1.9.0</span> borgmatic
|
||||
uses a runtime directory for temporary file storage, such as for streaming
|
||||
database dumps to Borg, creating filesystem snapshots, saving bootstrap
|
||||
metadata, and so on. To determine the path for this runtime directory, borgmatic
|
||||
probes the following values:
|
||||
|
||||
1. The `user_runtime_directory` borgmatic configuration option.
|
||||
2. The `XDG_RUNTIME_DIR` environment variable, usually `/run/user/$UID`
|
||||
(where `$UID` is the current user's ID), automatically set by PAM on Linux
|
||||
for a user with a session.
|
||||
3. <span class="minilink minilink-addedin">New in version 1.9.2</span>The
|
||||
`RUNTIME_DIRECTORY` environment variable, set by systemd if
|
||||
`RuntimeDirectory=borgmatic` is added to borgmatic's systemd service file.
|
||||
4. <span class="minilink minilink-addedin">New in version 1.9.1</span>The
|
||||
`TMPDIR` environment variable, set on macOS for a user with a session,
|
||||
among other operating systems.
|
||||
5. <span class="minilink minilink-addedin">New in version 1.9.1</span>The
|
||||
`TEMP` environment variable, set on various systems.
|
||||
6. <span class="minilink minilink-addedin">New in version 1.9.2</span>
|
||||
Hard-coded `/tmp`. <span class="minilink minilink-addedin">Prior to
|
||||
version 1.9.2</span>This was instead hard-coded to `/run/user/$UID`.
|
||||
|
||||
You can see the runtime directory path that borgmatic selects by running with
|
||||
`--verbosity 2` and looking for `Using runtime directory` in the output.
|
||||
|
||||
Regardless of the runtime directory selected, borgmatic stores its files
|
||||
within a `borgmatic` subdirectory of the runtime directory. Additionally, in
|
||||
the case of `TMPDIR`, `TEMP`, and the hard-coded `/tmp`, borgmatic creates a
|
||||
randomly named subdirectory in an effort to reduce path collisions in shared
|
||||
system temporary directories.
|
||||
|
||||
<span class="minilink minilink-addedin">Prior to version 1.9.0</span>
|
||||
borgmatic created temporary streaming database dumps within the `~/.borgmatic`
|
||||
directory by default. At that time, the path was configurable by the
|
||||
`borgmatic_source_directory` configuration option (now deprecated).
|
||||
|
|
@ -195,7 +195,7 @@ def test_comment_out_line_comments_twice_indented_option():
|
|||
assert module.comment_out_line(line) == ' # - item'
|
||||
|
||||
|
||||
def test_comment_out_optional_configuration_comments_optional_config_only():
|
||||
def test_transform_optional_configuration_comments_optional_config_only():
|
||||
# The "# COMMENT_OUT" comment is a sentinel used to express that the following key is optional.
|
||||
# It's stripped out of the final output.
|
||||
flexmock(module).comment_out_line = lambda line: '# ' + line
|
||||
|
|
@ -236,7 +236,54 @@ repositories:
|
|||
# other: thing
|
||||
'''
|
||||
|
||||
assert module.comment_out_optional_configuration(config.strip()) == expected_config.strip()
|
||||
assert module.transform_optional_configuration(config.strip()) == expected_config.strip()
|
||||
|
||||
|
||||
def test_transform_optional_configuration_with_comment_out_false_leaves_in_optional_config():
|
||||
# The "# COMMENT_OUT" comment is a sentinel used to express that the following key is optional.
|
||||
# It's stripped out of the final output.
|
||||
flexmock(module).comment_out_line = lambda line: '# ' + line
|
||||
config = '''
|
||||
# COMMENT_OUT
|
||||
foo:
|
||||
# COMMENT_OUT
|
||||
bar:
|
||||
- baz
|
||||
- quux
|
||||
|
||||
repositories:
|
||||
- path: foo
|
||||
# COMMENT_OUT
|
||||
label: bar
|
||||
- path: baz
|
||||
label: quux
|
||||
|
||||
# This comment should be kept.
|
||||
# COMMENT_OUT
|
||||
other: thing
|
||||
'''
|
||||
|
||||
# flake8: noqa
|
||||
expected_config = '''
|
||||
foo:
|
||||
bar:
|
||||
- baz
|
||||
- quux
|
||||
|
||||
repositories:
|
||||
- path: foo
|
||||
label: bar
|
||||
- path: baz
|
||||
label: quux
|
||||
|
||||
# This comment should be kept.
|
||||
other: thing
|
||||
'''
|
||||
|
||||
assert (
|
||||
module.transform_optional_configuration(config.strip(), comment_out=False)
|
||||
== expected_config.strip()
|
||||
)
|
||||
|
||||
|
||||
def test_render_configuration_converts_configuration_to_yaml_string():
|
||||
|
|
@ -377,13 +424,32 @@ def test_generate_sample_configuration_does_not_raise():
|
|||
)
|
||||
flexmock(module).should_receive('schema_to_sample_configuration')
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination')
|
||||
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration')
|
||||
flexmock(module).should_receive('comment_out_optional_configuration')
|
||||
flexmock(module).should_receive('transform_optional_configuration')
|
||||
flexmock(module).should_receive('write_configuration')
|
||||
|
||||
module.generate_sample_configuration(False, None, 'dest.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_generate_sample_configuration_with_destination_directory_error():
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('schema.yaml', encoding='utf-8').and_return('')
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
|
||||
flexmock(load=lambda filename: {})
|
||||
)
|
||||
flexmock(module).should_receive('schema_to_sample_configuration')
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination')
|
||||
flexmock(module.os.path).should_receive('exists').and_return(True)
|
||||
flexmock(module.os.path).should_receive('isfile').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration').never()
|
||||
flexmock(module).should_receive('transform_optional_configuration').never()
|
||||
flexmock(module).should_receive('write_configuration').never()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.generate_sample_configuration(False, None, 'dest.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_generate_sample_configuration_with_source_filename_omits_empty_bootstrap_field():
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('schema.yaml', encoding='utf-8').and_return('')
|
||||
|
|
@ -398,8 +464,9 @@ def test_generate_sample_configuration_with_source_filename_omits_empty_bootstra
|
|||
object, {'foo': 'bar'}
|
||||
).once()
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination')
|
||||
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration')
|
||||
flexmock(module).should_receive('comment_out_optional_configuration')
|
||||
flexmock(module).should_receive('transform_optional_configuration')
|
||||
flexmock(module).should_receive('write_configuration')
|
||||
|
||||
module.generate_sample_configuration(False, 'source.yaml', 'dest.yaml', 'schema.yaml')
|
||||
|
|
@ -418,8 +485,9 @@ def test_generate_sample_configuration_with_source_filename_keeps_non_empty_boot
|
|||
object, source_config
|
||||
).once()
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination')
|
||||
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration')
|
||||
flexmock(module).should_receive('comment_out_optional_configuration')
|
||||
flexmock(module).should_receive('transform_optional_configuration')
|
||||
flexmock(module).should_receive('write_configuration')
|
||||
|
||||
module.generate_sample_configuration(False, 'source.yaml', 'dest.yaml', 'schema.yaml')
|
||||
|
|
@ -433,8 +501,58 @@ def test_generate_sample_configuration_with_dry_run_does_not_write_file():
|
|||
)
|
||||
flexmock(module).should_receive('schema_to_sample_configuration')
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination')
|
||||
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration')
|
||||
flexmock(module).should_receive('comment_out_optional_configuration')
|
||||
flexmock(module).should_receive('transform_optional_configuration')
|
||||
flexmock(module).should_receive('write_configuration').never()
|
||||
|
||||
module.generate_sample_configuration(True, None, 'dest.yaml', 'schema.yaml')
|
||||
|
||||
|
||||
def test_generate_sample_configuration_with_split_writes_each_option_to_file():
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('schema.yaml', encoding='utf-8').and_return('')
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
|
||||
flexmock(load=lambda filename: {})
|
||||
)
|
||||
flexmock(module).should_receive('schema_to_sample_configuration')
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination').and_return(
|
||||
{'foo': 1, 'bar': 2}
|
||||
)
|
||||
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration')
|
||||
flexmock(module).should_receive('transform_optional_configuration')
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
flexmock(module).should_receive('write_configuration').with_args(
|
||||
'dest/foo.yaml',
|
||||
None,
|
||||
overwrite=False,
|
||||
).once()
|
||||
flexmock(module).should_receive('write_configuration').with_args(
|
||||
'dest/bar.yaml',
|
||||
None,
|
||||
overwrite=False,
|
||||
).once()
|
||||
|
||||
module.generate_sample_configuration(False, None, 'dest', 'schema.yaml', split=True)
|
||||
|
||||
|
||||
def test_generate_sample_configuration_with_split_and_file_destination_errors():
|
||||
builtins = flexmock(sys.modules['builtins'])
|
||||
builtins.should_receive('open').with_args('schema.yaml', encoding='utf-8').and_return('')
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
|
||||
flexmock(load=lambda filename: {})
|
||||
)
|
||||
flexmock(module).should_receive('schema_to_sample_configuration')
|
||||
flexmock(module).should_receive('merge_source_configuration_into_destination').and_return(
|
||||
{'foo': 1, 'bar': 2}
|
||||
)
|
||||
flexmock(module.os.path).should_receive('exists').and_return(True)
|
||||
flexmock(module.os.path).should_receive('isdir').and_return(False)
|
||||
flexmock(module).should_receive('render_configuration').never()
|
||||
flexmock(module).should_receive('transform_optional_configuration').never()
|
||||
flexmock(module.os).should_receive('makedirs').never()
|
||||
flexmock(module).should_receive('write_configuration').never()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.generate_sample_configuration(False, None, 'dest', 'schema.yaml', split=True)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ from borgmatic.actions.config import generate as module
|
|||
def test_run_generate_does_not_raise():
|
||||
generate_arguments = flexmock(
|
||||
source_filename=None,
|
||||
destination_filename='destination.yaml',
|
||||
destination_path='destination.yaml',
|
||||
overwrite=False,
|
||||
split=False,
|
||||
)
|
||||
global_arguments = flexmock(dry_run=False)
|
||||
flexmock(module.borgmatic.config.generate).should_receive('generate_sample_configuration')
|
||||
|
|
@ -18,8 +19,9 @@ def test_run_generate_does_not_raise():
|
|||
def test_run_generate_with_dry_run_does_not_raise():
|
||||
generate_arguments = flexmock(
|
||||
source_filename=None,
|
||||
destination_filename='destination.yaml',
|
||||
destination_path='destination.yaml',
|
||||
overwrite=False,
|
||||
split=False,
|
||||
)
|
||||
global_arguments = flexmock(dry_run=True)
|
||||
flexmock(module.borgmatic.config.generate).should_receive('generate_sample_configuration')
|
||||
|
|
@ -30,8 +32,22 @@ def test_run_generate_with_dry_run_does_not_raise():
|
|||
def test_run_generate_with_source_filename_does_not_raise():
|
||||
generate_arguments = flexmock(
|
||||
source_filename='source.yaml',
|
||||
destination_filename='destination.yaml',
|
||||
destination_path='destination.yaml',
|
||||
overwrite=False,
|
||||
split=False,
|
||||
)
|
||||
global_arguments = flexmock(dry_run=False)
|
||||
flexmock(module.borgmatic.config.generate).should_receive('generate_sample_configuration')
|
||||
|
||||
module.run_generate(generate_arguments, global_arguments)
|
||||
|
||||
|
||||
def test_run_generate_with_split_does_not_raise():
|
||||
generate_arguments = flexmock(
|
||||
source_filename=None,
|
||||
destination_path='destination.yaml',
|
||||
overwrite=False,
|
||||
split=True,
|
||||
)
|
||||
global_arguments = flexmock(dry_run=False)
|
||||
flexmock(module.borgmatic.config.generate).should_receive('generate_sample_configuration')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue