commit 2eceb3e2694136e5b3f99b7330f91fac15c1e45a Author: Nis Wechselberg Date: Wed Jul 26 20:58:07 2023 +0200 nitial version of proxmox backup collection Signed-off-by: Nis Wechselberg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c01f181 --- /dev/null +++ b/.gitignore @@ -0,0 +1,179 @@ +# Created by https://www.toptal.com/developers/gitignore/api/python,ansible +# Edit at https://www.toptal.com/developers/gitignore?templates=python,ansible + +### Ansible ### +*.retry + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +# End of https://www.toptal.com/developers/gitignore/api/python,ansible diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..90928d3 --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,10 @@ +--- +steps: + - name: 'Check the repository with ansible-lint' + image: 'python:bookworm' + when: + - event: 'manual' + - event: 'push' + commands: + - 'pip -q install ansible-lint' + - 'ansible-lint' diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000..bfe72e7 --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,26 @@ +--- +extends: 'default' + +ignore: + - '.ansible/' + +rules: + braces: + max-spaces-inside: 1 + comments: + min-spaces-from-content: 1 + comments-indentation: false + document-start: + present: true + line-length: + max: 120 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true + quoted-strings: + required: true + quote-type: 'single' + truthy: + allowed-values: + - 'true' + - 'false' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fac1c60 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 1.0.0 + +* Initial Release \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..034d05e --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Ansible Collection - de_enbewe.proxmox_backup + +Collection containing rules to backup data to some proxmox backup server. + +## Role - backup + +This role configures the host to be backed up through proxmox. diff --git a/galaxy.yml b/galaxy.yml new file mode 100644 index 0000000..6568b74 --- /dev/null +++ b/galaxy.yml @@ -0,0 +1,66 @@ +--- +### REQUIRED +# The namespace of the collection. This can be a company/brand/organization or product namespace under which all +# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with +# underscores or numbers and cannot contain consecutive underscores +namespace: 'enbewe' + +# The name of the collection. Has the same character restrictions as 'namespace' +name: 'proxmox_backup' + +# The version of the collection. Must be compatible with semantic versioning +version: '1.0.0' + +# The path to the Markdown (.md) readme file. This path is relative to the root of the collection +readme: 'README.md' + +# A list of the collection's content authors. Can be just the name or in the format 'Full Name (url) +# @nicks:irc/im.site#channel' +authors: + - 'eNBeWe ' + +### OPTIONAL but strongly recommended +# A short summary description of the collection +description: 'Roles to configure backups through proxmox' + +# Either a single license or a list of licenses for content inside of a collection. Ansible Galaxy currently only +# accepts L(SPDX,https://spdx.org/licenses/) licenses. This key is mutually exclusive with 'license_file' +license: + - 'MIT' + +# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character +# requirements as 'namespace' and 'name' +tags: + - 'linux' + - 'proxmox' + +# Collections that this collection requires to be installed for it to be usable. The key of the dict is the +# collection label 'namespace.name'. The value is a version range +# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version +# range specifiers can be set and are separated by ',' +dependencies: {} + +# The URL of the originating SCM repository +repository: 'https://git.enbewe.de/Coding/ansible-collection-proxmox-backup.git' + +# The URL to any online docs +# documentation: https://git.enbewe.de/Coding/ansible-collection-proxmox-backup/wiki + +# The URL to the homepage of the collection/project +# homepage: https://git.enbewe.de/Coding/ansible-collection-proxmox-backup + +# The URL to the collection issue tracker +# issues: https://git.enbewe.de/Coding/ansible-collection-proxmox-backup/issues + +# A list of file glob-like patterns used to filter any files or directories that should not be included in the build +# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This +# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry', +# and '.git' are always filtered. Mutually exclusive with 'manifest' +# build_ignore: [] + +# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a +# list of MANIFEST.in style +# L(directives,https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands). The key +# 'omit_default_directives' is a boolean that controls whether the default directives are used. Mutually exclusive +# with 'build_ignore' +# manifest: null diff --git a/meta/runtime.yml b/meta/runtime.yml new file mode 100644 index 0000000..ddab9ac --- /dev/null +++ b/meta/runtime.yml @@ -0,0 +1,52 @@ +--- +# Collections must specify a minimum required ansible version to upload +# to galaxy +requires_ansible: '>=2.18.0' + +# Content that Ansible needs to load from another location or that has +# been deprecated/removed +# plugin_routing: +# action: +# redirected_plugin_name: +# redirect: ns.col.new_location +# deprecated_plugin_name: +# deprecation: +# removal_version: "4.0.0" +# warning_text: | +# See the porting guide on how to update your playbook to +# use ns.col.another_plugin instead. +# removed_plugin_name: +# tombstone: +# removal_version: "2.0.0" +# warning_text: | +# See the porting guide on how to update your playbook to +# use ns.col.another_plugin instead. +# become: +# cache: +# callback: +# cliconf: +# connection: +# doc_fragments: +# filter: +# httpapi: +# inventory: +# lookup: +# module_utils: +# modules: +# netconf: +# shell: +# strategy: +# terminal: +# test: +# vars: + +# Python import statements that Ansible needs to load from another location +# import_redirection: +# ansible_collections.ns.col.plugins.module_utils.old_location: +# redirect: ansible_collections.ns.col.plugins.module_utils.new_location + +# Groups of actions/modules that take a common set of options +# action_groups: +# group_name: +# - module1 +# - module2 diff --git a/playbooks/deploy.yml b/playbooks/deploy.yml new file mode 100644 index 0000000..5f025cd --- /dev/null +++ b/playbooks/deploy.yml @@ -0,0 +1,5 @@ +--- +- name: 'Deploy backup client to all configured hosts' + hosts: 'backup' + roles: + - 'enbewe.proxmox_backup.backup' diff --git a/roles/backup/defaults/main.yml b/roles/backup/defaults/main.yml new file mode 100644 index 0000000..47278e9 --- /dev/null +++ b/roles/backup/defaults/main.yml @@ -0,0 +1,7 @@ +--- +backup_proxmox_cron_hour: '4' +backup_proxmox_paths: 'root.pxar:/' + +backup_proxmox_signing_key_url: 'https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg' +backup_proxmox_signing_key_file: '/etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg' +backup_proxmox_repo_url: 'http://download.proxmox.com/debian/pbs-client' diff --git a/roles/backup/tasks/main.yml b/roles/backup/tasks/main.yml new file mode 100644 index 0000000..6c39ec6 --- /dev/null +++ b/roles/backup/tasks/main.yml @@ -0,0 +1,72 @@ +--- +- name: 'Install proxmox repository signing key' + become: true + ansible.builtin.get_url: + url: '{{ backup_proxmox_signing_key_url }}' + dest: '{{ backup_proxmox_signing_key_file }}' + owner: 'root' + group: 'root' + mode: 'u=rw,g=r,o=r' + +- name: 'Install proxmox backup software repository' + become: true + ansible.builtin.apt_repository: + repo: 'deb [arch=amd64 signed-by={{ backup_proxmox_signing_key_file }}] {{ backup_proxmox_repo_url }} bookworm main' + filename: 'pbs-client' + +- name: 'Install static proxmox backup client' + become: true + ansible.builtin.apt: + name: 'proxmox-backup-client-static' + state: 'present' + +- name: 'Create directory for encryption key' + become: true + ansible.builtin.file: + path: '/root/.config/proxmox-backup' + state: 'directory' + owner: 'root' + group: 'root' + mode: 'u=rwx,g=rx,o=rx' + +- name: 'Deploy encryption key to host' + become: true + ansible.builtin.template: + src: 'encryption-key.json.j2' + dest: '/root/.config/proxmox-backup/encryption-key.json' + owner: 'root' + group: 'root' + mode: 'u=rw,g=,o=' + +- name: 'Create cronjob' + become: true + block: + - name: 'Generate the cronjob itself' + ansible.builtin.cron: + cron_file: 'proxmox-backup' + user: 'root' + name: 'proxmox-backup' + job: 'proxmox-backup-client backup {{ backup_proxmox_paths }}' + hour: '{{ backup_proxmox_cron_hour }}' + minute: '{{ backup_proxmox_cron_minute }}' + - name: 'Configure environment variable for repository' + ansible.builtin.cron: + cron_file: 'proxmox-backup' + user: 'root' + env: true + name: 'PBS_REPOSITORY' + value: '{{ backup_proxmox_repository }}' + - name: 'Configure environment variable for user password' + ansible.builtin.cron: + cron_file: 'proxmox-backup' + user: 'root' + env: true + name: 'PBS_PASSWORD' + value: '{{ backup_proxmox_password }}' + - name: 'Configure environment variable for encryption' + ansible.builtin.cron: + cron_file: 'proxmox-backup' + user: 'root' + env: true + name: 'PBS_ENCRYPTION_PASSWORD' + value: '{{ backup_proxmox_encryption_password }}' diff --git a/roles/backup/templates/encryption-key.json.j2 b/roles/backup/templates/encryption-key.json.j2 new file mode 100644 index 0000000..2c2bb97 --- /dev/null +++ b/roles/backup/templates/encryption-key.json.j2 @@ -0,0 +1,14 @@ +{ + "kdf": { + "Scrypt": { + "n": 65536, + "r": 8, + "p": 1, + "salt": "{{ backup_proxmox_encryption_key_kdf_salt }}" + } + }, + "created": "{{ backup_proxmox_encryption_key_created }}", + "modified": "{{ backup_proxmox_encryption_key_modified }}", + "data": "{{ backup_proxmox_encryption_key_data }}", + "fingerprint": "{{ backup_proxmox_encryption_key_fingerprint }}" +} \ No newline at end of file