restic-profile-cli 0.2.1__tar.gz → 0.4.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 (117) hide show
  1. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.ansible-lint +5 -1
  2. restic_profile_cli-0.2.1/.copier-answers.yaml → restic_profile_cli-0.4.0/.copier-answers.yml +2 -1
  3. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.github/workflows/docs.yaml +2 -3
  4. restic_profile_cli-0.4.0/AGENTS.md +51 -0
  5. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/CHANGELOG.md +39 -1
  6. restic_profile_cli-0.4.0/PKG-INFO +87 -0
  7. restic_profile_cli-0.4.0/README.md +63 -0
  8. restic_profile_cli-0.4.0/README.zh-CN.md +59 -0
  9. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/ansible.cfg +2 -2
  10. restic_profile_cli-0.4.0/docs/ansible-toolchain.md +78 -0
  11. restic_profile_cli-0.4.0/docs/ansible-toolchain.zh.md +75 -0
  12. restic_profile_cli-0.4.0/docs/index.md +56 -0
  13. restic_profile_cli-0.4.0/docs/index.zh.md +53 -0
  14. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/docs/restic-profile/cli.md +22 -22
  15. restic_profile_cli-0.4.0/docs/restic-profile/cli.zh.md +65 -0
  16. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/docs/restic-profile/examples.md +44 -4
  17. restic_profile_cli-0.4.0/docs/restic-profile/examples.zh.md +307 -0
  18. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/docs/restic-profile/toml-config.md +3 -2
  19. restic_profile_cli-0.4.0/docs/restic-profile/toml-config.zh.md +190 -0
  20. restic_profile_cli-0.2.1/docs/restic-rest-server/index.md → restic_profile_cli-0.4.0/docs/restic-rest-server.md +7 -7
  21. restic_profile_cli-0.4.0/docs/restic-rest-server.zh.md +85 -0
  22. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/galaxy.yml +3 -2
  23. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/justfile +17 -6
  24. restic_profile_cli-0.4.0/mkdocs.yml +57 -0
  25. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/playbooks/restic-profile.yaml +1 -1
  26. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/playbooks/restic-rest-server.yaml +1 -1
  27. restic_profile_cli-0.4.0/plugins/filter/restic_profile.py +386 -0
  28. restic_profile_cli-0.4.0/plugins/modules/systemd_timer_state.py +154 -0
  29. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/pyproject.toml +1 -1
  30. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/defaults/main.yaml +44 -41
  31. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/meta/main.yaml +8 -0
  32. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/molecule/default/converge.yaml +2 -2
  33. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/molecule/default/prepare.yaml +1 -1
  34. restic_profile_cli-0.4.0/roles/restic_profile/tasks/_config_target.yaml +148 -0
  35. restic_profile_cli-0.4.0/roles/restic_profile/tasks/_remove_target.yaml +86 -0
  36. restic_profile_cli-0.4.0/roles/restic_profile/tasks/_service_target.yaml +170 -0
  37. restic_profile_cli-0.4.0/roles/restic_profile/tasks/cleanup_orphans.yaml +11 -0
  38. restic_profile_cli-0.4.0/roles/restic_profile/tasks/config.yaml +7 -0
  39. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/tasks/hooks_phase.yaml +6 -6
  40. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/tasks/install.yaml +11 -4
  41. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/tasks/main.yaml +17 -0
  42. restic_profile_cli-0.4.0/roles/restic_profile/tasks/persist_registry.yaml +21 -0
  43. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/tasks/preflight.yaml +89 -4
  44. restic_profile_cli-0.4.0/roles/restic_profile/tasks/remove.yaml +31 -0
  45. restic_profile_cli-0.4.0/roles/restic_profile/tasks/service.yaml +7 -0
  46. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/templates/etc/restic-profile/restic-profile.env.j2 +4 -4
  47. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/templates/etc/restic-profile/restic-profile.toml.j2 +6 -4
  48. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/templates/etc/systemd/system/restic-profile.service.j2 +6 -6
  49. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/templates/etc/systemd/system/restic-profile.timer.j2 +7 -7
  50. restic_profile_cli-0.4.0/roles/restic_profile/vars/archlinux.yml +2 -0
  51. restic_profile_cli-0.4.0/roles/restic_profile/vars/debian.yml +2 -0
  52. restic_profile_cli-0.4.0/roles/restic_profile/vars/default.yml +2 -0
  53. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/vars/main.yaml +10 -1
  54. restic_profile_cli-0.4.0/roles/restic_profile/vars/redhat.yml +2 -0
  55. restic_profile_cli-0.4.0/roles/restic_profile/vars/suse.yml +2 -0
  56. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_rest_server/defaults/main.yaml +13 -17
  57. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_rest_server/files/users.htpasswd +1 -1
  58. restic_profile_cli-0.4.0/roles/restic_rest_server/meta/main.yaml +22 -0
  59. restic_profile_cli-0.4.0/roles/restic_rest_server/tasks/install.yaml +67 -0
  60. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_rest_server/tasks/main.yaml +11 -1
  61. restic_profile_cli-0.2.1/roles/restic_rest_server/tasks/validation.yaml → restic_profile_cli-0.4.0/roles/restic_rest_server/tasks/preflight.yaml +31 -6
  62. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_rest_server/tasks/service.yaml +9 -21
  63. restic_profile_cli-0.2.1/roles/restic_rest_server/templates/restic-rest-server.default.j2 → restic_profile_cli-0.4.0/roles/restic_rest_server/templates/restic-rest-server.env.j2 +2 -2
  64. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_rest_server/templates/restic-rest-server.service.j2 +1 -1
  65. restic_profile_cli-0.4.0/roles/restic_rest_server/vars/archlinux.yml +6 -0
  66. restic_profile_cli-0.4.0/roles/restic_rest_server/vars/debian.yml +7 -0
  67. restic_profile_cli-0.4.0/roles/restic_rest_server/vars/default.yml +4 -0
  68. restic_profile_cli-0.4.0/roles/restic_rest_server/vars/redhat.yml +6 -0
  69. restic_profile_cli-0.4.0/roles/restic_rest_server/vars/suse.yml +6 -0
  70. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/cli.py +28 -2
  71. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/notify.py +3 -3
  72. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/runner.py +2 -2
  73. restic_profile_cli-0.4.0/src/restic_profile/templates/notify_failure.md.j2 +6 -0
  74. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/templates/notify_success.md.j2 +8 -7
  75. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/tests/restic_profile/test_cli.py +9 -9
  76. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/tests/restic_profile/test_config.py +10 -10
  77. restic_profile_cli-0.4.0/tests/restic_profile/test_filters.py +532 -0
  78. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/tests/restic_profile/test_notify.py +8 -8
  79. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/tests/restic_profile/test_runner.py +21 -21
  80. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/uv.lock +171 -83
  81. restic_profile_cli-0.2.1/AGENTS.md +0 -76
  82. restic_profile_cli-0.2.1/PKG-INFO +0 -90
  83. restic_profile_cli-0.2.1/README.md +0 -66
  84. restic_profile_cli-0.2.1/docs/index.md +0 -68
  85. restic_profile_cli-0.2.1/roles/restic_profile/tasks/config.yaml +0 -189
  86. restic_profile_cli-0.2.1/roles/restic_profile/tasks/remove.yaml +0 -91
  87. restic_profile_cli-0.2.1/roles/restic_profile/tasks/service.yaml +0 -141
  88. restic_profile_cli-0.2.1/roles/restic_rest_server/meta/main.yaml +0 -14
  89. restic_profile_cli-0.2.1/roles/restic_rest_server/tasks/install.yaml +0 -73
  90. restic_profile_cli-0.2.1/src/restic_profile/templates/notify_failure.md.j2 +0 -6
  91. restic_profile_cli-0.2.1/zensical.toml +0 -42
  92. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.devcontainer/devcontainer.json +0 -0
  93. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.dockerignore +0 -0
  94. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.editorconfig +0 -0
  95. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.github/workflows/publish-to-pypi.yaml +0 -0
  96. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.github/workflows/publish-to-test-pypi.yaml +0 -0
  97. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.gitignore +0 -0
  98. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.pre-commit-config.yaml +0 -0
  99. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.prettierignore +0 -0
  100. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/.yamlfmt.yaml +0 -0
  101. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/Dockerfile +0 -0
  102. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/LICENSE +0 -0
  103. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/meta/runtime.yml +0 -0
  104. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/playbooks/go_build/restic-rest-server.yaml +0 -0
  105. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/playbooks/go_build/restic.yaml +0 -0
  106. restic_profile_cli-0.2.1/requirements.yml → restic_profile_cli-0.4.0/requirements.yaml +1 -1
  107. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/handlers/main.yaml +0 -0
  108. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/molecule/default/molecule.yaml +0 -0
  109. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/molecule/default/verify.yaml +0 -0
  110. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/tasks/hooks.yaml +0 -0
  111. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_profile/templates/usr/local/bin/restic-profile-scope.j2 +0 -0
  112. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/roles/restic_rest_server/handlers/main.yaml +0 -0
  113. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/ruff.toml +0 -0
  114. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/__init__.py +0 -0
  115. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/__main__.py +0 -0
  116. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/src/restic_profile/config.py +0 -0
  117. {restic_profile_cli-0.2.1 → restic_profile_cli-0.4.0}/tests/restic_profile/conftest.py +0 -0
@@ -5,7 +5,7 @@
5
5
  # Run with: ansible-lint
6
6
  # ansible-lint
7
7
 
8
- # Use the 'basic' profile — enforces the most important rules without
8
+ # Use the 'basic' profile - enforces the most important rules without
9
9
  # being overly strict for a project that is still evolving.
10
10
  # Profiles in ascending order of strictness:
11
11
  # min → basic → moderate → safety → shared → production
@@ -18,6 +18,10 @@ exclude_paths:
18
18
  - site/
19
19
  - dist/
20
20
  - molecule/
21
+ - examples/
22
+ - playbooks/host_vars/
23
+ - playbooks/group_vars/
24
+ - mkdocs.yaml
21
25
 
22
26
  # Rules to warn about instead of failing on.
23
27
  # These are either stylistic preferences or rules that generate too many
@@ -1,6 +1,7 @@
1
+ ---
1
2
  # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
2
3
  _commit: c7cc65d
3
- _src_path: .
4
+ _src_path: git+https://github.com/ak1ra-lab/copier-pyproject.git
4
5
  author_email: git@ak1ra.xyz
5
6
  author_name: ak1ra
6
7
  copyright_date: '2026'
@@ -9,7 +9,7 @@ on:
9
9
  paths:
10
10
  - "docs/**"
11
11
  - "README.md"
12
- - "zensical.toml"
12
+ - "mkdocs.yml"
13
13
  - ".github/workflows/docs.yaml"
14
14
 
15
15
  permissions:
@@ -18,7 +18,6 @@ permissions:
18
18
  pages: write
19
19
  id-token: write
20
20
 
21
-
22
21
  concurrency:
23
22
  group: docs
24
23
  cancel-in-progress: false
@@ -39,7 +38,7 @@ jobs:
39
38
  run: uv sync --locked --group docs
40
39
 
41
40
  - name: Build documentation
42
- run: uv run zensical build
41
+ run: NO_MKDOCS_2_WARNING=1 uv run mkdocs build
43
42
 
44
43
  - name: Upload artifact
45
44
  uses: actions/upload-pages-artifact@v4
@@ -0,0 +1,51 @@
1
+ # AGENTS.md
2
+
3
+ `restic-profile` = a Python CLI (`src/restic_profile/`, tests mirror it under
4
+ `tests/`) plus Ansible roles (`roles/restic_profile`, `roles/restic_rest_server`).
5
+ See `README.md` for the deployment workflow.
6
+
7
+ ## Tooling - use these, not the defaults
8
+
9
+ `just <recipe>` is a convenience wrapper for humans; each recipe is a thin
10
+ `uv run ...` (see `justfile`). Agents can call `uv run ...` directly when that is
11
+ more flexible - the two are equivalent, not mutually exclusive.
12
+
13
+ - Env/deps: **uv** (`just sync` = `uv sync --group dev`). Never `pip`/`poetry`/`pipenv`.
14
+ - Lint+format: **ruff** (`just lint` = `uv run ruff check --fix` then
15
+ `uv run ruff format`, over `src/ tests/ plugins/`). Never `black`/`isort`/`flake8`.
16
+ - Typecheck: **ty** (astral-sh/ty), `src/ plugins/` only
17
+ (`just typecheck` = `uv run ty check src/ plugins/`). Never `mypy`.
18
+ - Tests: **pytest**. `just test *ARGS` = `uv run pytest -v {{ARGS}} tests/` - ARGS
19
+ go *before* `tests/`, so `just test -k <pattern>`. Or run
20
+ `uv run pytest -v tests/test_file.py` directly.
21
+ - Docs: `just docs-build` = `NO_MKDOCS_2_WARNING=1 uv run mkdocs build`.
22
+ - Build: `just build` = `uv build`.
23
+
24
+ Python changes MUST pass lint, typecheck, and test before commit.
25
+
26
+ ## Ansible (self-contained layout)
27
+
28
+ `ansible.cfg` pins `roles_path=./roles` and `collections_path=./.ansible/collections`
29
+ and never reaches user-level/parent paths. Playbooks reference roles by FQCN
30
+ (`ak1ra_lab.restic_profile.*`). Before running `ansible-lint` or any playbook,
31
+ install the dependencies into the project-local tree:
32
+
33
+ ```shell
34
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
35
+ ```
36
+
37
+ - `requirements.yaml` deps: `ansible.posix`, `community.general` (usually resolve
38
+ from user-level ansible) and `ak1ra_lab.general` (not on Galaxy, pulled from git).
39
+ - `ansible-lint` (non-`offline` mode, run from repo root) auto-installs
40
+ `requirements.yaml` into its own cache dir `./.ansible/collections` - computed
41
+ by ansible-compat from the project dir, ignoring `ansible.cfg`'s `collections_path`.
42
+ - Molecule scenarios under `roles/*/molecule/` are dormant - don't rely on them.
43
+
44
+ Ansible changes MUST pass `ansible-lint` before commit.
45
+
46
+ ## Docs (bilingual)
47
+
48
+ `docs/` is served by mkdocs with the i18n plugin (`docs_structure: suffix`):
49
+ every page has an English `*.md` and a Simplified-Chinese `*.zh.md` sibling
50
+ (e.g. `cli.md` + `cli.zh.md`). When adding or changing user-facing behavior,
51
+ update BOTH language files.
@@ -5,6 +5,44 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.0] - 2026-08-11
9
+
10
+ ### Added
11
+
12
+ - Multi-Linux-distro support in Ansible roles (`restic_profile`,
13
+ `restic_rest_server`): Arch, Debian, RedHat, and SUSE, with per-distro
14
+ package-name mappings in `vars/*.yml` and an `os_family` preflight
15
+ check; replace `ansible.builtin.apt` with `ansible.builtin.package`
16
+
17
+ ### Changed
18
+
19
+ - Rename `install_source` value `apt` to `package` in both roles
20
+ (breaking for existing inventory/group_vars)
21
+ - Move the `restic-rest-server` env file to `/etc/restic-rest-server/env`
22
+ - Pin `ansible.cfg` `roles_path` and `collections_path` to project-local
23
+ paths (`./roles`, `./.ansible/collections`); rename `requirements.yml`
24
+ to `requirements.yaml`
25
+ - Add `restic_profile_file_prefix` vars for customizing managed file
26
+ paths
27
+
28
+ ### Fixed
29
+
30
+ - Only run `apt update_cache` on Debian-family hosts when
31
+ `install_source == 'package'`
32
+ - Correct `loop_control.label` typo in role tasks
33
+
34
+ ## [0.3.0] - 2026-07-13
35
+
36
+ ### Added
37
+
38
+ - Per-profile systemd user-scope support via `systemd_scope: user` and
39
+ `systemd_user` fields - deploys config to `~/.config/restic-profile/`
40
+ and systemd units to `~/.config/systemd/user/` with automatic
41
+ `loginctl enable-linger` and `XDG_RUNTIME_DIR` handling
42
+ - CLI config resolution via XDG search path - when `--config` is omitted,
43
+ searches `~/.config/restic-profile/restic-profile.toml` then falls back
44
+ to `/etc/restic-profile/restic-profile.toml`
45
+
8
46
  ## [0.2.1] - 2026-07-07
9
47
 
10
48
  ### Fixed
@@ -22,7 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
60
  `RESTIC_COMPRESSION`, `RESTIC_PACK_SIZE`, and `HTTP_PROXY`
23
61
  - Runtime environment variable injection at profile level
24
62
  (`[profiles.<name>.env]`) for hook credentials such as `PGPASSWORD`,
25
- `MYSQL_PWD` — applied after repository env so profile env takes precedence
63
+ `MYSQL_PWD` - applied after repository env so profile env takes precedence
26
64
  - Runtime environment variable injection at notify channel level
27
65
  (`[notify.<name>.env]`) for proxy settings that only affect notification
28
66
  HTTP calls
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.5
2
+ Name: restic-profile-cli
3
+ Version: 0.4.0
4
+ Summary: Profile-based restic wrapper with Ansible deployment support
5
+ Project-URL: Homepage, https://github.com/ak1ra-lab/restic-profile
6
+ Project-URL: Repository, https://github.com/ak1ra-lab/restic-profile
7
+ Project-URL: Documentation, https://ak1ra-lab.github.io/restic-profile/
8
+ Author-email: ak1ra <git@ak1ra.xyz>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ansible,backup,restic
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: argcomplete>=3.7.0
20
+ Requires-Dist: chaos-utils>=0.5.0
21
+ Requires-Dist: jinja2>=3.1.2
22
+ Requires-Dist: pydantic>=2.13.3
23
+ Description-Content-Type: text/markdown
24
+
25
+ # restic-profile
26
+
27
+ **English** | [简体中文](README.zh-CN.md)
28
+
29
+ [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ak1ra-lab/restic-profile/.github%2Fworkflows%2Fpublish-to-pypi.yaml)](https://github.com/ak1ra-lab/restic-profile/actions/workflows/publish-to-pypi.yaml)
30
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli)](https://pypi.org/project/restic-profile-cli/)
31
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli?label=test-pypi&pypiBaseUrl=https%3A%2F%2Ftest.pypi.org)](https://test.pypi.org/project/restic-profile-cli/)
32
+ [![Docs](https://img.shields.io/badge/docs-online-0a7ea4)](https://ak1ra-lab.github.io/restic-profile/)
33
+
34
+ Profile-based restic wrapper, deployed with Ansible.
35
+
36
+ This repository is an Ansible collection (`ak1ra_lab.restic_profile`) that
37
+ installs and configures the `restic-profile` CLI on local or remote hosts:
38
+
39
+ - **restic-profile** CLI - reads a TOML config and runs `restic backup` /
40
+ `forget` / `prune` with hooks and IM notifications.
41
+ - **restic_profile** role - deploys the CLI, renders the TOML config, and
42
+ manages one systemd timer per profile (including user-level `systemd_scope: user`).
43
+ - **restic_rest_server** role - deploys a [rest-server][rs] instance for remote
44
+ backup storage.
45
+
46
+ ## Deploy with Ansible
47
+
48
+ You need Ansible on the control node - see [Ansible toolchain](docs/ansible-toolchain.md)
49
+ for a uv-based setup. Clone the repo and install this collection with its
50
+ dependencies into the project-local tree:
51
+
52
+ ```shell
53
+ git clone https://github.com/ak1ra-lab/restic-profile.git
54
+ cd restic-profile
55
+ ansible-galaxy collection install --collections-path .ansible/collections -r requirements.yaml
56
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
57
+ ```
58
+
59
+ Then pick an example from [Ansible examples](docs/restic-profile/examples.md),
60
+ fill in your host_vars, and run the playbook. Building restic from source
61
+ (`restic_profile_restic_install_source: go_build`) also needs a `go` toolchain on
62
+ the control node.
63
+
64
+ ## Development
65
+
66
+ Only needed to work on `src/restic_profile` or the roles and plugins:
67
+
68
+ ```shell
69
+ uv sync --group dev
70
+ just lint
71
+ just typecheck
72
+ just test
73
+ ansible-lint
74
+ ```
75
+
76
+ To develop `ak1ra_lab.general` alongside this repo, clone
77
+ [ansible-collection-general][acg] next to this checkout and run
78
+ `just ansible-collection-install` - it installs this collection plus your local
79
+ `../ansible-collection-general` (skipping `ansible.posix`/`community.general`,
80
+ which come from your user-level Ansible).
81
+
82
+ ## Documentation
83
+
84
+ <https://ak1ra-lab.github.io/restic-profile/> - configuration lives in `mkdocs.yml`.
85
+
86
+ [rs]: https://github.com/restic/rest-server
87
+ [acg]: https://github.com/ak1ra-lab/ansible-collection-general
@@ -0,0 +1,63 @@
1
+ # restic-profile
2
+
3
+ **English** | [简体中文](README.zh-CN.md)
4
+
5
+ [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ak1ra-lab/restic-profile/.github%2Fworkflows%2Fpublish-to-pypi.yaml)](https://github.com/ak1ra-lab/restic-profile/actions/workflows/publish-to-pypi.yaml)
6
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli)](https://pypi.org/project/restic-profile-cli/)
7
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli?label=test-pypi&pypiBaseUrl=https%3A%2F%2Ftest.pypi.org)](https://test.pypi.org/project/restic-profile-cli/)
8
+ [![Docs](https://img.shields.io/badge/docs-online-0a7ea4)](https://ak1ra-lab.github.io/restic-profile/)
9
+
10
+ Profile-based restic wrapper, deployed with Ansible.
11
+
12
+ This repository is an Ansible collection (`ak1ra_lab.restic_profile`) that
13
+ installs and configures the `restic-profile` CLI on local or remote hosts:
14
+
15
+ - **restic-profile** CLI - reads a TOML config and runs `restic backup` /
16
+ `forget` / `prune` with hooks and IM notifications.
17
+ - **restic_profile** role - deploys the CLI, renders the TOML config, and
18
+ manages one systemd timer per profile (including user-level `systemd_scope: user`).
19
+ - **restic_rest_server** role - deploys a [rest-server][rs] instance for remote
20
+ backup storage.
21
+
22
+ ## Deploy with Ansible
23
+
24
+ You need Ansible on the control node - see [Ansible toolchain](docs/ansible-toolchain.md)
25
+ for a uv-based setup. Clone the repo and install this collection with its
26
+ dependencies into the project-local tree:
27
+
28
+ ```shell
29
+ git clone https://github.com/ak1ra-lab/restic-profile.git
30
+ cd restic-profile
31
+ ansible-galaxy collection install --collections-path .ansible/collections -r requirements.yaml
32
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
33
+ ```
34
+
35
+ Then pick an example from [Ansible examples](docs/restic-profile/examples.md),
36
+ fill in your host_vars, and run the playbook. Building restic from source
37
+ (`restic_profile_restic_install_source: go_build`) also needs a `go` toolchain on
38
+ the control node.
39
+
40
+ ## Development
41
+
42
+ Only needed to work on `src/restic_profile` or the roles and plugins:
43
+
44
+ ```shell
45
+ uv sync --group dev
46
+ just lint
47
+ just typecheck
48
+ just test
49
+ ansible-lint
50
+ ```
51
+
52
+ To develop `ak1ra_lab.general` alongside this repo, clone
53
+ [ansible-collection-general][acg] next to this checkout and run
54
+ `just ansible-collection-install` - it installs this collection plus your local
55
+ `../ansible-collection-general` (skipping `ansible.posix`/`community.general`,
56
+ which come from your user-level Ansible).
57
+
58
+ ## Documentation
59
+
60
+ <https://ak1ra-lab.github.io/restic-profile/> - configuration lives in `mkdocs.yml`.
61
+
62
+ [rs]: https://github.com/restic/rest-server
63
+ [acg]: https://github.com/ak1ra-lab/ansible-collection-general
@@ -0,0 +1,59 @@
1
+ # restic-profile
2
+
3
+ [English](README.md) | **简体中文**
4
+
5
+ [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ak1ra-lab/restic-profile/.github%2Fworkflows%2Fpublish-to-pypi.yaml)](https://github.com/ak1ra-lab/restic-profile/actions/workflows/publish-to-pypi.yaml)
6
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli)](https://pypi.org/project/restic-profile-cli/)
7
+ [![PyPI - Version](https://img.shields.io/pypi/v/restic-profile-cli?label=test-pypi&pypiBaseUrl=https%3A%2F%2Ftest.pypi.org)](https://test.pypi.org/project/restic-profile-cli/)
8
+ [![Docs](https://img.shields.io/badge/docs-online-0a7ea4)](https://ak1ra-lab.github.io/restic-profile/)
9
+
10
+ 基于配置文件的 restic 自动化工具,通过 Ansible 部署。
11
+
12
+ 本仓库是一个 Ansible 集合(`ak1ra_lab.restic_profile`),用于在本地或远程主机上
13
+ 安装并配置 `restic-profile` CLI:
14
+
15
+ - **restic-profile** CLI - 读取 TOML 配置文件,运行 `restic backup` / `forget` /
16
+ `prune`,支持钩子与即时通讯通知。
17
+ - **restic_profile** 角色 - 部署 CLI、渲染 TOML 配置,并为每个 profile 管理一个
18
+ systemd 定时器(含用户级 `systemd_scope: user`)。
19
+ - **restic_rest_server** 角色 - 部署 [rest-server][rs] 实例,提供远程备份存储。
20
+
21
+ ## 使用 Ansible 部署
22
+
23
+ 控制节点需要 Ansible - 参见 [Ansible 工具链](docs/ansible-toolchain.zh.md) 了解基于
24
+ uv 的搭建方式。克隆仓库并把本 collection 及其依赖安装到项目本地目录:
25
+
26
+ ```shell
27
+ git clone https://github.com/ak1ra-lab/restic-profile.git
28
+ cd restic-profile
29
+ ansible-galaxy collection install --collections-path .ansible/collections -r requirements.yaml
30
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
31
+ ```
32
+
33
+ 然后从 [Ansible 示例](docs/restic-profile/examples.zh.md) 中选择一个示例,填写你的
34
+ host_vars,再运行 playbook。若从源码构建 restic
35
+ (`restic_profile_restic_install_source: go_build`),控制节点还需要 `go` 工具链。
36
+
37
+ ## 开发
38
+
39
+ 仅在需要修改 `src/restic_profile` 或角色、插件时才需要:
40
+
41
+ ```shell
42
+ uv sync --group dev
43
+ just lint
44
+ just typecheck
45
+ just test
46
+ ansible-lint
47
+ ```
48
+
49
+ 如需与本仓库一起开发 `ak1ra_lab.general`,把 [ansible-collection-general][acg]
50
+ 克隆到本仓库同级目录,再运行 `just ansible-collection-install` - 它会安装本
51
+ collection 以及你本地的 `../ansible-collection-general`(`ansible.posix`、
52
+ `community.general` 则来自用户级别的 Ansible)。
53
+
54
+ ## 文档
55
+
56
+ <https://ak1ra-lab.github.io/restic-profile/> - 文档配置存储在 `mkdocs.yml` 中。
57
+
58
+ [rs]: https://github.com/restic/rest-server
59
+ [acg]: https://github.com/ak1ra-lab/ansible-collection-general
@@ -16,8 +16,8 @@ inventory_ignore_extensions=~, .orig, .bak, .retry, .pyc, .pyo, .creds, .gpg
16
16
  force_valid_group_names=ignore
17
17
 
18
18
  # paths
19
- roles_path=./roles:~/.ansible/roles
20
- collections_path=../../../../collections:~/.ansible/collections
19
+ roles_path=./roles
20
+ collections_path=./.ansible/collections
21
21
 
22
22
  # output
23
23
  callbacks_enabled=ansible.posix.profile_tasks, ansible.posix.timer
@@ -0,0 +1,78 @@
1
+ # Ansible toolchain
2
+
3
+ Project-neutral notes for setting up an Ansible authoring toolchain with `uv`,
4
+ and for understanding how `ansible-lint` resolves collection paths. Copy this
5
+ page into any repository that ships an Ansible collection.
6
+
7
+ ## Install the toolchain with uv
8
+
9
+ [ansible-dev-tools][adt] bundles `ansible-lint`, `ansible-navigator`, `molecule`,
10
+ `ansible-creator`, and friends behind a single `adt` entry point. The upstream
11
+ docs install it with `pip`/`pipx`; the `uv` recipe below is an equivalent that
12
+ keeps everything in one uv-managed tool environment:
13
+
14
+ ```shell
15
+ uv tool install ansible-dev-tools \
16
+ --with-executables-from ansible-builder \
17
+ --with-executables-from ansible-core \
18
+ --with-executables-from ansible-creator \
19
+ --with-executables-from ansible-dev-environment \
20
+ --with-executables-from ansible-lint \
21
+ --with-executables-from ansible-navigator \
22
+ --with-executables-from ansible-sign \
23
+ --with-executables-from molecule \
24
+ --with molecule-plugins[podman] \
25
+ --with ansible
26
+ ```
27
+
28
+ - `--with-executables-from` exposes each bundled tool's own entry point on
29
+ `PATH` (otherwise only `adt` is linked).
30
+ - `--with ansible` adds the full `ansible` PyPI package (the batteries-included
31
+ collection bundle) alongside `ansible-core`, so common Galaxy collections such
32
+ as `ansible.posix` and `community.general` resolve at user level without a
33
+ per-project copy.
34
+ - Add more runtime dependencies as needed, e.g.
35
+ `--with boto3 --with google-auth --with proxmoxer`.
36
+
37
+ Verify with `adt --version`.
38
+
39
+ !!! note
40
+ The `uv tool install` invocation above is **not** documented upstream - it is
41
+ a community recipe. See [the official installation docs][adt] for the supported installers.
42
+
43
+ ## Self-contained collection paths
44
+
45
+ To keep a repository's Ansible setup hermetic - never reaching into user-level or
46
+ parent directories - pin the paths in a project-local `ansible.cfg`:
47
+
48
+ ```ini
49
+ [defaults]
50
+ roles_path=./roles
51
+ collections_path=./.ansible/collections
52
+ ```
53
+
54
+ Install the collection's dependencies into that tree. If the playbooks reference
55
+ the collection's own roles by FQCN (`namespace.collection.*`), install the
56
+ collection itself there too:
57
+
58
+ ```shell
59
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
60
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
61
+ ```
62
+
63
+ ## Where ansible-lint installs collections
64
+
65
+ `ansible-lint` does **not** honor `collections_path` from `ansible.cfg` when it
66
+ auto-installs `requirements.yml` / `requirements.yaml`. Internally it uses
67
+ `ansible-compat`, which derives a cache directory from the **project directory**:
68
+
69
+ - Run from the project root (non-`offline` mode), it installs into
70
+ `./.ansible/collections` - regardless of what `collections_path` says.
71
+ - `offline: true` in the ansible-lint config disables the auto-install entirely.
72
+ - If the project root is not writable, it falls back to a temporary directory.
73
+
74
+ Pinning `collections_path` to `./.ansible/collections` therefore matches
75
+ `ansible-lint`'s own behavior: linting and playbook runs share one collection
76
+ tree, and nothing leaks to the user-level `~/.ansible`.
77
+
78
+ [adt]: https://ansible.readthedocs.io/projects/dev-tools/
@@ -0,0 +1,75 @@
1
+ # Ansible 工具链
2
+
3
+ 与具体项目无关的说明:如何用 `uv` 搭建 Ansible 开发工具链,以及 `ansible-lint`
4
+ 如何解析 collection 路径。可以把本页直接复制到任何附带 Ansible 集合的仓库中。
5
+
6
+ ## 用 uv 安装工具链
7
+
8
+ [ansible-dev-tools][adt] 将 `ansible-lint`、`ansible-navigator`、`molecule`、
9
+ `ansible-creator` 等工具捆绑在单一的 `adt` 入口点之后。上游文档使用 `pip`/`pipx`
10
+ 安装;下面的 `uv` 方式与之等价,并把一切放进单一的 uv 管理工具环境中:
11
+
12
+ ```shell
13
+ uv tool install ansible-dev-tools \
14
+ --with-executables-from ansible-builder \
15
+ --with-executables-from ansible-core \
16
+ --with-executables-from ansible-creator \
17
+ --with-executables-from ansible-dev-environment \
18
+ --with-executables-from ansible-lint \
19
+ --with-executables-from ansible-navigator \
20
+ --with-executables-from ansible-sign \
21
+ --with-executables-from molecule \
22
+ --with molecule-plugins[podman] \
23
+ --with ansible
24
+ ```
25
+
26
+ - `--with-executables-from` 将每个捆绑工具自身的入口点暴露到 `PATH`
27
+ (否则只会链接 `adt`)。
28
+ - `--with ansible` 会在 `ansible-core` 之外额外安装完整的 `ansible` PyPI 包
29
+ (batteries-included 的 collection 集合),因此 `ansible.posix`、
30
+ `community.general` 等常见 Galaxy collection 可在用户级别解析,无需每个项目各存一份。
31
+ - 按需追加更多运行时依赖,例如
32
+ `--with boto3 --with google-auth --with proxmoxer`。
33
+
34
+ 用 `adt --version` 查看版本。
35
+
36
+ !!! note
37
+ 上面的 `uv tool install` 命令**并未**记录在上游文档中 - 这是社区总结的用法。
38
+ 受支持的安装方式请参见[官方安装文档][adt]。
39
+
40
+ ## 自包含的 collection 路径
41
+
42
+ 要让仓库的 Ansible 配置保持隔离 - 绝不触及用户级别或上级目录 - 在项目本地的
43
+ `ansible.cfg` 中固定这些路径:
44
+
45
+ ```ini
46
+ [defaults]
47
+ roles_path=./roles
48
+ collections_path=./.ansible/collections
49
+ ```
50
+
51
+ 把 collection 的依赖安装到该目录树。如果 playbook 通过 FQCN
52
+ (`namespace.collection.*`)引用 collection 自身的角色,也把该 collection 本身
53
+ 安装进去:
54
+
55
+ ```shell
56
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
57
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
58
+ ```
59
+
60
+ ## ansible-lint 把 collection 安装到哪里
61
+
62
+ 在自动安装 `requirements.yml` / `requirements.yaml` 时,`ansible-lint`
63
+ **不会**遵循 `ansible.cfg` 中的 `collections_path`。它内部使用 `ansible-compat`,
64
+ 后者根据**项目目录**推导出一个缓存目录:
65
+
66
+ - 从项目根目录运行(非 `offline` 模式)时,它会安装到 `./.ansible/collections`
67
+ - 无论 `collections_path` 设为什么。
68
+ - ansible-lint 配置中的 `offline: true` 会完全禁用该自动安装。
69
+ - 如果项目根目录不可写,则回退到临时目录。
70
+
71
+ 因此把 `collections_path` 固定为 `./.ansible/collections` 恰好与 `ansible-lint`
72
+ 自身的行为一致:lint 与 playbook 运行共享同一份 collection 目录树,且不会泄漏到
73
+ 用户级别的 `~/.ansible`。
74
+
75
+ [adt]: https://ansible.readthedocs.io/projects/dev-tools/
@@ -0,0 +1,56 @@
1
+ # restic-profile
2
+
3
+ Profile-based [restic](https://restic.net/) wrapper, deployed with Ansible.
4
+
5
+ This project is an Ansible collection (`ak1ra_lab.restic_profile`) that installs
6
+ and configures the `restic-profile` CLI on local or remote hosts:
7
+
8
+ - **restic-profile** CLI - reads a TOML config and runs `restic backup` /
9
+ `forget` / `prune` with hooks and IM notifications.
10
+ - **restic_profile** role - deploys the CLI, renders the TOML config, and manages
11
+ one systemd timer per profile (including user-level `systemd_scope: user`).
12
+ - **restic_rest_server** role - deploys a [rest-server](https://github.com/restic/rest-server)
13
+ instance for remote backup storage.
14
+
15
+ ## Deploy with Ansible
16
+
17
+ You need Ansible on the control node - see [Ansible toolchain](ansible-toolchain.md)
18
+ for a uv-based setup. Clone the repo and install this collection with its
19
+ dependencies into the project-local tree:
20
+
21
+ ```shell
22
+ git clone https://github.com/ak1ra-lab/restic-profile.git
23
+ cd restic-profile
24
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
25
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
26
+ ```
27
+
28
+ Then pick an example from [restic-profile examples](restic-profile/examples.md)
29
+ and fill in your host_vars. Building restic from source
30
+ (`restic_profile_restic_install_source: go_build`) also needs a `go` toolchain on
31
+ the control node.
32
+
33
+ ## Standalone CLI (without Ansible)
34
+
35
+ The CLI is also published on PyPI for manual or cron-driven use - no Ansible,
36
+ root, or systemd required:
37
+
38
+ ```shell
39
+ uv tool install restic-profile-cli
40
+ restic-profile -c /path/to/my.toml --check
41
+ restic-profile -c /path/to/my.toml myprofile
42
+ ```
43
+
44
+ Start from the [TOML config template](restic-profile/toml-config.md).
45
+
46
+ ## Pages
47
+
48
+ | You want to... | Start here |
49
+ | ------------------------------------------- | ----------------------------------------------------- |
50
+ | Deploy backup profiles with Ansible | [Ansible examples](restic-profile/examples.md) |
51
+ | Set up the Ansible toolchain | [Ansible toolchain](ansible-toolchain.md) |
52
+ | Write a TOML config for use without Ansible | [TOML config template](restic-profile/toml-config.md) |
53
+ | Understand CLI flags | [CLI reference](restic-profile/cli.md) |
54
+ | Deploy a backup server (rest-server) | [restic-rest-server](restic-rest-server.md) |
55
+
56
+ See `roles/restic_profile/defaults/main.yaml` for all role variables and their defaults.
@@ -0,0 +1,53 @@
1
+ # restic-profile
2
+
3
+ 基于配置文件的 [restic](https://restic.net/) 自动化工具,通过 Ansible 部署。
4
+
5
+ 本项目是一个 Ansible 集合(`ak1ra_lab.restic_profile`),用于在本地或远程主机上
6
+ 安装并配置 `restic-profile` CLI:
7
+
8
+ - **restic-profile** CLI - 读取 TOML 配置文件,运行 `restic backup` / `forget` /
9
+ `prune`,支持钩子与即时通讯通知。
10
+ - **restic_profile** 角色 - 部署 CLI、渲染 TOML 配置,并为每个 profile 管理一个
11
+ systemd 定时器(含用户级 `systemd_scope: user`)。
12
+ - **restic_rest_server** 角色 - 部署 [rest-server](https://github.com/restic/rest-server)
13
+ 实例,提供远程备份存储。
14
+
15
+ ## 使用 Ansible 部署
16
+
17
+ 控制节点需要 Ansible - 参见 [Ansible 工具链](ansible-toolchain.md) 了解基于 uv 的
18
+ 搭建方式。克隆仓库并把本 collection 及其依赖安装到项目本地目录:
19
+
20
+ ```shell
21
+ git clone https://github.com/ak1ra-lab/restic-profile.git
22
+ cd restic-profile
23
+ ansible-galaxy collection install -r requirements.yaml -p ./.ansible/collections
24
+ ansible-galaxy collection install --force --collections-path .ansible/collections .
25
+ ```
26
+
27
+ 然后从 [restic-profile 示例](restic-profile/examples.md) 中选择一个示例并填写你的
28
+ host_vars。若从源码构建 restic(`restic_profile_restic_install_source: go_build`),
29
+ 控制节点还需要 `go` 工具链。
30
+
31
+ ## 独立 CLI(无需 Ansible)
32
+
33
+ 该 CLI 也发布到 PyPI,可用于手动或 cron 驱动的场景 - 无需 Ansible、root 或 systemd:
34
+
35
+ ```shell
36
+ uv tool install restic-profile-cli
37
+ restic-profile -c /path/to/my.toml --check
38
+ restic-profile -c /path/to/my.toml myprofile
39
+ ```
40
+
41
+ 可以从 [TOML 配置模板](restic-profile/toml-config.md) 开始。
42
+
43
+ ## 页面
44
+
45
+ | 你想... | 从这里开始 |
46
+ | ----------------------------------- | ---------------------------------------------- |
47
+ | 使用 Ansible 部署备份配置文件 | [Ansible 示例](restic-profile/examples.md) |
48
+ | 搭建 Ansible 工具链 | [Ansible 工具链](ansible-toolchain.md) |
49
+ | 编写用于非 Ansible 场景的 TOML 配置 | [TOML 配置模板](restic-profile/toml-config.md) |
50
+ | 了解 CLI 参数 | [CLI 参考](restic-profile/cli.md) |
51
+ | 部署备份服务器 (rest-server) | [restic-rest-server](restic-rest-server.md) |
52
+
53
+ 参见 `roles/restic_profile/defaults/main.yaml` 了解所有角色变量及其默认值。