Compare commits

..

1 Commits

Author SHA1 Message Date
072ad6f186 Removed load button 2025-07-11 10:15:58 +02:00
368 changed files with 976 additions and 1361 deletions

View File

@@ -3,16 +3,10 @@ import os
import argparse import argparse
import yaml import yaml
import json import json
import re from collections import deque
from typing import List, Dict, Any, Set from typing import List, Dict, Any, Set
JINJA_PATTERN = re.compile(r'{{.*}}')
ALL_DEP_TYPES = ['run_after', 'dependencies', 'include_tasks', 'import_tasks', 'include_role', 'import_role']
ALL_DIRECTIONS = ['to', 'from']
ALL_KEYS = [f"{dep}_{dir}" for dep in ALL_DEP_TYPES for dir in ALL_DIRECTIONS]
def find_role_meta(roles_dir: str, role: str) -> str: def find_role_meta(roles_dir: str, role: str) -> str:
path = os.path.join(roles_dir, role, 'meta', 'main.yml') path = os.path.join(roles_dir, role, 'meta', 'main.yml')
if not os.path.isfile(path): if not os.path.isfile(path):
@@ -20,14 +14,10 @@ def find_role_meta(roles_dir: str, role: str) -> str:
return path return path
def find_role_tasks(roles_dir: str, role: str) -> str:
path = os.path.join(roles_dir, role, 'tasks', 'main.yml')
if not os.path.isfile(path):
raise FileNotFoundError(f"Tasks not found for role: {role}")
return path
def load_meta(path: str) -> Dict[str, Any]: def load_meta(path: str) -> Dict[str, Any]:
"""
Load meta/main.yml → return galaxy_info + run_after + dependencies
"""
with open(path, 'r') as f: with open(path, 'r') as f:
data = yaml.safe_load(f) or {} data = yaml.safe_load(f) or {}
@@ -38,24 +28,6 @@ def load_meta(path: str) -> Dict[str, Any]:
'dependencies': data.get('dependencies', []) or [] 'dependencies': data.get('dependencies', []) or []
} }
def load_tasks(path: str, dep_type: str) -> List[str]:
with open(path, 'r') as f:
data = yaml.safe_load(f) or []
included_roles = []
for task in data:
if dep_type in task:
entry = task[dep_type]
if isinstance(entry, dict):
entry = entry.get('name', '')
if entry and not JINJA_PATTERN.search(entry):
included_roles.append(entry)
return included_roles
def build_single_graph( def build_single_graph(
start_role: str, start_role: str,
dep_type: str, dep_type: str,
@@ -63,73 +35,71 @@ def build_single_graph(
roles_dir: str, roles_dir: str,
max_depth: int max_depth: int
) -> Dict[str, Any]: ) -> Dict[str, Any]:
"""
Build one graph for one dependency type and direction:
- 'to': follow edges source→target
- 'from': reverse edges (find roles listing this role)
- max_depth > 0: limit hops to max_depth
- max_depth ≤ 0: stop when youd revisit a node already on the path
"""
nodes: Dict[str, Dict[str, Any]] = {} nodes: Dict[str, Dict[str, Any]] = {}
links: List[Dict[str, str]] = [] links: List[Dict[str, str]] = []
def traverse(role: str, depth: int, path: Set[str]): def traverse(role: str, depth: int, path: Set[str]):
# Register node once
if role not in nodes: if role not in nodes:
meta = load_meta(find_role_meta(roles_dir, role)) meta = load_meta(find_role_meta(roles_dir, role))
node = {'id': role} node = {'id': role}
node.update(meta['galaxy_info']) node.update(meta['galaxy_info'])
node['doc_url'] = f"https://docs.cymais.cloud/roles/{role}/README.html" node['doc_url'] = f"https://docs.cymais.cloud/roles/{role}/README.html"
node['source_url'] = f"https://github.com/kevinveenbirkenbach/cymais/tree/master/roles/{role}" node['source_url'] = (
f"https://github.com/kevinveenbirkenbach/cymais/tree/master/roles/{role}"
)
nodes[role] = node nodes[role] = node
# Depth guard
if max_depth > 0 and depth >= max_depth: if max_depth > 0 and depth >= max_depth:
return return
neighbors = [] # Determine neighbors according to direction
if dep_type in ['run_after', 'dependencies']:
meta = load_meta(find_role_meta(roles_dir, role))
neighbors = meta.get(dep_type, [])
else:
try:
neighbors = load_tasks(find_role_tasks(roles_dir, role), dep_type)
except FileNotFoundError:
neighbors = []
if direction == 'to': if direction == 'to':
neighbors = load_meta(find_role_meta(roles_dir, role)).get(dep_type, [])
for tgt in neighbors: for tgt in neighbors:
links.append({'source': role, 'target': tgt, 'type': dep_type}) links.append({'source': role, 'target': tgt, 'type': dep_type})
# General cycle check
if tgt in path: if tgt in path:
continue continue
traverse(tgt, depth + 1, path | {tgt}) traverse(tgt, depth + 1, path | {tgt})
else: # direction == 'from' else: # direction == 'from'
# Find all roles that list this role in their dep_type
for other in os.listdir(roles_dir): for other in os.listdir(roles_dir):
try: try:
other_neighbors = [] meta_o = load_meta(find_role_meta(roles_dir, other))
if dep_type in ['run_after', 'dependencies']:
meta_o = load_meta(find_role_meta(roles_dir, other))
other_neighbors = meta_o.get(dep_type, [])
else:
other_neighbors = load_tasks(find_role_tasks(roles_dir, other), dep_type)
if role in other_neighbors:
links.append({'source': other, 'target': role, 'type': dep_type})
if other in path:
continue
traverse(other, depth + 1, path | {other})
except FileNotFoundError: except FileNotFoundError:
continue continue
if role in meta_o.get(dep_type, []):
links.append({'source': other, 'target': role, 'type': dep_type})
if other in path:
continue
traverse(other, depth + 1, path | {other})
# Kick off recursion
traverse(start_role, depth=0, path={start_role}) traverse(start_role, depth=0, path={start_role})
return {'nodes': list(nodes.values()), 'links': links} return {'nodes': list(nodes.values()), 'links': links}
def build_mappings( def build_mappings(
start_role: str, start_role: str,
mappings: List[Dict[str, str]],
roles_dir: str, roles_dir: str,
max_depth: int max_depth: int
) -> Dict[str, Any]: ) -> Dict[str, Any]:
result: Dict[str, Any] = {} result: Dict[str, Any] = {}
for key in ALL_KEYS: for mapping in mappings:
dep_type, direction = key.rsplit('_', 1) for dep_type, direction in mapping.items():
try: key = f"{dep_type}_{direction}"
result[key] = build_single_graph(start_role, dep_type, direction, roles_dir, max_depth) result[key] = build_single_graph(
except Exception: start_role, dep_type, direction, roles_dir, max_depth)
result[key] = {'nodes': [], 'links': []}
return result return result
@@ -154,20 +124,64 @@ def main():
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
default_roles_dir = os.path.abspath(os.path.join(script_dir, '..', '..', 'roles')) default_roles_dir = os.path.abspath(os.path.join(script_dir, '..', '..', 'roles'))
parser = argparse.ArgumentParser(description="Generate dependency graphs") parser = argparse.ArgumentParser(
parser.add_argument('-r', '--role', required=True, help="Starting role name") description="Generate graphs based on dependency mappings"
parser.add_argument('-D', '--depth', type=int, default=0, help="Max recursion depth") )
parser.add_argument('-o', '--output', choices=['yaml', 'json', 'console'], default='console') parser.add_argument(
parser.add_argument('--roles-dir', default=default_roles_dir, help="Roles directory") '-r', '--role',
required=True,
help="Starting role name"
)
parser.add_argument(
'-m', '--mapping',
nargs='+',
default=[
'run_after:to',
'run_after:from',
'dependencies:to',
'dependencies:from'
],
help="Mapping entries as type:direction (default all 4 combos)"
)
parser.add_argument(
'-D', '--depth',
type=int,
default=0,
help="Max recursion depth (>0) or <=0 to stop on cycle"
)
parser.add_argument(
'-o', '--output',
choices=['yaml', 'json', 'console'],
default='console',
help="Output format"
)
parser.add_argument(
'--roles-dir',
default=default_roles_dir,
help="Roles directory"
)
args = parser.parse_args() args = parser.parse_args()
graphs = build_mappings(args.role, args.roles_dir, args.depth) mappings: List[Dict[str, str]] = []
for entry in args.mapping:
if ':' not in entry:
parser.error(f"Invalid mapping '{entry}', must be type:direction")
dep_type, direction = entry.split(':', 1)
if dep_type not in ('run_after', 'dependencies'):
parser.error(f"Unknown dependency type '{dep_type}'")
if direction not in ('to', 'from'):
parser.error(f"Unknown direction '{direction}'")
mappings.append({dep_type: direction})
for key in ALL_KEYS: graphs = build_mappings(
graph_data = graphs.get(key, {'nodes': [], 'links': []}) start_role=args.role,
mappings=mappings,
roles_dir=args.roles_dir,
max_depth=args.depth
)
for key, graph_data in graphs.items():
output_graph(graph_data, args.output, args.role, key) output_graph(graph_data, args.output, args.role, key)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -2,7 +2,7 @@
import os import os
import argparse import argparse
import json import json
from typing import Dict, Any from typing import List, Dict, Any
from cli.generate.graph import build_mappings, output_graph from cli.generate.graph import build_mappings, output_graph
@@ -21,13 +21,22 @@ def main():
default_roles_dir = os.path.abspath(os.path.join(script_dir, '..', '..', 'roles')) default_roles_dir = os.path.abspath(os.path.join(script_dir, '..', '..', 'roles'))
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Generate all graphs for each role and write meta/tree.json" description="Generate mappings-based graphs for each role and write tree.json"
) )
parser.add_argument( parser.add_argument(
'-d', '--role_dir', '-d', '--role_dir',
default=default_roles_dir, default=default_roles_dir,
help=f"Path to roles directory (default: {default_roles_dir})" help=f"Path to roles directory (default: {default_roles_dir})"
) )
parser.add_argument(
'-m', '--mapping',
nargs='+',
default=[
'run_after:to', 'run_after:from',
'dependencies:to', 'dependencies:from'
],
help="Mapping entries as type:direction (default all 4 combos)"
)
parser.add_argument( parser.add_argument(
'-D', '--depth', '-D', '--depth',
type=int, type=int,
@@ -52,8 +61,17 @@ def main():
) )
args = parser.parse_args() args = parser.parse_args()
# parse mappings
mappings: List[Dict[str, str]] = []
for entry in args.mapping:
if ':' not in entry:
parser.error(f"Invalid mapping '{entry}', must be type:direction")
dep_type, direction = entry.split(':', 1)
mappings.append({dep_type: direction})
if args.verbose: if args.verbose:
print(f"Roles directory: {args.role_dir}") print(f"Roles directory: {args.role_dir}")
print(f"Mappings: {mappings}")
print(f"Max depth: {args.depth}") print(f"Max depth: {args.depth}")
print(f"Output format: {args.output}") print(f"Output format: {args.output}")
print(f"Preview mode: {args.preview}") print(f"Preview mode: {args.preview}")
@@ -62,12 +80,15 @@ def main():
if args.verbose: if args.verbose:
print(f"Processing role: {role_name}") print(f"Processing role: {role_name}")
graphs: Dict[str, Any] = build_mappings( # Build graphs for each mapping
graphs = build_mappings(
start_role=role_name, start_role=role_name,
mappings=mappings,
roles_dir=args.role_dir, roles_dir=args.role_dir,
max_depth=args.depth max_depth=args.depth
) )
# Prepare output file or previews
if args.preview: if args.preview:
for key, data in graphs.items(): for key, data in graphs.items():
if args.verbose: if args.verbose:
@@ -76,10 +97,13 @@ def main():
else: else:
tree_file = os.path.join(role_path, 'meta', 'tree.json') tree_file = os.path.join(role_path, 'meta', 'tree.json')
os.makedirs(os.path.dirname(tree_file), exist_ok=True) os.makedirs(os.path.dirname(tree_file), exist_ok=True)
# write combined JSON
with open(tree_file, 'w') as f: with open(tree_file, 'w') as f:
json.dump(graphs, f, indent=2) json.dump(graphs, f, indent=2)
print(f"Wrote {tree_file}") if args.verbose:
print(f"Wrote {tree_file}")
else:
print(f"Wrote {tree_file}")
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
CLI for extracting invokable or non-invokable role paths from a nested roles YAML file using argparse. CLI for extracting invokable role paths from a nested roles YAML file using argparse.
Assumes a default roles file at the project root if none is provided. Assumes a default roles file at the project root if none is provided.
""" """
@@ -18,12 +18,12 @@ sys.path.insert(0, project_root)
import argparse import argparse
import yaml import yaml
from filter_plugins.invokable_paths import get_invokable_paths, get_non_invokable_paths from filter_plugins.invokable_paths import get_invokable_paths
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Extract invokable or non-invokable role paths from a nested roles YAML file." description="Extract invokable role paths from a nested roles YAML file."
) )
parser.add_argument( parser.add_argument(
"roles_file", "roles_file",
@@ -33,33 +33,13 @@ def main():
) )
parser.add_argument( parser.add_argument(
"--suffix", "-s", "--suffix", "-s",
help="Optional suffix to append to each path.", help="Optional suffix to append to each invokable path.",
default=None default=None
) )
mode_group = parser.add_mutually_exclusive_group()
mode_group.add_argument(
"--non-invokable", "-n",
action='store_true',
help="List paths where 'invokable' is False or not set."
)
mode_group.add_argument(
"--invokable", "-i",
action='store_true',
help="List paths where 'invokable' is True. (default behavior)"
)
args = parser.parse_args() args = parser.parse_args()
# Default to invokable if neither flag is provided
list_non = args.non_invokable
list_inv = args.invokable or not (args.non_invokable or args.invokable)
try: try:
if list_non: paths = get_invokable_paths(args.roles_file, args.suffix)
paths = get_non_invokable_paths(args.roles_file, args.suffix)
else:
paths = get_invokable_paths(args.roles_file, args.suffix)
except FileNotFoundError as e: except FileNotFoundError as e:
print(f"Error: {e}", file=sys.stderr) print(f"Error: {e}", file=sys.stderr)
sys.exit(1) sys.exit(1)

View File

@@ -1,76 +0,0 @@
#!/usr/bin/env python3
"""
CLI Script: get_role_folder_cli.py
This script determines the appropriate Ansible role folder based on the provided application_id
by inspecting each role's vars/main.yml within the roles directory. By default, it assumes the
roles directory is located at the project root, relative to this script's location.
Example:
./get_role_folder_cli.py --application-id my-app-id
"""
import os
import sys
import argparse
import yaml
def get_role_folder(application_id, roles_path):
"""
Find the role directory under `roles_path` whose vars/main.yml contains the specified application_id.
:param application_id: The application_id to match.
:param roles_path: Path to the roles directory.
:return: The name of the matching role directory.
:raises RuntimeError: If no match is found or if an error occurs while reading files.
"""
if not os.path.isdir(roles_path):
raise RuntimeError(f"Roles path not found: {roles_path}")
for role in sorted(os.listdir(roles_path)):
role_dir = os.path.join(roles_path, role)
vars_file = os.path.join(role_dir, 'vars', 'main.yml')
if os.path.isfile(vars_file):
try:
with open(vars_file, 'r') as f:
data = yaml.safe_load(f) or {}
except Exception as e:
raise RuntimeError(f"Failed to load {vars_file}: {e}")
if data.get('application_id') == application_id:
return role
raise RuntimeError(f"No role found with application_id '{application_id}' in {roles_path}")
def main():
parser = argparse.ArgumentParser(
description='Determine the Ansible role folder by application_id'
)
parser.add_argument(
'application_id',
help='The application_id defined in vars/main.yml to search for'
)
parser.add_argument(
'-r', '--roles-path',
default=os.path.join(
os.path.dirname(os.path.realpath(__file__)),
os.pardir, os.pardir,
'roles'
),
help='Path to the roles directory (default: roles/ at project root)'
)
args = parser.parse_args()
try:
folder = get_role_folder(args.application_id, args.roles_path)
print(folder)
sys.exit(0)
except RuntimeError as err:
print(f"Error: {err}", file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
main()

View File

@@ -12,10 +12,10 @@ CyMaIS covers everything from essential system setups to advanced configurations
Every business is unique, and so is CyMaIS! With a modular architecture, it adapts to specific requirements, whether for startups, growing businesses, NGOs, or large enterprises. Every business is unique, and so is CyMaIS! With a modular architecture, it adapts to specific requirements, whether for startups, growing businesses, NGOs, or large enterprises.
## Proactive Monitoring & Maintenance 🔍 ## Proactive Monitoring & Maintenance 🔍
With automated updates, system health checks, and security audits, CyMaIS ensures your infrastructure is always up-to-date and running smoothly. Roles such as `sys-hlth-docker-container`, `sys-hlth-btrfs`, and `sys-hlth-webserver` help monitor system integrity. With automated updates, system health checks, and security audits, CyMaIS ensures your infrastructure is always up-to-date and running smoothly. Roles such as `mon-bot-docker-container`, `mon-bot-btrfs`, and `mon-bot-webserver` help monitor system integrity.
## Uncompromised Security 🔒 ## Uncompromised Security 🔒
Security is a top priority! CyMaIS includes robust security features like full-disk encryption recommendations, 2FA enforcement, encrypted server deployments (`web-app-keycloak`, `svc-openldap`), and secure backup solutions (`sys-bkp-remote-to-local`, `svc-sys-bkp-data-to-usb`). Security is a top priority! CyMaIS includes robust security features like full-disk encryption recommendations, 2FA enforcement, encrypted server deployments (`web-app-keycloak`, `svc-openldap`), and secure backup solutions (`bkp-remote-to-local`, `bkp-data-to-usb`).
## User-Friendly with Expert Support 👩‍💻 ## User-Friendly with Expert Support 👩‍💻
No need to be a Linux or Docker expert! CyMaIS simplifies deployment with intuitive role-based automation. Documentation and community support make IT administration accessible to all experience levels. No need to be a Linux or Docker expert! CyMaIS simplifies deployment with intuitive role-based automation. Documentation and community support make IT administration accessible to all experience levels.

View File

@@ -10,13 +10,13 @@ Follow these guides to install and configure CyMaIS:
## Key Responsibilities 🔧 ## Key Responsibilities 🔧
- **User Management** - Configure LDAP, Keycloak, and user permissions. - **User Management** - Configure LDAP, Keycloak, and user permissions.
- **Security & Backups** - Set up `sys-bkp-remote-to-local`, `svc-sys-bkp-data-to-usb`, and `core-security` roles. - **Security & Backups** - Set up `bkp-remote-to-local`, `bkp-data-to-usb`, and `core-security` roles.
- **Application Hosting** - Deploy services like `Nextcloud`, `Matrix`, `Gitea`, and more. - **Application Hosting** - Deploy services like `Nextcloud`, `Matrix`, `Gitea`, and more.
- **Networking & VPN** - Configure `WireGuard`, `OpenVPN`, and `Nginx Reverse Proxy`. - **Networking & VPN** - Configure `WireGuard`, `OpenVPN`, and `Nginx Reverse Proxy`.
## Managing & Updating CyMaIS 🔄 ## Managing & Updating CyMaIS 🔄
- Regularly update services using `update-docker`, `update-pacman`, or `update-apt`. - Regularly update services using `update-docker`, `update-pacman`, or `update-apt`.
- Monitor system health with `sys-hlth-btrfs`, `sys-hlth-webserver`, and `sys-hlth-docker-container`. - Monitor system health with `mon-bot-btrfs`, `mon-bot-webserver`, and `mon-bot-docker-container`.
- Automate system maintenance with `sys-lock`, `sys-cln-bkps-service`, and `sys-rpr-docker-hard`. - Automate system maintenance with `maint-lock`, `cln-backups-service`, and `maint-docker-restart`.
For more details, refer to the specific guides above. For more details, refer to the specific guides above.

View File

@@ -5,12 +5,14 @@ from ansible.errors import AnsibleFilterError
class FilterModule(object): class FilterModule(object):
def filters(self): def filters(self):
# module_util-Verzeichnis ermitteln und zum Import-Pfad hinzufügen
plugin_dir = os.path.dirname(__file__) plugin_dir = os.path.dirname(__file__)
project_root = os.path.dirname(plugin_dir) project_root = os.path.dirname(plugin_dir)
module_utils = os.path.join(project_root, 'module_utils') module_utils = os.path.join(project_root, 'module_utils')
if module_utils not in sys.path: if module_utils not in sys.path:
sys.path.append(module_utils) sys.path.append(module_utils)
# jetzt kannst Du domain_utils importieren
try: try:
from domain_utils import get_domain from domain_utils import get_domain
except ImportError as e: except ImportError as e:

View File

@@ -1,48 +0,0 @@
'''
Ansible filter plugin: get_role_folder
This filter inspects each role under the given roles directory, loads its vars/main.yml,
and returns the role folder name whose application_id matches the provided value.
'''
from ansible.errors import AnsibleFilterError
import os
import yaml
def get_role_folder(application_id, roles_path='roles'):
"""
Find the role directory under `roles_path` whose vars/main.yml contains the given application_id.
:param application_id: The application_id to match.
:param roles_path: Path to the roles directory (default: 'roles').
:return: The name of the matching role directory.
:raises AnsibleFilterError: If vars file is unreadable or no match is found.
"""
if not os.path.isdir(roles_path):
raise AnsibleFilterError(f"Roles path not found: {roles_path}")
for role in os.listdir(roles_path):
role_dir = os.path.join(roles_path, role)
vars_file = os.path.join(role_dir, 'vars', 'main.yml')
if os.path.isfile(vars_file):
try:
with open(vars_file, 'r') as f:
data = yaml.safe_load(f) or {}
except Exception as e:
raise AnsibleFilterError(f"Failed to load {vars_file}: {e}")
if data.get('application_id') == application_id:
return role
raise AnsibleFilterError(f"No role found with application_id '{application_id}' in {roles_path}")
class FilterModule(object):
"""
Register the get_role_folder filter
"""
def filters(self):
return {
'get_role_folder': get_role_folder,
}

View File

@@ -2,18 +2,29 @@ import os
import yaml import yaml
from typing import Dict, List, Optional from typing import Dict, List, Optional
def get_invokable_paths( def get_invokable_paths(
roles_file: Optional[str] = None, roles_file: Optional[str] = None,
suffix: Optional[str] = None suffix: Optional[str] = None
) -> List[str]: ) -> List[str]:
""" """
Load nested roles YAML and return dash-joined paths where 'invokable' is True. Appends suffix if provided. Load nested roles YAML from the given file (or default at project root) and return
dash-joined paths where 'invokable' is True. Appends suffix if provided.
:param roles_file: Optional path to YAML file. Defaults to '<project_root>/roles/categories.yml'.
:param suffix: Optional suffix to append to each invokable path.
:return: List of invokable paths.
:raises FileNotFoundError: If the YAML file cannot be found.
:raises yaml.YAMLError: If the YAML file cannot be parsed.
:raises ValueError: If the root of the YAML is not a dictionary.
""" """
# Determine default roles_file if not provided
if not roles_file: if not roles_file:
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir) project_root = os.path.dirname(script_dir)
roles_file = os.path.join(project_root, 'roles', 'categories.yml') roles_file = os.path.join(project_root, 'roles', 'categories.yml')
# Load and validate YAML
try: try:
with open(roles_file, 'r') as f: with open(roles_file, 'r') as f:
data = yaml.safe_load(f) or {} data = yaml.safe_load(f) or {}
@@ -25,6 +36,7 @@ def get_invokable_paths(
if not isinstance(data, dict): if not isinstance(data, dict):
raise ValueError("YAML root is not a dictionary") raise ValueError("YAML root is not a dictionary")
# Unwrap if single 'roles' key
roles = data roles = data
if 'roles' in roles and isinstance(roles['roles'], dict) and len(roles) == 1: if 'roles' in roles and isinstance(roles['roles'], dict) and len(roles) == 1:
roles = roles['roles'] roles = roles['roles']
@@ -42,6 +54,7 @@ def get_invokable_paths(
p += suffix p += suffix
found.append(p) found.append(p)
# Recurse into non-metadata child dicts
children = { children = {
ck: cv for ck, cv in cfg.items() ck: cv for ck, cv in cfg.items()
if ck not in METADATA and isinstance(cv, dict) if ck not in METADATA and isinstance(cv, dict)
@@ -53,61 +66,6 @@ def get_invokable_paths(
return _recurse(roles) return _recurse(roles)
def get_non_invokable_paths(
roles_file: Optional[str] = None,
suffix: Optional[str] = None
) -> List[str]:
"""
Load nested roles YAML and return dash-joined paths where 'invokable' is False or missing.
Appends suffix if provided.
"""
if not roles_file:
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
roles_file = os.path.join(project_root, 'roles', 'categories.yml')
try:
with open(roles_file, 'r') as f:
data = yaml.safe_load(f) or {}
except FileNotFoundError:
raise FileNotFoundError(f"Roles file not found: {roles_file}")
except yaml.YAMLError as e:
raise yaml.YAMLError(f"Error parsing YAML {roles_file}: {e}")
if not isinstance(data, dict):
raise ValueError("YAML root is not a dictionary")
roles = data
if 'roles' in roles and isinstance(roles['roles'], dict) and len(roles) == 1:
roles = roles['roles']
def _recurse_non(subroles: Dict[str, dict], parent: List[str] = None) -> List[str]:
parent = parent or []
found: List[str] = []
METADATA = {'title', 'description', 'icon', 'invokable'}
for key, cfg in subroles.items():
path = parent + [key]
p = '-'.join(path)
inv = cfg.get('invokable', False)
if not inv:
entry = p + (suffix or "")
found.append(entry)
children = {
ck: cv for ck, cv in cfg.items()
if ck not in METADATA and isinstance(cv, dict)
}
if children:
found.extend(_recurse_non(children, path))
return found
return _recurse_non(roles)
class FilterModule: class FilterModule:
def filters(self): def filters(self):
return { return {'invokable_paths': get_invokable_paths}
'invokable_paths': get_invokable_paths,
'non_invokable_paths': get_non_invokable_paths
}

View File

@@ -13,23 +13,23 @@ system_maintenance_lock_timeout_restart_docker: "{{system_maintenance_lock_ti
### Defined Services for Backup Tasks ### Defined Services for Backup Tasks
system_maintenance_backup_services: system_maintenance_backup_services:
- "sys-bkp-docker-to-local" - "bkp-docker-to-local"
- "svc-sys-bkp-rmt-2-loc" - "bkp-remote-to-local"
- "svc-sys-bkp-data-to-usb" - "bkp-data-to-usb"
- "sys-bkp-docker-to-local-everything" - "bkp-docker-to-local-everything"
### Defined Services for System Cleanup ### Defined Services for System Cleanup
system_maintenance_cleanup_services: system_maintenance_cleanup_services:
- "sys-cln-backups" - "cln-backups"
- "sys-cln-disc-space" - "cln-disc-space"
- "sys-cln-faild-bkps" - "cln-failed-docker-backups"
### Services that Manipulate the System ### Services that Manipulate the System
system_maintenance_manipulation_services: system_maintenance_manipulation_services:
- "sys-rpr-docker-soft" - "maint-docker-heal"
- "update-docker" - "update-docker"
- "sys-opt-ssd-hdd" - "cln-docker-storage-optimizer"
- "sys-rpr-docker-hard" - "maint-docker-restart"
## Total System Maintenance Services ## Total System Maintenance Services
system_maintenance_services: "{{ system_maintenance_backup_services + system_maintenance_cleanup_services + system_maintenance_manipulation_services }}" system_maintenance_services: "{{ system_maintenance_backup_services + system_maintenance_cleanup_services + system_maintenance_manipulation_services }}"

View File

@@ -3,4 +3,4 @@
path_administrator_home: "/home/administrator/" path_administrator_home: "/home/administrator/"
path_administrator_scripts: "/opt/scripts/" path_administrator_scripts: "/opt/scripts/"
path_docker_compose_instances: "/opt/docker/" path_docker_compose_instances: "/opt/docker/"
path_system_lock_script: "/opt/scripts/sys-lock.py" path_system_lock_script: "/opt/scripts/maint-lock.py"

View File

@@ -15,7 +15,7 @@ For a complete list of role categories and detailed definitions, see:
Fundamental system configuration (SSH, journald, sudo, etc.) Fundamental system configuration (SSH, journald, sudo, etc.)
- **gen-*** - **gen-***
Generic helpers and language/tool installers (e.g. `gen-git`, `gen-locales`, `sys-timer`) Generic helpers and language/tool installers (e.g. `gen-git`, `gen-locales`, `gen-timer`)
- **desk-*** - **desk-***
Desktop environment and application roles (e.g. `desk-gnome`, `desk-browser`, `desk-libreoffice`) Desktop environment and application roles (e.g. `desk-gnome`, `desk-browser`, `desk-libreoffice`)
@@ -59,13 +59,13 @@ For a complete list of role categories and detailed definitions, see:
## Monitoring & Alerting ## Monitoring & Alerting
- **sys-hlth-*** - **mon-bot-***
“Bot”-style health checks (Btrfs, diskspace, Docker, journalctl, CSP crawler, webserver) with alerts. “Bot”-style health checks (Btrfs, diskspace, Docker, journalctl, CSP crawler, webserver) with alerts.
- **monitor-core-*** - **monitor-core-***
Low-level system monitors (journalctl, Docker containers, disk space, etc.) Low-level system monitors (journalctl, Docker containers, disk space, etc.)
- **sys-alm-*** - **alert-***
Notification handlers for failures (core, email, Telegram). Notification handlers for failures (core, email, Telegram).
--- ---
@@ -78,14 +78,14 @@ For a complete list of role categories and detailed definitions, see:
- **maint-docker-*** - **maint-docker-***
Automated recovery and restarts for Docker Compose workloads. Automated recovery and restarts for Docker Compose workloads.
- **sys-cln-*** - **cln-***
Housekeeping tasks (old backups, expired certs, log rotation). Housekeeping tasks (old backups, expired certs, log rotation).
--- ---
## Backup & Restore ## Backup & Restore
- **sys-bkp-*** - **bkp-***
Local and remote backup strategies for files, Docker volumes, databases. Local and remote backup strategies for files, Docker volumes, databases.
--- ---
@@ -112,8 +112,8 @@ For a complete list of role categories and detailed definitions, see:
> **Tip:** To find a role quickly, search for its prefix: > **Tip:** To find a role quickly, search for its prefix:
> `core-`, `gen-`, `desk-`, `srv-web-`, `web-svc-`, `web-app-`, > `core-`, `gen-`, `desk-`, `srv-web-`, `web-svc-`, `web-app-`,
> `net-`, `svc-`, `sys-hlth-`, `monitor-core-`, `sys-alm-`, > `net-`, `svc-`, `mon-bot-`, `monitor-core-`, `alert-`,
> `maint-`, `maint-docker-`, `sys-cln-`, `sys-bkp-`, `update-`, > `maint-`, `maint-docker-`, `cln-`, `bkp-`, `update-`,
> `pkgmgr-`, `user-`. > `pkgmgr-`, `user-`.
--- ---

View File

@@ -2,7 +2,7 @@
## Description ## Description
This role installs a systemd service that sends notifications via both [sys-alm-telegram](../sys-alm-telegram/README.md) and [sys-alm-email](../sys-alm-email/README.md) when any service fails. This role installs a systemd service that sends notifications via both [alert-telegram](../alert-telegram/README.md) and [alert-email](../alert-email/README.md) when any service fails.
## Overview ## Overview
@@ -15,6 +15,6 @@ The primary purpose of this role is to provide a centralized mechanism for servi
## Features ## Features
- **Unified Notification Service:** Installs a systemd service that triggers both Telegram and Email alerts. - **Unified Notification Service:** Installs a systemd service that triggers both Telegram and Email alerts.
- **Dependency Integration:** Works seamlessly with the [sys-alm-telegram](../sys-alm-telegram/README.md) and [sys-alm-email](../sys-alm-email/README.md) roles. - **Dependency Integration:** Works seamlessly with the [alert-telegram](../alert-telegram/README.md) and [alert-email](../alert-email/README.md) roles.
- **Automated Service Management:** Automatically restarts the notifier service upon configuration changes. - **Automated Service Management:** Automatically restarts the notifier service upon configuration changes.
- **Centralized Alerting:** Provides a unified approach to monitor and notify about service failures. - **Centralized Alerting:** Provides a unified approach to monitor and notify about service failures.

View File

@@ -1,6 +1,6 @@
- name: "restart sys-alm-compose service" - name: "restart alert-compose service"
systemd: systemd:
name: sys-alm-compose.cymais.service name: alert-compose.cymais.service
daemon_reload: yes daemon_reload: yes
when: run_once_systemd_notifier_service is not defined when: run_once_systemd_notifier_service is not defined

View File

@@ -23,5 +23,5 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-alm-telegram - alert-telegram
- sys-alm-email - alert-email

View File

@@ -1,9 +1,9 @@
--- ---
- name: configure sys-alm-compose.cymais@.service - name: configure alert-compose.cymais@.service
template: template:
src: sys-alm-compose@.service.j2 src: alert-compose@.service.j2
dest: "/etc/systemd/system/sys-alm-compose.cymais@.service" dest: "/etc/systemd/system/alert-compose.cymais@.service"
notify: "restart sys-alm-compose service" notify: "restart alert-compose service"
when: run_once_systemd_notifier_service is not defined when: run_once_systemd_notifier_service is not defined
- name: run the systemd_notifier_service tasks once - name: run the systemd_notifier_service tasks once

View File

@@ -0,0 +1,8 @@
[Unit]
Description=Notifier for %i
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl start alert-telegram.cymais@%i.service alert-email.cymais@%i.service
User=root
Group=systemd-journal

View File

@@ -0,0 +1 @@
application_id: compose

View File

@@ -2,11 +2,11 @@
## Description ## Description
This role installs and configures the necessary components for sending email notifications via systemd when a service fails. It sets up the `sys-alm-email` service and configures email parameters and templates using msmtp. This role installs and configures the necessary components for sending email notifications via systemd when a service fails. It sets up the `alert-email` service and configures email parameters and templates using msmtp.
## Overview ## Overview
Optimized for secure and reliable service failure notifications, this role is an integral part of the overall `sys-alm-compose` suite. It ensures that, upon failure of a critical service, an email alert is sent automatically to enable prompt troubleshooting. Optimized for secure and reliable service failure notifications, this role is an integral part of the overall `alert-compose` suite. It ensures that, upon failure of a critical service, an email alert is sent automatically to enable prompt troubleshooting.
## Purpose ## Purpose
@@ -17,7 +17,7 @@ The primary purpose of this role is to provide a comprehensive solution for auto
- **Service Installation & Configuration:** Installs msmtp and configures the email sending service. - **Service Installation & Configuration:** Installs msmtp and configures the email sending service.
- **Customizable Templates:** Supports tailoring email templates for service failure notifications. - **Customizable Templates:** Supports tailoring email templates for service failure notifications.
- **Secure Notifications:** Integrates with systemd to trigger email alerts when services fail. - **Secure Notifications:** Integrates with systemd to trigger email alerts when services fail.
- **Suite Integration:** Part of the `sys-alm-compose` suite, offering a unified approach to service failure notifications. - **Suite Integration:** Part of the `alert-compose` suite, offering a unified approach to service failure notifications.
## Other Resources ## Other Resources

View File

@@ -0,0 +1,4 @@
- name: "restart alert-email service"
systemd:
name: alert-email.cymais.service
daemon_reload: yes

View File

@@ -1,7 +1,7 @@
--- ---
galaxy_info: galaxy_info:
author: "Kevin Veen-Birkenbach" author: "Kevin Veen-Birkenbach"
description: "Installs and configures components for sending email notifications. This role is part of the sys-alm-compose suite, providing automated alerts when services fail." description: "Installs and configures components for sending email notifications. This role is part of the alert-compose suite, providing automated alerts when services fail."
license: "CyMaIS NonCommercial License (CNCL)" license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl" license_url: "https://s.veen.world/cncl"
company: | company: |
@@ -23,5 +23,5 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-svc-msmtp - gen-msmtp
- sys-rst-daemon - core-daemon

View File

@@ -5,17 +5,17 @@
mode: 0755 mode: 0755
when: run_once_systemd_notifier_email is not defined when: run_once_systemd_notifier_email is not defined
- name: configure sys-alm-email.sh - name: configure alert-email.sh
template: template:
src: sys-alm-email.sh.j2 src: alert-email.sh.j2
dest: "{{systemd_notifier_email_folder}}sys-alm-email.sh" dest: "{{systemd_notifier_email_folder}}alert-email.sh"
when: run_once_systemd_notifier_email is not defined when: run_once_systemd_notifier_email is not defined
- name: configure sys-alm-email.cymais.service - name: configure alert-email.cymais.service
template: template:
src: sys-alm-email@.service.j2 src: alert-email@.service.j2
dest: /etc/systemd/system/sys-alm-email.cymais@.service dest: /etc/systemd/system/alert-email.cymais@.service
notify: restart sys-alm-email service notify: restart alert-email service
when: run_once_systemd_notifier_email is not defined when: run_once_systemd_notifier_email is not defined
- name: run the systemd_notifier_email tasks once - name: run the systemd_notifier_email tasks once

View File

@@ -3,6 +3,6 @@ Description=status email for %i to user
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/bin/bash {{systemd_notifier_email_folder}}sys-alm-email.sh %i ExecStart=/bin/bash {{systemd_notifier_email_folder}}alert-email.sh %i
User=root User=root
Group=systemd-journal Group=systemd-journal

View File

@@ -0,0 +1,2 @@
systemd_notifier_email_folder: '{{path_administrator_scripts}}alert-email/'
application_id: email

View File

@@ -2,11 +2,11 @@
## Description ## Description
This role installs and configures the necessary components for sending notifications via systemd when a service fails. It sets up the `sys-alm-telegram` service and configures parameters and customizable templates for sending messages through [Telegram](https://telegram.org). This role installs and configures the necessary components for sending notifications via systemd when a service fails. It sets up the `alert-telegram` service and configures parameters and customizable templates for sending messages through [Telegram](https://telegram.org).
## Overview ## Overview
Optimized for real-time alerts, this role is a key component of the overall [`sys-alm-compose` suite](../). It ensures that, upon failure of a critical service, a Telegram message is automatically sent to notify administrators and enable prompt troubleshooting. Optimized for real-time alerts, this role is a key component of the overall [`alert-compose` suite](../). It ensures that, upon failure of a critical service, a Telegram message is automatically sent to notify administrators and enable prompt troubleshooting.
## Purpose ## Purpose
@@ -17,7 +17,7 @@ The primary purpose of this role is to provide a robust solution for automated T
- **Service Installation & Configuration:** Installs and configures necessary components (including the `curl` package). - **Service Installation & Configuration:** Installs and configures necessary components (including the `curl` package).
- **Customizable Templates:** Supports tailored Telegram message templates for service failure notifications. - **Customizable Templates:** Supports tailored Telegram message templates for service failure notifications.
- **Secure Notifications:** Leverages systemd to trigger alerts automatically when services fail. - **Secure Notifications:** Leverages systemd to trigger alerts automatically when services fail.
- **Suite Integration:** Part of the [`sys-alm-compose` suite](../) which includes related roles such as [sys-alm-email](../sys-alm-email/README.md) and others. - **Suite Integration:** Part of the [`alert-compose` suite](../) which includes related roles such as [alert-email](../alert-email/README.md) and others.
## Other Resources ## Other Resources

View File

@@ -0,0 +1,4 @@
- name: "restart alert-telegram service"
systemd:
name: alert-telegram.cymais.service
daemon_reload: yes

View File

@@ -1,7 +1,7 @@
--- ---
galaxy_info: galaxy_info:
author: "Kevin Veen-Birkenbach" author: "Kevin Veen-Birkenbach"
description: "Installs and configures components for sending Telegram notifications through systemd. This role is part of the sys-alm-compose suite, providing automated alerts when services fail." description: "Installs and configures components for sending Telegram notifications through systemd. This role is part of the alert-compose suite, providing automated alerts when services fail."
license: "CyMaIS NonCommercial License (CNCL)" license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl" license_url: "https://s.veen.world/cncl"
company: | company: |
@@ -23,4 +23,4 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-rst-daemon - core-daemon

View File

@@ -11,17 +11,17 @@
mode: '0755' mode: '0755'
when: run_once_systemd_notifier_telegram is not defined when: run_once_systemd_notifier_telegram is not defined
- name: configure sys-alm-telegram.sh - name: configure alert-telegram.sh
template: template:
src: sys-alm-telegram.sh.j2 src: alert-telegram.sh.j2
dest: "{{ systemd_telegram_script }}" dest: "{{ systemd_telegram_script }}"
when: run_once_systemd_notifier_telegram is not defined when: run_once_systemd_notifier_telegram is not defined
- name: configure sys-alm-telegram.cymais.service - name: configure alert-telegram.cymais.service
template: template:
src: sys-alm-telegram@.service.j2 src: alert-telegram@.service.j2
dest: "/etc/systemd/system/sys-alm-telegram.cymais@.service" dest: "/etc/systemd/system/alert-telegram.cymais@.service"
notify: "restart sys-alm-telegram service" notify: "restart alert-telegram service"
when: run_once_systemd_notifier_telegram is not defined when: run_once_systemd_notifier_telegram is not defined
- name: run the systemd_notifier_telegram tasks once - name: run the systemd_notifier_telegram tasks once

View File

@@ -0,0 +1,3 @@
systemd_telegram_folder: /opt/ansible-roles/alert-telegram/
systemd_telegram_script: '{{systemd_telegram_folder}}alert-telegram.sh'
application_id: telegram

View File

@@ -21,7 +21,7 @@ def main():
machine_id = subprocess.run(["sha256sum", "/etc/machine-id"], capture_output=True, text=True).stdout.strip()[:64] machine_id = subprocess.run(["sha256sum", "/etc/machine-id"], capture_output=True, text=True).stdout.strip()[:64]
print(f"machine id: {machine_id}") print(f"machine id: {machine_id}")
versions_path = os.path.join(backup_to_usb_destination_path, f"{machine_id}/svc-sys-bkp-data-to-usb/") versions_path = os.path.join(backup_to_usb_destination_path, f"{machine_id}/bkp-data-to-usb/")
print(f"versions path: {versions_path}") print(f"versions path: {versions_path}")
if not os.path.isdir(versions_path): if not os.path.isdir(versions_path):

View File

@@ -0,0 +1,5 @@
- name: "reload bkp-data-to-usb.cymais.service"
systemd:
name: bkp-data-to-usb.cymais.service
state: reloaded
daemon_reload: yes

View File

@@ -23,5 +23,5 @@ galaxy_info:
issue_tracker_url: https://s.veen.world/cymaisissues issue_tracker_url: https://s.veen.world/cymaisissues
documentation: https://s.veen.world/cymais documentation: https://s.veen.world/cymais
dependencies: dependencies:
- sys-cln-bkps-service - cln-backups-service
- sys-lock - maint-lock

View File

@@ -1,6 +1,6 @@
- name: Copy backup script to the scripts directory - name: Copy backup script to the scripts directory
copy: copy:
src: svc-sys-bkp-data-to-usb.python src: bkp-data-to-usb.python
dest: "{{ backup_to_usb_script_path }}" dest: "{{ backup_to_usb_script_path }}"
owner: root owner: root
group: root group: root
@@ -8,9 +8,9 @@
- name: Copy systemd service to systemd directory - name: Copy systemd service to systemd directory
template: template:
src: svc-sys-bkp-data-to-usb.service.j2 src: bkp-data-to-usb.service.j2
dest: /etc/systemd/system/svc-sys-bkp-data-to-usb.cymais.service dest: /etc/systemd/system/bkp-data-to-usb.cymais.service
owner: root owner: root
group: root group: root
mode: '0644' mode: '0644'
notify: reload svc-sys-bkp-data-to-usb.cymais.service notify: reload bkp-data-to-usb.cymais.service

View File

@@ -1,12 +1,12 @@
[Unit] [Unit]
Description=Backup to USB when mounted to {{ backup_to_usb_mount }} Description=Backup to USB when mounted to {{ backup_to_usb_mount }}
Wants={{systemctl_mount_service_name}} Wants={{systemctl_mount_service_name}}
OnFailure=sys-alm-compose.cymais@%n.service OnFailure=alert-compose.cymais@%n.service
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/bin/python {{ backup_to_usb_script_path }} {{backup_to_usb_source}} {{backup_to_usb_destination}} ExecStart=/bin/python {{ backup_to_usb_script_path }} {{backup_to_usb_source}} {{backup_to_usb_destination}}
ExecStartPost=/bin/systemctl start sys-cln-backups.cymais.service ExecStartPost=/bin/systemctl start cln-backups.cymais.service
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@@ -1,6 +1,6 @@
backup_to_usb_script_path: /usr/local/sbin/svc-sys-bkp-data-to-usb.python backup_to_usb_script_path: /usr/local/sbin/bkp-data-to-usb.python
backup_to_usb_destination: '{{backup_to_usb_mount}}{{backup_to_usb_destination_subdirectory}}' backup_to_usb_destination: '{{backup_to_usb_mount}}{{backup_to_usb_destination_subdirectory}}'
backups_folder_path: '{{backup_to_usb_destination}}' backups_folder_path: '{{backup_to_usb_destination}}'
systemctl_mount_service_name: '{{ backup_to_usb_mount | trim(''/'') | replace(''/'', systemctl_mount_service_name: '{{ backup_to_usb_mount | trim(''/'') | replace(''/'',
''-'') }}.mount' ''-'') }}.mount'
application_id: svc-sys-bkp-data-to-usb application_id: data-to-usb

View File

@@ -2,7 +2,7 @@
## Description ## Description
This Ansible role installs the [directory-validator](https://github.com/kevinveenbirkenbach/directory-validator.git). It is used by the sys-bkp-docker-to-local and sys-cln-faild-bkps roles to verify whether backups have been successfully created. This Ansible role installs the [directory-validator](https://github.com/kevinveenbirkenbach/directory-validator.git). It is used by the bkp-docker-to-local and cln-failed-docker-backups roles to verify whether backups have been successfully created.
## Overview ## Overview
@@ -16,5 +16,5 @@ The primary purpose of this role is to validate backup directories. By fetching
- **Git Repository Pull:** Automatically pulls the latest version of the directory-validator from Git. - **Git Repository Pull:** Automatically pulls the latest version of the directory-validator from Git.
- **Idempotent Execution:** Ensures that the repository is fetched only once per playbook run. - **Idempotent Execution:** Ensures that the repository is fetched only once per playbook run.
- **Backup Verification:** Serves as a validation step for other sys-bkp-related roles. - **Backup Verification:** Serves as a validation step for other bkp-related roles.
- **Configurable Destination:** The target folder is customizable via the `backup_directory_validator_folder` variable. - **Configurable Destination:** The target folder is customizable via the `backup_directory_validator_folder` variable.

View File

@@ -0,0 +1,2 @@
backup_directory_validator_folder: '{{path_administrator_scripts}}directory-validator/'
application_id: directory-validator

View File

@@ -2,16 +2,16 @@
## Description ## Description
This Ansible role automates the process of backing up Docker volumes to a local folder. It pulls the [sys-bkp-docker-to-local repository](https://github.com/kevinveenbirkenbach/sys-bkp-docker-to-local.git), installs required software, configures systemd services for both standard and "everything" backup modes, and seeds backup database entries as needed. This Ansible role automates the process of backing up Docker volumes to a local folder. It pulls the [bkp-docker-to-local repository](https://github.com/kevinveenbirkenbach/bkp-docker-to-local.git), installs required software, configures systemd services for both standard and "everything" backup modes, and seeds backup database entries as needed.
## Overview ## Overview
Optimized for Archlinux, this role ensures that Docker volume backups are performed reliably with minimal manual intervention. It integrates with several dependent roles to verify backup success and manage related tasks, including: Optimized for Archlinux, this role ensures that Docker volume backups are performed reliably with minimal manual intervention. It integrates with several dependent roles to verify backup success and manage related tasks, including:
- [sys-bkp-directory-validator](../sys-bkp-directory-validator/) Validates backup directories. - [bkp-directory-validator](../bkp-directory-validator/) Validates backup directories.
- [sys-cln-faild-bkps](../sys-cln-faild-bkps/) Cleans up unsuccessful backup attempts. - [cln-failed-docker-backups](../cln-failed-docker-backups/) Cleans up unsuccessful backup attempts.
- [sys-timer](../sys-timer/) Schedules recurring backup tasks. - [gen-timer](../gen-timer/) Schedules recurring backup tasks.
- [sys-bkp-provider](../sys-bkp-provider/) Manages backup sources. - [bkp-provider](../bkp-provider/) Manages backup sources.
- [sys-lock](../sys-lock/) Ensures coordinated maintenance operations. - [maint-lock](../maint-lock/) Ensures coordinated maintenance operations.
## Purpose ## Purpose
@@ -20,7 +20,7 @@ Backup Docker Volumes to Local is a comprehensive solution that leverages rsync
## Features ## Features
- **Required Software Installation:** Installs necessary packages (e.g., lsof, python-pandas) via pacman. - **Required Software Installation:** Installs necessary packages (e.g., lsof, python-pandas) via pacman.
- **Git Repository Pull:** Automatically pulls the latest version of the [sys-bkp-docker-to-local repository](https://github.com/kevinveenbirkenbach/sys-bkp-docker-to-local.git). - **Git Repository Pull:** Automatically pulls the latest version of the [bkp-docker-to-local repository](https://github.com/kevinveenbirkenbach/bkp-docker-to-local.git).
- **Systemd Service Configuration:** Deploys and reloads two systemd service templates to manage backup tasks. - **Systemd Service Configuration:** Deploys and reloads two systemd service templates to manage backup tasks.
- **Database Seeding:** Includes tasks to seed and manage a backup database (`databases.csv`) for tracking backup details. - **Database Seeding:** Includes tasks to seed and manage a backup database (`databases.csv`) for tracking backup details.
- **Dependency Integration:** Works in conjunction with the dependent roles listed above to verify and manage backups. - **Dependency Integration:** Works in conjunction with the dependent roles listed above to verify and manage backups.

View File

@@ -0,0 +1,9 @@
- name: "reload bkp-docker-to-local-everything.cymais.service"
systemd:
name: bkp-docker-to-local-everything.cymais.service
daemon_reload: yes
- name: "reload bkp-docker-to-local.cymais.service"
systemd:
name: bkp-docker-to-local.cymais.service
daemon_reload: yes

View File

@@ -23,8 +23,8 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-bkp-provider - bkp-provider
- sys-alm-compose - alert-compose
- sys-cln-faild-bkps - cln-failed-docker-backups
- sys-lock - maint-lock
- sys-bkp-directory-validator - bkp-directory-validator

View File

@@ -21,18 +21,18 @@
include_tasks: reset.yml include_tasks: reset.yml
when: mode_reset | bool and run_once_bkp_docker_to_local is not defined when: mode_reset | bool and run_once_bkp_docker_to_local is not defined
- name: configure sys-bkp-docker-to-local-everything.cymais.service - name: configure bkp-docker-to-local-everything.cymais.service
template: template:
src: sys-bkp-docker-to-local-everything.service.j2 src: bkp-docker-to-local-everything.service.j2
dest: /etc/systemd/system/sys-bkp-docker-to-local-everything.cymais.service dest: /etc/systemd/system/bkp-docker-to-local-everything.cymais.service
notify: reload sys-bkp-docker-to-local-everything.cymais.service notify: reload bkp-docker-to-local-everything.cymais.service
when: run_once_bkp_docker_to_local is not defined when: run_once_bkp_docker_to_local is not defined
- name: configure sys-bkp-docker-to-local.cymais.service - name: configure bkp-docker-to-local.cymais.service
template: template:
src: sys-bkp-docker-to-local.service.j2 src: bkp-docker-to-local.service.j2
dest: /etc/systemd/system/sys-bkp-docker-to-local.cymais.service dest: /etc/systemd/system/bkp-docker-to-local.cymais.service
notify: reload sys-bkp-docker-to-local.cymais.service notify: reload bkp-docker-to-local.cymais.service
when: run_once_bkp_docker_to_local is not defined when: run_once_bkp_docker_to_local is not defined
- name: "set 'service_name' to '{{ role_name }}'" - name: "set 'service_name' to '{{ role_name }}'"
@@ -40,9 +40,9 @@
service_name: "{{ role_name }}" service_name: "{{ role_name }}"
when: run_once_bkp_docker_to_local is not defined when: run_once_bkp_docker_to_local is not defined
- name: "include role for sys-timer for {{service_name}}" - name: "include role for gen-timer for {{service_name}}"
include_role: include_role:
name: sys-timer name: gen-timer
vars: vars:
on_calendar: "{{on_calendar_backup_docker_to_local}}" on_calendar: "{{on_calendar_backup_docker_to_local}}"
when: run_once_bkp_docker_to_local is not defined when: run_once_bkp_docker_to_local is not defined

View File

@@ -1,9 +1,9 @@
[Unit] [Unit]
Description=backup docker volumes to local folder Description=backup docker volumes to local folder
OnFailure=sys-alm-compose.cymais@%n.service sys-cln-faild-bkps.cymais.service OnFailure=alert-compose.cymais@%n.service cln-failed-docker-backups.cymais.service
[Service] [Service]
Type=oneshot Type=oneshot
ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{ system_maintenance_backup_services | reject('equalto', 'sys-bkp-docker-to-local') | join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"' ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{ system_maintenance_backup_services | reject('equalto', 'bkp-docker-to-local') | join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"'
ExecStart=/bin/sh -c '/usr/bin/python {{backup_docker_to_local_folder}}backup-docker-to-local.py --compose-dir {{path_docker_compose_instances}} --everything' ExecStart=/bin/sh -c '/usr/bin/python {{backup_docker_to_local_folder}}backup-docker-to-local.py --compose-dir {{path_docker_compose_instances}} --everything'
ExecStartPost=/bin/sh -c '/bin/systemctl start sys-rpr-docker-soft.cymais.service &' ExecStartPost=/bin/sh -c '/bin/systemctl start maint-docker-heal.cymais.service &'

View File

@@ -1,9 +1,9 @@
[Unit] [Unit]
Description=backup docker volumes to local folder Description=backup docker volumes to local folder
OnFailure=sys-alm-compose.cymais@%n.service sys-cln-faild-bkps.cymais.service OnFailure=alert-compose.cymais@%n.service cln-failed-docker-backups.cymais.service
[Service] [Service]
Type=oneshot Type=oneshot
ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{ system_maintenance_backup_services | reject('equalto', 'sys-bkp-docker-to-local-everything') | join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"' ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{ system_maintenance_backup_services | reject('equalto', 'bkp-docker-to-local-everything') | join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"'
ExecStart=/bin/sh -c '/usr/bin/python {{backup_docker_to_local_folder}}backup-docker-to-local.py --compose-dir {{path_docker_compose_instances}}' ExecStart=/bin/sh -c '/usr/bin/python {{backup_docker_to_local_folder}}backup-docker-to-local.py --compose-dir {{path_docker_compose_instances}}'
ExecStartPost=/bin/sh -c '/bin/systemctl start sys-rpr-docker-soft.cymais.service &' ExecStartPost=/bin/sh -c '/bin/systemctl start maint-docker-heal.cymais.service &'

View File

@@ -1,2 +1,2 @@
bkp_docker_to_local_pkg: backup-docker-to-local bkp_docker_to_local_pkg: backup-docker-to-local
application_id: docker-to-local

View File

@@ -12,8 +12,8 @@ hashed_machine_id="$($get_hashed_machine_id | head -c 64)"
get_backup_types="find /Backups/$hashed_machine_id/ -maxdepth 1 -type d -execdir basename {} ;"; get_backup_types="find /Backups/$hashed_machine_id/ -maxdepth 1 -type d -execdir basename {} ;";
# @todo This configuration is not scalable yet. If other backup services then sys-bkp-docker-to-local are integrated, this logic needs to be optimized # @todo This configuration is not scalable yet. If other backup services then bkp-docker-to-local are integrated, this logic needs to be optimized
get_version_directories="ls -d /Backups/$hashed_machine_id/sys-bkp-docker-to-local/*" get_version_directories="ls -d /Backups/$hashed_machine_id/bkp-docker-to-local/*"
last_version_directory="$($get_version_directories | tail -1)" last_version_directory="$($get_version_directories | tail -1)"
rsync_command="sudo rsync --server --sender -blogDtpre.iLsfxCIvu . $last_version_directory/" rsync_command="sudo rsync --server --sender -blogDtpre.iLsfxCIvu . $last_version_directory/"

View File

@@ -23,4 +23,4 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-svc-sshd - core-sshd

View File

@@ -1,3 +1,3 @@
authorized_keys_path: '{{ inventory_dir }}/files/{{ inventory_hostname }}/home/backup/.ssh/authorized_keys' authorized_keys_path: '{{ inventory_dir }}/files/{{ inventory_hostname }}/home/backup/.ssh/authorized_keys'
authorized_keys_list: '{{ lookup(''file'', authorized_keys_path).splitlines() }}' authorized_keys_list: '{{ lookup(''file'', authorized_keys_path).splitlines() }}'
application_id: provider-user

View File

@@ -8,7 +8,7 @@ This role sets up and manages the host as a backup provider. It establishes the
Optimized for automated backup processes, this role: Optimized for automated backup processes, this role:
- Configures the host to provide backup services. - Configures the host to provide backup services.
- Integrates seamlessly with the [sys-bkp-provider-user](../sys-bkp-provider-user/README.md) and [sys-cln-bkps-timer](../sys-cln-bkps-timer/README.md) roles. - Integrates seamlessly with the [bkp-provider-user](../bkp-provider-user/README.md) and [cln-backups-timer](../cln-backups-timer/README.md) roles.
- Lays the foundation for secure and extensible backup operations. - Lays the foundation for secure and extensible backup operations.
## Purpose ## Purpose

View File

@@ -23,5 +23,5 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-bkp-provider-user - bkp-provider-user
- sys-cln-bkps-timer - cln-backups-timer

View File

@@ -0,0 +1 @@
application_id: provider

View File

@@ -9,17 +9,17 @@ To track what the service is doing, execute one of the following commands:
#### Using systemctl #### Using systemctl
```bash ```bash
watch -n2 "systemctl status sys-bkp-remote-to-local.cymais.service" watch -n2 "systemctl status bkp-remote-to-local.cymais.service"
``` ```
#### Using journalctl #### Using journalctl
```bash ```bash
journalctl -fu sys-bkp-remote-to-local.cymais.service journalctl -fu bkp-remote-to-local.cymais.service
``` ```
### Viewing History ### Viewing History
```bash ```bash
sudo journalctl -u sys-bkp-remote-to-local.cymais.service sudo journalctl -u bkp-remote-to-local.cymais.service
``` ```

View File

@@ -17,7 +17,7 @@ Backup Remote to Local is a robust solution for retrieving backup data from remo
- **Remote Backup Retrieval:** Pulls backups from a remote server using secure SSH connections. - **Remote Backup Retrieval:** Pulls backups from a remote server using secure SSH connections.
- **Incremental Backup with rsync:** Uses rsync with options for archive, backup, and hard linking to efficiently manage changes. - **Incremental Backup with rsync:** Uses rsync with options for archive, backup, and hard linking to efficiently manage changes.
- **Retry Logic:** Implements a retry mechanism to handle transient network issues or remote errors. - **Retry Logic:** Implements a retry mechanism to handle transient network issues or remote errors.
- **Integration with Other Roles:** Works alongside roles like sys-bkp-directory-validator, sys-cln-faild-bkps, sys-timer, sys-bkp-provider, and sys-lock. - **Integration with Other Roles:** Works alongside roles like bkp-directory-validator, cln-failed-docker-backups, gen-timer, bkp-provider, and maint-lock.
- **Administrative Debugging:** Detailed debug instructions and administrative tasks are provided in a separate file. - **Administrative Debugging:** Detailed debug instructions and administrative tasks are provided in a separate file.
## Other Resources ## Other Resources

View File

@@ -0,0 +1,4 @@
- name: "reload bkp-remote-to-local service"
systemd:
name: bkp-remote-to-local.cymais.service
daemon_reload: yes

View File

@@ -26,9 +26,9 @@ galaxy_info:
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- gen-git - gen-git
- sys-alm-compose - alert-compose
- sys-cln-bkps-timer - cln-backups-timer
- sys-cln-faild-bkps - cln-failed-docker-backups
- sys-lock - maint-lock
- user-root - user-root
- sys-rst-daemon - core-daemon

View File

@@ -4,17 +4,17 @@
state: directory state: directory
mode: 0755 mode: 0755
- name: create svc-sys-bkp-rmt-2-loc.sh - name: create bkp-remote-to-local.sh
copy: copy:
src: svc-sys-bkp-rmt-2-loc.sh src: bkp-remote-to-local.sh
dest: "{{docker_backup_remote_to_local_folder}}svc-sys-bkp-rmt-2-loc.sh" dest: "{{docker_backup_remote_to_local_folder}}bkp-remote-to-local.sh"
mode: 0755 mode: 0755
- name: create svc-sys-bkp-rmt-2-loc.cymais.service - name: create bkp-remote-to-local.cymais.service
template: template:
src: svc-sys-bkp-rmt-2-loc.service.j2 src: bkp-remote-to-local.service.j2
dest: /etc/systemd/system/svc-sys-bkp-rmt-2-loc.cymais.service dest: /etc/systemd/system/bkp-remote-to-local.cymais.service
notify: reload svc-sys-bkp-rmt-2-loc service notify: reload bkp-remote-to-local service
- name: create backups-remote-to-local.sh - name: create backups-remote-to-local.sh
template: template:
@@ -26,9 +26,9 @@
set_fact: set_fact:
service_name: "{{ role_name }}" service_name: "{{ role_name }}"
- name: "include role for sys-timer for {{service_name}}" - name: "include role for gen-timer for {{service_name}}"
include_role: include_role:
name: sys-timer name: gen-timer
vars: vars:
on_calendar: "{{on_calendar_backup_remote_to_local}}" on_calendar: "{{on_calendar_backup_remote_to_local}}"

View File

@@ -3,6 +3,6 @@
hosts="{{ pull_remote_backups | join(' ') }}"; hosts="{{ pull_remote_backups | join(' ') }}";
errors=0 errors=0
for host in $hosts; do for host in $hosts; do
bash {{ docker_backup_remote_to_local_folder }}svc-sys-bkp-rmt-2-loc.sh $host || ((errors+=1)); bash {{ docker_backup_remote_to_local_folder }}bkp-remote-to-local.sh $host || ((errors+=1));
done; done;
exit $errors; exit $errors;

View File

@@ -1,6 +1,6 @@
[Unit] [Unit]
Description=pull remote backups Description=pull remote backups
OnFailure=sys-alm-compose.cymais@%n.service sys-cln-faild-bkps.cymais.service OnFailure=alert-compose.cymais@%n.service cln-failed-docker-backups.cymais.service
[Service] [Service]
Type=oneshot Type=oneshot

View File

@@ -0,0 +1,2 @@
docker_backup_remote_to_local_folder: '{{path_administrator_scripts}}bkp-remote-to-local/'
application_id: bkp-remote-to-local

View File

@@ -1,42 +1,14 @@
roles: roles:
sys: core:
title: "System" title: "Core & System"
invokable: false description: "Fundamental system configuration"
alm: icon: "fas fa-cogs"
title: "Alerting" invokable: true
description: "Notification handlers for system events"
icon: "fas fa-bell"
invokable: false
cln:
title: "Cleanup"
description: "Roles for cleaning up various system resources—old backups, unused certificates, temporary files, Docker volumes, disk caches, deprecated domains, and more."
icon: "fas fa-trash-alt"
invokable: false
hlth:
title: "Monitoring"
description: "Roles for system monitoring and health checks—encompassing bot-style automated checks and core low-level monitors for logs, containers, disk usage, and more."
icon: "fas fa-chart-area"
invokable: false
bkp:
title: "Backup & Restore"
description: "Backup strategies & restore procedures"
icon: "fas fa-hdd"
invokable: false
update:
title: "Updates & Package Management"
description: "OS & package updates"
icon: "fas fa-sync"
invokable: false
drv: drv:
title: "Drivers" title: "Drivers"
description: "Roles for installing and configuring hardware drivers—covering printers, graphics, input devices, and other peripheral support." description: "Roles for installing and configuring hardware drivers—covering printers, graphics, input devices, and other peripheral support."
icon: "fas fa-microchip" icon: "fas fa-microchip"
invokable: true invokable: true
# core:
# title: "Core & System"
# description: "Fundamental system configuration"
# icon: "fas fa-cogs"
# invokable: true
gen: gen:
title: "Generic" title: "Generic"
description: "Helper roles & installers (git, locales, timer, etc.)" description: "Helper roles & installers (git, locales, timer, etc.)"
@@ -101,8 +73,38 @@ roles:
description: "Docker infrastructure services (DBMS, LDAP, Redis, etc.)" description: "Docker infrastructure services (DBMS, LDAP, Redis, etc.)"
icon: "fas fa-database" icon: "fas fa-database"
invokable: true invokable: true
mon:
title: "Monitoring"
description: "Roles for system monitoring and health checks—encompassing bot-style automated checks and core low-level monitors for logs, containers, disk usage, and more."
icon: "fas fa-chart-area"
invokable: true
alert:
title: "Alerting"
description: "Notification handlers for system events"
icon: "fas fa-bell"
invokable: true
maint:
title: "Maintenance & Healing"
description: "Periodic maintenance & auto-recovery"
icon: "fas fa-tools"
invokable: true
bkp:
title: "Backup & Restore"
description: "Backup strategies & restore procedures"
icon: "fas fa-hdd"
invokable: true
update:
title: "Updates & Package Management"
description: "OS & package updates"
icon: "fas fa-sync"
invokable: true
user: user:
title: "Users & Access" title: "Users & Access"
description: "User accounts & access control" description: "User accounts & access control"
icon: "fas fa-users" icon: "fas fa-users"
invokable: false invokable: false
cln:
title: "Cleanup"
description: "Roles for cleaning up various system resources—old backups, unused certificates, temporary files, Docker volumes, disk caches, deprecated domains, and more."
icon: "fas fa-trash-alt"
invokable: true

View File

@@ -10,7 +10,7 @@ Optimized for effective disk space management, this role:
- Installs required packages (e.g. [lsof](https://en.wikipedia.org/wiki/Lsof) and [psutil](https://pypi.org/project/psutil/)) using pacman. - Installs required packages (e.g. [lsof](https://en.wikipedia.org/wiki/Lsof) and [psutil](https://pypi.org/project/psutil/)) using pacman.
- Creates a directory for storing cleanup scripts. - Creates a directory for storing cleanup scripts.
- Deploys a Python script that deletes old backup directories when disk usage is too high. - Deploys a Python script that deletes old backup directories when disk usage is too high.
- Configures a systemd service to run the cleanup script, with notifications via [sys-alm-compose](../sys-alm-compose/README.md). - Configures a systemd service to run the cleanup script, with notifications via [alert-compose](../alert-compose/README.md).
## Purpose ## Purpose

View File

@@ -0,0 +1,5 @@
- name: "reload cln-backups.cymais.service"
systemd:
name: cln-backups.cymais.service
enabled: yes
daemon_reload: yes

View File

@@ -23,6 +23,6 @@ galaxy_info:
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- gen-python-pip - gen-python-pip
- sys-alm-compose - alert-compose
- sys-lock - maint-lock
- sys-rst-daemon - core-daemon

View File

@@ -13,17 +13,17 @@
mode: 0755 mode: 0755
when: run_once_cleanup_backups_service is not defined when: run_once_cleanup_backups_service is not defined
- name: create sys-cln-backups.py - name: create cln-backups.py
copy: copy:
src: "sys-cln-backups.py" src: "cln-backups.py"
dest: "{{cleanup_backups_directory}}sys-cln-backups.py" dest: "{{cleanup_backups_directory}}cln-backups.py"
when: run_once_cleanup_backups_service is not defined when: run_once_cleanup_backups_service is not defined
- name: create sys-cln-backups.cymais.service - name: create cln-backups.cymais.service
template: template:
src: "sys-cln-backups.service.j2" src: "cln-backups.service.j2"
dest: "/etc/systemd/system/sys-cln-backups.cymais.service" dest: "/etc/systemd/system/cln-backups.cymais.service"
notify: reload sys-cln-backups.cymais.service notify: reload cln-backups.cymais.service
when: run_once_cleanup_backups_service is not defined when: run_once_cleanup_backups_service is not defined
- name: run the cleanup_backups_service tasks once - name: run the cleanup_backups_service tasks once

View File

@@ -1,8 +1,8 @@
[Unit] [Unit]
Description=delete old backups Description=delete old backups
OnFailure=sys-alm-compose.cymais@%n.service OnFailure=alert-compose.cymais@%n.service
[Service] [Service]
Type=oneshot Type=oneshot
ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{system_maintenance_cleanup_services| join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"' ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{system_maintenance_cleanup_services| join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"'
ExecStart=/bin/sh -c '/usr/bin/python {{cleanup_backups_directory}}sys-cln-backups.py --backups-folder-path {{backups_folder_path}} --maximum-backup-size-percent {{size_percent_maximum_backup}}' ExecStart=/bin/sh -c '/usr/bin/python {{cleanup_backups_directory}}cln-backups.py --backups-folder-path {{backups_folder_path}} --maximum-backup-size-percent {{size_percent_maximum_backup}}'

View File

@@ -0,0 +1,2 @@
cleanup_backups_directory: '{{path_administrator_scripts}}cln-backups/'
application_id: backups-service

View File

@@ -2,13 +2,13 @@
## Description ## Description
This role sets up a systemd timer to schedule the periodic cleanup of old backups. It leverages the sys-cln-bkps-service role to perform the actual cleanup operation. This role sets up a systemd timer to schedule the periodic cleanup of old backups. It leverages the cln-backups-service role to perform the actual cleanup operation.
## Overview ## Overview
Optimized for automated maintenance, this role: Optimized for automated maintenance, this role:
- Sets a fact for the service name. - Sets a fact for the service name.
- Integrates with the [sys-timer](../sys-timer/README.md) role to schedule sys-cln-backups tasks at defined intervals. - Integrates with the [gen-timer](../gen-timer/README.md) role to schedule cln-backups tasks at defined intervals.
## Purpose ## Purpose
@@ -17,5 +17,5 @@ The primary purpose of this role is to automate the scheduling of backup cleanup
## Features ## Features
- **Timer Scheduling:** Configures a systemd timer to trigger the backup cleanup service. - **Timer Scheduling:** Configures a systemd timer to trigger the backup cleanup service.
- **Role Integration:** Works in conjunction with the sys-cln-bkps-service role. - **Role Integration:** Works in conjunction with the cln-backups-service role.
- **Idempotency:** Ensures the timer tasks execute only once per playbook run. - **Idempotency:** Ensures the timer tasks execute only once per playbook run.

View File

@@ -1,7 +1,7 @@
--- ---
galaxy_info: galaxy_info:
author: "Kevin Veen-Birkenbach" author: "Kevin Veen-Birkenbach"
description: "Schedules periodic cleanup of old backups by configuring a systemd timer to trigger the sys-cln-bkps-service role." description: "Schedules periodic cleanup of old backups by configuring a systemd timer to trigger the cln-backups-service role."
license: "CyMaIS NonCommercial License (CNCL)" license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl" license_url: "https://s.veen.world/cncl"
company: | company: |
@@ -22,5 +22,5 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-cln-bkps-service - cln-backups-service
- sys-rst-daemon - core-daemon

View File

@@ -1,11 +1,11 @@
- name: set service_name to sys-cln-backups - name: set service_name to cln-backups
set_fact: set_fact:
service_name: "sys-cln-backups" service_name: "cln-backups"
when: run_once_cleanup_backups_timer is not defined when: run_once_cleanup_backups_timer is not defined
- name: "include role for sys-timer for {{service_name}}" - name: "include role for gen-timer for {{service_name}}"
include_role: include_role:
name: sys-timer name: gen-timer
vars: vars:
on_calendar: "{{on_calendar_cleanup_backups}}" on_calendar: "{{on_calendar_cleanup_backups}}"
when: run_once_cleanup_backups_timer is not defined when: run_once_cleanup_backups_timer is not defined

View File

@@ -0,0 +1 @@
application_id: backups-timer

View File

@@ -7,9 +7,9 @@ This Ansible role automates the detection, revocation and deletion of unused Let
## Overview ## Overview
- Installs the `certreap` cleanup tool using the `pkgmgr-install` role - Installs the `certreap` cleanup tool using the `pkgmgr-install` role
- Deploys and configures a `sys-cln-certs.cymais.service` systemd unit - Deploys and configures a `cln-certs.cymais.service` systemd unit
- (Optionally) Sets up a recurring cleanup via a systemd timer using the `sys-timer` role - (Optionally) Sets up a recurring cleanup via a systemd timer using the `gen-timer` role
- Integrates with `sys-alm-compose` to send failure notifications - Integrates with `alert-compose` to send failure notifications
- Ensures idempotent execution with a `run_once_cleanup_certs` flag - Ensures idempotent execution with a `run_once_cleanup_certs` flag
## Features ## Features
@@ -18,16 +18,16 @@ This Ansible role automates the detection, revocation and deletion of unused Let
Uses `pkgmgr-install` to install the `certreap` binary. Uses `pkgmgr-install` to install the `certreap` binary.
- **Systemd Service Configuration** - **Systemd Service Configuration**
Deploys `sys-cln-certs.cymais.service` and reloads/restarts it on changes. Deploys `cln-certs.cymais.service` and reloads/restarts it on changes.
- **Systemd Timer Scheduling** - **Systemd Timer Scheduling**
Optionally wires in a timer via the `sys-timer` role, controlled by the `on_calendar_cleanup_certs` variable. Optionally wires in a timer via the `gen-timer` role, controlled by the `on_calendar_cleanup_certs` variable.
- **Smart Execution Logic** - **Smart Execution Logic**
Prevents multiple runs in one play by setting a `run_once_cleanup_certs` fact. Prevents multiple runs in one play by setting a `run_once_cleanup_certs` fact.
- **Failure Notification** - **Failure Notification**
Triggers `sys-alm-compose.cymais@sys-cln-certs.cymais.service` on failure. Triggers `alert-compose.cymais@cln-certs.cymais.service` on failure.
## Further Resources ## Further Resources

View File

@@ -0,0 +1,6 @@
- name: "Reload and restart cln-certs.cymais.service"
systemd:
name: cln-certs.cymais.service
enabled: yes
daemon_reload: yes
state: restarted

View File

@@ -24,5 +24,5 @@ galaxy_info:
documentation: "https://github.com/kevinveenbirkenbach/certreap#readme" documentation: "https://github.com/kevinveenbirkenbach/certreap#readme"
dependencies: dependencies:
- sys-alm-compose - alert-compose
- sys-rst-daemon - core-daemon

View File

@@ -5,11 +5,11 @@
package_name: certreap package_name: certreap
when: run_once_cleanup_certs is not defined when: run_once_cleanup_certs is not defined
- name: configure sys-cln-certs.cymais.service - name: configure cln-certs.cymais.service
template: template:
src: sys-cln-certs.service.j2 src: cln-certs.service.j2
dest: /etc/systemd/system/sys-cln-certs.cymais.service dest: /etc/systemd/system/cln-certs.cymais.service
notify: Reload and restart sys-cln-certs.cymais.service notify: Reload and restart cln-certs.cymais.service
when: run_once_cleanup_certs is not defined when: run_once_cleanup_certs is not defined
- name: "set 'service_name' to '{{ role_name }}'" - name: "set 'service_name' to '{{ role_name }}'"
@@ -17,9 +17,9 @@
service_name: "{{ role_name }}" service_name: "{{ role_name }}"
when: run_once_cleanup_certs is not defined when: run_once_cleanup_certs is not defined
- name: "include role for sys-timer for {{service_name}}" - name: "include role for gen-timer for {{service_name}}"
include_role: include_role:
name: sys-timer name: gen-timer
vars: vars:
on_calendar: "{{ on_calendar_cleanup_certs }}" on_calendar: "{{ on_calendar_cleanup_certs }}"
when: run_once_cleanup_certs is not defined when: run_once_cleanup_certs is not defined

View File

@@ -1,6 +1,6 @@
[Unit] [Unit]
Description=Detect, revoke, and delete unused Let's Encrypt certificates based on active NGINX configuration files. Description=Detect, revoke, and delete unused Let's Encrypt certificates based on active NGINX configuration files.
OnFailure=sys-alm-compose.cymais@%n.service OnFailure=alert-compose.cymais@%n.service
[Service] [Service]
Type=oneshot Type=oneshot

View File

@@ -0,0 +1 @@
application_id: certs

View File

@@ -0,0 +1,5 @@
- name: "reload cln-disc-space.cymais.service"
systemd:
name: cln-disc-space.cymais.service
enabled: yes
daemon_reload: yes

View File

@@ -22,6 +22,6 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- sys-alm-compose - alert-compose
- sys-lock - maint-lock
- sys-rst-daemon - core-daemon

View File

@@ -0,0 +1,26 @@
- name: "create {{cleanup_disc_space_folder}}"
file:
path: "{{cleanup_disc_space_folder}}"
state: directory
mode: 0755
- name: create cln-disc-space.sh
template:
src: cln-disc-space.sh.j2
dest: "{{cleanup_disc_space_folder}}cln-disc-space.sh"
- name: create cln-disc-space.cymais.service
template:
src: cln-disc-space.service.j2
dest: /etc/systemd/system/cln-disc-space.cymais.service
notify: reload cln-disc-space.cymais.service
- name: "set 'service_name' to '{{ role_name }}'"
set_fact:
service_name: "{{ role_name }}"
- name: "include role for gen-timer for {{service_name}}"
include_role:
name: gen-timer
vars:
on_calendar: "{{on_calendar_cleanup_disc_space}}"

View File

@@ -1,8 +1,8 @@
[Unit] [Unit]
Description=freeing disc space Description=freeing disc space
OnFailure=sys-alm-compose.cymais@%n.service OnFailure=alert-compose.cymais@%n.service
[Service] [Service]
Type=oneshot Type=oneshot
ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{system_maintenance_cleanup_services| join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"' ExecStartPre=/bin/sh -c '/usr/bin/python {{ path_system_lock_script }} {{ system_maintenance_services | join(' ') }} --ignore {{system_maintenance_cleanup_services| join(' ') }} --timeout "{{system_maintenance_lock_timeout_backup_services}}"'
ExecStart=/bin/sh -c '/bin/bash {{cleanup_disc_space_folder}}sys-cln-disc-space.sh {{size_percent_cleanup_disc_space}}' ExecStart=/bin/sh -c '/bin/bash {{cleanup_disc_space_folder}}cln-disc-space.sh {{size_percent_cleanup_disc_space}}'

View File

@@ -24,7 +24,7 @@ if [ "$force_freeing" = true ]; then
{% if backups_folder_path is defined and size_percent_maximum_backup is defined %} {% if backups_folder_path is defined and size_percent_maximum_backup is defined %}
echo "cleaning up backups" && echo "cleaning up backups" &&
python {{path_administrator_scripts}}sys-cln-backups/sys-cln-backups.py --backups-folder-path {{backups_folder_path}} --maximum-backup-size-percent {{size_percent_maximum_backup}} || exit 2 python {{path_administrator_scripts}}cln-backups/cln-backups.py --backups-folder-path {{backups_folder_path}} --maximum-backup-size-percent {{size_percent_maximum_backup}} || exit 2
{% endif %} {% endif %}
if pacman -Qs $package > /dev/null ; then if pacman -Qs $package > /dev/null ; then

View File

@@ -0,0 +1,2 @@
cleanup_disc_space_folder: '{{path_administrator_scripts}}cln-disc-space/'
application_id: disc-space

View File

@@ -24,4 +24,4 @@ galaxy_info:
issue_tracker_url: "https://github.com/kevinveenbirkenbach/web-app-volume-cleaner/issues" issue_tracker_url: "https://github.com/kevinveenbirkenbach/web-app-volume-cleaner/issues"
documentation: "https://github.com/kevinveenbirkenbach/web-app-volume-cleaner" documentation: "https://github.com/kevinveenbirkenbach/web-app-volume-cleaner"
dependencies: dependencies:
- sys-rst-daemon - core-daemon

View File

@@ -0,0 +1 @@
application_id: docker-anonymous-volumes

Some files were not shown because too many files have changed in this diff Show More