فهرست منبع

Merge release/v0.1.3 into main

xcad 1 ماه پیش
والد
کامیت
b95e89438e
100فایلهای تغییر یافته به همراه3925 افزوده شده و 3640 حذف شده
  1. 8 0
      CHANGELOG.md
  2. 1 1
      cli/__init__.py
  3. 1 3
      cli/core/display/display_table.py
  4. 0 4
      cli/core/display/display_template.py
  5. 16 0
      cli/core/exceptions.py
  6. 22 11
      cli/core/library.py
  7. 51 11
      cli/core/module/base_commands.py
  8. 0 6
      cli/core/module/base_module.py
  9. 0 17
      cli/core/schema/__init__.py
  10. 0 15
      cli/core/schema/ansible/v1.0.json
  11. 0 229
      cli/core/schema/compose/v1.0.json
  12. 0 312
      cli/core/schema/compose/v1.1.json
  13. 0 528
      cli/core/schema/compose/v1.2.json
  14. 0 202
      cli/core/schema/helm/v1.0.json
  15. 0 247
      cli/core/schema/kubernetes/v1.0.json
  16. 0 220
      cli/core/schema/loader.py
  17. 0 14
      cli/core/schema/packer/v1.0.json
  18. 0 87
      cli/core/schema/terraform/v1.0.json
  19. 12 1
      cli/core/template/__init__.py
  20. 57 136
      cli/core/template/template.py
  21. 3 1
      cli/core/template/variable_collection.py
  22. 1 71
      cli/modules/ansible/__init__.py
  23. 1 71
      cli/modules/compose/__init__.py
  24. 1 70
      cli/modules/helm/__init__.py
  25. 1 71
      cli/modules/kubernetes/__init__.py
  26. 1 70
      cli/modules/packer/__init__.py
  27. 1 71
      cli/modules/terraform/__init__.py
  28. 7 1
      library/ansible/checkmk-install-agent/template.yaml
  29. 7 1
      library/ansible/checkmk-manage-host/template.yaml
  30. 5 1
      library/ansible/docker-certs-enable/template.yaml
  31. 5 1
      library/ansible/docker-certs/template.yaml
  32. 4 4
      library/ansible/docker-install-ubuntu/template.yaml
  33. 5 1
      library/ansible/docker-prune/template.yaml
  34. 5 1
      library/ansible/ubuntu-add-sshkey/template.yaml
  35. 1 1
      library/ansible/ubuntu-apt-update/template.yaml
  36. 5 1
      library/ansible/ubuntu-vm-core/template.yaml
  37. 135 21
      library/compose/adguardhome/template.yaml
  38. 1 1
      library/compose/alloy/config/config.alloy.j2
  39. 44 1
      library/compose/alloy/template.yaml
  40. 136 11
      library/compose/authentik/template.yaml
  41. 95 6
      library/compose/bind9/template.yaml
  42. 60 7
      library/compose/checkmk/template.yaml
  43. 41 4
      library/compose/dockge/template.yaml
  44. 78 8
      library/compose/gitea/template.yaml
  45. 10 1
      library/compose/gitlab-runner/template.yaml
  46. 0 2
      library/compose/gitlab/.env.j2
  47. 0 0
      library/compose/gitlab/.env.password.j2
  48. 0 0
      library/compose/gitlab/.env.registry.j2
  49. 6 130
      library/compose/gitlab/compose.yaml.j2
  50. 160 63
      library/compose/gitlab/template.yaml
  51. 87 7
      library/compose/grafana/template.yaml
  52. 123 5
      library/compose/homepage/template.yaml
  53. 136 40
      library/compose/homer/template.yaml
  54. 59 12
      library/compose/influxdb/template.yaml
  55. 216 34
      library/compose/komodo/template.yaml
  56. 40 5
      library/compose/loki/template.yaml
  57. 18 1
      library/compose/mariadb/template.yaml
  58. 154 86
      library/compose/n8n/template.yaml
  59. 92 7
      library/compose/netbox/template.yaml
  60. 93 17
      library/compose/nextcloud/template.yaml
  61. 37 18
      library/compose/nginx/template.yaml
  62. 58 6
      library/compose/openwebui/template.yaml
  63. 0 158
      library/compose/pangolin/compose.yaml.j2
  64. 0 117
      library/compose/pangolin/template.yaml
  65. 3 1
      library/compose/passbolt/template.yaml
  66. 142 13
      library/compose/pihole/template.yaml
  67. 96 5
      library/compose/portainer/template.yaml
  68. 57 15
      library/compose/postgres/template.yaml
  69. 61 30
      library/compose/prometheus/template.yaml
  70. 4 1
      library/compose/renovate/template.yaml
  71. 68 13
      library/compose/semaphoreui/template.yaml
  72. 122 25
      library/compose/traefik/template.yaml
  73. 67 9
      library/compose/twingate-connector/template.yaml
  74. 1 1
      library/compose/uptimekuma/template.yaml
  75. 65 0
      library/compose/whoami/template.yaml
  76. 86 3
      library/helm/authentik/template.yaml
  77. 48 3
      library/helm/certmanager/template.yaml
  78. 48 3
      library/helm/longhorn/template.yaml
  79. 97 1
      library/helm/netbox/template.yaml
  80. 63 1
      library/helm/portainer/template.yaml
  81. 48 3
      library/helm/traefik/template.yaml
  82. 47 1
      library/kubernetes/certmanager-certificate/template.yaml
  83. 51 1
      library/kubernetes/certmanager-clusterissuer/template.yaml
  84. 47 1
      library/kubernetes/certmanager-issuer/template.yaml
  85. 47 1
      library/kubernetes/core-configmap/template.yaml
  86. 43 1
      library/kubernetes/core-ingress/template.yaml
  87. 47 1
      library/kubernetes/core-ingressclass/template.yaml
  88. 47 1
      library/kubernetes/core-persistentvolume/template.yaml
  89. 47 1
      library/kubernetes/core-persistentvolumeclaim/template.yaml
  90. 47 1
      library/kubernetes/core-secret/template.yaml
  91. 47 1
      library/kubernetes/core-service/template.yaml
  92. 47 1
      library/kubernetes/core-serviceaccount/template.yaml
  93. 47 1
      library/kubernetes/core-storageclass/template.yaml
  94. 39 3
      library/kubernetes/traefik-ingressroute/template.yaml
  95. 46 3
      library/kubernetes/traefik-ingressroutetcp/template.yaml
  96. 47 1
      library/kubernetes/traefik-middleware/template.yaml
  97. 49 1
      library/kubernetes/twingate-connector/template.yaml
  98. 4 1
      library/packer/proxmox-iso-ubuntu/template.yaml
  99. 0 14
      library/schemas/ansible/v1.0.json
  100. 0 229
      library/schemas/compose/v1.0.json

+ 8 - 0
CHANGELOG.md

@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 
 ## [Unreleased]
 ## [Unreleased]
 
 
+## [0.1.3] - 2026-01-06
+
+### Added
+- Draft template visibility in list command (#1610) - Draft templates now shown with dimmed styling and status indicator instead of being hidden
+
+### Changed
+- Schema deprecation postponed (#1636) - Template-only variable definitions deferred to maintain backward compatibility and reduce migration complexity
+
 ## [0.1.2] - 2025-12-11
 ## [0.1.2] - 2025-12-11
 
 
 ### Fixed
 ### Fixed

+ 1 - 1
cli/__init__.py

@@ -2,6 +2,6 @@
 Boilerplates CLI - A sophisticated command-line tool for managing infrastructure boilerplates.
 Boilerplates CLI - A sophisticated command-line tool for managing infrastructure boilerplates.
 """
 """
 
 
-__version__ = "0.1.2"
+__version__ = "0.1.3"
 __author__ = "Christian Lempa"
 __author__ = "Christian Lempa"
 __description__ = "CLI tool for managing infrastructure boilerplates"
 __description__ = "CLI tool for managing infrastructure boilerplates"

+ 1 - 3
cli/core/display/display_table.py

@@ -92,7 +92,6 @@ class TableDisplay:
         table.add_column("Name")
         table.add_column("Name")
         table.add_column("Tags")
         table.add_column("Tags")
         table.add_column("Version", no_wrap=True)
         table.add_column("Version", no_wrap=True)
-        table.add_column("Schema", no_wrap=True)
         table.add_column("Library", no_wrap=True)
         table.add_column("Library", no_wrap=True)
 
 
         settings = self.settings
         settings = self.settings
@@ -102,7 +101,6 @@ class TableDisplay:
             tags_list = template.metadata.tags or []
             tags_list = template.metadata.tags or []
             tags = ", ".join(tags_list) if tags_list else "-"
             tags = ", ".join(tags_list) if tags_list else "-"
             version = str(template.metadata.version) if template.metadata.version else ""
             version = str(template.metadata.version) if template.metadata.version else ""
-            schema = template.schema_version if hasattr(template, "schema_version") else "1.0"
 
 
             # Format library with icon and color
             # Format library with icon and color
             library_name = template.metadata.library or ""
             library_name = template.metadata.library or ""
@@ -111,7 +109,7 @@ class TableDisplay:
             color = "yellow" if library_type == "static" else "blue"
             color = "yellow" if library_type == "static" else "blue"
             library_display = f"[{color}]{icon} {library_name}[/{color}]"
             library_display = f"[{color}]{icon} {library_name}[/{color}]"
 
 
-            table.add_row(template.id, name, tags, version, schema, library_display)
+            table.add_row(template.id, name, tags, version, library_display)
 
 
         self.base._print_table(table)
         self.base._print_table(table)
 
 

+ 0 - 4
cli/core/display/display_template.py

@@ -67,7 +67,6 @@ class TemplateDisplay:
 
 
         template_name = template.metadata.name or settings.TEXT_UNNAMED_TEMPLATE
         template_name = template.metadata.name or settings.TEXT_UNNAMED_TEMPLATE
         version = str(template.metadata.version) if template.metadata.version else settings.TEXT_VERSION_NOT_SPECIFIED
         version = str(template.metadata.version) if template.metadata.version else settings.TEXT_VERSION_NOT_SPECIFIED
-        schema = template.schema_version if hasattr(template, "schema_version") else "1.0"
         description = template.metadata.description or settings.TEXT_NO_DESCRIPTION
         description = template.metadata.description or settings.TEXT_NO_DESCRIPTION
 
 
         # Get library information and format with icon/color
         # Get library information and format with icon/color
@@ -88,9 +87,6 @@ class TemplateDisplay:
         header_content.append("version:", style="white")
         header_content.append("version:", style="white")
         header_content.append(version, style="cyan")
         header_content.append(version, style="cyan")
         header_content.append(" │ ", style="dim")
         header_content.append(" │ ", style="dim")
-        header_content.append("schema:", style="white")
-        header_content.append(schema, style="magenta")
-        header_content.append(" │ ", style="dim")
         header_content.append("library:", style="white")
         header_content.append("library:", style="white")
         header_content.append(icon + " ", style=color)
         header_content.append(icon + " ", style=color)
         header_content.append(library_name, style=color)
         header_content.append(library_name, style=color)

+ 16 - 0
cli/core/exceptions.py

@@ -45,6 +45,22 @@ class TemplateNotFoundError(TemplateError):
         super().__init__(msg)
         super().__init__(msg)
 
 
 
 
+class TemplateDraftError(TemplateError):
+    """Raised when attempting to use a draft template."""
+
+    def __init__(self, template_id: str, module_name: str | None = None):
+        self.template_id = template_id
+        self.module_name = module_name
+
+        module_suffix = f" in module '{module_name}'" if module_name else ""
+        msg = (
+            f"Template '{template_id}' is in draft mode and not yet available for use{module_suffix}.\n"
+            "Draft templates are work-in-progress and cannot be generated yet.\n"
+            "To get updates when published, run 'boilerplates repo update' to sync your library."
+        )
+        super().__init__(msg)
+
+
 class DuplicateTemplateError(TemplateError):
 class DuplicateTemplateError(TemplateError):
     """Raised when duplicate template IDs are found within the same library."""
     """Raised when duplicate template IDs are found within the same library."""
 
 

+ 22 - 11
cli/core/library.py

@@ -6,7 +6,7 @@ from pathlib import Path
 import yaml
 import yaml
 
 
 from .config import ConfigManager
 from .config import ConfigManager
-from .exceptions import DuplicateTemplateError, LibraryError, TemplateNotFoundError
+from .exceptions import DuplicateTemplateError, LibraryError, TemplateDraftError, TemplateNotFoundError
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
@@ -53,17 +53,22 @@ class Library:
             return False
             return False
 
 
     def find_by_id(self, module_name: str, template_id: str) -> tuple[Path, str]:
     def find_by_id(self, module_name: str, template_id: str) -> tuple[Path, str]:
-        """Find a template by its ID in this library.
+        """Find a template by its ID in this library for generation/show operations.
+
+        Note: Draft templates are intentionally excluded from this method.
+        They are visible in list/search commands (via find()) but cannot be
+        used for generation as they are work-in-progress.
 
 
         Args:
         Args:
             module_name: The module name (e.g., 'compose', 'terraform')
             module_name: The module name (e.g., 'compose', 'terraform')
             template_id: The template ID to find
             template_id: The template ID to find
 
 
         Returns:
         Returns:
-            Path to the template directory if found
+            Path to the template directory if found and not draft
 
 
         Raises:
         Raises:
-            FileNotFoundError: If the template ID is not found in this library or is marked as draft
+            TemplateDraftError: If the template exists but is marked as draft
+            TemplateNotFoundError: If the template ID is not found in this library
         """
         """
         logger.debug(f"Looking for template '{template_id}' in module '{module_name}' in library '{self.name}'")
         logger.debug(f"Looking for template '{template_id}' in module '{module_name}' in library '{self.name}'")
 
 
@@ -75,23 +80,28 @@ class Library:
             (template_path / f).exists() for f in ("template.yaml", "template.yml")
             (template_path / f).exists() for f in ("template.yaml", "template.yml")
         )
         )
 
 
-        if not has_template or self._is_template_draft(template_path):
+        # Template not found at all
+        if not has_template:
             raise TemplateNotFoundError(template_id, module_name)
             raise TemplateNotFoundError(template_id, module_name)
 
 
+        # Template exists but is in draft mode
+        if self._is_template_draft(template_path):
+            raise TemplateDraftError(template_id, module_name)
+
         logger.debug(f"Found template '{template_id}' at: {template_path}")
         logger.debug(f"Found template '{template_id}' at: {template_path}")
         return template_path, self.name
         return template_path, self.name
 
 
     def find(self, module_name: str, sort_results: bool = False) -> list[tuple[Path, str]]:
     def find(self, module_name: str, sort_results: bool = False) -> list[tuple[Path, str]]:
         """Find templates in this library for a specific module.
         """Find templates in this library for a specific module.
 
 
-        Excludes templates marked as draft.
+        Includes all templates (both published and draft).
 
 
         Args:
         Args:
             module_name: The module name (e.g., 'compose', 'terraform')
             module_name: The module name (e.g., 'compose', 'terraform')
             sort_results: Whether to return results sorted alphabetically
             sort_results: Whether to return results sorted alphabetically
 
 
         Returns:
         Returns:
-            List of Path objects representing template directories (excluding drafts)
+            List of Path objects representing template directories (including drafts)
 
 
         Raises:
         Raises:
             FileNotFoundError: If the module directory is not found in this library
             FileNotFoundError: If the module directory is not found in this library
@@ -111,7 +121,7 @@ class Library:
         try:
         try:
             for item in module_path.iterdir():
             for item in module_path.iterdir():
                 has_template = item.is_dir() and any((item / f).exists() for f in ("template.yaml", "template.yml"))
                 has_template = item.is_dir() and any((item / f).exists() for f in ("template.yaml", "template.yml"))
-                if has_template and not self._is_template_draft(item):
+                if has_template:
                     template_id = item.name
                     template_id = item.name
 
 
                     # Check for duplicate within same library
                     # Check for duplicate within same library
@@ -120,8 +130,6 @@ class Library:
 
 
                     seen_ids[template_id] = True
                     seen_ids[template_id] = True
                     template_dirs.append((item, self.name))
                     template_dirs.append((item, self.name))
-                elif has_template:
-                    logger.debug(f"Skipping draft template: {item.name}")
         except PermissionError as e:
         except PermissionError as e:
             raise LibraryError(
             raise LibraryError(
                 f"Permission denied accessing module '{module_name}' in library '{self.name}': {e}"
                 f"Permission denied accessing module '{module_name}' in library '{self.name}': {e}"
@@ -252,7 +260,7 @@ class LibraryManager:
                             template_path, lib_name = library.find_by_id(module_name, base_id)
                             template_path, lib_name = library.find_by_id(module_name, base_id)
                             logger.debug(f"Found template '{base_id}' in library '{requested_lib}'")
                             logger.debug(f"Found template '{base_id}' in library '{requested_lib}'")
                             return template_path, lib_name
                             return template_path, lib_name
-                        except TemplateNotFoundError:
+                        except (TemplateNotFoundError, TemplateDraftError):
                             logger.debug(f"Template '{base_id}' not found in library '{requested_lib}'")
                             logger.debug(f"Template '{base_id}' not found in library '{requested_lib}'")
                             return None
                             return None
 
 
@@ -268,6 +276,9 @@ class LibraryManager:
             except TemplateNotFoundError:
             except TemplateNotFoundError:
                 # Continue searching in next library
                 # Continue searching in next library
                 continue
                 continue
+            except TemplateDraftError:
+                # Draft error should propagate immediately (don't search other libraries)
+                raise
 
 
         logger.debug(f"Template '{template_id}' not found in any library")
         logger.debug(f"Template '{template_id}' not found in any library")
         return None
         return None

+ 51 - 11
cli/core/module/base_commands.py

@@ -17,7 +17,11 @@ from ..exceptions import (
     TemplateValidationError,
     TemplateValidationError,
 )
 )
 from ..input import InputManager
 from ..input import InputManager
-from ..template import Template
+from ..template import (
+    TEMPLATE_STATUS_DRAFT,
+    TEMPLATE_STATUS_PUBLISHED,
+    Template,
+)
 from ..validators import get_validator_registry
 from ..validators import get_validator_registry
 from .helpers import (
 from .helpers import (
     apply_cli_overrides,
     apply_cli_overrides,
@@ -83,14 +87,34 @@ def list_templates(module_instance, raw: bool = False) -> list:
                 tags_list = template.metadata.tags or []
                 tags_list = template.metadata.tags or []
                 tags = ", ".join(tags_list) if tags_list else "-"
                 tags = ", ".join(tags_list) if tags_list else "-"
                 version = str(template.metadata.version) if template.metadata.version else ""
                 version = str(template.metadata.version) if template.metadata.version else ""
-                schema = template.schema_version if hasattr(template, "schema_version") else "1.0"
+
+                # Get status and format it
+                status = template.status
+                if status == TEMPLATE_STATUS_PUBLISHED:
+                    status_display = "[green]Published[/green]"
+                elif status == TEMPLATE_STATUS_DRAFT:
+                    status_display = "[dim]Draft[/dim]"
+                else:  # TEMPLATE_STATUS_INVALID
+                    status_display = "[red]Invalid[/red]"
+
                 library_name = template.metadata.library or ""
                 library_name = template.metadata.library or ""
                 library_type = template.metadata.library_type or "git"
                 library_type = template.metadata.library_type or "git"
                 # Format library with icon and color
                 # Format library with icon and color
                 icon = IconManager.UI_LIBRARY_STATIC if library_type == "static" else IconManager.UI_LIBRARY_GIT
                 icon = IconManager.UI_LIBRARY_STATIC if library_type == "static" else IconManager.UI_LIBRARY_GIT
                 color = "yellow" if library_type == "static" else "blue"
                 color = "yellow" if library_type == "static" else "blue"
                 library_display = f"[{color}]{icon} {library_name}[/{color}]"
                 library_display = f"[{color}]{icon} {library_name}[/{color}]"
-                return (template.id, name, tags, version, schema, library_display)
+
+                # Apply dimmed style to entire row if draft
+                if status == TEMPLATE_STATUS_DRAFT:
+                    template_id = f"[dim]{template.id}[/dim]"
+                    name = f"[dim]{name}[/dim]"
+                    tags = f"[dim]{tags}[/dim]"
+                    version = f"[dim]{version}[/dim]"
+                    library_display = f"[dim]{icon} {library_name}[/dim]"
+                else:
+                    template_id = template.id
+
+                return (template_id, name, tags, version, status_display, library_display)
 
 
             module_instance.display.data_table(
             module_instance.display.data_table(
                 columns=[
                 columns=[
@@ -98,7 +122,7 @@ def list_templates(module_instance, raw: bool = False) -> list:
                     {"name": "Name"},
                     {"name": "Name"},
                     {"name": "Tags"},
                     {"name": "Tags"},
                     {"name": "Version", "no_wrap": True},
                     {"name": "Version", "no_wrap": True},
-                    {"name": "Schema", "no_wrap": True},
+                    {"name": "Status", "no_wrap": True},
                     {"name": "Library", "no_wrap": True},
                     {"name": "Library", "no_wrap": True},
                 ],
                 ],
                 rows=filtered_templates,
                 rows=filtered_templates,
@@ -129,14 +153,34 @@ def search_templates(module_instance, query: str) -> list:
             tags_list = template.metadata.tags or []
             tags_list = template.metadata.tags or []
             tags = ", ".join(tags_list) if tags_list else "-"
             tags = ", ".join(tags_list) if tags_list else "-"
             version = str(template.metadata.version) if template.metadata.version else ""
             version = str(template.metadata.version) if template.metadata.version else ""
-            schema = template.schema_version if hasattr(template, "schema_version") else "1.0"
+
+            # Get status and format it
+            status = template.status
+            if status == TEMPLATE_STATUS_PUBLISHED:
+                status_display = "[green]Published[/green]"
+            elif status == TEMPLATE_STATUS_DRAFT:
+                status_display = "[dim]Draft[/dim]"
+            else:  # TEMPLATE_STATUS_INVALID
+                status_display = "[red]Invalid[/red]"
+
             library_name = template.metadata.library or ""
             library_name = template.metadata.library or ""
             library_type = template.metadata.library_type or "git"
             library_type = template.metadata.library_type or "git"
             # Format library with icon and color
             # Format library with icon and color
             icon = IconManager.UI_LIBRARY_STATIC if library_type == "static" else IconManager.UI_LIBRARY_GIT
             icon = IconManager.UI_LIBRARY_STATIC if library_type == "static" else IconManager.UI_LIBRARY_GIT
             color = "yellow" if library_type == "static" else "blue"
             color = "yellow" if library_type == "static" else "blue"
             library_display = f"[{color}]{icon} {library_name}[/{color}]"
             library_display = f"[{color}]{icon} {library_name}[/{color}]"
-            return (template.id, name, tags, version, schema, library_display)
+
+            # Apply dimmed style to entire row if draft
+            if status == TEMPLATE_STATUS_DRAFT:
+                template_id = f"[dim]{template.id}[/dim]"
+                name = f"[dim]{name}[/dim]"
+                tags = f"[dim]{tags}[/dim]"
+                version = f"[dim]{version}[/dim]"
+                library_display = f"[dim]{icon} {library_name}[/dim]"
+            else:
+                template_id = template.id
+
+            return (template_id, name, tags, version, status_display, library_display)
 
 
         module_instance.display.data_table(
         module_instance.display.data_table(
             columns=[
             columns=[
@@ -144,7 +188,7 @@ def search_templates(module_instance, query: str) -> list:
                 {"name": "Name"},
                 {"name": "Name"},
                 {"name": "Tags"},
                 {"name": "Tags"},
                 {"name": "Version", "no_wrap": True},
                 {"name": "Version", "no_wrap": True},
-                {"name": "Schema", "no_wrap": True},
+                {"name": "Status", "no_wrap": True},
                 {"name": "Library", "no_wrap": True},
                 {"name": "Library", "no_wrap": True},
             ],
             ],
             rows=filtered_templates,
             rows=filtered_templates,
@@ -176,9 +220,6 @@ def show_template(module_instance, id: str, var: list[str] | None = None, var_fi
         apply_var_file(template, var_file, module_instance.display)
         apply_var_file(template, var_file, module_instance.display)
         apply_cli_overrides(template, var)
         apply_cli_overrides(template, var)
 
 
-        # Re-sort sections after applying overrides (toggle values may have changed)
-        template.variables.sort_sections()
-
         # Reset disabled bool variables to False to prevent confusion
         # Reset disabled bool variables to False to prevent confusion
         reset_vars = template.variables.reset_disabled_bool_variables()
         reset_vars = template.variables.reset_disabled_bool_variables()
         if reset_vars:
         if reset_vars:
@@ -347,7 +388,6 @@ def _prepare_template(
     apply_cli_overrides(template, var)
     apply_cli_overrides(template, var)
 
 
     if template.variables:
     if template.variables:
-        template.variables.sort_sections()
         reset_vars = template.variables.reset_disabled_bool_variables()
         reset_vars = template.variables.reset_disabled_bool_variables()
         if reset_vars:
         if reset_vars:
             logger.debug(f"Reset {len(reset_vars)} disabled bool variables to False")
             logger.debug(f"Reset {len(reset_vars)} disabled bool variables to False")

+ 0 - 6
cli/core/module/base_module.py

@@ -79,9 +79,6 @@ class Module(ABC):
 
 
                 template = Template(template_dir, library_name=library_name, library_type=library_type)
                 template = Template(template_dir, library_name=library_name, library_type=library_type)
 
 
-                # Validate schema version compatibility
-                template._validate_schema_version(self.schema_version, self.name)
-
                 # If template ID needs qualification, set qualified ID
                 # If template ID needs qualification, set qualified ID
                 if needs_qualification:
                 if needs_qualification:
                     template.set_qualified_id()
                     template.set_qualified_id()
@@ -115,9 +112,6 @@ class Module(ABC):
         try:
         try:
             template = Template(template_dir, library_name=library_name, library_type=library_type)
             template = Template(template_dir, library_name=library_name, library_type=library_type)
 
 
-            # Validate schema version compatibility
-            template._validate_schema_version(self.schema_version, self.name)
-
             # If the original ID was qualified, preserve it
             # If the original ID was qualified, preserve it
             if "." in id:
             if "." in id:
                 template.id = id
                 template.id = id

+ 0 - 17
cli/core/schema/__init__.py

@@ -1,17 +0,0 @@
-"""Schema loading and management for boilerplate modules."""
-
-from .loader import (
-    SchemaLoader,
-    get_loader,
-    has_schema,
-    list_versions,
-    load_schema,
-)
-
-__all__ = [
-    "SchemaLoader",
-    "get_loader",
-    "has_schema",
-    "list_versions",
-    "load_schema",
-]

+ 0 - 15
cli/core/schema/ansible/v1.0.json

@@ -1,15 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "target_hosts",
-        "description": "Target hosts",
-        "type": "str",
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 229
cli/core/schema/compose/v1.0.json

@@ -1,229 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "toggle": "network_enabled",
-    "vars": [
-      {
-        "name": "network_enabled",
-        "description": "Enable custom network block",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge"
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "toggle": "ports_enabled",
-    "vars": [
-      {
-        "name": "ports_enabled",
-        "description": "Expose ports via 'ports' mapping",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": "traefik",
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "description": "Deploy service in Docker Swarm mode with replicas.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas in Swarm",
-        "type": "int",
-        "default": 1
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["global", "replicated"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Limit placement to specific node",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["postgres", "mysql"],
-        "default": "postgres"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

+ 0 - 312
cli/core/schema/compose/v1.1.json

@@ -1,312 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_hostname",
-        "description": "Container internal hostname",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "container_loglevel",
-        "description": "Container log level",
-        "type": "enum",
-        "options": ["debug", "info", "warn", "error"],
-        "default": "info"
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Docker network mode",
-        "type": "enum",
-        "options": ["bridge", "host", "macvlan"],
-        "default": "bridge",
-        "extra": "bridge=default Docker networking, host=use host network stack, macvlan=dedicated MAC address on physical network"
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge",
-        "needs": "network_mode=bridge,macvlan"
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network (external)",
-        "type": "bool",
-        "default": false,
-        "needs": "network_mode=bridge,macvlan"
-      },
-      {
-        "name": "network_macvlan_ipv4_address",
-        "description": "Static IP address for container",
-        "type": "str",
-        "default": "192.168.1.253",
-        "needs": "network_mode=macvlan"
-      },
-      {
-        "name": "network_macvlan_parent_interface",
-        "description": "Host network interface name",
-        "type": "str",
-        "default": "eth0",
-        "needs": "network_mode=macvlan"
-      },
-      {
-        "name": "network_macvlan_subnet",
-        "description": "Network subnet in CIDR notation",
-        "type": "str",
-        "default": "192.168.1.0/24",
-        "needs": "network_mode=macvlan"
-      },
-      {
-        "name": "network_macvlan_gateway",
-        "description": "Network gateway IP address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": "network_mode=macvlan"
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "needs": "network_mode=bridge",
-    "vars": []
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "needs": "network_mode=bridge",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": "traefik_enabled=true;network_mode=bridge",
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "needs": "network_mode=bridge",
-    "description": "Deploy service in Docker Swarm mode.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["replicated", "global"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas",
-        "type": "int",
-        "default": 1,
-        "needs": "swarm_placement_mode=replicated"
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Target hostname for placement constraint",
-        "type": "str",
-        "default": "",
-        "optional": true,
-        "needs": "swarm_placement_mode=replicated",
-        "extra": "Constrains service to run on specific node by hostname"
-      },
-      {
-        "name": "swarm_volume_mode",
-        "description": "Swarm volume storage backend",
-        "type": "enum",
-        "options": ["local", "mount", "nfs"],
-        "default": "local",
-        "extra": "WARNING: 'local' only works on single-node deployments!"
-      },
-      {
-        "name": "swarm_volume_mount_path",
-        "description": "Host path for bind mount",
-        "type": "str",
-        "default": "/mnt/storage",
-        "needs": "swarm_volume_mode=mount",
-        "extra": "Useful for shared/replicated storage"
-      },
-      {
-        "name": "swarm_volume_nfs_server",
-        "description": "NFS server address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": "swarm_volume_mode=nfs",
-        "extra": "IP address or hostname of NFS server"
-      },
-      {
-        "name": "swarm_volume_nfs_path",
-        "description": "NFS export path",
-        "type": "str",
-        "default": "/export",
-        "needs": "swarm_volume_mode=nfs",
-        "extra": "Path to NFS export on the server"
-      },
-      {
-        "name": "swarm_volume_nfs_options",
-        "description": "NFS mount options",
-        "type": "str",
-        "default": "rw,nolock,soft",
-        "needs": "swarm_volume_mode=nfs",
-        "extra": "Comma-separated NFS mount options"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["default", "sqlite", "postgres", "mysql"],
-        "default": "default"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

+ 0 - 528
cli/core/schema/compose/v1.2.json

@@ -1,528 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_hostname",
-        "description": "Container internal hostname",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "container_loglevel",
-        "description": "Container log level",
-        "type": "enum",
-        "options": ["debug", "info", "warn", "error"]
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Docker network mode",
-        "type": "enum",
-        "options": ["bridge", "host", "macvlan"],
-        "extra": "bridge=default Docker networking, host=use host network stack, macvlan=dedicated MAC address on physical network"
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge",
-        "needs": ["network_mode=bridge,macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network (external)",
-        "type": "bool",
-        "default": false,
-        "needs": ["network_mode=bridge,macvlan"]
-      },
-      {
-        "name": "network_macvlan_ipv4_address",
-        "description": "Static IP address for container",
-        "type": "str",
-        "default": "192.168.1.253",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_parent_interface",
-        "description": "Host network interface name",
-        "type": "str",
-        "default": "eth0",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_subnet",
-        "description": "Network subnet in CIDR notation",
-        "type": "str",
-        "default": "192.168.1.0/24",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_gateway",
-        "description": "Network gateway IP address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Expose service ports to the host.",
-    "vars": [
-      {
-        "name": "ports_http",
-        "description": "HTTP port on host",
-        "type": "int",
-        "needs": ["traefik_enabled=false"],
-        "default": 8080,
-        "required": true
-      },
-      {
-        "name": "ports_https",
-        "description": "HTTPS port on host",
-        "type": "int",
-        "needs": ["traefik_enabled=false"],
-        "default": 8443,
-        "required": true
-      },
-      {
-        "name": "ports_ssh",
-        "description": "SSH port on host",
-        "type": "int",
-        "default": 22,
-        "required": true
-      },
-      {
-        "name": "ports_dns",
-        "description": "DNS port on host",
-        "type": "int",
-        "default": 53,
-        "required": true
-      },
-      {
-        "name": "ports_dhcp",
-        "description": "DHCP port on host",
-        "type": "int",
-        "default": 67,
-        "required": true
-      },
-      {
-        "name": "ports_smtp",
-        "description": "SMTP port on host",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "ports_snmp",
-        "description": "SNMP trap port",
-        "type": "int",
-        "default": 162,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik",
-        "required": true
-      },
-      {
-        "name": "traefik_host",
-        "description": "Service subdomain or full hostname (e.g., 'app' or 'app.example.com')",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "traefik_domain",
-        "description": "Base domain (e.g., example.com)",
-        "type": "str",
-        "default": "home.arpa",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik_enabled=true", "network_mode!=host,macvlan"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "volume",
-    "title": "Volume Storage",
-    "description": "Configure persistent storage for your service.",
-    "vars": [
-      {
-        "name": "volume_mode",
-        "description": "Volume storage backend",
-        "type": "enum",
-        "options": ["local", "mount", "nfs"],
-        "default": "local",
-        "required": true
-      },
-      {
-        "name": "volume_mount_path",
-        "description": "Host path for bind mounts",
-        "type": "str",
-        "default": "/mnt/storage",
-        "needs": ["volume_mode=mount"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_server",
-        "description": "NFS server address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_path",
-        "description": "NFS export path",
-        "type": "str",
-        "default": "/export",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_options",
-        "description": "NFS mount options (comma-separated)",
-        "type": "str",
-        "default": "rw,nolock,soft",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "resources",
-    "title": "Resource Limits",
-    "toggle": "resources_enabled",
-    "description": "Set CPU and memory limits for the service.",
-    "vars": [
-      {
-        "name": "resources_enabled",
-        "description": "Enable resource limits",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "resources_cpu_limit",
-        "description": "Maximum CPU cores (e.g., 0.5, 1.0, 2.0)",
-        "type": "str",
-        "default": "1.0",
-        "required": true
-      },
-      {
-        "name": "resources_cpu_reservation",
-        "description": "Reserved CPU cores",
-        "type": "str",
-        "default": "0.25",
-        "needs": ["swarm_enabled=true"],
-        "required": true
-      },
-      {
-        "name": "resources_memory_limit",
-        "description": "Maximum memory (e.g., 512M, 1G, 2G)",
-        "type": "str",
-        "default": "1G",
-        "required": true
-      },
-      {
-        "name": "resources_memory_reservation",
-        "description": "Reserved memory",
-        "type": "str",
-        "default": "512M",
-        "needs": ["swarm_enabled=true"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Deploy service in Docker Swarm mode.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["replicated", "global"],
-        "default": "replicated",
-        "required": true
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas",
-        "type": "int",
-        "default": 1,
-        "needs": ["swarm_placement_mode=replicated"],
-        "required": true
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Target hostname for placement constraint",
-        "type": "str",
-        "default": "",
-        "needs": ["swarm_placement_mode=replicated"],
-        "extra": "Constrains service to run on specific node by hostname"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["sqlite", "postgres", "mysql"],
-        "default": "sqlite",
-        "required": true
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "needs": ["database_type=postgres,mysql"],
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "needs": ["database_external=true;database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "needs": ["database_external=true;database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str",
-        "needs": ["database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str",
-        "needs": ["database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "needs": ["database_type=postgres,mysql"],
-        "sensitive": true,
-        "autogenerated": true,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Server",
-    "toggle": "email_enabled",
-    "description": "Configure email server for notifications and user management.",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email server configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_encryption",
-        "description": "Email encryption method to use",
-        "type": "enum",
-        "options": ["none", "starttls", "ssl"]
-      }
-    ]
-  },
-  {
-    "key": "authentik",
-    "title": "Authentik SSO",
-    "toggle": "authentik_enabled",
-    "description": "Integrate with Authentik for Single Sign-On authentication.",
-    "vars": [
-      {
-        "name": "authentik_enabled",
-        "description": "Enable Authentik SSO integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "authentik_url",
-        "description": "Authentik base URL (e.g., https://auth.example.com)",
-        "type": "url",
-        "required": true
-      },
-      {
-        "name": "authentik_slug",
-        "description": "Authentik application slug",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "authentik_traefik_middleware",
-        "description": "Traefik middleware name for Authentik authentication",
-        "type": "str",
-        "default": "authentik-middleware@file",
-        "needs": ["traefik_enabled=true"],
-        "required": true
-      },
-      {
-        "name": "authentik_client_id",
-        "description": "Authentik OAuth2 client ID",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "authentik_client_secret",
-        "description": "Authentik OAuth2 client secret",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 202
cli/core/schema/helm/v1.0.json

@@ -1,202 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "release_name",
-        "description": "Helm release name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "namespace",
-        "description": "Kubernetes namespace",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "networking",
-    "title": "Networking",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Kubernetes service type",
-        "type": "enum",
-        "options": ["ClusterIP", "NodePort", "LoadBalancer"],
-        "default": "ClusterIP"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database Configuration",
-    "toggle": "database_enabled",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["postgres", "mysql", "mariadb"],
-        "default": "postgres"
-      },
-      {
-        "name": "database_host",
-        "description": "Database hostname",
-        "type": "hostname"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "default": 5432
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database username",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "sensitive": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Configuration",
-    "toggle": "email_enabled",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "hostname"
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 587
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str"
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "email"
-      },
-      {
-        "name": "email_use_tls",
-        "description": "Use TLS encryption",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "email_use_ssl",
-        "description": "Use SSL encryption",
-        "type": "bool",
-        "default": false
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik Ingress",
-    "toggle": "traefik_enabled",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik ingress",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_host",
-        "description": "Ingress hostname (FQDN)",
-        "type": "hostname"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "needs": "traefik",
-    "toggle": "traefik_tls_enabled",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable TLS for ingress",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certmanager",
-        "description": "Use cert-manager for TLS certificates",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "certmanager_issuer",
-        "description": "Cert-manager cluster issuer name",
-        "type": "str",
-        "needs": "traefik_tls_certmanager=true",
-        "default": "letsencrypt-prod"
-      },
-      {
-        "name": "traefik_tls_secret",
-        "description": "TLS secret name",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "volumes",
-    "title": "Persistent Volumes",
-    "vars": [
-      {
-        "name": "volumes_mode",
-        "description": "Volume configuration mode",
-        "type": "enum",
-        "options": ["dynamic-pvc", "existing-pvc"],
-        "default": "dynamic-pvc",
-        "extra": "dynamic-pvc=auto-provision storage, existing-pvc=use existing PVC"
-      },
-      {
-        "name": "volumes_pvc_name",
-        "description": "Existing PVC name",
-        "type": "str",
-        "needs": "volumes_mode=existing-pvc"
-      }
-    ]
-  }
-]

+ 0 - 247
cli/core/schema/kubernetes/v1.0.json

@@ -1,247 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "resource_name",
-        "description": "Kubernetes resource name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "namespace",
-        "description": "Kubernetes namespace",
-        "type": "str",
-        "default": "default",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "resources",
-    "title": "Resource Limits",
-    "toggle": "resources_enabled",
-    "description": "Set CPU and memory limits for the resource.",
-    "vars": [
-      {
-        "name": "resources_enabled",
-        "description": "Enable resource limits",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "resources_cpu_limit",
-        "description": "Maximum CPU cores (e.g., 100m, 500m, 1, 2)",
-        "type": "str",
-        "default": "1",
-        "required": true
-      },
-      {
-        "name": "resources_cpu_request",
-        "description": "Requested CPU cores",
-        "type": "str",
-        "default": "250m",
-        "required": true
-      },
-      {
-        "name": "resources_memory_limit",
-        "description": "Maximum memory (e.g., 512Mi, 1Gi, 2Gi)",
-        "type": "str",
-        "default": "1Gi",
-        "required": true
-      },
-      {
-        "name": "resources_memory_request",
-        "description": "Requested memory",
-        "type": "str",
-        "default": "512Mi",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik ingress configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_host",
-        "description": "Service subdomain or full hostname (e.g., 'app' or 'app.example.com')",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "traefik_domain",
-        "description": "Base domain (e.g., example.com)",
-        "type": "str",
-        "default": "home.arpa",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["sqlite", "postgres", "mysql", "mariadb"],
-        "default": "postgres",
-        "required": true
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database",
-        "required": true
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "required": true
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Server",
-    "toggle": "email_enabled",
-    "description": "Configure email server for notifications and user management.",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email server configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_encryption",
-        "description": "Email encryption method to use",
-        "type": "enum",
-        "options": ["none", "starttls", "ssl"]
-      }
-    ]
-  },
-  {
-    "key": "authentik",
-    "title": "Authentik SSO",
-    "toggle": "authentik_enabled",
-    "description": "Integrate with Authentik for Single Sign-On authentication.",
-    "vars": [
-      {
-        "name": "authentik_enabled",
-        "description": "Enable Authentik SSO integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "authentik_url",
-        "description": "Authentik base URL (e.g., https://auth.example.com)",
-        "type": "url",
-        "required": true
-      },
-      {
-        "name": "authentik_slug",
-        "description": "Authentik application slug",
-        "type": "str",
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 220
cli/core/schema/loader.py

@@ -1,220 +0,0 @@
-"""JSON Schema Loading and Validation.
-
-This module provides functionality to load, cache, and validate JSON schemas
-for boilerplate modules. Schemas are stored in cli/core/schema/<module>/v*.json files.
-"""
-
-import json
-from pathlib import Path
-from typing import Any
-
-from cli.core.exceptions import SchemaError
-
-
-class SchemaLoader:
-    """Loads and validates JSON schemas for modules."""
-
-    def __init__(self, schema_dir: Path | None = None):
-        """Initialize schema loader.
-
-        Args:
-            schema_dir: Directory containing schema files. If None, uses cli/core/schema/
-        """
-        if schema_dir is None:
-            # Use path relative to this file (in cli/core/schema/)
-            # __file__ is cli/core/schema/loader.py, parent is cli/core/schema/
-            self.schema_dir = Path(__file__).parent
-        else:
-            self.schema_dir = schema_dir
-
-    def load_schema(self, module: str, version: str) -> list[dict[str, Any]]:
-        """Load a JSON schema from file.
-
-        Args:
-            module: Module name (e.g., 'compose', 'ansible')
-            version: Schema version (e.g., '1.0', '1.2')
-
-        Returns:
-            Schema as list of section specifications
-
-        Raises:
-            SchemaError: If schema file not found or invalid JSON
-        """
-        schema_file = self.schema_dir / module / f"v{version}.json"
-
-        if not schema_file.exists():
-            raise SchemaError(
-                f"Schema file not found: {schema_file}",
-                details=f"Module: {module}, Version: {version}",
-            )
-
-        try:
-            with schema_file.open(encoding="utf-8") as f:
-                schema = json.load(f)
-        except json.JSONDecodeError as e:
-            raise SchemaError(
-                f"Invalid JSON in schema file: {schema_file}",
-                details=f"Error: {e}",
-            ) from e
-        except Exception as e:
-            raise SchemaError(
-                f"Failed to read schema file: {schema_file}",
-                details=f"Error: {e}",
-            ) from e
-
-        # Validate schema structure
-        self._validate_schema_structure(schema, module, version)
-
-        return schema
-
-    def _validate_schema_structure(self, schema: Any, module: str, version: str) -> None:
-        """Validate that schema has correct structure.
-
-        Args:
-            schema: Schema to validate
-            module: Module name for error messages
-            version: Version for error messages
-
-        Raises:
-            SchemaError: If schema structure is invalid
-        """
-        if not isinstance(schema, list):
-            raise SchemaError(
-                f"Schema must be a list, got {type(schema).__name__}",
-                details=f"Module: {module}, Version: {version}",
-            )
-
-        for idx, section in enumerate(schema):
-            if not isinstance(section, dict):
-                raise SchemaError(
-                    f"Section {idx} must be a dict, got {type(section).__name__}",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            # Check required fields
-            if "key" not in section:
-                raise SchemaError(
-                    f"Section {idx} missing required field 'key'",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            if "vars" not in section:
-                raise SchemaError(
-                    f"Section '{section.get('key')}' missing required field 'vars'",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            if not isinstance(section["vars"], list):
-                raise SchemaError(
-                    f"Section '{section['key']}' vars must be a list",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            # Validate variables
-            for var_idx, var in enumerate(section["vars"]):
-                if not isinstance(var, dict):
-                    raise SchemaError(
-                        f"Variable {var_idx} in section '{section['key']}' must be a dict",
-                        details=f"Module: {module}, Version: {version}",
-                    )
-
-                if "name" not in var:
-                    raise SchemaError(
-                        f"Variable {var_idx} in section '{section['key']}' missing 'name'",
-                        details=f"Module: {module}, Version: {version}",
-                    )
-
-                if "type" not in var:
-                    raise SchemaError(
-                        f"Variable '{var.get('name')}' in section '{section['key']}' missing 'type'",
-                        details=f"Module: {module}, Version: {version}",
-                    )
-
-    def list_versions(self, module: str) -> list[str]:
-        """List available schema versions for a module.
-
-        Args:
-            module: Module name
-
-        Returns:
-            List of version strings (e.g., ['1.0', '1.1', '1.2'])
-        """
-        module_dir = self.schema_dir / module
-
-        if not module_dir.exists():
-            return []
-
-        versions = []
-        for file in module_dir.glob("v*.json"):
-            # Extract version from filename (v1.0.json -> 1.0)
-            version = file.stem[1:]  # Remove 'v' prefix
-            versions.append(version)
-
-        return sorted(versions)
-
-    def has_schema(self, module: str, version: str) -> bool:
-        """Check if a schema exists.
-
-        Args:
-            module: Module name
-            version: Schema version
-
-        Returns:
-            True if schema exists
-        """
-        schema_file = self.schema_dir / module / f"v{version}.json"
-        return schema_file.exists()
-
-
-# Global schema loader instance
-_loader: SchemaLoader | None = None
-
-
-def get_loader() -> SchemaLoader:
-    """Get global schema loader instance.
-
-    Returns:
-        SchemaLoader instance
-    """
-    global _loader  # noqa: PLW0603
-    if _loader is None:
-        _loader = SchemaLoader()
-    return _loader
-
-
-def load_schema(module: str, version: str) -> list[dict[str, Any]]:
-    """Load a schema using the global loader.
-
-    Args:
-        module: Module name
-        version: Schema version
-
-    Returns:
-        Schema as list of section specifications
-    """
-    return get_loader().load_schema(module, version)
-
-
-def list_versions(module: str) -> list[str]:
-    """List available versions for a module.
-
-    Args:
-        module: Module name
-
-    Returns:
-        List of version strings
-    """
-    return get_loader().list_versions(module)
-
-
-def has_schema(module: str, version: str) -> bool:
-    """Check if a schema exists.
-
-    Args:
-        module: Module name
-        version: Schema version
-
-    Returns:
-        True if schema exists
-    """
-    return get_loader().has_schema(module, version)

+ 0 - 14
cli/core/schema/packer/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 87
cli/core/schema/terraform/v1.0.json

@@ -1,87 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "resource_name",
-        "description": "Terraform resource name (alphanumeric and underscores only)",
-        "type": "str",
-        "default": "resource"
-      }
-    ]
-  },
-  {
-    "key": "depends_on",
-    "title": "Dependencies",
-    "toggle": "depends_on_enabled",
-    "required": false,
-    "vars": [
-      {
-        "name": "depends_on_enabled",
-        "description": "Enable resource dependencies",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "dependencies",
-        "description": "Comma-separated list of resource dependencies",
-        "type": "str",
-        "default": ""
-      }
-    ]
-  },
-  {
-    "key": "lifecycle",
-    "title": "Lifecycle",
-    "toggle": "lifecycle_enabled",
-    "required": false,
-    "vars": [
-      {
-        "name": "lifecycle_enabled",
-        "description": "Enable lifecycle rules",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "prevent_destroy",
-        "description": "Prevent resource destruction",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "create_before_destroy",
-        "description": "Create replacement before destroying",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "ignore_changes",
-        "description": "Comma-separated list of attributes to ignore changes for",
-        "type": "str",
-        "default": ""
-      }
-    ]
-  },
-  {
-    "key": "tags",
-    "title": "Tags",
-    "toggle": "tags_enabled",
-    "required": false,
-    "vars": [
-      {
-        "name": "tags_enabled",
-        "description": "Enable resource tags",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "tags_json",
-        "description": "Resource tags in JSON format (e.g., {\"Environment\": \"Production\"})",
-        "type": "str",
-        "default": "{}"
-      }
-    ]
-  }
-]

+ 12 - 1
cli/core/template/__init__.py

@@ -4,12 +4,23 @@ This package provides Template, VariableCollection, VariableSection, and Variabl
 classes for managing templates and their variables.
 classes for managing templates and their variables.
 """
 """
 
 
-from .template import Template, TemplateErrorHandler, TemplateFile, TemplateMetadata
+from .template import (
+    TEMPLATE_STATUS_DRAFT,
+    TEMPLATE_STATUS_INVALID,
+    TEMPLATE_STATUS_PUBLISHED,
+    Template,
+    TemplateErrorHandler,
+    TemplateFile,
+    TemplateMetadata,
+)
 from .variable import Variable
 from .variable import Variable
 from .variable_collection import VariableCollection
 from .variable_collection import VariableCollection
 from .variable_section import VariableSection
 from .variable_section import VariableSection
 
 
 __all__ = [
 __all__ = [
+    "TEMPLATE_STATUS_DRAFT",
+    "TEMPLATE_STATUS_INVALID",
+    "TEMPLATE_STATUS_PUBLISHED",
     "Template",
     "Template",
     "TemplateErrorHandler",
     "TemplateErrorHandler",
     "TemplateFile",
     "TemplateFile",

+ 57 - 136
cli/core/template/template.py

@@ -1,14 +1,12 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
 import base64
 import base64
-import importlib
 import logging
 import logging
 import os
 import os
 import re
 import re
 import secrets
 import secrets
 import string
 import string
 from dataclasses import dataclass, field
 from dataclasses import dataclass, field
-from functools import lru_cache
 from pathlib import Path
 from pathlib import Path
 from typing import Any, Literal
 from typing import Any, Literal
 
 
@@ -29,7 +27,6 @@ from jinja2.exceptions import (
 from jinja2.sandbox import SandboxedEnvironment
 from jinja2.sandbox import SandboxedEnvironment
 
 
 from ..exceptions import (
 from ..exceptions import (
-    IncompatibleSchemaVersionError,
     RenderErrorContext,
     RenderErrorContext,
     TemplateLoadError,
     TemplateLoadError,
     TemplateRenderError,
     TemplateRenderError,
@@ -37,11 +34,15 @@ from ..exceptions import (
     TemplateValidationError,
     TemplateValidationError,
     YAMLParseError,
     YAMLParseError,
 )
 )
-from ..version import is_compatible
 from .variable_collection import VariableCollection
 from .variable_collection import VariableCollection
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
+# Template Status Constants
+TEMPLATE_STATUS_PUBLISHED = "published"
+TEMPLATE_STATUS_DRAFT = "draft"
+TEMPLATE_STATUS_INVALID = "invalid"
+
 
 
 class TemplateErrorHandler:
 class TemplateErrorHandler:
     """Handles parsing and formatting of template rendering errors.
     """Handles parsing and formatting of template rendering errors.
@@ -314,8 +315,6 @@ class Template:
         self.library_type = library_type
         self.library_type = library_type
 
 
         # Initialize caches for lazy loading
         # Initialize caches for lazy loading
-        self.__module_specs: dict | None = None
-        self.__merged_specs: dict | None = None
         self.__jinja_env: Environment | None = None
         self.__jinja_env: Environment | None = None
         self.__used_variables: set[str] | None = None
         self.__used_variables: set[str] | None = None
         self.__variables: VariableCollection | None = None
         self.__variables: VariableCollection | None = None
@@ -350,12 +349,6 @@ class Template:
             # Validate 'kind' field (always needed)
             # Validate 'kind' field (always needed)
             self._validate_kind(self._template_data)
             self._validate_kind(self._template_data)
 
 
-            # Extract schema version (default to 1.0 for backward compatibility)
-            self.schema_version = str(self._template_data.get("schema", "1.0"))
-            logger.debug(f"Template schema version: {self.schema_version}")
-
-            # Note: Schema version validation is done by the module when loading templates
-
             # NOTE: File collection is now lazy-loaded via the template_files property
             # NOTE: File collection is now lazy-loaded via the template_files property
             # This significantly improves performance when listing many templates
             # This significantly improves performance when listing many templates
 
 
@@ -389,80 +382,36 @@ class Template:
                 return path
                 return path
         raise FileNotFoundError(f"Main template file (template.yaml or template.yml) not found in {self.template_dir}")
         raise FileNotFoundError(f"Main template file (template.yaml or template.yml) not found in {self.template_dir}")
 
 
-    @staticmethod
-    @lru_cache(maxsize=32)
-    def _load_module_specs_for_schema(kind: str, schema_version: str) -> dict:
-        """Load specifications from the corresponding module for a specific schema version.
+    def _warn_about_unused_variables(self, template_specs: dict) -> None:
+        """Warn about variables defined in spec but not used in template files.
 
 
-        Uses LRU cache to avoid re-loading the same module spec multiple times.
-        This significantly improves performance when listing many templates of the same kind.
+        This helps identify unnecessary variable definitions that can be removed.
 
 
         Args:
         Args:
-            kind: The module kind (e.g., 'compose', 'terraform')
-            schema_version: The schema version to load (e.g., '1.0', '1.1')
-
-        Returns:
-            Dictionary containing the module's spec for the requested schema version,
-            or empty dict if kind is empty
-
-        Raises:
-            ValueError: If module cannot be loaded or spec is invalid
-        """
-        if not kind:
-            return {}
-
-        # Log cache statistics for performance monitoring
-        cache_info = Template._load_module_specs_for_schema.cache_info()
-        logger.debug(
-            f"Loading module spec: kind='{kind}', schema={schema_version} "
-            f"(cache: hits={cache_info.hits}, misses={cache_info.misses}, size={cache_info.currsize})"
-        )
-
-        try:
-            module = importlib.import_module(f"cli.modules.{kind}")
-
-            # Check if module has schema-specific specs (multi-schema support)
-            # Try SCHEMAS constant first (uppercase), then schemas attribute
-            schemas = getattr(module, "SCHEMAS", None) or getattr(module, "schemas", None)
-            if schemas and schema_version in schemas:
-                spec = schemas[schema_version]
-                logger.debug(f"Loaded and cached module spec for kind '{kind}' schema {schema_version}")
-            else:
-                # Fallback to default spec if schema mapping not available
-                spec = getattr(module, "spec", {})
-                logger.debug(f"Loaded and cached module spec for kind '{kind}' (default/no schema mapping)")
-
-            return spec
-        except Exception as e:
-            raise ValueError(f"Error loading module specifications for kind '{kind}': {e}") from e
-
-    def _merge_specs(self, module_specs: dict, template_specs: dict) -> dict:
-        """Deep merge template specs with module specs using VariableCollection.
-
-        Uses VariableCollection's native merge() method for consistent merging logic.
-        Module specs are base, template specs override with origin tracking.
+            template_specs: Variables defined in template.yaml spec
         """
         """
-        # Create VariableCollection from module specs (base)
-        module_collection = VariableCollection(module_specs) if module_specs else VariableCollection({})
-
-        # Set origin for module variables
-        for section in module_collection.get_sections().values():
-            for variable in section.variables.values():
-                if not variable.origin:
-                    variable.origin = "module"
-
-        # Merge template specs into module specs (template overrides)
-        if template_specs:
-            merged_collection = module_collection.merge(template_specs, origin="template")
-        else:
-            merged_collection = module_collection
-
-        # Convert back to dict format
-        merged_spec = {}
-        for section_key, section in merged_collection.get_sections().items():
-            merged_spec[section_key] = section.to_dict()
-
-        return merged_spec
+        # Collect variables explicitly defined in template
+        defined_vars = set()
+        for section_data in (template_specs or {}).values():
+            if isinstance(section_data, dict) and "vars" in section_data:
+                defined_vars.update(section_data["vars"].keys())
+
+        # Get variables actually used in template files
+        used_vars = self.used_variables
+
+        # Find variables that are defined but not used
+        unused_vars = defined_vars - used_vars
+
+        if unused_vars:
+            # Show first N variables in warning, full list in debug
+            max_shown_vars = 10
+            shown_vars = sorted(list(unused_vars)[:max_shown_vars])
+            ellipsis = "..." if len(unused_vars) > max_shown_vars else ""
+            logger.warning(
+                f"Template '{self.id}' defines {len(unused_vars)} variable(s) that are not used in template files. "
+                f"Consider removing them from the spec: {', '.join(shown_vars)}{ellipsis}"
+            )
+            logger.debug(f"Template '{self.id}' unused variables: {sorted(unused_vars)}")
 
 
     def _collect_template_files(self) -> None:
     def _collect_template_files(self) -> None:
         """Collects all TemplateFile objects in the template directory."""
         """Collects all TemplateFile objects in the template directory."""
@@ -537,8 +486,6 @@ class Template:
     def _filter_specs_to_used(
     def _filter_specs_to_used(
         self,
         self,
         used_variables: set,
         used_variables: set,
-        merged_specs: dict,
-        _module_specs: dict,
         template_specs: dict,
         template_specs: dict,
     ) -> dict:
     ) -> dict:
         """Filter specs to only include variables used in templates using VariableCollection.
         """Filter specs to only include variables used in templates using VariableCollection.
@@ -552,15 +499,15 @@ class Template:
             if isinstance(section_data, dict) and "vars" in section_data:
             if isinstance(section_data, dict) and "vars" in section_data:
                 template_defined_vars.update(section_data["vars"].keys())
                 template_defined_vars.update(section_data["vars"].keys())
 
 
-        # Create VariableCollection from merged specs
-        merged_collection = VariableCollection(merged_specs)
+        # Create VariableCollection from template specs
+        template_collection = VariableCollection(template_specs)
 
 
         # Filter to only used variables (and sensitive ones that are template-defined)
         # Filter to only used variables (and sensitive ones that are template-defined)
         # We keep sensitive variables that are either:
         # We keep sensitive variables that are either:
         # 1. Actually used in template files, OR
         # 1. Actually used in template files, OR
         # 2. Explicitly defined in the template spec (even if not yet used)
         # 2. Explicitly defined in the template spec (even if not yet used)
         variables_to_keep = used_variables | template_defined_vars
         variables_to_keep = used_variables | template_defined_vars
-        filtered_collection = merged_collection.filter_to_used(variables_to_keep, keep_sensitive=False)
+        filtered_collection = template_collection.filter_to_used(variables_to_keep, keep_sensitive=False)
 
 
         # Convert back to dict format
         # Convert back to dict format
         filtered_specs = {}
         filtered_specs = {}
@@ -569,36 +516,6 @@ class Template:
 
 
         return filtered_specs
         return filtered_specs
 
 
-    def _validate_schema_version(self, module_schema: str, module_name: str) -> None:
-        """Validate that template schema version is supported by the module.
-
-        Args:
-            module_schema: Schema version supported by the module
-            module_name: Name of the module (for error messages)
-
-        Raises:
-            IncompatibleSchemaVersionError: If template schema > module schema
-        """
-        template_schema = self.schema_version
-
-        # Compare schema versions
-        if not is_compatible(module_schema, template_schema):
-            logger.error(
-                f"Template '{self.id}' uses schema version {template_schema}, "
-                f"but module '{module_name}' only supports up to {module_schema}"
-            )
-            raise IncompatibleSchemaVersionError(
-                template_id=self.id,
-                template_schema=template_schema,
-                module_schema=module_schema,
-                module_name=module_name,
-            )
-
-        logger.debug(
-            f"Template '{self.id}' schema version compatible: "
-            f"template uses {template_schema}, module supports {module_schema}"
-        )
-
     @staticmethod
     @staticmethod
     def _validate_kind(template_data: dict) -> None:
     def _validate_kind(template_data: dict) -> None:
         """Validate that template has required 'kind' field.
         """Validate that template has required 'kind' field.
@@ -865,20 +782,6 @@ class Template:
         """Get the spec section from template YAML data."""
         """Get the spec section from template YAML data."""
         return self._template_data.get("spec", {})
         return self._template_data.get("spec", {})
 
 
-    @property
-    def module_specs(self) -> dict:
-        """Get the spec from the module definition for this template's schema version."""
-        if self.__module_specs is None:
-            kind = self._template_data.get("kind")
-            self.__module_specs = self._load_module_specs_for_schema(kind, self.schema_version)
-        return self.__module_specs
-
-    @property
-    def merged_specs(self) -> dict:
-        if self.__merged_specs is None:
-            self.__merged_specs = self._merge_specs(self.module_specs, self.template_specs)
-        return self.__merged_specs
-
     @property
     @property
     def jinja_env(self) -> Environment:
     def jinja_env(self) -> Environment:
         if self.__jinja_env is None:
         if self.__jinja_env is None:
@@ -894,17 +797,35 @@ class Template:
     @property
     @property
     def variables(self) -> VariableCollection:
     def variables(self) -> VariableCollection:
         if self.__variables is None:
         if self.__variables is None:
+            # Warn about unused variables in spec
+            self._warn_about_unused_variables(self.template_specs)
+
             # Validate that all used variables are defined
             # Validate that all used variables are defined
-            self._validate_variable_definitions(self.used_variables, self.merged_specs)
+            self._validate_variable_definitions(self.used_variables, self.template_specs)
+
             # Filter specs to only used variables
             # Filter specs to only used variables
             filtered_specs = self._filter_specs_to_used(
             filtered_specs = self._filter_specs_to_used(
                 self.used_variables,
                 self.used_variables,
-                self.merged_specs,
-                self.module_specs,
                 self.template_specs,
                 self.template_specs,
             )
             )
 
 
             self.__variables = VariableCollection(filtered_specs)
             self.__variables = VariableCollection(filtered_specs)
-            # Sort sections: required first, then enabled, then disabled
-            self.__variables.sort_sections()
         return self.__variables
         return self.__variables
+
+    @property
+    def status(self) -> str:
+        """Get the status of the template.
+
+        Returns:
+            Status string: 'published' or 'draft'
+
+        Note:
+            The 'invalid' status is reserved for future use when template validation
+            is implemented without impacting list command performance.
+        """
+        # Check if template is marked as draft in metadata
+        if self.metadata.draft:
+            return TEMPLATE_STATUS_DRAFT
+
+        # Template is published (valid and not draft)
+        return TEMPLATE_STATUS_PUBLISHED

+ 3 - 1
cli/core/template/variable_collection.py

@@ -775,7 +775,9 @@ class VariableCollection:
             try:
             try:
                 variable = self._variable_map.get(var_name)
                 variable = self._variable_map.get(var_name)
                 if not variable:
                 if not variable:
-                    logger.warning(f"Variable '{var_name}' not found in template")
+                    logger.debug(
+                        f"Default value for '{var_name}' not applicable to this template (variable not defined)"
+                    )
                     continue
                     continue
 
 
                 # Check if variable's needs are satisfied
                 # Check if variable's needs are satisfied

+ 1 - 71
cli/modules/ansible/__init__.py

@@ -1,88 +1,18 @@
-"""Ansible module with multi-schema support."""
+"""Ansible module."""
 
 
 import logging
 import logging
-from collections import OrderedDict
 
 
 from ...core.module import Module
 from ...core.module import Module
 from ...core.registry import registry
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def _load_json_spec_as_dict(version: str) -> OrderedDict:
-    """Load JSON schema and convert to dict format for backward compatibility.
-
-    Args:
-        version: Schema version
-
-    Returns:
-        OrderedDict in the same format as Python specs
-    """
-    logger.debug(f"Loading ansible schema {version} from JSON")
-    json_spec = load_schema("ansible", version)
-
-    # Convert JSON array format to OrderedDict format
-    spec_dict = OrderedDict()
-    for section_data in json_spec:
-        section_key = section_data["key"]
-
-        # Build section dict
-        section_dict = {}
-        if "title" in section_data:
-            section_dict["title"] = section_data["title"]
-        if "description" in section_data:
-            section_dict["description"] = section_data["description"]
-        if "toggle" in section_data:
-            section_dict["toggle"] = section_data["toggle"]
-        if "required" in section_data:
-            section_dict["required"] = section_data["required"]
-        if "needs" in section_data:
-            section_dict["needs"] = section_data["needs"]
-
-        # Convert vars array to dict
-        vars_dict = OrderedDict()
-        for var_data in section_data["vars"]:
-            var_name = var_data["name"]
-            var_dict = {k: v for k, v in var_data.items() if k != "name"}
-            vars_dict[var_name] = var_dict
-
-        section_dict["vars"] = vars_dict
-        spec_dict[section_key] = section_dict
-
-    return spec_dict
-
-
-# Schema version mapping - loads JSON schemas on-demand
-class _SchemaDict(dict):
-    """Dict subclass that loads JSON schemas on-demand."""
-
-    def __getitem__(self, version):
-        if not has_schema("ansible", version):
-            raise KeyError(
-                f"Schema version {version} not found for ansible module. "
-                f"Available: {', '.join(list_versions('ansible'))}"
-            )
-        return _load_json_spec_as_dict(version)
-
-    def __contains__(self, version):
-        return has_schema("ansible", version)
-
-
-# Initialize schema dict
-SCHEMAS = _SchemaDict()
-
-# Default spec - load latest version
-spec = _load_json_spec_as_dict("1.0")
-
-
 class AnsibleModule(Module):
 class AnsibleModule(Module):
     """Ansible module."""
     """Ansible module."""
 
 
     name = "ansible"
     name = "ansible"
     description = "Manage Ansible configurations"
     description = "Manage Ansible configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 
 
 registry.register(AnsibleModule)
 registry.register(AnsibleModule)

+ 1 - 71
cli/modules/compose/__init__.py

@@ -1,7 +1,6 @@
-"""Docker Compose module with multi-schema support."""
+"""Docker Compose module."""
 
 
 import logging
 import logging
-from collections import OrderedDict
 from typing import Annotated
 from typing import Annotated
 
 
 from typer import Argument, Option
 from typer import Argument, Option
@@ -9,85 +8,16 @@ from typer import Argument, Option
 from ...core.module import Module
 from ...core.module import Module
 from ...core.module.base_commands import validate_templates
 from ...core.module.base_commands import validate_templates
 from ...core.registry import registry
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 from .validate import run_docker_validation
 from .validate import run_docker_validation
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def _load_json_spec_as_dict(version: str) -> OrderedDict:
-    """Load JSON schema and convert to dict format for backward compatibility.
-
-    Args:
-        version: Schema version
-
-    Returns:
-        OrderedDict in the same format as Python specs
-    """
-    logger.debug(f"Loading compose schema {version} from JSON")
-    json_spec = load_schema("compose", version)
-
-    # Convert JSON array format to OrderedDict format
-    spec_dict = OrderedDict()
-    for section_data in json_spec:
-        section_key = section_data["key"]
-
-        # Build section dict
-        section_dict = {}
-        if "title" in section_data:
-            section_dict["title"] = section_data["title"]
-        if "description" in section_data:
-            section_dict["description"] = section_data["description"]
-        if "toggle" in section_data:
-            section_dict["toggle"] = section_data["toggle"]
-        if "required" in section_data:
-            section_dict["required"] = section_data["required"]
-        if "needs" in section_data:
-            section_dict["needs"] = section_data["needs"]
-
-        # Convert vars array to dict
-        vars_dict = OrderedDict()
-        for var_data in section_data["vars"]:
-            var_name = var_data["name"]
-            var_dict = {k: v for k, v in var_data.items() if k != "name"}
-            vars_dict[var_name] = var_dict
-
-        section_dict["vars"] = vars_dict
-        spec_dict[section_key] = section_dict
-
-    return spec_dict
-
-
-# Schema version mapping - loads JSON schemas on-demand
-class _SchemaDict(dict):
-    """Dict subclass that loads JSON schemas on-demand."""
-
-    def __getitem__(self, version):
-        if not has_schema("compose", version):
-            raise KeyError(
-                f"Schema version {version} not found for compose module. "
-                f"Available: {', '.join(list_versions('compose'))}"
-            )
-        return _load_json_spec_as_dict(version)
-
-    def __contains__(self, version):
-        return has_schema("compose", version)
-
-
-# Initialize schema dict
-SCHEMAS = _SchemaDict()
-
-# Default spec - load latest version
-spec = _load_json_spec_as_dict("1.2")
-
-
 class ComposeModule(Module):
 class ComposeModule(Module):
     """Docker Compose module with extended validation."""
     """Docker Compose module with extended validation."""
 
 
     name = "compose"
     name = "compose"
     description = "Manage Docker Compose configurations"
     description = "Manage Docker Compose configurations"
-    schema_version = "1.2"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
     def validate(  # noqa: PLR0913
     def validate(  # noqa: PLR0913
         self,
         self,

+ 1 - 70
cli/modules/helm/__init__.py

@@ -1,87 +1,18 @@
-"""Helm module with multi-schema support."""
+"""Helm module."""
 
 
 import logging
 import logging
-from collections import OrderedDict
 
 
 from ...core.module import Module
 from ...core.module import Module
 from ...core.registry import registry
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def _load_json_spec_as_dict(version: str) -> OrderedDict:
-    """Load JSON schema and convert to dict format for backward compatibility.
-
-    Args:
-        version: Schema version
-
-    Returns:
-        OrderedDict in the same format as Python specs
-    """
-    logger.debug(f"Loading helm schema {version} from JSON")
-    json_spec = load_schema("helm", version)
-
-    # Convert JSON array format to OrderedDict format
-    spec_dict = OrderedDict()
-    for section_data in json_spec:
-        section_key = section_data["key"]
-
-        # Build section dict
-        section_dict = {}
-        if "title" in section_data:
-            section_dict["title"] = section_data["title"]
-        if "description" in section_data:
-            section_dict["description"] = section_data["description"]
-        if "toggle" in section_data:
-            section_dict["toggle"] = section_data["toggle"]
-        if "required" in section_data:
-            section_dict["required"] = section_data["required"]
-        if "needs" in section_data:
-            section_dict["needs"] = section_data["needs"]
-
-        # Convert vars array to dict
-        vars_dict = OrderedDict()
-        for var_data in section_data["vars"]:
-            var_name = var_data["name"]
-            var_dict = {k: v for k, v in var_data.items() if k != "name"}
-            vars_dict[var_name] = var_dict
-
-        section_dict["vars"] = vars_dict
-        spec_dict[section_key] = section_dict
-
-    return spec_dict
-
-
-# Schema version mapping - loads JSON schemas on-demand
-class _SchemaDict(dict):
-    """Dict subclass that loads JSON schemas on-demand."""
-
-    def __getitem__(self, version):
-        if not has_schema("helm", version):
-            raise KeyError(
-                f"Schema version {version} not found for helm module. Available: {', '.join(list_versions('helm'))}"
-            )
-        return _load_json_spec_as_dict(version)
-
-    def __contains__(self, version):
-        return has_schema("helm", version)
-
-
-# Initialize schema dict
-SCHEMAS = _SchemaDict()
-
-# Default spec - load latest version
-spec = _load_json_spec_as_dict("1.0")
-
-
 class HelmModule(Module):
 class HelmModule(Module):
     """Helm module."""
     """Helm module."""
 
 
     name = "helm"
     name = "helm"
     description = "Manage Helm configurations"
     description = "Manage Helm configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 
 
 registry.register(HelmModule)
 registry.register(HelmModule)

+ 1 - 71
cli/modules/kubernetes/__init__.py

@@ -1,88 +1,18 @@
-"""Kubernetes module with multi-schema support."""
+"""Kubernetes module."""
 
 
 import logging
 import logging
-from collections import OrderedDict
 
 
 from ...core.module import Module
 from ...core.module import Module
 from ...core.registry import registry
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def _load_json_spec_as_dict(version: str) -> OrderedDict:
-    """Load JSON schema and convert to dict format for backward compatibility.
-
-    Args:
-        version: Schema version
-
-    Returns:
-        OrderedDict in the same format as Python specs
-    """
-    logger.debug(f"Loading kubernetes schema {version} from JSON")
-    json_spec = load_schema("kubernetes", version)
-
-    # Convert JSON array format to OrderedDict format
-    spec_dict = OrderedDict()
-    for section_data in json_spec:
-        section_key = section_data["key"]
-
-        # Build section dict
-        section_dict = {}
-        if "title" in section_data:
-            section_dict["title"] = section_data["title"]
-        if "description" in section_data:
-            section_dict["description"] = section_data["description"]
-        if "toggle" in section_data:
-            section_dict["toggle"] = section_data["toggle"]
-        if "required" in section_data:
-            section_dict["required"] = section_data["required"]
-        if "needs" in section_data:
-            section_dict["needs"] = section_data["needs"]
-
-        # Convert vars array to dict
-        vars_dict = OrderedDict()
-        for var_data in section_data["vars"]:
-            var_name = var_data["name"]
-            var_dict = {k: v for k, v in var_data.items() if k != "name"}
-            vars_dict[var_name] = var_dict
-
-        section_dict["vars"] = vars_dict
-        spec_dict[section_key] = section_dict
-
-    return spec_dict
-
-
-# Schema version mapping - loads JSON schemas on-demand
-class _SchemaDict(dict):
-    """Dict subclass that loads JSON schemas on-demand."""
-
-    def __getitem__(self, version):
-        if not has_schema("kubernetes", version):
-            raise KeyError(
-                f"Schema version {version} not found for kubernetes module. "
-                f"Available: {', '.join(list_versions('kubernetes'))}"
-            )
-        return _load_json_spec_as_dict(version)
-
-    def __contains__(self, version):
-        return has_schema("kubernetes", version)
-
-
-# Initialize schema dict
-SCHEMAS = _SchemaDict()
-
-# Default spec - load latest version
-spec = _load_json_spec_as_dict("1.0")
-
-
 class KubernetesModule(Module):
 class KubernetesModule(Module):
     """Kubernetes module."""
     """Kubernetes module."""
 
 
     name = "kubernetes"
     name = "kubernetes"
     description = "Manage Kubernetes configurations"
     description = "Manage Kubernetes configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 
 
 registry.register(KubernetesModule)
 registry.register(KubernetesModule)

+ 1 - 70
cli/modules/packer/__init__.py

@@ -1,87 +1,18 @@
-"""Packer module with multi-schema support."""
+"""Packer module."""
 
 
 import logging
 import logging
-from collections import OrderedDict
 
 
 from ...core.module import Module
 from ...core.module import Module
 from ...core.registry import registry
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def _load_json_spec_as_dict(version: str) -> OrderedDict:
-    """Load JSON schema and convert to dict format for backward compatibility.
-
-    Args:
-        version: Schema version
-
-    Returns:
-        OrderedDict in the same format as Python specs
-    """
-    logger.debug(f"Loading packer schema {version} from JSON")
-    json_spec = load_schema("packer", version)
-
-    # Convert JSON array format to OrderedDict format
-    spec_dict = OrderedDict()
-    for section_data in json_spec:
-        section_key = section_data["key"]
-
-        # Build section dict
-        section_dict = {}
-        if "title" in section_data:
-            section_dict["title"] = section_data["title"]
-        if "description" in section_data:
-            section_dict["description"] = section_data["description"]
-        if "toggle" in section_data:
-            section_dict["toggle"] = section_data["toggle"]
-        if "required" in section_data:
-            section_dict["required"] = section_data["required"]
-        if "needs" in section_data:
-            section_dict["needs"] = section_data["needs"]
-
-        # Convert vars array to dict
-        vars_dict = OrderedDict()
-        for var_data in section_data["vars"]:
-            var_name = var_data["name"]
-            var_dict = {k: v for k, v in var_data.items() if k != "name"}
-            vars_dict[var_name] = var_dict
-
-        section_dict["vars"] = vars_dict
-        spec_dict[section_key] = section_dict
-
-    return spec_dict
-
-
-# Schema version mapping - loads JSON schemas on-demand
-class _SchemaDict(dict):
-    """Dict subclass that loads JSON schemas on-demand."""
-
-    def __getitem__(self, version):
-        if not has_schema("packer", version):
-            raise KeyError(
-                f"Schema version {version} not found for packer module. Available: {', '.join(list_versions('packer'))}"
-            )
-        return _load_json_spec_as_dict(version)
-
-    def __contains__(self, version):
-        return has_schema("packer", version)
-
-
-# Initialize schema dict
-SCHEMAS = _SchemaDict()
-
-# Default spec - load latest version
-spec = _load_json_spec_as_dict("1.0")
-
-
 class PackerModule(Module):
 class PackerModule(Module):
     """Packer module."""
     """Packer module."""
 
 
     name = "packer"
     name = "packer"
     description = "Manage Packer configurations"
     description = "Manage Packer configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 
 
 registry.register(PackerModule)
 registry.register(PackerModule)

+ 1 - 71
cli/modules/terraform/__init__.py

@@ -1,88 +1,18 @@
-"""Terraform module with multi-schema support."""
+"""Terraform module."""
 
 
 import logging
 import logging
-from collections import OrderedDict
 
 
 from ...core.module import Module
 from ...core.module import Module
 from ...core.registry import registry
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def _load_json_spec_as_dict(version: str) -> OrderedDict:
-    """Load JSON schema and convert to dict format for backward compatibility.
-
-    Args:
-        version: Schema version
-
-    Returns:
-        OrderedDict in the same format as Python specs
-    """
-    logger.debug(f"Loading terraform schema {version} from JSON")
-    json_spec = load_schema("terraform", version)
-
-    # Convert JSON array format to OrderedDict format
-    spec_dict = OrderedDict()
-    for section_data in json_spec:
-        section_key = section_data["key"]
-
-        # Build section dict
-        section_dict = {}
-        if "title" in section_data:
-            section_dict["title"] = section_data["title"]
-        if "description" in section_data:
-            section_dict["description"] = section_data["description"]
-        if "toggle" in section_data:
-            section_dict["toggle"] = section_data["toggle"]
-        if "required" in section_data:
-            section_dict["required"] = section_data["required"]
-        if "needs" in section_data:
-            section_dict["needs"] = section_data["needs"]
-
-        # Convert vars array to dict
-        vars_dict = OrderedDict()
-        for var_data in section_data["vars"]:
-            var_name = var_data["name"]
-            var_dict = {k: v for k, v in var_data.items() if k != "name"}
-            vars_dict[var_name] = var_dict
-
-        section_dict["vars"] = vars_dict
-        spec_dict[section_key] = section_dict
-
-    return spec_dict
-
-
-# Schema version mapping - loads JSON schemas on-demand
-class _SchemaDict(dict):
-    """Dict subclass that loads JSON schemas on-demand."""
-
-    def __getitem__(self, version):
-        if not has_schema("terraform", version):
-            raise KeyError(
-                f"Schema version {version} not found for terraform module. "
-                f"Available: {', '.join(list_versions('terraform'))}"
-            )
-        return _load_json_spec_as_dict(version)
-
-    def __contains__(self, version):
-        return has_schema("terraform", version)
-
-
-# Initialize schema dict
-SCHEMAS = _SchemaDict()
-
-# Default spec - load latest version
-spec = _load_json_spec_as_dict("1.0")
-
-
 class TerraformModule(Module):
 class TerraformModule(Module):
     """Terraform module."""
     """Terraform module."""
 
 
     name = "terraform"
     name = "terraform"
     description = "Manage Terraform configurations"
     description = "Manage Terraform configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 
 
 registry.register(TerraformModule)
 registry.register(TerraformModule)

+ 7 - 1
library/ansible/checkmk-install-agent/template.yaml

@@ -16,8 +16,14 @@ metadata:
     id: checkmk
     id: checkmk
   draft: false
   draft: false
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
+  general:
+    vars:
+      target_hosts:
+        description: Target hosts
+        type: str
+        required: true
   checkmk:
   checkmk:
     title: Checkmk Configuration
     title: Checkmk Configuration
     vars:
     vars:

+ 7 - 1
library/ansible/checkmk-manage-host/template.yaml

@@ -16,8 +16,14 @@ metadata:
     id: checkmk
     id: checkmk
   draft: false
   draft: false
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
+  general:
+    vars:
+      target_hosts:
+        description: Target hosts or group
+        type: str
+        required: true
   checkmk:
   checkmk:
     title: Checkmk Configuration
     title: Checkmk Configuration
     vars:
     vars:

+ 5 - 1
library/ansible/docker-certs-enable/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,9 +17,14 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
+      target_hosts:
+        description: Target hosts
+        type: str
+        required: true
       playbook_name:
       playbook_name:
         default: Docker Certs enable
         default: Docker Certs enable
       become:
       become:

+ 5 - 1
library/ansible/docker-certs/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,9 +17,14 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
+      target_hosts:
+        description: Target hosts
+        type: str
+        required: true
       playbook_name:
       playbook_name:
         default: Docker Certs
         default: Docker Certs
       become:
       become:

+ 4 - 4
library/ansible/docker-install-ubuntu/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,10 +17,11 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       target_hosts:
       target_hosts:
-        type: string
-        default: all
-        description: Target hosts for the Ansible playbook.
+        type: str
+        description: Target hosts or group
+        required: true

+ 5 - 1
library/ansible/docker-prune/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,9 +17,14 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
+      target_hosts:
+        description: Target hosts
+        type: str
+        required: true
       playbook_name:
       playbook_name:
         default: Clean docker
         default: Clean docker
       become:
       become:

+ 5 - 1
library/ansible/ubuntu-add-sshkey/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,9 +17,14 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
+      target_hosts:
+        description: Target hosts
+        type: str
+        required: true
       playbook_name:
       playbook_name:
         default: Add ssh key
         default: Add ssh key
       become:
       become:

+ 1 - 1
library/ansible/ubuntu-apt-update/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,6 +17,7 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:

+ 5 - 1
library/ansible/ubuntu-vm-core/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: ansible
 kind: ansible
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -18,9 +17,14 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
+      target_hosts:
+        description: Target hosts
+        type: str
+        required: true
       playbook_name:
       playbook_name:
         default: Install core packages for virtual machines
         default: Install core packages for virtual machines
       become:
       become:

+ 135 - 21
library/compose/adguardhome/template.yaml

@@ -2,23 +2,37 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: AdGuard Home
   name: AdGuard Home
-  description: |-
-    Network-wide software for blocking ads and tracking. AdGuard Home operates as a DNS server that
+  description: 'Network-wide software for blocking ads and tracking. AdGuard Home operates as a DNS server that
+
     re-routes tracking domains to a "black hole", thus preventing your devices from connecting to those servers.
     re-routes tracking domains to a "black hole", thus preventing your devices from connecting to those servers.
+
     It features advanced DNS filtering, parental controls, safe browsing, and HTTPS/DNS-over-TLS/DNS-over-QUIC support.
     It features advanced DNS filtering, parental controls, safe browsing, and HTTPS/DNS-over-TLS/DNS-over-QUIC support.
+
     ## Prerequisites
     ## Prerequisites
+
     - :info: During the initial setup, AdGuard Home runs an HTTP server on port 3000 to guide you through configuration.
     - :info: During the initial setup, AdGuard Home runs an HTTP server on port 3000 to guide you through configuration.
+
     **With Traefik enabled:** Access initial setup via container IP at `http://<container-ip>:3000`.
     **With Traefik enabled:** Access initial setup via container IP at `http://<container-ip>:3000`.
+
     After setup completes, access the admin interface via the configured domain.
     After setup completes, access the admin interface via the configured domain.
+
     - :warning: **Security Notice:** The initial setup on port 3000 uses an unencrypted HTTP connection.
     - :warning: **Security Notice:** The initial setup on port 3000 uses an unencrypted HTTP connection.
+
     Only use this for initial configuration and disable it (`initial_setup=false`) after setup is complete.
     Only use this for initial configuration and disable it (`initial_setup=false`) after setup is complete.
+
     - :warning: If you require DHCP functionality or want AdGuard Home to bind directly to port 53,
     - :warning: If you require DHCP functionality or want AdGuard Home to bind directly to port 53,
+
     you must set `network_mode` to `host` or `macvlan`. Note this exposes all container ports directly on the host.
     you must set `network_mode` to `host` or `macvlan`. Note this exposes all container ports directly on the host.
-    You can't use `traefik_enabled` in this case!
+
+    You can''t use `traefik_enabled` in this case!
+
     ## References
     ## References
+
     - **Project:** https://adguard.com/adguard-home/overview.html
     - **Project:** https://adguard.com/adguard-home/overview.html
+
     - **Documentation:** https://github.com/AdguardTeam/AdGuardHome/wiki
     - **Documentation:** https://github.com/AdguardTeam/AdGuardHome/wiki
-    - **GitHub:** https://github.com/AdguardTeam/AdGuardHome
+
+    - **GitHub:** https://github.com/AdguardTeam/AdGuardHome'
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: adguard-home
     id: adguard-home
@@ -29,46 +43,86 @@ metadata:
     - traefik
     - traefik
     - network
     - network
     - volume
     - volume
-  next_steps:
-schema: 1.2
+  next_steps: null
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: adguardhome
         default: adguardhome
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       initial_setup:
       initial_setup:
         description: Enable initial setup wizard on port 3000 (only used without Traefik)
         description: Enable initial setup wizard on port 3000 (only used without Traefik)
         type: bool
         type: bool
         default: true
         default: true
-        extra: >
-          Port 3000 is only used during the initial setup wizard when Traefik is disabled.
-          With Traefik enabled, access setup via container IP instead.
-          After completing setup, AdGuard Home switches to port 80 and port 3000 becomes inactive.
-  traefik:
-    vars:
-      traefik_host:
-        default: adguardhome
+        extra: 'Port 3000 is only used during the initial setup wizard when Traefik is disabled. With Traefik enabled, access
+          setup via container IP instead. After completing setup, AdGuard Home switches to port 80 and port 3000 becomes inactive.
+          '
   network:
   network:
     vars:
     vars:
       network_mode:
       network_mode:
-        extra: >
-          Use 'host' mode if you need DHCP functionality or want AdGuard Home to bind directly to port 53.
+        extra: 'Use ''host'' mode if you need DHCP functionality or want AdGuard Home to bind directly to port 53.
+
+          '
       network_name:
       network_name:
         default: adguardhome_network
         default: adguardhome_network
+      network_macvlan_ipv4_address:
+        type: str
+        default: 192.168.1.253
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_parent_interface:
+        type: str
+        default: eth0
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_subnet:
+        type: str
+        default: 192.168.1.0/24
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_gateway:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
         default: 80
         default: 80
       ports_https:
       ports_https:
         default: 443
         default: 443
+      ports_dns:
+        type: int
+        default: 53
+        required: true
       ports_initial:
       ports_initial:
         description: Initial setup wizard port (only when Traefik is disabled)
         description: Initial setup wizard port (only when Traefik is disabled)
         type: int
         type: int
         default: 3000
         default: 3000
-        needs: ["traefik_enabled=false", "initial_setup=true"]
-        extra: >
-          Only used during first-time setup without Traefik. After configuration, port becomes inactive.
-          With Traefik, access setup via container IP instead.
+        needs:
+          - traefik_enabled=false
+          - initial_setup=true
+        extra: 'Only used during first-time setup without Traefik. After configuration, port becomes inactive. With Traefik,
+          access setup via container IP instead.
+
+          '
       ports_tls:
       ports_tls:
         description: DNS over TLS Port
         description: DNS over TLS Port
         type: int
         type: int
@@ -78,4 +132,64 @@ spec:
         description: DNSCrypt Port
         description: DNSCrypt Port
         type: int
         type: int
         default: 5443
         default: 5443
-        required: true
+        required: true
+  traefik:
+    vars:
+      traefik_host:
+        default: adguardhome
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true

+ 1 - 1
library/compose/alloy/config/config.alloy.j2

@@ -174,7 +174,7 @@ prometheus.exporter.unix "metrics" {
   filesystem {
   filesystem {
     fs_types_exclude     = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|tmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
     fs_types_exclude     = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|tmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
     mount_points_exclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
     mount_points_exclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
-    mount_timeout        = "5s"
+    mount_out        = "5s"
   }
   }
   netclass {
   netclass {
     ignored_devices = "^(veth.*|cali.*|[a-f0-9]{15})$"
     ignored_devices = "^(veth.*|cali.*|[a-f0-9]{15})$"

+ 44 - 1
library/compose/alloy/template.yaml

@@ -20,12 +20,25 @@ metadata:
     provider: selfh
     provider: selfh
     id: grafana
     id: grafana
   next_steps:
   next_steps:
-schema: 1.2
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: alloy
         default: alloy
+      container_hostname:
+        description: Container internal hostname
+        type: str
+      restart_policy:
+        description: Container restart policy
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   logs:
   logs:
     title: Log Collection
     title: Log Collection
     toggle: logs_enabled
     toggle: logs_enabled
@@ -69,12 +82,42 @@ spec:
         type: bool
         type: bool
         default: true
         default: true
   ports:
   ports:
+    title: Ports
     vars:
     vars:
       ports_webui:
       ports_webui:
         description: Port for Alloy web UI
         description: Port for Alloy web UI
         type: int
         type: int
         default: 12345
         default: 12345
   traefik:
   traefik:
+    title: Traefik
+    toggle: traefik_enabled
     vars:
     vars:
+      traefik_enabled:
+        description: Enable Traefik reverse proxy integration
+        type: bool
+        default: false
+      traefik_network:
+        description: Traefik network name
+        type: str
+        default: traefik
+        required: true
       traefik_host:
       traefik_host:
         default: alloy
         default: alloy
+      traefik_domain:
+        description: Base domain (e.g., example.com)
+        type: str
+        default: home.arpa
+        required: true
+  traefik_tls:
+    title: Traefik TLS/SSL
+    toggle: traefik_tls_enabled
+    vars:
+      traefik_tls_enabled:
+        description: Enable HTTPS/TLS
+        type: bool
+        default: true
+      traefik_tls_certresolver:
+        description: Traefik certificate resolver name
+        type: str
+        default: cloudflare
+        required: true

+ 136 - 11
library/compose/authentik/template.yaml

@@ -2,48 +2,85 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: Authentik
   name: Authentik
-  description: |-
-    Integrate Authentik Single Sign-On (SSO) for secure and streamlined user authentication.
+  description: 'Integrate Authentik Single Sign-On (SSO) for secure and streamlined user authentication.
+
     Authentik is an open-source identity provider that supports various authentication protocols.
     Authentik is an open-source identity provider that supports various authentication protocols.
+
     This configuration enables OAuth-based SSO, allowing users to log in using their Authentik
     This configuration enables OAuth-based SSO, allowing users to log in using their Authentik
+
     credentials, enhancing security and user experience.
     credentials, enhancing security and user experience.
+
     ## Prerequisites
     ## Prerequisites
+
     - :warning: The `authentik_secret_key` must be generated using the following command
     - :warning: The `authentik_secret_key` must be generated using the following command
+
     according to the official documentation.
     according to the official documentation.
+
     ```bash
     ```bash
-    echo "$(openssl rand -base64 60 | tr -d '\n')"
+
+    echo "$(openssl rand -base64 60 | tr -d ''\n'')"
+
     ```
     ```
+
     ## References
     ## References
+
     * **Project:** https://goauthentik.io/
     * **Project:** https://goauthentik.io/
+
     * **Documentation:** https://goauthentik.io/docs/
     * **Documentation:** https://goauthentik.io/docs/
-    * **GitHub:** https://github.com/goauthentik/authentik
+
+    * **GitHub:** https://github.com/goauthentik/authentik'
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: authentik
     id: authentik
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
     ```bash
+
     Username: akadmin
     Username: akadmin
+
     Password: {{ authentik_admin_password }}
     Password: {{ authentik_admin_password }}
-    ```
+
+    ```'
   version: 2025.10.3
   version: 2025.10.3
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-16'
   date: '2025-12-16'
   tags:
   tags:
     - traefik
     - traefik
     - volume
     - volume
-schema: "1.2"
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: authentik
         default: authentik
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   database:
   database:
     vars:
     vars:
-      database_name:
-        default: authentik
+      database_password:
+        description: Database password
+        type: str
+        sensitive: true
+        required: true
       database_user:
       database_user:
-        default: authentik
+        type: str
+        default: ''
+        description: The database user
+      database_name:
+        type: str
+        default: ''
+        description: The database name
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -54,6 +91,18 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: authentik
         default: authentik
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
   authentik:
   authentik:
     description: Configure Authentik application settings
     description: Configure Authentik application settings
     required: true
     required: true
@@ -72,3 +121,79 @@ spec:
       authentik_error_reporting:
       authentik_error_reporting:
         description: Enable error reporting to Authentik developers
         description: Enable error reporting to Authentik developers
         type: bool
         type: bool
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true
+  email:
+    vars:
+      email_host:
+        description: SMTP server hostname
+        type: str
+        required: true
+      email_port:
+        description: SMTP server port
+        type: int
+        default: 25
+        required: true
+      email_username:
+        description: SMTP username
+        type: str
+        required: true
+      email_password:
+        description: SMTP password
+        type: str
+        sensitive: true
+        required: true
+      email_from:
+        description: From email address
+        type: str
+        required: true
+      email_enabled:
+        type: bool
+        default: false
+        description: Enable email integration
+      email_encryption:
+        type: str
+        default: tls
+        description: The email encryption type

+ 95 - 6
library/compose/bind9/template.yaml

@@ -2,16 +2,20 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: BIND9
   name: BIND9
-  description: |-
-    BIND9 is the most widely used DNS server on the Internet.
+  description: 'BIND9 is the most widely used DNS server on the Internet.
+
     This template provides an authoritative and recursive DNS server with example zones,
     This template provides an authoritative and recursive DNS server with example zones,
+
     TSIG authentication for secure zone transfers, and DNSSEC support.
     TSIG authentication for secure zone transfers, and DNSSEC support.
+
     ## References
     ## References
+
     * **Project:** https://www.isc.org/bind/
     * **Project:** https://www.isc.org/bind/
-    * **Documentation:** https://bind9.readthedocs.io/
+
+    * **Documentation:** https://bind9.readthedocs.io/'
   version: 9.20-24.10_edge
   version: 9.20-24.10_edge
   author: Christian Lempa
   author: Christian Lempa
-  date: "2025-10-02"
+  date: '2025-10-02'
   tags:
   tags:
     - network
     - network
     - volume
     - volume
@@ -19,7 +23,7 @@ metadata:
     provider: selfh
     provider: selfh
     id: bind-9
     id: bind-9
   draft: true
   draft: true
-schema: "1.2"
+schema: '1.2'
 spec:
 spec:
   dns_security:
   dns_security:
     title: dns_security
     title: dns_security
@@ -42,8 +46,93 @@ spec:
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
-        needs: [tsig_enabled=true]
+        needs:
+          - tsig_enabled=true
+  network:
+    vars:
+      network_name:
+        type: str
+        required: true
+      network_macvlan_ipv4_address:
+        type: str
+        default: 192.168.1.253
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_parent_interface:
+        type: str
+        default: eth0
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_subnet:
+        type: str
+        default: 192.168.1.0/24
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_gateway:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
+      network_mode:
+        type: str
+        default: bridge
+        description: The network mode for the container
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: bind9
         default: bind9
+      container_hostname:
+        type: str
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true

+ 60 - 7
library/compose/checkmk/template.yaml

@@ -5,32 +5,58 @@ metadata:
     provider: selfh
     provider: selfh
     id: checkmk
     id: checkmk
   name: Checkmk
   name: Checkmk
-  description: |-
-    Checkmk is a comprehensive IT monitoring solution that provides real-time insights
+  description: 'Checkmk is a comprehensive IT monitoring solution that provides real-time insights
+
     into the health and performance of your infrastructure, applications, and services.
     into the health and performance of your infrastructure, applications, and services.
+
     It offers a wide range of monitoring capabilities, including server, network, cloud,
     It offers a wide range of monitoring capabilities, including server, network, cloud,
+
     and application monitoring, with an emphasis on ease of use and scalability.
     and application monitoring, with an emphasis on ease of use and scalability.
+
     ## References
     ## References
+
     * **Project:** https://checkmk.com/
     * **Project:** https://checkmk.com/
+
     * **Documentation:** https://docs.checkmk.com/latest/en/
     * **Documentation:** https://docs.checkmk.com/latest/en/
-    * **GitHub:** https://github.com/tribe29/checkmk
-  next_steps: |-
-    Log in with your initial admin user:
+
+    * **GitHub:** https://github.com/tribe29/checkmk'
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
     ```bash
+
     Username: cmkadmin
     Username: cmkadmin
+
     Password: {{ cmk_password }}
     Password: {{ cmk_password }}
-    ```
+
+    ```'
   version: 2.4.0-latest
   version: 2.4.0-latest
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-10'
   date: '2025-12-10'
   tags:
   tags:
     - traefik
     - traefik
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: checkmk
         default: checkmk
+      container_timezone:
+        type: str
+      user_uid:
+        type: int
+        default: 1000
+      user_gid:
+        type: int
+        default: 1000
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       cmk_password:
       cmk_password:
         type: str
         type: str
         description: CheckMK admin password
         description: CheckMK admin password
@@ -46,6 +72,18 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: checkmk
         default: checkmk
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -55,3 +93,18 @@ spec:
         type: int
         type: int
         default: 5000
         default: 5000
         required: true
         required: true
+      ports_snmp:
+        description: SNMP trap port
+        type: int
+        default: 162
+        required: true
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS

+ 41 - 4
library/compose/dockge/template.yaml

@@ -5,24 +5,39 @@ metadata:
     provider: selfh
     provider: selfh
     id: dockge
     id: dockge
   name: Dockge
   name: Dockge
-  description: |-
-    Dockge is a powerful Docker management platform that simplifies container orchestration and monitoring.
+  description: 'Dockge is a powerful Docker management platform that simplifies container orchestration and monitoring.
+
     It provides an intuitive web interface to manage Docker containers, images, networks, and volumes with ease.
     It provides an intuitive web interface to manage Docker containers, images, networks, and volumes with ease.
+
     ## Prerequisites
     ## Prerequisites
+
     * **Project:** https://dockge.com/
     * **Project:** https://dockge.com/
+
     * **Documentation:** https://docs.dockge.com/
     * **Documentation:** https://docs.dockge.com/
-    * **GitHub:** https://github.com/dockge/dockge
+
+    * **GitHub:** https://github.com/dockge/dockge'
   version: 1.5.0
   version: 1.5.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-09-28'
   date: '2025-09-28'
   tags:
   tags:
     - traefik
     - traefik
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: dockge
         default: dockge
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       stacks_path:
       stacks_path:
         type: str
         type: str
         description: Docker Compose Path
         description: Docker Compose Path
@@ -32,6 +47,28 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: dockge
         default: dockge
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:

+ 78 - 8
library/compose/gitea/template.yaml

@@ -2,18 +2,27 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: Gitea
   name: Gitea
-  description: |-
-    Self-hosted Git service with web interface. Gitea is a painless, self-hosted Git service
-    written in Go. It's similar to GitHub, Bitbucket, and GitLab, providing Git repository
+  description: 'Self-hosted Git service with web interface. Gitea is a painless, self-hosted Git service
+
+    written in Go. It''s similar to GitHub, Bitbucket, and GitLab, providing Git repository
+
     hosting, code review, team collaboration, and more.
     hosting, code review, team collaboration, and more.
+
     ## Prerequisites
     ## Prerequisites
+
     - :info: Gitea supports multiple database backends. You can choose between SQLite (default),
     - :info: Gitea supports multiple database backends. You can choose between SQLite (default),
+
     PostgreSQL, or MySQL. SQLite is suitable for small deployments, while PostgreSQL and MySQL
     PostgreSQL, or MySQL. SQLite is suitable for small deployments, while PostgreSQL and MySQL
+
     are recommended for larger installations.
     are recommended for larger installations.
+
     ## References
     ## References
+
     - **Project:** https://gitea.io/
     - **Project:** https://gitea.io/
+
     - **Documentation:** https://docs.gitea.io/
     - **Documentation:** https://docs.gitea.io/
-    - **GitHub:** https://github.com/go-gitea/gitea
+
+    - **GitHub:** https://github.com/go-gitea/gitea'
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: gitea
     id: gitea
@@ -22,23 +31,62 @@ metadata:
   date: '2025-12-19'
   date: '2025-12-19'
   tags:
   tags:
     - traefik
     - traefik
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: gitea
         default: gitea
+      container_timezone:
+        type: str
+      user_uid:
+        type: int
+        default: 1000
+      user_gid:
+        type: int
+        default: 1000
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       gitea_url:
       gitea_url:
-        description: "Public URL"
+        description: Public URL
         type: str
         type: str
-        needs: ["traefik_enabled=false"]
-        default: "https://git.example.com"
+        needs:
+          - traefik_enabled=false
+        default: https://git.example.com
   database:
   database:
     vars:
     vars:
+      database_type:
+        type: enum
+        options:
+          - sqlite
+          - postgres
+          - mysql
+        default: sqlite
+        required: true
+      database_host:
+        type: str
+        needs:
+          - database_external=true;database_type=postgres,mysql
+        required: true
       database_name:
       database_name:
         default: gitea
         default: gitea
       database_user:
       database_user:
         default: gitea
         default: gitea
+      database_password:
+        type: str
+        sensitive: true
+        required: true
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -49,3 +97,25 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: gitea
         default: gitea
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS

+ 10 - 1
library/compose/gitlab-runner/template.yaml

@@ -19,4 +19,13 @@ metadata:
   draft: true
   draft: true
   next_steps: ""
   next_steps: ""
 schema: "1.2"
 schema: "1.2"
-spec: {}
+spec:
+  general:
+    vars:
+      service_name:
+        default: gitlab-runner
+      restart_policy:
+        type: enum
+        options: [unless-stopped, always, on-failure, "no"]
+        default: unless-stopped
+        required: true

+ 0 - 2
library/compose/gitlab/.env.j2

@@ -1,3 +1 @@
-{% if not swarm_enabled %}
 GITLAB_ROOT_PASSWORD={{ root_password }}
 GITLAB_ROOT_PASSWORD={{ root_password }}
-{% endif %}

+ 0 - 0
library/compose/gitlab/.env.password.j2


+ 0 - 0
library/compose/gitlab/.env.registry.j2


+ 6 - 130
library/compose/gitlab/compose.yaml.j2

@@ -1,12 +1,9 @@
 services:
 services:
   {{ service_name }}:
   {{ service_name }}:
-    image: docker.io/gitlab/gitlab-ce:18.5.4-ce.0
-    {% if not swarm_enabled %}
+    image: docker.io/gitlab/gitlab-ce:18.6.1-ce.0
     restart: {{ restart_policy }}
     restart: {{ restart_policy }}
-    {% endif %}
     shm_size: '256m'
     shm_size: '256m'
-    environment:
-      - 
+    env_file: .env
     {% if traefik_enabled %}
     {% if traefik_enabled %}
     networks:
     networks:
       {{ traefik_network }}:
       {{ traefik_network }}:
@@ -16,26 +13,15 @@ services:
       - "{{ ports_http }}:80"
       - "{{ ports_http }}:80"
       {% endif %}
       {% endif %}
       - "{{ ports_ssh }}:22"
       - "{{ ports_ssh }}:22"
-      {% if registry_enabled %}
+      {% if registry_enabled and not traefik_enabled %}
       - "{{ ports_registry }}:5000"
       - "{{ ports_registry }}:5000"
       {% endif %}
       {% endif %}
     volumes:
     volumes:
-      {% if volume_mode == 'mount' %}
-      {% if not swarm_enabled %}
-      - {{ volume_mount_path }}/config/gitlab.rb:/etc/gitlab/gitlab.rb:ro
-      {% endif %}
-      - {{ volume_mount_path }}/config:/etc/gitlab
-      - {{ volume_mount_path }}/logs:/var/log/gitlab
-      - {{ volume_mount_path }}/data:/var/opt/gitlab
-      {% else %}
-      {% if not swarm_enabled %}
       - ./config/gitlab.rb:/etc/gitlab/gitlab.rb:ro
       - ./config/gitlab.rb:/etc/gitlab/gitlab.rb:ro
-      {% endif %}
       - {{ service_name }}_config:/etc/gitlab
       - {{ service_name }}_config:/etc/gitlab
       - {{ service_name }}_logs:/var/log/gitlab
       - {{ service_name }}_logs:/var/log/gitlab
       - {{ service_name }}_data:/var/opt/gitlab
       - {{ service_name }}_data:/var/opt/gitlab
-      {% endif %}
-    {% if traefik_enabled and not swarm_enabled %}
+    {% if traefik_enabled  %}
     labels:
     labels:
       - traefik.enable=true
       - traefik.enable=true
       - traefik.docker.network={{ traefik_network }}
       - traefik.docker.network={{ traefik_network }}
@@ -53,84 +39,18 @@ services:
       {% if registry_enabled %}
       {% if registry_enabled %}
       - traefik.http.services.{{ service_name }}_registry.loadBalancer.server.port=5000
       - traefik.http.services.{{ service_name }}_registry.loadBalancer.server.port=5000
       - traefik.http.routers.{{ service_name }}_registry-http.service={{ service_name }}_registry
       - traefik.http.routers.{{ service_name }}_registry-http.service={{ service_name }}_registry
-      - traefik.http.routers.{{ service_name }}_registry-http.rule=Host(`{{ traefik_registry_host }}`)
+      - traefik.http.routers.{{ service_name }}_registry-http.rule=Host(`{{ traefik_registry_host }}`.{{ traefik_domain }}`)
       - traefik.http.routers.{{ service_name }}_registry-http.entrypoints=web
       - traefik.http.routers.{{ service_name }}_registry-http.entrypoints=web
       {% if traefik_tls_enabled %}
       {% if traefik_tls_enabled %}
       - traefik.http.routers.{{ service_name }}_registry-https.service={{ service_name }}_registry
       - traefik.http.routers.{{ service_name }}_registry-https.service={{ service_name }}_registry
-      - traefik.http.routers.{{ service_name }}_registry-https.rule=Host(`{{ traefik_registry_host }}`)
+      - traefik.http.routers.{{ service_name }}_registry-https.rule=Host(`{{ traefik_registry_host }}`.{{ traefik_domain }}`)
       - traefik.http.routers.{{ service_name }}_registry-https.entrypoints=websecure
       - traefik.http.routers.{{ service_name }}_registry-https.entrypoints=websecure
       - traefik.http.routers.{{ service_name }}_registry-https.tls=true
       - traefik.http.routers.{{ service_name }}_registry-https.tls=true
       - traefik.http.routers.{{ service_name }}_registry-https.tls.certresolver={{ traefik_tls_certresolver }}
       - traefik.http.routers.{{ service_name }}_registry-https.tls.certresolver={{ traefik_tls_certresolver }}
       {% endif %}
       {% endif %}
       {% endif %}
       {% endif %}
     {% endif %}
     {% endif %}
-    {#
-      Docker Swarm configuration (only when swarm_enabled is set):
-      - Configs: GitLab configuration file
-      - Secrets: Root password and registry secret (if registry enabled)
-      - Deploy: Replication, placement, restart policy, and Traefik labels
-    #}
-    {% if swarm_enabled %}
-    configs:
-      - source: gitlab_config
-        target: /etc/gitlab/gitlab.rb
-    secrets:
-      - source: {{ service_name }}_root_password
-        target: /run/secrets/gitlab_root_password
-        mode: 0400
-      {% if registry_enabled %}
-      - source: {{ service_name }}_registry_secret
-        target: /run/secrets/gitlab_registry_secret
-        mode: 0400
-      {% endif %}
-    deploy:
-      mode: replicated
-      replicas: 1
-      {% if swarm_placement_host %}
-      placement:
-        constraints:
-          - node.hostname == {{ swarm_placement_host }}
-      {% endif %}
-      restart_policy:
-        condition: on-failure
-      {% if traefik_enabled %}
-      labels:
-        - traefik.enable=true
-        - traefik.docker.network={{ traefik_network }}
-        - traefik.http.services.{{ service_name }}_web.loadBalancer.server.port=80
-        - traefik.http.routers.{{ service_name }}_http.service={{ service_name }}_web
-        - traefik.http.routers.{{ service_name }}_http.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
-        - traefik.http.routers.{{ service_name }}_http.entrypoints=web
-        {% if traefik_tls_enabled %}
-        - traefik.http.routers.{{ service_name }}_https.service={{ service_name }}_web
-        - traefik.http.routers.{{ service_name }}_https.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
-        - traefik.http.routers.{{ service_name }}_https.entrypoints=websecure
-        - traefik.http.routers.{{ service_name }}_https.tls=true
-        - traefik.http.routers.{{ service_name }}_https.tls.certresolver={{ traefik_tls_certresolver }}
-        {% endif %}
-        {% if registry_enabled %}
-        - traefik.http.services.{{ service_name }}_registry.loadBalancer.server.port=5000
-        - traefik.http.routers.{{ service_name }}_registry-http.service={{ service_name }}_registry
-        - traefik.http.routers.{{ service_name }}_registry-http.rule=Host(`{{ traefik_registry_host }}`)
-        - traefik.http.routers.{{ service_name }}_registry-http.entrypoints=web
-        {% if traefik_tls_enabled %}
-        - traefik.http.routers.{{ service_name }}_registry-https.service={{ service_name }}_registry
-        - traefik.http.routers.{{ service_name }}_registry-https.rule=Host(`{{ traefik_registry_host }}`)
-        - traefik.http.routers.{{ service_name }}_registry-https.entrypoints=websecure
-        - traefik.http.routers.{{ service_name }}_registry-https.tls=true
-        - traefik.http.routers.{{ service_name }}_registry-https.tls.certresolver={{ traefik_tls_certresolver }}
-        {% endif %}
-        {% endif %}
-      {% endif %}
-    {% endif %}
 
 
-{#
-  Volume definitions:
-  - When volume_mode is 'local' (default): use docker-managed local volumes
-  - When volume_mode is 'nfs': configure NFS-backed volumes
-  - When volume_mode is 'mount': no volume definition needed (bind mounts used directly)
-#}
-{% if volume_mode == 'local' %}
 volumes:
 volumes:
   {{ service_name }}_config:
   {{ service_name }}_config:
     driver: local
     driver: local
@@ -138,51 +58,7 @@ volumes:
     driver: local
     driver: local
   {{ service_name }}_data:
   {{ service_name }}_data:
     driver: local
     driver: local
-{% elif volume_mode == 'nfs' %}
-volumes:
-  {{ service_name }}_config:
-    driver: local
-    driver_opts:
-      type: nfs
-      o: addr={{ volume_nfs_server }},nfsvers=4,{{ volume_nfs_options }}
-      device: ":{{ volume_nfs_path }}/config"
-  {{ service_name }}_logs:
-    driver: local
-    driver_opts:
-      type: nfs
-      o: addr={{ volume_nfs_server }},nfsvers=4,{{ volume_nfs_options }}
-      device: ":{{ volume_nfs_path }}/logs"
-  {{ service_name }}_data:
-    driver: local
-    driver_opts:
-      type: nfs
-      o: addr={{ volume_nfs_server }},nfsvers=4,{{ volume_nfs_options }}
-      device: ":{{ volume_nfs_path }}/data"
-{% endif %}
-
-{#
-  Docker Swarm configs and secrets (only when swarm_enabled is set):
-  - Config: GitLab configuration file
-  - Secrets: Root password and registry secret (if registry enabled)
-#}
-{% if swarm_enabled %}
-configs:
-  gitlab_config:
-    file: ./config/gitlab.rb
-
-secrets:
-  {{ service_name }}_root_password:
-    file: ./.env.secret
-  {% if registry_enabled %}
-  {{ service_name }}_registry_secret:
-    file: ./.env.registry.secret
-  {% endif %}
-{% endif %}
 
 
-{#
-  Network definitions (only when Traefik is enabled):
-  - Traefik network: always external (managed by Traefik)
-#}
 {% if traefik_enabled %}
 {% if traefik_enabled %}
 networks:
 networks:
   {{ traefik_network }}:
   {{ traefik_network }}:

+ 160 - 63
library/compose/gitlab/template.yaml

@@ -1,9 +1,8 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   name: GitLab
   name: GitLab
-  description: |
+  description: |-
     A **complete DevOps platform** that provides Git repository management, CI/CD pipelines,
     A **complete DevOps platform** that provides Git repository management, CI/CD pipelines,
     issue tracking, and container registry in a single application.
     issue tracking, and container registry in a single application.
     ## Prerequisites
     ## Prerequisites
@@ -24,48 +23,58 @@ metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: gitlab
     id: gitlab
-  version: 18.5.4-ce.0
+  version: 18.6.1-ce.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
   tags:
   tags:
     - traefik
     - traefik
-    - swarm
-  next_steps: |
+  next_steps: |-
     ## Post-Installation Steps
     ## Post-Installation Steps
     1. **Start GitLab**:
     1. **Start GitLab**:
-       ```bash
-       docker compose up -d
-       ```
-    2. **Wait for initialization** (2-5 minutes):
-       ```bash
-       docker compose logs -f gitlab
-       ```
-       Wait for message: `gitlab Reconfigured!`
-    3. **Access the web interface**:
-       {% if traefik_enabled -%}
-       - Via Traefik: https://{{ traefik_host }}
-       {% if not traefik_enabled and network_mode == 'bridge' %}- Direct access: http://localhost:{{ ports_http }}{% endif %}
-       {%- else -%}
-       - Open {{ external_url }} in your browser
-       {% if network_mode == 'bridge' %}- Or: http://localhost:{{ ports_http }}{% endif %}
-       {%- endif %}
-    4. **Initial login credentials**:
-       - **Username**: `root`
-       - **Password**: `{{ root_password }}`
-       > **Important**: This password only works on FIRST initialization.
-       > Change it immediately after first login via GitLab's web interface!
-    5. **Configure SSH** (optional):
-       - SSH clone URLs will use port `{{ ports_ssh }}`
-       - Update your Git remote if needed
-    ## Additional Resources
-    - Documentation: https://docs.gitlab.com/
-    - GitLab Runner: https://docs.gitlab.com/runner/
-  draft: true
+      ```bash
+      docker compose up -d
+      ```
+    2. **Wait for\
+      \ initialization** (2-5 minutes):
+        ```bash
+        docker compose logs -f gitlab
+        ```
+        Wait for message: `gitlab\
+      \ Reconfigured!`
+      3. **Access the web interface**:
+        {% if traefik_enabled -%}
+        - Via Traefik: https://{{ traefik_host\
+      \ }}
+        {% if not traefik_enabled and network_mode == 'bridge' %}- Direct access: http://localhost:{{ ports_http }}{%\
+      \ endif %}
+        {%- else -%}
+        - Open {{ external_url }} in your browser
+        {% if network_mode == 'bridge' %}- Or: http://localhost:{{\
+      \ ports_http }}{% endif %}
+        {%- endif %}
+      4. **Initial login credentials**:
+        - **Username**: `root`
+        - **Password**:\
+      \ `{{ root_password }}`
+        > **Important**: This password only works on FIRST initialization.
+        > Change it immediately\
+      \ after first login via GitLab's web interface!
+      5. **Configure SSH** (optional):
+        - SSH clone URLs will use port `{{\
+      \ ports_ssh }}`
+        - Update your Git remote if needed
+      ## Additional Resources
+      - Documentation: https://docs.gitlab.com/
+      \
+      - GitLab Runner: https://docs.gitlab.com/runner/
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
-        default: "gitlab"
+        type: str
+        description: Docker service name
+        default: gitlab
       external_url:
       external_url:
         type: str
         type: str
         description: External URL for GitLab
         description: External URL for GitLab
@@ -79,68 +88,156 @@ spec:
         description: Initial root user password (only used on first initialization)
         description: Initial root user password (only used on first initialization)
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
-        extra: "Leave empty to auto-generate. WARNING: Only sets password on FIRST startup!"
+        extra: 'Leave empty to auto-generate. WARNING: Only sets password on FIRST startup!'
       default_theme:
       default_theme:
         type: int
         type: int
         description: Default GitLab UI theme (2 = dark mode)
         description: Default GitLab UI theme (2 = dark mode)
         default: 2
         default: 2
-        extra: "1 = Indigo, 2 = Dark, 3 = Light, 4 = Blue, 5 = Green"
+        extra: 1 = Indigo, 2 = Dark, 3 = Light, 4 = Blue, 5 = Green
       default_color_mode:
       default_color_mode:
         type: int
         type: int
         description: Default color mode (2 = dark mode)
         description: Default color mode (2 = dark mode)
         default: 2
         default: 2
-        extra: "1 = Light, 2 = Dark"
+        extra: 1 = Light, 2 = Dark
       disable_usage_data:
       disable_usage_data:
         type: bool
         type: bool
         description: Disable product usage metrics upload to GitLab
         description: Disable product usage metrics upload to GitLab
         default: true
         default: true
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
+  advanced:
+    title: Advanced Settings
+    description: Performance tuning and advanced configuration options
+    vars:
+      performance_preset:
+        type: enum
+        description: Performance optimization profile
+        options:
+          - homelab
+          - default
+        default: homelab
+        extra: homelab is optimized for low-resource environments, default is for standard servers
+      prometheus_enabled:
+        type: bool
+        description: Enable Prometheus monitoring
+        default: false
+        extra: Disabling saves ~200-400MB RAM. GitLab UI metrics will be unavailable.
   ports:
   ports:
     vars:
     vars:
+      ports_http:
+        default: 80
       ports_ssh:
       ports_ssh:
         default: 2424
         default: 2424
       ports_registry:
       ports_registry:
         type: int
         type: int
         description: Container Registry port
         description: Container Registry port
         default: 5000
         default: 5000
-  network:
+  registry:
+    description: GitLab Container Registry configuration
+    toggle: registry_enabled
     vars:
     vars:
-      network_name:
-        default: "gitlab_network"
+      registry_enabled:
+        type: bool
+        description: Enable GitLab Container Registry
+        default: false
+      registry_external_url:
+        type: str
+        description: External URL for Container Registry
+        default: http://localhost:5000
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: gitlab.home.arpa
         default: gitlab.home.arpa
       traefik_registry_host:
       traefik_registry_host:
-        needs: ["registry_enabled=true"]
+        needs:
+          - registry_enabled=true
         default: registry.home.arpa
         default: registry.home.arpa
         type: str
         type: str
         description: Hostname for Container Registry in Traefik (if enabled)
         description: Hostname for Container Registry in Traefik (if enabled)
-  registry:
-    description: GitLab Container Registry configuration
-    toggle: registry_enabled
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
     vars:
     vars:
-      registry_enabled:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
         type: bool
         type: bool
-        description: Enable GitLab Container Registry
         default: false
         default: false
-      registry_external_url:
+        description: Enable Traefik TLS
+  email:
+    vars:
+      email_enabled:
+        type: bool
+        default: false
+        description: Enable email server configuration
+      email_host:
         type: str
         type: str
-        description: External URL for Container Registry
-        default: http://localhost:5000
-  advanced:
-    title: Advanced Settings
-    description: Performance tuning and advanced configuration options
+        default: ''
+        description: SMTP server hostname
+      email_port:
+        type: int
+        default: 587
+        description: SMTP server port
+      email_username:
+        type: str
+        default: ''
+        description: SMTP username
+      email_password:
+        type: str
+        sensitive: true
+        default: ''
+        description: SMTP password
+      email_from:
+        type: str
+        default: ''
+        description: From email address
+      email_use_tls:
+        type: bool
+        default: true
+        description: Use TLS encryption
+      email_use_ssl:
+        type: bool
+        default: false
+        description: Use SSL encryption
+  authentik:
     vars:
     vars:
-      performance_preset:
-        type: enum
-        description: Performance optimization profile
-        options:
-          - homelab
-          - default
-        default: homelab
-        extra: homelab is optimized for low-resource environments, default is for standard servers
-      prometheus_enabled:
+      authentik_enabled:
         type: bool
         type: bool
-        description: Enable Prometheus monitoring
         default: false
         default: false
-        extra: Disabling saves ~200-400MB RAM. GitLab UI metrics will be unavailable.
+        description: Enable Authentik SSO integration
+      authentik_url:
+        type: str
+        default: https://auth.home.arpa
+        description: Authentik base URL (e.g., https://auth.example.com)
+      authentik_slug:
+        type: str
+        default: gitlab
+        description: Authentik application slug
+      authentik_client_id:
+        type: str
+        default: ''
+        description: OAuth client ID from Authentik provider
+      authentik_client_secret:
+        type: str
+        sensitive: true
+        default: ''
+        description: OAuth client secret from Authentik provider

+ 87 - 7
library/compose/grafana/template.yaml

@@ -2,34 +2,51 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: Grafana
   name: Grafana
-  description: |-
-    Grafana is an open-source platform for monitoring and observability that allows you to visualize and analyze metrics, logs, and traces from various data
+  description: 'Grafana is an open-source platform for monitoring and observability that allows you to visualize and analyze
+    metrics, logs, and traces from various data
+
     sources. It provides a powerful and flexible dashboarding solution for IT infrastructure and application monitoring.
     sources. It provides a powerful and flexible dashboarding solution for IT infrastructure and application monitoring.
+
     ## Prerequisites
     ## Prerequisites
+
     - **Project:** https://grafana.com/
     - **Project:** https://grafana.com/
+
     - **Documentation:** https://grafana.com/docs/grafana/latest/
     - **Documentation:** https://grafana.com/docs/grafana/latest/
-    - **GitHub:** https://github.com/grafana/grafana
+
+    - **GitHub:** https://github.com/grafana/grafana'
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: grafana
     id: grafana
-  next_steps: |-
-    Log in with the initial admin user:
+  next_steps: 'Log in with the initial admin user:
+
     ```bash
     ```bash
+
     Username: admin
     Username: admin
+
     Password: admin
     Password: admin
-    ```
+
+    ```'
   version: 12.3.1
   version: 12.3.1
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-16'
   date: '2025-12-16'
   tags:
   tags:
     - traefik
     - traefik
     - authentik
     - authentik
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: grafana
         default: grafana
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -40,10 +57,44 @@ spec:
         default: https://auth.home.arpa
         default: https://auth.home.arpa
       authentik_slug:
       authentik_slug:
         default: grafana
         default: grafana
+      authentik_client_id:
+        type: str
+        sensitive: true
+        required: true
+      authentik_client_secret:
+        type: str
+        sensitive: true
+        required: true
+      authentik_enabled:
+        type: bool
+        default: false
+        description: Enable Authentik SSO integration
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: grafana
         default: grafana
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   database:
   database:
     vars:
     vars:
       database_type:
       database_type:
@@ -54,3 +105,32 @@ spec:
         default: grafana
         default: grafana
       database_user:
       database_user:
         default: grafana
         default: grafana
+      database_host:
+        type: str
+        required: true
+      database_password:
+        type: str
+        sensitive: true
+        required: true
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
+  swarm:
+    vars:
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_host:
+        type: str
+        default: ''
+        description: The placement host
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode
+      swarm_replicas:
+        type: int
+        default: 1
+        description: The number of replicas

+ 123 - 5
library/compose/homepage/template.yaml

@@ -2,13 +2,16 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: Homepage
   name: Homepage
-  description: |-
-    Homepage is a modern, fully static, fast, secure fully customizable application dashboard with integrations
+  description: 'Homepage is a modern, fully static, fast, secure fully customizable application dashboard with integrations
+
     for over 100 services and translations into multiple languages.
     for over 100 services and translations into multiple languages.
 
 
+
     Project: https://gethomepage.dev/
     Project: https://gethomepage.dev/
+
     Documentation: https://gethomepage.dev/latest/
     Documentation: https://gethomepage.dev/latest/
-    GitHub: https://github.com/gethomepage/homepage
+
+    GitHub: https://github.com/gethomepage/homepage'
   version: v1.8.0
   version: v1.8.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-12'
   date: '2025-12-12'
@@ -20,8 +23,8 @@ metadata:
     provider: simpleicons
     provider: simpleicons
     id: homepage
     id: homepage
   draft: true
   draft: true
-  next_steps: ""
-schema: "1.2"
+  next_steps: ''
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -31,6 +34,24 @@ spec:
         default: homepage
         default: homepage
       service_name:
       service_name:
         default: homepage
         default: homepage
+      container_timezone:
+        type: str
+      container_loglevel:
+        type: enum
+        options:
+          - debug
+          - info
+          - warn
+          - error
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -39,3 +60,100 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: homepage
         default: homepage
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_options:
+        type: str
+        default: nfsvers=4,soft,timeo=180,intr
+        description: The NFS mount options
+      volume_nfs_path:
+        type: str
+        default: ''
+        description: The NFS path
+      volume_nfs_server:
+        type: str
+        default: ''
+        description: The NFS server
+  resources:
+    vars:
+      resources_enabled:
+        type: bool
+        default: false
+      resources_cpu_limit:
+        type: str
+        default: 1.0
+        required: true
+      resources_cpu_reservation:
+        type: str
+        default: 0.25
+        needs:
+          - swarm_enabled=true
+        required: true
+      resources_memory_limit:
+        type: str
+        default: 1G
+        required: true
+      resources_memory_reservation:
+        type: str
+        default: 512M
+        needs:
+          - swarm_enabled=true
+        required: true
+  swarm:
+    vars:
+      swarm_replicas:
+        type: int
+        default: 1
+        needs:
+          - swarm_placement_mode=replicated
+        required: true
+      swarm_placement_host:
+        type: str
+        default: ''
+        needs:
+          - swarm_placement_mode=replicated
+        extra: Constrains service to run on specific node by hostname
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode

+ 136 - 40
library/compose/homer/template.yaml

@@ -1,18 +1,19 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: homer
     id: homer
   name: Homer
   name: Homer
-  description: >
-    A very simple static homepage for your server to keep your services on hand, from a simple yaml configuration file.
+  description: 'A very simple static homepage for your server to keep your services on hand, from a simple yaml configuration
+    file.
 
 
 
 
     Project: https://github.com/bastienwirtz/homer
     Project: https://github.com/bastienwirtz/homer
 
 
     Documentation: https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md
     Documentation: https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md
+
+    '
   version: v25.11.1
   version: v25.11.1
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
@@ -21,60 +22,155 @@ metadata:
     - swarm
     - swarm
     - authentik
     - authentik
   draft: true
   draft: true
-  next_steps: |
-    1. Start the Homer dashboard:
-       docker compose up -d
-
-    2. Customize your dashboard:
-       - Edit assets/config.yml to add your services
-       - Organize services into groups (Applications, Monitoring, etc.)
-       - Add links to the navbar for quick access
-
-    3. Optional: Add a logo:
-       - Place your logo.png file in the assets/ directory
-       - Or update the logo path in assets/config.yml
-       - Supported formats: PNG, SVG, JPG
-
-    4. Optional: Customize the theme:
-       - Uncomment and modify the colors section in config.yml
-       - Available themes: default, sui
-       - See documentation for advanced theming options
-
-    5. Access your dashboard:
-       {% if traefik_enabled -%}
-       - Via Traefik: https://{{ traefik_host }}
-       {% if not traefik_enabled and network_mode == 'bridge' %}- Direct access: http://localhost:{{ ports_http }}{% endif %}
-       {%- else -%}
-       - Open http://localhost:{{ ports_http }} in your browser
-       {%- endif %}
-
-    For more information, visit: https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md
+  next_steps: "1. Start the Homer dashboard:\n   docker compose up -d\n\n2. Customize your dashboard:\n   - Edit assets/config.yml\
+    \ to add your services\n   - Organize services into groups (Applications, Monitoring, etc.)\n   - Add links to the navbar\
+    \ for quick access\n\n3. Optional: Add a logo:\n   - Place your logo.png file in the assets/ directory\n   - Or update\
+    \ the logo path in assets/config.yml\n   - Supported formats: PNG, SVG, JPG\n\n4. Optional: Customize the theme:\n   -\
+    \ Uncomment and modify the colors section in config.yml\n   - Available themes: default, sui\n   - See documentation for\
+    \ advanced theming options\n\n5. Access your dashboard:\n   {% if traefik_enabled -%}\n   - Via Traefik: https://{{ traefik_host\
+    \ }}\n   {% if not traefik_enabled and network_mode == 'bridge' %}- Direct access: http://localhost:{{ ports_http }}{%\
+    \ endif %}\n   {%- else -%}\n   - Open http://localhost:{{ ports_http }} in your browser\n   {%- endif %}\n\nFor more\
+    \ information, visit: https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md\n"
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
-        default: "homer"
+        default: homer
       container_name:
       container_name:
-        default: "homer"
+        default: homer
+      container_hostname:
+        type: str
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       homer_title:
       homer_title:
-        description: "Dashboard title"
+        description: Dashboard title
         type: str
         type: str
-        default: "My Dashboard"
+        default: My Dashboard
       homer_subtitle:
       homer_subtitle:
-        description: "Dashboard subtitle"
+        description: Dashboard subtitle
         type: str
         type: str
-        default: "Homer"
+        default: Homer
       homer_logo:
       homer_logo:
-        description: "Logo file path (relative to assets/)"
+        description: Logo file path (relative to assets/)
         type: str
         type: str
-        default: "logo.png"
+        default: logo.png
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
-        description: "Host port for HTTP (8080)"
+        description: Host port for HTTP (8080)
         type: int
         type: int
         default: 8080
         default: 8080
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: homer.home.arpa
         default: homer.home.arpa
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
+  resources:
+    vars:
+      resources_enabled:
+        type: bool
+        default: false
+      resources_cpu_limit:
+        type: str
+        default: 1.0
+        required: true
+      resources_cpu_reservation:
+        type: str
+        default: 0.25
+        needs:
+          - swarm_enabled=true
+        required: true
+      resources_memory_limit:
+        type: str
+        default: 1G
+        required: true
+      resources_memory_reservation:
+        type: str
+        default: 512M
+        needs:
+          - swarm_enabled=true
+        required: true
+  swarm:
+    vars:
+      swarm_placement_mode:
+        type: enum
+        options:
+          - replicated
+          - global
+        default: replicated
+        required: true
+      swarm_replicas:
+        type: int
+        default: 1
+        needs:
+          - swarm_placement_mode=replicated
+        required: true
+      swarm_placement_host:
+        type: str
+        default: ''
+        needs:
+          - swarm_placement_mode=replicated
+        extra: Constrains service to run on specific node by hostname
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+  authentik:
+    vars:
+      authentik_traefik_middleware:
+        type: str
+        default: authentik-middleware@file
+        needs:
+          - traefik_enabled=true
+        required: true
+      authentik_client_id:
+        type: str
+        default: ''
+        description: The Authentik client ID
+      authentik_client_secret:
+        type: str
+        default: ''
+        description: The Authentik client secret
+      authentik_enabled:
+        type: bool
+        default: false
+        description: Enable Authentik SSO integration
+      authentik_slug:
+        type: str
+        default: ''
+        description: The Authentik application slug
+      authentik_url:
+        type: str
+        default: ''
+        description: The Authentik URL

+ 59 - 12
library/compose/influxdb/template.yaml

@@ -5,50 +5,97 @@ metadata:
     provider: selfh
     provider: selfh
     id: influxdb
     id: influxdb
   name: Influxdb
   name: Influxdb
-  description: |-
-    InfluxDB is a powerful, open-source time series database designed for high-performance handling of time-stamped data.
+  description: 'InfluxDB is a powerful, open-source time series database designed for high-performance handling of time-stamped
+    data.
+
     It is commonly used for monitoring, analytics, and IoT applications.
     It is commonly used for monitoring, analytics, and IoT applications.
+
     ## References
     ## References
+
     * **Project:** https://www.influxdata.com/
     * **Project:** https://www.influxdata.com/
+
     * **Documentation:** https://docs.influxdata.com/influxdb/
     * **Documentation:** https://docs.influxdata.com/influxdb/
-    * **GitHub:** https://github.com/influxdata/influxdb
-  next_steps: |-
-    Log in with your initial admin user:
+
+    * **GitHub:** https://github.com/influxdata/influxdb'
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
     ```bash
+
     Username: {{ influxdb_init_username }}
     Username: {{ influxdb_init_username }}
+
     Password: {{ influxdb_init_password }}
     Password: {{ influxdb_init_password }}
-    ```
+
+    ```'
   version: 2.8.0-alpine
   version: 2.8.0-alpine
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
   tags:
   tags:
     - traefik
     - traefik
   draft: true
   draft: true
-schema: "1.2"
+schema: '1.2'
 spec:
 spec:
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
-        description: "Host port for HTTP API (8086)"
+        description: Host port for HTTP API (8086)
         type: int
         type: int
         default: 8086
         default: 8086
   influxdb:
   influxdb:
-    description: "InfluxDB initialization settings"
+    description: InfluxDB initialization settings
     required: true
     required: true
     vars:
     vars:
       influxdb_init_username:
       influxdb_init_username:
-        description: "Initial admin username"
+        description: Initial admin username
         type: str
         type: str
-        default: "admin"
+        default: admin
         required: true
         required: true
       influxdb_init_password:
       influxdb_init_password:
-        description: "Initial admin password"
+        description: Initial admin password
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
         required: true
         required: true
+  traefik:
+    vars:
+      traefik_host:
+        default: influxdb
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   general:
   general:
     vars:
     vars:
+      service_name:
+        default: influxdb
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       influxdb_version:
       influxdb_version:
         type: str
         type: str
         description: Influxdb version
         description: Influxdb version

+ 216 - 34
library/compose/komodo/template.yaml

@@ -1,24 +1,35 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: komodo
     id: komodo
   name: Komodo
   name: Komodo
-  description: |
-    Build and deployment automation tool for managing software across multiple servers. Komodo provides
+  description: 'Build and deployment automation tool for managing software across multiple servers. Komodo provides
+
     unlimited server connections, flexible API access, and comprehensive management of Docker deployments,
     unlimited server connections, flexible API access, and comprehensive management of Docker deployments,
+
     stacks, and builds. Features include real-time container monitoring, batch operations, and integration
     stacks, and builds. Features include real-time container monitoring, batch operations, and integration
+
     with Docker, Docker Compose, and build systems. Supports both MongoDB and FerretDB as database backends.
     with Docker, Docker Compose, and build systems. Supports both MongoDB and FerretDB as database backends.
+
     ## Important Notes
     ## Important Notes
+
     * Requires MongoDB or FerretDB for data storage (database not included in this template)
     * Requires MongoDB or FerretDB for data storage (database not included in this template)
+
     * Requires Periphery agent on managed servers for remote operations
     * Requires Periphery agent on managed servers for remote operations
+
     * Web interface and API accessible through configured ports
     * Web interface and API accessible through configured ports
+
     ## References
     ## References
+
     * **Project:** https://github.com/moghtech/komodo
     * **Project:** https://github.com/moghtech/komodo
+
     * **Documentation:** https://github.com/moghtech/komodo/tree/main/docsite/docs
     * **Documentation:** https://github.com/moghtech/komodo/tree/main/docsite/docs
+
     * **Docker Hub:** https://hub.docker.com/r/moghtech/komodo
     * **Docker Hub:** https://hub.docker.com/r/moghtech/komodo
+
+    '
   draft: true
   draft: true
   version: latest
   version: latest
   author: Christian Lempa
   author: Christian Lempa
@@ -28,107 +39,278 @@ metadata:
     - swarm
     - swarm
     - deployment
     - deployment
     - automation
     - automation
-  next_steps: |
-    ### 1. Prerequisites
+  next_steps: '### 1. Prerequisites
+
     * Deploy MongoDB or FerretDB database
     * Deploy MongoDB or FerretDB database
+
     * Configure database connection in environment variables
     * Configure database connection in environment variables
+
     * Install Periphery agent on servers you want to manage
     * Install Periphery agent on servers you want to manage
+
     ### 2. Deploy the Service
     ### 2. Deploy the Service
+
     {% if swarm_enabled -%}
     {% if swarm_enabled -%}
+
     Deploy to Docker Swarm:
     Deploy to Docker Swarm:
+
     ```bash
     ```bash
+
     docker stack deploy -c compose.yaml komodo
     docker stack deploy -c compose.yaml komodo
+
     ```
     ```
+
     {% else -%}
     {% else -%}
+
     Start Komodo using Docker Compose:
     Start Komodo using Docker Compose:
+
     ```bash
     ```bash
+
     docker compose up -d
     docker compose up -d
+
     ```
     ```
+
     {% endif -%}
     {% endif -%}
+
     ### 3. Access the Web Interface
     ### 3. Access the Web Interface
+
     {% if traefik_enabled -%}
     {% if traefik_enabled -%}
+
     * Navigate to: **https://{{ traefik_host }}.{{ traefik_domain }}**
     * Navigate to: **https://{{ traefik_host }}.{{ traefik_domain }}**
+
     {% else -%}
     {% else -%}
+
     * Navigate to: **http://localhost:{{ ports_http }}**
     * Navigate to: **http://localhost:{{ ports_http }}**
+
     {% endif -%}
     {% endif -%}
+
     * Complete initial setup and create admin user
     * Complete initial setup and create admin user
+
     ### 4. Install Periphery Agent
     ### 4. Install Periphery Agent
+
     On each server you want to manage:
     On each server you want to manage:
+
     ```bash
     ```bash
+
     curl -sSL https://raw.githubusercontent.com/moghtech/komodo/main/scripts/setup-periphery.py | python3
     curl -sSL https://raw.githubusercontent.com/moghtech/komodo/main/scripts/setup-periphery.py | python3
+
     ```
     ```
+
     ### 5. Configure Servers
     ### 5. Configure Servers
+
     * Add servers to Komodo through the web interface
     * Add servers to Komodo through the web interface
+
     * Configure API keys for programmatic access
     * Configure API keys for programmatic access
+
     * Start managing deployments, stacks, and builds
     * Start managing deployments, stacks, and builds
+
+    '
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
-        default: "komodo"
+        default: komodo
       container_name:
       container_name:
-        default: "komodo"
+        default: komodo
       container_hostname:
       container_hostname:
-        default: "komodo"
+        default: komodo
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
-        default: "komodo"
+        default: komodo
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   network:
   network:
     vars:
     vars:
       network_name:
       network_name:
-        default: "komodo_network"
+        default: komodo_network
+      network_macvlan_ipv4_address:
+        type: str
+        default: 192.168.1.253
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_parent_interface:
+        type: str
+        default: eth0
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_subnet:
+        type: str
+        default: 192.168.1.0/24
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_gateway:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
+      network_mode:
+        type: str
+        default: bridge
+        description: The network mode for the container
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
-        description: "External HTTP port (web interface and API)"
+        description: External HTTP port (web interface and API)
         type: int
         type: int
         default: 9120
         default: 9120
-        needs: ["traefik_enabled=false", "network_mode=bridge"]
+        needs:
+          - traefik_enabled=false
+          - network_mode=bridge
   volume:
   volume:
     vars:
     vars:
       volume_mount_path:
       volume_mount_path:
-        default: "/mnt/storage/komodo"
+        default: /mnt/storage/komodo
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        description: The volume mode
+  resources:
+    vars:
+      resources_enabled:
+        type: bool
+        default: false
+      resources_cpu_limit:
+        type: str
+        default: 1.0
+        required: true
+      resources_cpu_reservation:
+        type: str
+        default: 0.25
+        needs:
+          - swarm_enabled=true
+        required: true
+      resources_memory_limit:
+        type: str
+        default: 1G
+        required: true
+      resources_memory_reservation:
+        type: str
+        default: 512M
+        needs:
+          - swarm_enabled=true
+        required: true
   environment:
   environment:
-    title: "Environment Variables"
+    title: Environment Variables
     toggle: environment_enabled
     toggle: environment_enabled
     required: true
     required: true
     vars:
     vars:
       environment_enabled:
       environment_enabled:
         type: bool
         type: bool
         default: true
         default: true
-        description: "Configure environment variables (required)"
+        description: Configure environment variables (required)
       environment_database_address:
       environment_database_address:
         type: str
         type: str
-        default: "mongodb://mongo:27017"
-        description: "Database connection address (MongoDB or FerretDB)"
-        needs: "environment_enabled=true"
+        default: mongodb://mongo:27017
+        description: Database connection address (MongoDB or FerretDB)
+        needs: environment_enabled=true
       environment_database_name:
       environment_database_name:
         type: str
         type: str
-        default: "komodo"
-        description: "Database name"
-        needs: "environment_enabled=true"
+        default: komodo
+        description: Database name
+        needs: environment_enabled=true
       environment_database_username:
       environment_database_username:
         type: str
         type: str
-        default: ""
-        description: "Database username (optional)"
-        needs: "environment_enabled=true"
+        default: ''
+        description: Database username (optional)
+        needs: environment_enabled=true
       environment_database_password:
       environment_database_password:
         type: str
         type: str
-        default: ""
+        default: ''
         sensitive: true
         sensitive: true
-        description: "Database password (optional)"
-        needs: "environment_enabled=true"
+        description: Database password (optional)
+        needs: environment_enabled=true
       environment_jwt_secret:
       environment_jwt_secret:
         type: str
         type: str
-        default: ""
+        default: ''
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
-        description: "JWT secret for authentication (auto-generated if empty)"
-        needs: "environment_enabled=true"
+        description: JWT secret for authentication (auto-generated if empty)
+        needs: environment_enabled=true
       environment_log_level:
       environment_log_level:
         type: enum
         type: enum
-        default: "info"
-        options: ["debug", "info", "warn", "error"]
-        description: "Log level"
-        needs: "environment_enabled=true"
+        default: info
+        options:
+          - debug
+          - info
+          - warn
+          - error
+        description: Log level
+        needs: environment_enabled=true
+  swarm:
+    vars:
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_host:
+        type: str
+        default: ''
+        description: The placement host
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode
+      swarm_replicas:
+        type: int
+        default: 1
+        description: The number of replicas

+ 40 - 5
library/compose/loki/template.yaml

@@ -5,27 +5,40 @@ metadata:
     provider: selfh
     provider: selfh
     id: loki
     id: loki
   name: Loki
   name: Loki
-  description: |-
-    Loki is a horizontally scalable, highly available, multi-tenant log aggregation system inspired by Prometheus.
+  description: 'Loki is a horizontally scalable, highly available, multi-tenant log aggregation system inspired by Prometheus.
+
     This template sets up Loki in a Docker container using Docker Compose.
     This template sets up Loki in a Docker container using Docker Compose.
+
     ## References
     ## References
+
     * **Project:** https://grafana.com/oss/loki/
     * **Project:** https://grafana.com/oss/loki/
+
     * **Documentation:** https://grafana.com/docs/loki/latest/
     * **Documentation:** https://grafana.com/docs/loki/latest/
-    * **GitHub:** https://github.com/grafana/loki
+
+    * **GitHub:** https://github.com/grafana/loki'
   version: 3.6.3
   version: 3.6.3
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
   tags:
   tags:
     - traefik
     - traefik
     - authentik
     - authentik
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: loki
         default: loki
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       data_retention_days:
       data_retention_days:
-        description: "Number of days to retain logs"
+        description: Number of days to retain logs
         type: int
         type: int
         default: 7
         default: 7
   ports:
   ports:
@@ -36,3 +49,25 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: loki
         default: loki
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS

+ 18 - 1
library/compose/mariadb/template.yaml

@@ -23,12 +23,17 @@ metadata:
   date: '2025-09-28'
   date: '2025-09-28'
   tags: []
   tags: []
   draft: true
   draft: true
-schema: 1.2
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: mariadb
         default: mariadb
+      restart_policy:
+        type: enum
+        options: [unless-stopped, always, on-failure, "no"]
+        default: unless-stopped
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_mariadb:
       ports_mariadb:
@@ -36,3 +41,15 @@ spec:
         type: int
         type: int
         default: 3306
         default: 3306
         required: true
         required: true
+  database:
+    vars:
+      database_name:
+        type: str
+        required: true
+      database_user:
+        type: str
+        required: true
+      database_password:
+        type: str
+        sensitive: true
+        required: true

+ 154 - 86
library/compose/n8n/template.yaml

@@ -5,24 +5,41 @@ metadata:
     provider: selfh
     provider: selfh
     id: n8n
     id: n8n
   name: N8N
   name: N8N
-  description: |
-    N8n is a free and source-available workflow automation tool. It enables you to connect
+  description: 'N8n is a free and source-available workflow automation tool. It enables you to connect
+
     various apps and services to automate repetitive tasks without coding.
     various apps and services to automate repetitive tasks without coding.
+
     With its user-friendly interface, you can create complex workflows by simply dragging
     With its user-friendly interface, you can create complex workflows by simply dragging
+
     and dropping nodes that represent different actions and triggers.
     and dropping nodes that represent different actions and triggers.
+
     ## Prerequisites
     ## Prerequisites
+
     - :info: By default, n8n uses SQLite as its database, which is suitable for small-scale or
     - :info: By default, n8n uses SQLite as its database, which is suitable for small-scale or
+
     personal use. For production environments, it is recommended to use an external
     personal use. For production environments, it is recommended to use an external
+
     database like PostgreSQL or MySQL for better performance and reliability. This is also
     database like PostgreSQL or MySQL for better performance and reliability. This is also
+
     required when using Queue Mode.
     required when using Queue Mode.
+
     - :info: Queue mode allows n8n to handle a large number of workflows and tasks efficiently, by using
     - :info: Queue mode allows n8n to handle a large number of workflows and tasks efficiently, by using
+
     multiple Workers, and Redis as the queue backend. This is essential for high-availability
     multiple Workers, and Redis as the queue backend. This is essential for high-availability
+
     setups where multiple n8n instances work together. It also supports Queue Monitoring
     setups where multiple n8n instances work together. It also supports Queue Monitoring
+
     (when Prometheus metrics are enabled).
     (when Prometheus metrics are enabled).
+
     ## Resources
     ## Resources
+
     - **Project**: https://n8n.io/
     - **Project**: https://n8n.io/
+
     - **Documentation**: https://docs.n8n.io/
     - **Documentation**: https://docs.n8n.io/
+
     - **GitHub**: https://github.com/n8n-io/n8n
     - **GitHub**: https://github.com/n8n-io/n8n
+
+    '
   version: 8-alpine
   version: 8-alpine
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-17'
   date: '2025-12-17'
@@ -30,185 +47,236 @@ metadata:
     - traefik
     - traefik
     - database
     - database
   draft: true
   draft: true
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
-        default: "n8n"
+        default: n8n
       container_name:
       container_name:
-        default: "n8n-server"
+        default: n8n-server
       container_hostname:
       container_hostname:
-        default: "n8n-server"
+        default: n8n-server
+      container_timezone:
+        type: str
+      container_loglevel:
+        type: enum
+        options:
+          - debug
+          - info
+          - warn
+          - error
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   queue:
   queue:
-    title: "Queue Mode"
-    description: "Enable queue mode with Redis for scaled deployments"
+    title: Queue Mode
+    description: Enable queue mode with Redis for scaled deployments
     toggle: queue_enabled
     toggle: queue_enabled
-    needs: "database_enabled=true"
+    needs: database_enabled=true
     vars:
     vars:
       queue_enabled:
       queue_enabled:
         type: bool
         type: bool
-        description: "Enable queue mode (requires Redis)"
+        description: Enable queue mode (requires Redis)
         default: false
         default: false
-        extra: "Required for multiple workers and scaled deployments"
+        extra: Required for multiple workers and scaled deployments
       queue_redis_external:
       queue_redis_external:
         type: bool
         type: bool
-        description: "Use external Redis instance"
+        description: Use external Redis instance
         default: false
         default: false
-        needs: "queue_enabled"
+        needs: queue_enabled
       queue_redis_host:
       queue_redis_host:
         type: str
         type: str
-        description: "Redis host"
-        default: "redis"
-        needs: "queue_enabled"
+        description: Redis host
+        default: redis
+        needs: queue_enabled
       queue_redis_port:
       queue_redis_port:
         type: int
         type: int
-        description: "Redis port"
+        description: Redis port
         default: 6379
         default: 6379
-        needs: "queue_enabled"
+        needs: queue_enabled
       queue_embedded_worker:
       queue_embedded_worker:
         type: bool
         type: bool
-        description: "Include embedded worker in this deployment"
+        description: Include embedded worker in this deployment
         default: false
         default: false
-        needs: "queue_enabled"
-        extra: "Add a worker service to this compose file. For production, use separate n8n-worker template."
+        needs: queue_enabled
+        extra: Add a worker service to this compose file. For production, use separate n8n-worker template.
   database:
   database:
-    title: "Database"
-    description: "External database configuration"
+    title: Database
+    description: External database configuration
     vars:
     vars:
       database_enabled:
       database_enabled:
         type: bool
         type: bool
-        description: "Use external database"
+        description: Use external database
         default: false
         default: false
       database_type:
       database_type:
         type: enum
         type: enum
-        description: "Database type"
+        description: Database type
         options:
         options:
-          - "postgres"
-          - "mysql"
-        default: "postgres"
-        needs: "database_enabled"
+          - postgres
+          - mysql
+        default: postgres
+        needs: database_enabled
       database_host:
       database_host:
         type: str
         type: str
-        description: "Database host"
-        default: "postgres"
-        needs: "database_enabled"
+        description: Database host
+        default: postgres
+        needs: database_enabled
       database_port:
       database_port:
         type: int
         type: int
-        description: "Database port"
+        description: Database port
         default: 5432
         default: 5432
-        needs: "database_enabled"
+        needs: database_enabled
       database_name:
       database_name:
         type: str
         type: str
-        description: "Database name"
-        default: "n8n"
-        needs: "database_enabled"
+        description: Database name
+        default: n8n
+        needs: database_enabled
       database_user:
       database_user:
         type: str
         type: str
-        description: "Database username"
-        default: "n8n"
-        needs: "database_enabled"
+        description: Database username
+        default: n8n
+        needs: database_enabled
       database_password:
       database_password:
         type: str
         type: str
-        description: "Database password"
+        description: Database password
         sensitive: true
         sensitive: true
-        needs: "database_enabled"
+        needs: database_enabled
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
   security:
   security:
-    title: "Security"
+    title: Security
     vars:
     vars:
       encryption_key:
       encryption_key:
         type: str
         type: str
-        description: "N8N encryption key for credentials"
+        description: N8N encryption key for credentials
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
-        extra: "Keep this secure! Used to encrypt stored credentials."
+        extra: Keep this secure! Used to encrypt stored credentials.
       proxy_hops:
       proxy_hops:
         type: int
         type: int
-        description: "Number of proxy hops (X-Forwarded-For)"
+        description: Number of proxy hops (X-Forwarded-For)
         default: 1
         default: 1
-        extra: "Set to 2 if behind multiple proxies (e.g., Cloudflare + Traefik)"
+        extra: Set to 2 if behind multiple proxies (e.g., Cloudflare + Traefik)
   webhooks:
   webhooks:
-    title: "Webhooks"
-    description: "Webhook configuration for external triggers"
+    title: Webhooks
+    description: Webhook configuration for external triggers
     vars:
     vars:
       webhook_url:
       webhook_url:
         type: url
         type: url
-        description: "Webhook base URL"
-        default: ""
-        extra: "Optional separate webhook URL (e.g., https://webhooks.example.com/)"
+        description: Webhook base URL
+        default: ''
+        extra: Optional separate webhook URL (e.g., https://webhooks.example.com/)
   metrics:
   metrics:
-    title: "Metrics"
-    description: "Prometheus metrics configuration"
+    title: Metrics
+    description: Prometheus metrics configuration
     vars:
     vars:
       metrics_enabled:
       metrics_enabled:
         type: bool
         type: bool
-        description: "Enable Prometheus metrics"
+        description: Enable Prometheus metrics
         default: false
         default: false
       metrics_detailed:
       metrics_detailed:
         type: bool
         type: bool
-        description: "Include detailed metrics (workflows, nodes, API endpoints)"
+        description: Include detailed metrics (workflows, nodes, API endpoints)
         default: false
         default: false
-        needs: "metrics_enabled"
+        needs: metrics_enabled
   execution:
   execution:
-    title: "Execution Settings"
+    title: Execution Settings
     vars:
     vars:
       execution_save_on_error:
       execution_save_on_error:
         type: enum
         type: enum
-        description: "Save execution data on error"
+        description: Save execution data on error
         options:
         options:
-          - "all"
-          - "none"
-        default: "all"
+          - all
+          - none
+        default: all
       execution_save_on_success:
       execution_save_on_success:
         type: enum
         type: enum
-        description: "Save execution data on success"
+        description: Save execution data on success
         options:
         options:
-          - "all"
-          - "none"
-        default: "none"
-        extra: "Set to 'none' to reduce database size"
+          - all
+          - none
+        default: none
+        extra: Set to 'none' to reduce database size
   network:
   network:
     vars:
     vars:
       network_mode:
       network_mode:
-        extra: "For queue mode with workers, use 'bridge' with shared networks. Swarm only supports 'bridge'."
+        extra: For queue mode with workers, use 'bridge' with shared networks. Swarm only supports 'bridge'.
       network_name:
       network_name:
-        default: "n8n_network"
+        default: n8n_network
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
   traefik:
   traefik:
     vars:
     vars:
       traefik_enabled:
       traefik_enabled:
-        needs: "network_mode=bridge"
+        needs: network_mode=bridge
       traefik_host:
       traefik_host:
-        default: "n8n.home.arpa"
+        default: n8n.home.arpa
       traefik_webhook_host:
       traefik_webhook_host:
         type: hostname
         type: hostname
-        description: "Separate hostname for webhooks (optional)"
-        default: ""
-        needs: "traefik_enabled"
-        extra: "Leave empty to use same host for webhooks"
+        description: Separate hostname for webhooks (optional)
+        default: ''
+        needs: traefik_enabled
+        extra: Leave empty to use same host for webhooks
       traefik_network:
       traefik_network:
         type: str
         type: str
-        description: "Traefik network name"
-        default: "traefik"
-        needs: "traefik_enabled"
+        description: Traefik network name
+        default: traefik
+        needs: traefik_enabled
       traefik_network_external:
       traefik_network_external:
         type: bool
         type: bool
-        description: "Use external Traefik network"
+        description: Use external Traefik network
         default: true
         default: true
-        needs: "traefik_enabled"
+        needs: traefik_enabled
+      traefik_domain:
+        type: str
+        default: home.arpa
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
-        description: "External HTTP port"
+        description: External HTTP port
         type: int
         type: int
         default: 5678
         default: 5678
-        needs: ["traefik_enabled=false", "network_mode=bridge"]
+        needs:
+          - traefik_enabled=false
+          - network_mode=bridge
   swarm:
   swarm:
     vars:
     vars:
       swarm_enabled:
       swarm_enabled:
-        needs: "network_mode=bridge"
+        needs: network_mode=bridge
       swarm_replicas:
       swarm_replicas:
         type: int
         type: int
-        description: "Number of server replicas"
+        description: Number of server replicas
         default: 1
         default: 1
-        needs: "swarm_enabled"
-        extra: "For HA, set > 1 (requires queue mode)"
+        needs: swarm_enabled
+        extra: For HA, set > 1 (requires queue mode)
+      swarm_placement_host:
+        type: str
+        description: Target hostname for placement constraint
+        default: ''
+        extra: Constrains service to run on specific node by hostname
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS

+ 92 - 7
library/compose/netbox/template.yaml

@@ -2,14 +2,20 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: NetBox
   name: NetBox
-  description: |-
-    Network infrastructure management (IPAM/DCIM) and network automation source of truth. Provides comprehensive API
+  description: 'Network infrastructure management (IPAM/DCIM) and network automation source of truth. Provides comprehensive
+    API
+
     for managing IP addresses, circuits, devices, racks, cables, and other network infrastructure components with powerful
     for managing IP addresses, circuits, devices, racks, cables, and other network infrastructure components with powerful
+
     automation capabilities.
     automation capabilities.
+
     ## References
     ## References
+
     - **Project:** https://netbox.dev/
     - **Project:** https://netbox.dev/
+
     - **Documentation:** https://docs.netbox.dev/
     - **Documentation:** https://docs.netbox.dev/
-    - **GitHub:** https://github.com/netbox-community/netbox
+
+    - **GitHub:** https://github.com/netbox-community/netbox'
   version: v4.4.8
   version: v4.4.8
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-12'
   date: '2025-12-12'
@@ -21,13 +27,16 @@ metadata:
     provider: selfh
     provider: selfh
     id: netbox
     id: netbox
   draft: false
   draft: false
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
     ```bash
+
     Username: admin
     Username: admin
+
     Password: admin
     Password: admin
-    ```
-schema: 1.2
+
+    ```'
+schema: '1.2'
 spec:
 spec:
   database:
   database:
     vars:
     vars:
@@ -35,16 +44,70 @@ spec:
         default: netbox
         default: netbox
       database_user:
       database_user:
         default: netbox
         default: netbox
+      database_host:
+        type: str
+        required: true
+      database_password:
+        type: str
+        sensitive: true
+        required: true
       redis_password:
       redis_password:
         description: Redis password for authentication
         description: Redis password for authentication
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
         required: true
         required: true
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
+  email:
+    vars:
+      email_host:
+        description: SMTP server hostname
+        type: str
+        required: true
+      email_port:
+        description: SMTP server port
+        type: int
+        default: 25
+        required: true
+      email_username:
+        description: SMTP username
+        type: str
+        required: true
+      email_password:
+        description: SMTP password
+        type: str
+        sensitive: true
+        required: true
+      email_from:
+        description: From email address
+        type: str
+        required: true
+      email_enabled:
+        type: bool
+        default: false
+        description: Enable email integration
+      email_encryption:
+        type: str
+        default: tls
+        description: The email encryption type
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: netbox
         default: netbox
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   netbox:
   netbox:
     title: NetBox Configuration
     title: NetBox Configuration
     description: Configure NetBox application settings
     description: Configure NetBox application settings
@@ -70,3 +133,25 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: netbox
         default: netbox
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS

+ 93 - 17
library/compose/nextcloud/template.yaml

@@ -1,12 +1,10 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   name: Nextcloud
   name: Nextcloud
-  description: >
-    Self-hosted file sync and share platform. Nextcloud is a suite of client-server
-    software for creating and using file hosting services. It provides functionality
-    similar to Dropbox, with the added benefit of being self-hosted and open-source.
+  description: 'Self-hosted file sync and share platform. Nextcloud is a suite of client-server software for creating and
+    using file hosting services. It provides functionality similar to Dropbox, with the added benefit of being self-hosted
+    and open-source.
 
 
 
 
     Project: https://nextcloud.com/
     Project: https://nextcloud.com/
@@ -14,6 +12,8 @@ metadata:
     Documentation: https://docs.nextcloud.com/
     Documentation: https://docs.nextcloud.com/
 
 
     GitHub: https://github.com/nextcloud/server
     GitHub: https://github.com/nextcloud/server
+
+    '
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: nextcloud
     id: nextcloud
@@ -23,38 +23,114 @@ metadata:
   tags:
   tags:
     - traefik
     - traefik
   draft: true
   draft: true
+schema: '1.2'
 spec:
 spec:
   database:
   database:
     required: true
     required: true
     vars:
     vars:
       database_type:
       database_type:
-        description: "Database type (Nextcloud supports PostgreSQL or MySQL/MariaDB)"
+        description: Database type (Nextcloud supports PostgreSQL or MySQL/MariaDB)
         type: enum
         type: enum
-        options: ["postgres", "mysql"]
-        default: "postgres"
+        options:
+          - postgres
+          - mysql
+        default: postgres
+      database_name:
+        type: str
+        required: true
+      database_user:
+        type: str
+        required: true
+      database_password:
+        type: str
+        sensitive: true
+        required: true
+  general:
+    vars:
+      service_name:
+        default: nextcloud
+      container_name:
+        default: nextcloud
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   network:
   network:
     vars:
     vars:
       network_macvlan_ipv4_address_db:
       network_macvlan_ipv4_address_db:
-        description: "Static IP address for database container (macvlan only)"
+        description: Static IP address for database container (macvlan only)
         type: str
         type: str
-        default: "192.168.1.252"
-        needs: "network_mode=macvlan"
+        default: 192.168.1.252
+        needs: network_mode=macvlan
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
-        description: "Host port for HTTP"
+        description: Host port for HTTP
         type: int
         type: int
         default: 80
         default: 80
   nextcloud:
   nextcloud:
-    description: "Configure Nextcloud application settings"
+    description: Configure Nextcloud application settings
     vars:
     vars:
       admin_user:
       admin_user:
-        description: "Nextcloud admin username"
+        description: Nextcloud admin username
         type: str
         type: str
-        default: "admin"
+        default: admin
       admin_password:
       admin_password:
-        description: "Nextcloud admin password"
+        description: Nextcloud admin password
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
-        default: ""
+        default: ''
+  traefik:
+    vars:
+      traefik_host:
+        default: nextcloud
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
+  swarm:
+    vars:
+      swarm_replicas:
+        type: int
+        default: 1
+        needs:
+          - swarm_placement_mode=replicated
+        required: true
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_host:
+        type: str
+        default: ''
+        description: The placement host
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode

+ 37 - 18
library/compose/nginx/template.yaml

@@ -1,20 +1,23 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: nginx
     id: nginx
   name: Nginx
   name: Nginx
-  description: |-
-    Nginx is a high-performance web server, reverse proxy, and load balancer known for its stability, rich feature set, simple configuration, and low resource
+  description: 'Nginx is a high-performance web server, reverse proxy, and load balancer known for its stability, rich feature
+    set, simple configuration, and low resource
+
     consumption. It is widely used to serve static content, handle HTTP requests, and distribute traffic across multiple servers.
     consumption. It is widely used to serve static content, handle HTTP requests, and distribute traffic across multiple servers.
 
 
+
     ## Prerequisites
     ## Prerequisites
+
     * **Project:** https://nginx.org/
     * **Project:** https://nginx.org/
+
     * **Documentation:** https://nginx.org/en/docs/
     * **Documentation:** https://nginx.org/en/docs/
-    * **GitHub:** https://github.com/nginx/nginx
 
 
+    * **GitHub:** https://github.com/nginx/nginx'
   version: 1.28.1-alpine
   version: 1.28.1-alpine
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-24'
   date: '2025-12-24'
@@ -22,19 +25,24 @@ metadata:
     - traefik
     - traefik
     - swarm
     - swarm
   draft: true
   draft: true
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
-        default: "nginx"
+        default: nginx
       restart_policy:
       restart_policy:
         type: enum
         type: enum
-        options: ["unless-stopped", "always", "on-failure", "no"]
-        default: "unless-stopped"
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
       container_name:
       container_name:
-        default: "nginx"
+        default: nginx
       container_timezone:
       container_timezone:
-        default: "UTC"
+        default: UTC
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -51,28 +59,31 @@ spec:
         type: bool
         type: bool
         default: false
         default: false
       traefik_network:
       traefik_network:
-        default: "traefik"
+        default: traefik
       traefik_host:
       traefik_host:
-        default: "nginx"
+        default: nginx
       traefik_domain:
       traefik_domain:
-        default: "home.arpa"
+        default: home.arpa
       traefik_entrypoint:
       traefik_entrypoint:
-        default: "web"
+        default: web
       traefik_tls_entrypoint:
       traefik_tls_entrypoint:
-        default: "websecure"
+        default: websecure
       traefik_tls_enabled:
       traefik_tls_enabled:
         type: bool
         type: bool
         default: true
         default: true
       traefik_tls_certresolver:
       traefik_tls_certresolver:
-        default: "cloudflare"
+        default: cloudflare
   network:
   network:
     vars:
     vars:
       network_mode:
       network_mode:
         type: enum
         type: enum
-        options: ["bridge", "host", "macvlan"]
-        default: "bridge"
+        options:
+          - bridge
+          - host
+          - macvlan
+        default: bridge
       network_name:
       network_name:
-        default: "bridge"
+        default: bridge
   swarm:
   swarm:
     vars:
     vars:
       swarm_enabled:
       swarm_enabled:
@@ -82,3 +93,11 @@ spec:
         description: Number of replicas for Swarm mode
         description: Number of replicas for Swarm mode
         type: int
         type: int
         default: 1
         default: 1
+      swarm_placement_host:
+        type: str
+        default: ''
+        description: The placement host
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode

+ 58 - 6
library/compose/openwebui/template.yaml

@@ -1,16 +1,14 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: open-webui
     id: open-webui
   name: Openwebui
   name: Openwebui
-  description: >
-    OpenWebUI is an open-source web-based user interface for managing and interacting with AI models.
-    It provides a user-friendly platform to deploy, monitor, and utilize various AI models for tasks such as
-    image generation, text generation, and more. OpenWebUI supports integration with popular AI frameworks
-    and offers features like model management, user authentication, and real-time interaction.
+  description: 'OpenWebUI is an open-source web-based user interface for managing and interacting with AI models. It provides
+    a user-friendly platform to deploy, monitor, and utilize various AI models for tasks such as image generation, text generation,
+    and more. OpenWebUI supports integration with popular AI frameworks and offers features like model management, user authentication,
+    and real-time interaction.
 
 
 
 
     Project: https://openwebui.io/
     Project: https://openwebui.io/
@@ -18,6 +16,8 @@ metadata:
     Documentation: https://docs.openwebui.io/
     Documentation: https://docs.openwebui.io/
 
 
     GitHub: https://github.com/openwebui/openwebui
     GitHub: https://github.com/openwebui/openwebui
+
+    '
   version: 0.6.41
   version: 0.6.41
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
@@ -25,6 +25,7 @@ metadata:
     - traefik
     - traefik
     - authentik
     - authentik
   draft: true
   draft: true
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -32,6 +33,19 @@ spec:
         default: openwebui
         default: openwebui
       container_name:
       container_name:
         default: openwebui
         default: openwebui
+      container_hostname:
+        type: str
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       ollama_base_url:
       ollama_base_url:
         type: str
         type: str
         description: Ollama API base URL
         description: Ollama API base URL
@@ -40,6 +54,28 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: openwebui.home.arpa
         default: openwebui.home.arpa
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -66,3 +102,19 @@ spec:
         type: bool
         type: bool
         description: Merge OAuth accounts by email
         description: Merge OAuth accounts by email
         default: false
         default: false
+      authentik_client_id:
+        type: str
+        sensitive: true
+        required: true
+      authentik_client_secret:
+        type: str
+        sensitive: true
+        required: true
+      authentik_slug:
+        type: str
+        default: ''
+        description: The Authentik application slug
+      authentik_url:
+        type: str
+        default: ''
+        description: The Authentik URL

+ 0 - 158
library/compose/pangolin/compose.yaml.j2

@@ -1,158 +0,0 @@
----
-services:
-  {{ service_name }}:
-    image: docker.io/fosrl/pangolin:latest
-    {% if not swarm_enabled %}
-    restart: {{ restart_policy }}
-    container_name: {{ container_name }}
-    {% endif %}
-    hostname: {{ container_hostname }}
-    {% if network_mode == 'host' %}
-    network_mode: host
-    {% else %}
-    networks:
-      {% if traefik_enabled %}
-      {{ traefik_network }}:
-      {% endif %}
-      {% if network_mode == 'macvlan' %}
-      {{ network_name }}:
-        ipv4_address: {{ network_macvlan_ipv4_address }}
-      {% elif network_mode == 'bridge' %}
-      {{ network_name }}:
-      {% endif %}
-    {% endif %}
-    {% if network_mode == 'bridge' and not traefik_enabled %}
-    ports:
-      {% if swarm_enabled %}
-      - target: 8080
-        published: {{ ports_http }}
-        protocol: tcp
-        mode: host
-      {% else %}
-      - "{{ ports_http }}:8080/tcp"
-      {% endif %}
-    {% endif %}
-    {% if environment_enabled or postgres_enabled %}
-    environment:
-      {% if postgres_enabled %}
-      POSTGRES_CONNECTION_STRING: "{{ postgres_connection_string }}"
-      {% endif %}
-      {% if environment_enabled %}
-      {% if environment_log_level %}
-      LOG_LEVEL: "{{ environment_log_level }}"
-      {% endif %}
-      {% if environment_crowdsec_enabled %}
-      CROWDSEC_ENABLED: "true"
-      {% endif %}
-      {% endif %}
-    {% endif %}
-    volumes:
-      {% if volume_mode == 'mount' %}
-      - {{ volume_mount_path }}/data:/app/data:rw
-      - {{ volume_mount_path }}/config:/app/config:rw
-      {% elif volume_mode in ['local', 'nfs'] %}
-      - {{ service_name }}-data:/app/data
-      - {{ service_name }}-config:/app/config
-      {% endif %}
-    {% if swarm_enabled or resources_enabled %}
-    deploy:
-      {% if swarm_enabled %}
-      mode: replicated
-      replicas: 1
-      restart_policy:
-        condition: on-failure
-      {% endif %}
-      {% if resources_enabled %}
-      resources:
-        limits:
-          cpus: '{{ resources_cpu_limit }}'
-          memory: {{ resources_memory_limit }}
-        {% if swarm_enabled %}
-        reservations:
-          cpus: '{{ resources_cpu_reservation }}'
-          memory: {{ resources_memory_reservation }}
-        {% endif %}
-      {% endif %}
-      {% if swarm_enabled and traefik_enabled %}
-      labels:
-        - traefik.enable=true
-        - traefik.docker.network={{ traefik_network }}
-        - traefik.http.services.{{ service_name }}-web.loadBalancer.server.port=8080
-        - traefik.http.routers.{{ service_name }}-http.service={{ service_name }}-web
-        - traefik.http.routers.{{ service_name }}-http.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
-        - traefik.http.routers.{{ service_name }}-http.entrypoints={{ traefik_entrypoint }}
-        {% if traefik_tls_enabled %}
-        - traefik.http.routers.{{ service_name }}-https.service={{ service_name }}-web
-        - traefik.http.routers.{{ service_name }}-https.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
-        - traefik.http.routers.{{ service_name }}-https.entrypoints={{ traefik_tls_entrypoint }}
-        - traefik.http.routers.{{ service_name }}-https.tls=true
-        - traefik.http.routers.{{ service_name }}-https.tls.certresolver={{ traefik_tls_certresolver }}
-        {% endif %}
-      {% endif %}
-    {% endif %}
-    {% if traefik_enabled and not swarm_enabled %}
-    labels:
-      - traefik.enable=true
-      - traefik.docker.network={{ traefik_network }}
-      - traefik.http.services.{{ service_name }}-web.loadBalancer.server.port=8080
-      - traefik.http.routers.{{ service_name }}-http.service={{ service_name }}-web
-      - traefik.http.routers.{{ service_name }}-http.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
-      - traefik.http.routers.{{ service_name }}-http.entrypoints={{ traefik_entrypoint }}
-      {% if traefik_tls_enabled %}
-      - traefik.http.routers.{{ service_name }}-https.service={{ service_name }}-web
-      - traefik.http.routers.{{ service_name }}-https.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
-      - traefik.http.routers.{{ service_name }}-https.entrypoints={{ traefik_tls_entrypoint }}
-      - traefik.http.routers.{{ service_name }}-https.tls=true
-      - traefik.http.routers.{{ service_name }}-https.tls.certresolver={{ traefik_tls_certresolver }}
-      {% endif %}
-    {% endif %}
-
-{% if volume_mode == 'local' %}
-volumes:
-  {{ service_name }}-data:
-    driver: local
-  {{ service_name }}-config:
-    driver: local
-{% elif volume_mode == 'nfs' %}
-volumes:
-  {{ service_name }}-data:
-    driver: local
-    driver_opts:
-      type: nfs
-      o: addr={{ volume_nfs_server }},{{ volume_nfs_options }}
-      device: ":{{ volume_nfs_path }}/data"
-  {{ service_name }}-config:
-    driver: local
-    driver_opts:
-      type: nfs
-      o: addr={{ volume_nfs_server }},{{ volume_nfs_options }}
-      device: ":{{ volume_nfs_path }}/config"
-{% endif %}
-
-{% if network_mode != 'host' %}
-networks:
-  {{ network_name }}:
-    {% if network_external %}
-    external: true
-    {% else %}
-    {% if network_mode == 'macvlan' %}
-    driver: macvlan
-    driver_opts:
-      parent: {{ network_macvlan_parent_interface }}
-    ipam:
-      config:
-        - subnet: {{ network_macvlan_subnet }}
-          gateway: {{ network_macvlan_gateway }}
-    name: {{ network_name }}
-    {% elif swarm_enabled %}
-    driver: overlay
-    attachable: true
-    {% else %}
-    driver: bridge
-    {% endif %}
-    {% endif %}
-  {% if traefik_enabled %}
-  {{ traefik_network }}:
-    external: true
-  {% endif %}
-{% endif %}

+ 0 - 117
library/compose/pangolin/template.yaml

@@ -1,117 +0,0 @@
----
-kind: compose
-schema: "1.2"
-metadata:
-  icon:
-    provider: selfh
-    id: pangolin
-  name: Pangolin
-  description: |
-    Self-hosted reverse proxy server that securely exposes private resources on distributed networks through
-    encrypted WireGuard tunnels. Pangolin enables access from anywhere without opening ports, using a custom
-    user-space WireGuard client (Newt) for secure connectivity. Features include automatic tunnel management,
-    integrated CrowdSec security, and support for both PostgreSQL and SQLite databases.
-    ## References
-    * **Project:** https://github.com/fosrl/pangolin
-    * **Documentation:** https://github.com/fosrl/pangolin/blob/main/README.md
-    * **Docker Hub:** https://hub.docker.com/r/fosrl/pangolin
-  version: latest
-  author: Christian Lempa
-  date: '2025-11-13'
-  tags:
-    - traefik
-    - swarm
-    - proxy
-    - wireguard
-  draft: true
-  next_steps: |
-    ### 1. Configure Database
-    {% if postgres_enabled -%}
-    Make sure PostgreSQL is running and accessible at:
-    * Connection string: {{ postgres_connection_string }}
-    {% else -%}
-    Pangolin will use SQLite database stored in the data volume.
-    {% endif -%}
-    ### 2. Deploy the Service
-    {% if swarm_enabled -%}
-    Deploy to Docker Swarm:
-    ```bash
-    docker stack deploy -c compose.yaml pangolin
-    ```
-    {% else -%}
-    Start Pangolin using Docker Compose:
-    ```bash
-    docker compose up -d
-    ```
-    {% endif -%}
-    ### 3. Access the Web Interface
-    {% if traefik_enabled -%}
-    * Navigate to: **https://{{ traefik_host }}.{{ traefik_domain }}**
-    {% else -%}
-    * Navigate to: **http://localhost:{{ ports_http }}**
-    {% endif -%}
-    ### 4. Configure WireGuard Clients
-    * Use the Pangolin web interface to create and manage WireGuard tunnels
-    * Deploy Newt client on remote machines to establish secure connections
-spec:
-  general:
-    vars:
-      service_name:
-        default: "pangolin"
-      container_name:
-        default: "pangolin"
-      container_hostname:
-        default: "pangolin"
-  traefik:
-    vars:
-      traefik_host:
-        default: "pangolin"
-  network:
-    vars:
-      network_name:
-        default: "pangolin_network"
-  ports:
-    vars:
-      ports_http:
-        description: "External HTTP port (web interface)"
-        type: int
-        default: 8080
-        needs: ["traefik_enabled=false", "network_mode=bridge"]
-  volume:
-    vars:
-      volume_mount_path:
-        default: "/mnt/storage/pangolin"
-  postgres:
-    title: "PostgreSQL Configuration"
-    toggle: postgres_enabled
-    needs: null
-    vars:
-      postgres_enabled:
-        type: bool
-        default: false
-        description: "Use PostgreSQL database (SQLite is default)"
-      postgres_connection_string:
-        type: str
-        default: "postgresql://postgres:postgres@localhost:5432"
-        description: "PostgreSQL connection string"
-        needs: "postgres_enabled=true"
-  environment:
-    title: "Environment Variables"
-    toggle: environment_enabled
-    needs: null
-    vars:
-      environment_enabled:
-        type: bool
-        default: false
-        description: "Configure additional environment variables"
-      environment_crowdsec_enabled:
-        type: bool
-        default: false
-        description: "Enable CrowdSec integration"
-        needs: "environment_enabled=true"
-      environment_log_level:
-        type: enum
-        default: "info"
-        options: ["debug", "info", "warn", "error"]
-        description: "Log level"
-        needs: "environment_enabled=true"

+ 3 - 1
library/compose/passbolt/template.yaml

@@ -19,12 +19,14 @@ metadata:
     - traefik
     - traefik
     - database
     - database
   draft: true
   draft: true
-schema: 1.2
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: passbolt
         default: passbolt
+      container_timezone:
+        type: str
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:

+ 142 - 13
library/compose/pihole/template.yaml

@@ -1,22 +1,31 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: pi-hole
     id: pi-hole
   name: Pihole
   name: Pihole
-  description: |
-    Network-wide advertisement and internet tracker blocking application that functions as a DNS blackhole.
+  description: 'Network-wide advertisement and internet tracker blocking application that functions as a DNS blackhole.
+
     Provides DNS-level content filtering for all network devices, improving browsing performance, privacy, and security.
     Provides DNS-level content filtering for all network devices, improving browsing performance, privacy, and security.
+
     Supports custom blocklists, whitelists, and seamless integration with existing network infrastructure.
     Supports custom blocklists, whitelists, and seamless integration with existing network infrastructure.
+
     ## Prerequisites
     ## Prerequisites
+
     - :warning: Pi-hole uses local storage and configuration files and does NOT support running multiple replicas.
     - :warning: Pi-hole uses local storage and configuration files and does NOT support running multiple replicas.
+
     This template enforces a single replica with node placement constraints to ensure stable DNS resolution.
     This template enforces a single replica with node placement constraints to ensure stable DNS resolution.
+
     ## References
     ## References
+
     - **Project:** https://pi-hole.net/
     - **Project:** https://pi-hole.net/
+
     - **Documentation:** https://docs.pi-hole.net/
     - **Documentation:** https://docs.pi-hole.net/
+
     - **GitHub:** https://github.com/pi-hole/pi-hole
     - **GitHub:** https://github.com/pi-hole/pi-hole
+
+    '
   version: 2025.11.1
   version: 2025.11.1
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
@@ -25,12 +34,16 @@ metadata:
     - swarm
     - swarm
     - network
     - network
     - volume
     - volume
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
     ```bash
+
     Username: admin
     Username: admin
+
     Password: {{ webpassword }}
     Password: {{ webpassword }}
-    ```
+
+    ```'
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -38,17 +51,41 @@ spec:
         default: pihole
         default: pihole
       container_name:
       container_name:
         default: pihole
         default: pihole
+      container_hostname:
+        type: str
+      container_timezone:
+        type: str
+      user_uid:
+        type: int
+        default: 1000
+      user_gid:
+        type: int
+        default: 1000
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   admin_settings:
   admin_settings:
-    description: "Admin Pi-hole Settings"
+    description: Admin Pi-hole Settings
     required: true
     required: true
     vars:
     vars:
       webpassword:
       webpassword:
-        description: "Web interface admin password"
+        description: Web interface admin password
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
   ports:
   ports:
     vars:
     vars:
+      ports_dns:
+        description: DNS port for Pi-hole
+        type: int
+        default: 53
+        required: true
       ports_http:
       ports_http:
         description: HTTP port for Pi-hole
         description: HTTP port for Pi-hole
         type: int
         type: int
@@ -58,7 +95,7 @@ spec:
         type: int
         type: int
         default: 443
         default: 443
       ports_ntp:
       ports_ntp:
-        description: "External NTP port"
+        description: External NTP port
         type: int
         type: int
         default: 123
         default: 123
         required: true
         required: true
@@ -66,14 +103,64 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: pihole
         default: pihole
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   network:
   network:
     vars:
     vars:
       network_mode:
       network_mode:
-        extra: >
-          If you need DHCP functionality, use 'host' or 'macvlan' mode.
-          NOTE: Swarm only supports 'bridge' mode!"
+        extra: 'If you need DHCP functionality, use ''host'' or ''macvlan'' mode. NOTE: Swarm only supports ''bridge'' mode!"
+
+          '
       network_name:
       network_name:
-        default: "pihole_network"
+        default: pihole_network
+      network_macvlan_ipv4_address:
+        type: str
+        default: 192.168.1.253
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_parent_interface:
+        type: str
+        default: eth0
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_subnet:
+        type: str
+        default: 192.168.1.0/24
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_macvlan_gateway:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - network_mode=macvlan
+        required: true
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
   swarm:
   swarm:
     vars:
     vars:
       swarm_placement_host:
       swarm_placement_host:
@@ -84,3 +171,45 @@ spec:
         description: Number of replicas for Swarm mode
         description: Number of replicas for Swarm mode
         type: int
         type: int
         default: 1
         default: 1
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true

+ 96 - 5
library/compose/portainer/template.yaml

@@ -5,14 +5,19 @@ metadata:
     provider: selfh
     provider: selfh
     id: portainer
     id: portainer
   name: Portainer
   name: Portainer
-  description: |-
-    Portainer is a powerful and user-friendly management tool for Docker and Kubernetes environments.
+  description: 'Portainer is a powerful and user-friendly management tool for Docker and Kubernetes environments.
+
     It provides a simple web-based interface to manage containers, images, networks, and volumes,
     It provides a simple web-based interface to manage containers, images, networks, and volumes,
+
     making it easier to deploy and monitor applications.
     making it easier to deploy and monitor applications.
+
     ## References
     ## References
+
     - **Project:** https://www.portainer.io/
     - **Project:** https://www.portainer.io/
+
     - **Documentation:** https://docs.portainer.io/
     - **Documentation:** https://docs.portainer.io/
-    - **GitHub:** https://github.com/portainer/portainer
+
+    - **GitHub:** https://github.com/portainer/portainer'
   version: 2.37.0-alpine
   version: 2.37.0-alpine
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-12'
   date: '2025-12-12'
@@ -20,12 +25,23 @@ metadata:
     - traefik
     - traefik
     - swarm
     - swarm
     - volumes
     - volumes
-schema: 1.2
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: portainer
         default: portainer
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
@@ -33,7 +49,7 @@ spec:
       ports_https:
       ports_https:
         default: 9443
         default: 9443
       ports_edge:
       ports_edge:
-        description: "Host port for Edge agent (8000)"
+        description: Host port for Edge agent (8000)
         type: int
         type: int
         default: 8000
         default: 8000
         required: true
         required: true
@@ -41,3 +57,78 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: portainer
         default: portainer
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true
+  swarm:
+    vars:
+      swarm_placement_host:
+        type: str
+        description: Target hostname for placement constraint
+        default: ''
+        extra: Constrains service to run on specific node by hostname
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode
+      swarm_replicas:
+        type: int
+        default: 1
+        description: The number of replicas

+ 57 - 15
library/compose/postgres/template.yaml

@@ -1,13 +1,11 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: postgresql
     id: postgresql
   name: PostgreSQL
   name: PostgreSQL
-  description: >
-    PostgreSQL is a powerful, open source object-relational database system with over 30 years of active development
+  description: 'PostgreSQL is a powerful, open source object-relational database system with over 30 years of active development
     that has earned it a strong reputation for reliability, feature robustness, and performance.
     that has earned it a strong reputation for reliability, feature robustness, and performance.
 
 
 
 
@@ -16,19 +14,35 @@ metadata:
     Documentation: https://www.postgresql.org/docs/
     Documentation: https://www.postgresql.org/docs/
 
 
     GitHub: https://github.com/postgres/postgres
     GitHub: https://github.com/postgres/postgres
+
+    '
   version: 18.1
   version: 18.1
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-11'
   date: '2025-12-11'
   tags:
   tags:
     - swarm
     - swarm
   draft: true
   draft: true
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
-        default: "postgres"
+        default: postgres
       container_name:
       container_name:
-        default: "postgres"
+        default: postgres
+      container_hostname:
+        type: str
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_postgres:
       ports_postgres:
@@ -38,27 +52,43 @@ spec:
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
-        default: "postgres"
+        default: postgres
   network:
   network:
     vars:
     vars:
       network_mode:
       network_mode:
-        extra: >
-          Use 'host' mode if you need to bind directly to port 5432.
-          NOTE: Swarm only supports 'bridge' mode!
+        extra: 'Use ''host'' mode if you need to bind directly to port 5432. NOTE: Swarm only supports ''bridge'' mode!
+
+          '
       network_name:
       network_name:
-        default: "postgres_network"
+        default: postgres_network
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
   swarm:
   swarm:
     vars:
     vars:
       swarm_replicas:
       swarm_replicas:
         description: Number of replicas for Swarm mode
         description: Number of replicas for Swarm mode
         type: int
         type: int
         default: 1
         default: 1
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_host:
+        type: str
+        default: ''
+        description: The placement host
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode
   volume:
   volume:
     vars:
     vars:
       volume_mode:
       volume_mode:
         description: Volume mounting mode (local, mount, nfs)
         description: Volume mounting mode (local, mount, nfs)
         type: str
         type: str
-        default: "local"
+        default: local
         options:
         options:
           - local
           - local
           - mount
           - mount
@@ -66,16 +96,28 @@ spec:
       volume_mount_path:
       volume_mount_path:
         description: Path for bind mounts when volume_mode is 'mount'
         description: Path for bind mounts when volume_mode is 'mount'
         type: str
         type: str
-        default: "/var/lib/postgresql/data"
+        default: /var/lib/postgresql/data
       volume_nfs_server:
       volume_nfs_server:
         description: NFS server address when volume_mode is 'nfs'
         description: NFS server address when volume_mode is 'nfs'
         type: str
         type: str
-        default: ""
+        default: ''
       volume_nfs_path:
       volume_nfs_path:
         description: NFS path when volume_mode is 'nfs'
         description: NFS path when volume_mode is 'nfs'
         type: str
         type: str
-        default: ""
+        default: ''
       volume_nfs_options:
       volume_nfs_options:
         description: NFS mount options when volume_mode is 'nfs'
         description: NFS mount options when volume_mode is 'nfs'
         type: str
         type: str
-        default: "rw"
+        default: rw
+  database:
+    vars:
+      database_port:
+        type: int
+        default: 5432
+        required: true
+      database_name:
+        type: str
+        required: true
+      database_user:
+        type: str
+        required: true

+ 61 - 30
library/compose/prometheus/template.yaml

@@ -1,24 +1,34 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: prometheus
     id: prometheus
   name: Prometheus
   name: Prometheus
-  description: |
-    Prometheus is an open-source systems monitoring and alerting toolkit originally built at SoundCloud.
+  description: 'Prometheus is an open-source systems monitoring and alerting toolkit originally built at SoundCloud.
+
     It is designed for reliability and scalability, making it suitable for monitoring dynamic cloud environments.
     It is designed for reliability and scalability, making it suitable for monitoring dynamic cloud environments.
-    Prometheus collects and stores metrics as time series data, providing powerful querying capabilities and integration with various visualization tools.
+
+    Prometheus collects and stores metrics as time series data, providing powerful querying capabilities and integration with
+    various visualization tools.
+
     ##  Swarm Deployment Warning
     ##  Swarm Deployment Warning
+
     Prometheus uses local TSDB storage and does NOT support running multiple replicas.
     Prometheus uses local TSDB storage and does NOT support running multiple replicas.
-    This template enforces a single replica with node placement constraints. For true HA, consider remote storage solutions (Thanos, Cortex, VictoriaMetrics).
+
+    This template enforces a single replica with node placement constraints. For true HA, consider remote storage solutions
+    (Thanos, Cortex, VictoriaMetrics).
+
 
 
     Project: https://prometheus.io/
     Project: https://prometheus.io/
 
 
+
     Documentation: https://prometheus.io/docs/
     Documentation: https://prometheus.io/docs/
 
 
+
     GitHub: https://github.com/prometheus/prometheus
     GitHub: https://github.com/prometheus/prometheus
+
+    '
   version: v3.8.1
   version: v3.8.1
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-16'
   date: '2025-12-16'
@@ -26,52 +36,73 @@ metadata:
     - traefik
     - traefik
     - swarm
     - swarm
     - authentik
     - authentik
-  next_steps: |
-    {% if swarm_enabled -%}
-    1. Deploy to Docker Swarm:
-       docker stack deploy -c compose.yaml {{ service_name }}
-    2. Access Prometheus:
-       {%- if traefik_enabled %} https://{{ traefik_host }}
-       {%- else %} http://<swarm-node-ip>:{{ ports_http }}{%- endif %}
-    {% else -%}
-    1. Start Prometheus with Docker Compose:
-       docker compose up -d
-    2. Access Prometheus:
-       {%- if traefik_enabled %} https://{{ traefik_host }}
-       {%- else %} http://localhost:{{ ports_http }}{%- endif %}
-    {% endif -%}
-    3. Edit config/prometheus.yaml to add scrape targets
-    4. Reload configuration: docker exec {{ container_name if not swarm_enabled else service_name }} kill -HUP 1
+  next_steps: "{% if swarm_enabled -%}\n1. Deploy to Docker Swarm:\n   docker stack deploy -c compose.yaml {{ service_name\
+    \ }}\n2. Access Prometheus:\n   {%- if traefik_enabled %} https://{{ traefik_host }}\n   {%- else %} http://<swarm-node-ip>:{{\
+    \ ports_http }}{%- endif %}\n{% else -%}\n1. Start Prometheus with Docker Compose:\n   docker compose up -d\n2. Access\
+    \ Prometheus:\n   {%- if traefik_enabled %} https://{{ traefik_host }}\n   {%- else %} http://localhost:{{ ports_http\
+    \ }}{%- endif %}\n{% endif -%}\n3. Edit config/prometheus.yaml to add scrape targets\n4. Reload configuration: docker\
+    \ exec {{ container_name if not swarm_enabled else service_name }} kill -HUP 1\n"
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: prometheus
         default: prometheus
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   metrics:
   metrics:
     title: Metrics & Storage
     title: Metrics & Storage
     description: Configure data retention and storage settings
     description: Configure data retention and storage settings
     vars:
     vars:
       metrics_retention_time:
       metrics_retention_time:
         type: str
         type: str
-        description: "How long to retain samples (e.g., 15d, 30d, 1y)"
-        default: "15d"
-        extra: "Older data will be deleted. Use 'h', 'd', 'w', 'y' for time units."
+        description: How long to retain samples (e.g., 15d, 30d, 1y)
+        default: 15d
+        extra: Older data will be deleted. Use 'h', 'd', 'w', 'y' for time units.
       metrics_retention_size:
       metrics_retention_size:
         type: str
         type: str
-        description: "Maximum storage size (e.g., 5GB, 10GB, 1TB)"
-        default: "0"
-        extra: "Set to 0 for unlimited. Triggers deletion when exceeded."
+        description: Maximum storage size (e.g., 5GB, 10GB, 1TB)
+        default: '0'
+        extra: Set to 0 for unlimited. Triggers deletion when exceeded.
       metrics_enable_remote_write:
       metrics_enable_remote_write:
         type: bool
         type: bool
-        description: "Enable remote write receiver (allows pushing metrics via /api/v1/write)"
+        description: Enable remote write receiver (allows pushing metrics via /api/v1/write)
         default: false
         default: false
-        extra: "Caution: Intended for low-volume use cases only. Not efficient for general ingestion."
+        extra: 'Caution: Intended for low-volume use cases only. Not efficient for general ingestion.'
   ports:
   ports:
     vars:
     vars:
       ports_http:
       ports_http:
         default: 9090
         default: 9090
-
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: prometheus
         default: prometheus
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS

+ 4 - 1
library/compose/renovate/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -29,6 +28,7 @@ metadata:
     - traefik
     - traefik
     - swarm
     - swarm
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -44,6 +44,9 @@ spec:
         default: "renovate"
         default: "renovate"
       container_timezone:
       container_timezone:
         default: "UTC"
         default: "UTC"
+      container_loglevel:
+        type: enum
+        options: [debug, info, warn, error]
   renovate_settings:
   renovate_settings:
     title: "Renovate Settings"
     title: "Renovate Settings"
     required: true
     required: true

+ 68 - 13
library/compose/semaphoreui/template.yaml

@@ -5,32 +5,45 @@ metadata:
     provider: selfh
     provider: selfh
     id: semaphore-ui
     id: semaphore-ui
   name: Semaphore UI
   name: Semaphore UI
-  description: |-
-    Modern UI for Ansible automation with task scheduling and web-based management.
+  description: 'Modern UI for Ansible automation with task scheduling and web-based management.
+
     Semaphore provides a beautiful web interface to run Ansible playbooks, manage
     Semaphore provides a beautiful web interface to run Ansible playbooks, manage
+
     inventories, and schedule automated tasks. Perfect for teams who want a
     inventories, and schedule automated tasks. Perfect for teams who want a
+
     user-friendly way to execute and monitor Ansible automation.
     user-friendly way to execute and monitor Ansible automation.
+
     ## Prerequisites
     ## Prerequisites
+
     - :info: SemaphoreUI supports multiple database backends. You can choose between SQLite (default),
     - :info: SemaphoreUI supports multiple database backends. You can choose between SQLite (default),
+
     PostgreSQL, or MySQL. SQLite is suitable for small deployments, while PostgreSQL and MySQL
     PostgreSQL, or MySQL. SQLite is suitable for small deployments, while PostgreSQL and MySQL
+
     are recommended for larger installations.
     are recommended for larger installations.
+
     ## References
     ## References
+
     - **Project:** https://www.semaphoreui.com/
     - **Project:** https://www.semaphoreui.com/
+
     - **Documentation:** https://docs.semaphoreui.com/
     - **Documentation:** https://docs.semaphoreui.com/
-    - **GitHub:** https://github.com/semaphoreui/semaphore
+
+    - **GitHub:** https://github.com/semaphoreui/semaphore'
   version: v2.16.47
   version: v2.16.47
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-17'
   date: '2025-12-17'
   tags:
   tags:
     - traefik
     - traefik
     - database
     - database
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
     ```bash
+
     Username: {{ admin_user }}
     Username: {{ admin_user }}
+
     Password: {{ admin_pass }}
     Password: {{ admin_pass }}
-    ```
-schema: 1.2
+
+    ```'
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -38,35 +51,44 @@ spec:
         default: semaphoreui
         default: semaphoreui
       container_name:
       container_name:
         default: semaphoreui
         default: semaphoreui
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       secret_key:
       secret_key:
-        description: "Secret key for encrypting access keys"
+        description: Secret key for encrypting access keys
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
         required: true
         required: true
       admin_user:
       admin_user:
-        description: "Administrator username"
+        description: Administrator username
         type: str
         type: str
         required: true
         required: true
         default: admin
         default: admin
       admin_name:
       admin_name:
-        description: "Administrator full name"
+        description: Administrator full name
         type: str
         type: str
         required: true
         required: true
         default: Administrator
         default: Administrator
       admin_email:
       admin_email:
-        description: "Administrator email address"
+        description: Administrator email address
         type: str
         type: str
         required: true
         required: true
         default: admin@home.arpa
         default: admin@home.arpa
       admin_pass:
       admin_pass:
-        description: "Administrator password"
+        description: Administrator password
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
         required: true
         required: true
       ansible_host_key_checking:
       ansible_host_key_checking:
-        description: "Enable Ansible SSH host key checking"
+        description: Enable Ansible SSH host key checking
         type: bool
         type: bool
   ports:
   ports:
     vars:
     vars:
@@ -76,6 +98,28 @@ spec:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: semaphoreui
         default: semaphoreui
+      traefik_network:
+        default: traefik
+        type: str
+        required: true
+      traefik_domain:
+        default: home.arpa
+        type: str
+        required: true
+      traefik_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik integration
+  traefik_tls:
+    vars:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
+        type: bool
+        default: false
+        description: Enable Traefik TLS
   database:
   database:
     vars:
     vars:
       database_type:
       database_type:
@@ -87,3 +131,14 @@ spec:
         default: semaphore
         default: semaphore
       database_user:
       database_user:
         default: semaphore
         default: semaphore
+      database_host:
+        type: str
+        required: true
+      database_password:
+        type: str
+        sensitive: true
+        required: true
+      database_external:
+        type: bool
+        default: false
+        description: Use external database

+ 122 - 25
library/compose/traefik/template.yaml

@@ -2,13 +2,17 @@
 kind: compose
 kind: compose
 metadata:
 metadata:
   name: Traefik
   name: Traefik
-  description: |-
-    Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy.
-    This template sets up Traefik with automatic HTTPS using Let's Encrypt and can be integrated with Authentik for SSO.
+  description: 'Traefik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy.
+
+    This template sets up Traefik with automatic HTTPS using Let''s Encrypt and can be integrated with Authentik for SSO.
+
     ## References
     ## References
+
     - **Project:** https://traefik.io/
     - **Project:** https://traefik.io/
+
     - **Documentation:** https://doc.traefik.io/traefik/
     - **Documentation:** https://doc.traefik.io/traefik/
-    - **GitHub:** https://github.com/traefik/traefik
+
+    - **GitHub:** https://github.com/traefik/traefik'
   version: v3.6.5
   version: v3.6.5
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-12-17'
   date: '2025-12-17'
@@ -19,22 +23,38 @@ metadata:
     provider: simpleicons
     provider: simpleicons
     id: traefikproxy
     id: traefikproxy
   draft: false
   draft: false
-  next_steps: |-
-    Start the `{{ service_name }}` project
-    {% if swarm_enabled %}
-    1. Deploy Traefik to Docker Swarm:
-      `docker stack deploy -c docker-compose.yaml {{ service_name }}`
-    {% else %}
-    1. Copy the project directory for `{{ service_name }}` to the host.
-    2. Start Traefik with Docker Compose from the project directory:
-      `docker compose up -d`
-    {% endif %}
-schema: "1.2"
+  next_steps: "Start the `{{ service_name }}` project\n{% if swarm_enabled %}\n1. Deploy Traefik to Docker Swarm:\n  `docker\
+    \ stack deploy -c docker-compose.yaml {{ service_name }}`\n{% else %}\n1. Copy the project directory for `{{ service_name\
+    \ }}` to the host.\n2. Start Traefik with Docker Compose from the project directory:\n  `docker compose up -d`\n{% endif\
+    \ %}"
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       service_name:
       service_name:
         default: traefik
         default: traefik
+      container_name:
+        type: str
+      container_hostname:
+        type: str
+      container_timezone:
+        type: str
+      container_loglevel:
+        type: enum
+        options:
+          - debug
+          - info
+          - warn
+          - error
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
   ports:
     vars:
     vars:
       ports_dashboard:
       ports_dashboard:
@@ -42,7 +62,8 @@ spec:
         type: int
         type: int
         default: 8080
         default: 8080
         required: true
         required: true
-        needs: [dashboard_enabled=true]
+        needs:
+          - dashboard_enabled=true
         extra: Only used when dashboard is enabled
         extra: Only used when dashboard is enabled
       ports_http:
       ports_http:
         default: 80
         default: 80
@@ -89,44 +110,58 @@ spec:
         type: str
         type: str
         default: us-east-1
         default: us-east-1
         required: true
         required: true
-        needs: [traefik_tls_certresolver=route53]
+        needs:
+          - traefik_tls_certresolver=route53
       traefik_tls_acme_resource_group:
       traefik_tls_acme_resource_group:
         description: Azure Resource Group
         description: Azure Resource Group
         type: str
         type: str
         required: true
         required: true
-        needs: [traefik_tls_certresolver=azure]
+        needs:
+          - traefik_tls_certresolver=azure
       traefik_tls_acme_secret_key:
       traefik_tls_acme_secret_key:
         description: DNS provider secret key
         description: DNS provider secret key
         type: str
         type: str
         sensitive: true
         sensitive: true
         required: true
         required: true
-        needs: ['traefik_tls_certresolver=azure,godaddy,porkbun,route53']
+        needs:
+          - traefik_tls_certresolver=azure,godaddy,porkbun,route53
         extra: AZURE_CLIENT_SECRET, GODADDY_API_SECRET, PORKBUN_SECRET_API_KEY, or AWS_SECRET_ACCESS_KEY
         extra: AZURE_CLIENT_SECRET, GODADDY_API_SECRET, PORKBUN_SECRET_API_KEY, or AWS_SECRET_ACCESS_KEY
       traefik_tls_acme_subscription_id:
       traefik_tls_acme_subscription_id:
         description: Azure Subscription ID
         description: Azure Subscription ID
         type: str
         type: str
         required: true
         required: true
-        needs: [traefik_tls_certresolver=azure]
+        needs:
+          - traefik_tls_certresolver=azure
       traefik_tls_acme_tenant_id:
       traefik_tls_acme_tenant_id:
         description: Azure Tenant ID
         description: Azure Tenant ID
         type: str
         type: str
         required: true
         required: true
-        needs: [traefik_tls_certresolver=azure]
+        needs:
+          - traefik_tls_certresolver=azure
       traefik_tls_acme_token:
       traefik_tls_acme_token:
         description: DNS provider API token
         description: DNS provider API token
         type: str
         type: str
         sensitive: true
         sensitive: true
         required: true
         required: true
-        needs: ['traefik_tls_certresolver=cloudflare,digitalocean,godaddy,namecheap,porkbun']
+        needs:
+          - traefik_tls_certresolver=cloudflare,digitalocean,godaddy,namecheap,porkbun
         extra: CF_DNS_API_TOKEN, DO_AUTH_TOKEN, GODADDY_API_KEY, NAMECHEAP_API_KEY, or PORKBUN_API_KEY
         extra: CF_DNS_API_TOKEN, DO_AUTH_TOKEN, GODADDY_API_KEY, NAMECHEAP_API_KEY, or PORKBUN_API_KEY
       traefik_tls_acme_username:
       traefik_tls_acme_username:
         description: Namecheap API username
         description: Namecheap API username
         type: str
         type: str
         required: true
         required: true
-        needs: [traefik_tls_certresolver=namecheap]
+        needs:
+          - traefik_tls_certresolver=namecheap
       traefik_tls_certresolver:
       traefik_tls_certresolver:
         description: ACME DNS challenge provider
         description: ACME DNS challenge provider
-        options: [cloudflare, porkbun, godaddy, digitalocean, route53, azure, namecheap]
+        options:
+          - cloudflare
+          - porkbun
+          - godaddy
+          - digitalocean
+          - route53
+          - azure
+          - namecheap
         extra: DNS provider for domain validation
         extra: DNS provider for domain validation
       traefik_tls_enabled:
       traefik_tls_enabled:
         description: Enable HTTPS/TLS with ACME
         description: Enable HTTPS/TLS with ACME
@@ -134,7 +169,9 @@ spec:
       traefik_tls_min_version:
       traefik_tls_min_version:
         description: Minimum TLS version
         description: Minimum TLS version
         type: enum
         type: enum
-        options: [VersionTLS12, VersionTLS13]
+        options:
+          - VersionTLS12
+          - VersionTLS13
         extra: TLS 1.2 is recommended for compatibility, TLS 1.3 for maximum security
         extra: TLS 1.2 is recommended for compatibility, TLS 1.3 for maximum security
       traefik_tls_redirect:
       traefik_tls_redirect:
         description: Redirect all HTTP traffic to HTTPS
         description: Redirect all HTTP traffic to HTTPS
@@ -148,3 +185,63 @@ spec:
         description: Skip TLS verification for backend servers
         description: Skip TLS verification for backend servers
         type: bool
         type: bool
         extra: 'WARNING: Only enable for self-signed certificates in trusted environments'
         extra: 'WARNING: Only enable for self-signed certificates in trusted environments'
+  volume:
+    vars:
+      volume_mode:
+        type: enum
+        options:
+          - local
+          - mount
+          - nfs
+        default: local
+        required: true
+      volume_mount_path:
+        type: str
+        default: /mnt/storage
+        needs:
+          - volume_mode=mount
+        required: true
+      volume_nfs_server:
+        type: str
+        default: 192.168.1.1
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_path:
+        type: str
+        default: /export
+        needs:
+          - volume_mode=nfs
+        required: true
+      volume_nfs_options:
+        type: str
+        default: rw,nolock,soft
+        needs:
+          - volume_mode=nfs
+        required: true
+  swarm:
+    vars:
+      swarm_placement_mode:
+        type: enum
+        options:
+          - replicated
+          - global
+        default: replicated
+        required: true
+      swarm_replicas:
+        type: int
+        default: 1
+        needs:
+          - swarm_placement_mode=replicated
+        required: true
+      swarm_placement_host:
+        type: str
+        description: Target hostname for placement constraint
+        default: ''
+        needs:
+          - swarm_placement_mode=replicated
+        extra: Constrains service to run on specific node by hostname
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode

+ 67 - 9
library/compose/twingate-connector/template.yaml

@@ -1,16 +1,14 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
     id: twingate
     id: twingate
   name: Twingate_Connector
   name: Twingate_Connector
-  description: >
-    The Twingate Connector is a lightweight software component that establishes secure connections between your private network and the
-    Twingate service. It acts as a bridge, allowing authorized users to access internal resources without exposing them directly to the
-    internet. The Connector uses strong encryption and authentication mechanisms to ensure that all data transmitted between users and
-    resources remains confidential and secure.
+  description: 'The Twingate Connector is a lightweight software component that establishes secure connections between your
+    private network and the Twingate service. It acts as a bridge, allowing authorized users to access internal resources
+    without exposing them directly to the internet. The Connector uses strong encryption and authentication mechanisms to
+    ensure that all data transmitted between users and resources remains confidential and secure.
 
 
 
 
     Project: https://www.twingate.com/
     Project: https://www.twingate.com/
@@ -18,12 +16,15 @@ metadata:
     Documentation: https://docs.twingate.com/docs/architecture/connectors
     Documentation: https://docs.twingate.com/docs/architecture/connectors
 
 
     GitHub: https://github.com/twingate/twingate-connector
     GitHub: https://github.com/twingate/twingate-connector
+
+    '
   version: 1.80.0
   version: 1.80.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-11-11'
   date: '2025-11-11'
   tags:
   tags:
     - swarm
     - swarm
   draft: true
   draft: true
+schema: '1.2'
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -33,10 +34,21 @@ spec:
         default: twingate_connector
         default: twingate_connector
       container_hostname:
       container_hostname:
         default: twingate_connector
         default: twingate_connector
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       twingate_version:
       twingate_version:
         type: str
         type: str
         description: Twingate Connector version
         description: Twingate Connector version
-        default: "1.79.0"
+        default: 1.79.0
   twingate:
   twingate:
     title: Twingate Configuration
     title: Twingate Configuration
     required: true
     required: true
@@ -44,7 +56,7 @@ spec:
       twingate_network:
       twingate_network:
         type: str
         type: str
         description: Your Twingate network name
         description: Your Twingate network name
-        prompt: "Enter your Twingate network name"
+        prompt: Enter your Twingate network name
       twingate_log_level:
       twingate_log_level:
         type: int
         type: int
         description: Log level (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
         description: Log level (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
@@ -52,4 +64,50 @@ spec:
       twingate_dns:
       twingate_dns:
         type: str
         type: str
         description: Local DNS server IP (optional, leave empty to use default)
         description: Local DNS server IP (optional, leave empty to use default)
-        default: ""
+        default: ''
+  resources:
+    vars:
+      resources_enabled:
+        type: bool
+        default: false
+      resources_cpu_limit:
+        type: str
+        default: 1.0
+        required: true
+      resources_cpu_reservation:
+        type: str
+        default: 0.25
+        needs:
+          - swarm_enabled=true
+        required: true
+      resources_memory_limit:
+        type: str
+        default: 1G
+        required: true
+      resources_memory_reservation:
+        type: str
+        default: 512M
+        needs:
+          - swarm_enabled=true
+        required: true
+  swarm:
+    vars:
+      swarm_replicas:
+        type: int
+        default: 1
+        needs:
+          - swarm_placement_mode=replicated
+        required: true
+      swarm_placement_host:
+        type: str
+        description: Target hostname for placement constraint
+        default: ''
+        extra: Constrains service to run on specific node by hostname
+      swarm_enabled:
+        type: bool
+        default: false
+        description: Enable Docker Swarm mode
+      swarm_placement_mode:
+        type: str
+        default: replicated
+        description: The placement mode

+ 1 - 1
library/compose/uptimekuma/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: compose
 kind: compose
-schema: "1.2"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -21,6 +20,7 @@ metadata:
   date: '2025-10-31'
   date: '2025-10-31'
   tags: []
   tags: []
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:

+ 65 - 0
library/compose/whoami/template.yaml

@@ -28,7 +28,72 @@ spec:
     vars:
     vars:
       service_name:
       service_name:
         default: whoami
         default: whoami
+      restart_policy:
+        description: Container restart policy
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   traefik:
   traefik:
     vars:
     vars:
       traefik_host:
       traefik_host:
         default: whoami
         default: whoami
+      traefik_network:
+        description: Traefik network name
+        type: str
+        default: traefik
+        required: true
+      traefik_domain:
+        description: Base domain (e.g., example.com)
+        type: str
+        default: home.arpa
+        required: true
+  traefik_tls:
+    vars:
+      traefik_tls_enabled:
+        description: Enable HTTPS/TLS
+        type: bool
+        default: true
+      traefik_tls_certresolver:
+        description: Traefik certificate resolver name
+        type: str
+        default: cloudflare
+        required: true
+  resources:
+    vars:
+      resources_enabled:
+        description: Enable resource limits
+        type: bool
+        default: false
+  swarm:
+    vars:
+      swarm_enabled:
+        description: Enable Docker Swarm mode
+        type: bool
+        default: false
+      swarm_placement_mode:
+        description: Swarm placement mode
+        type: enum
+        options:
+          - replicated
+          - global
+        default: replicated
+        required: true
+      swarm_replicas:
+        description: Number of replicas
+        type: int
+        default: 1
+        needs:
+          - swarm_placement_mode=replicated
+        required: true
+      swarm_placement_host:
+        description: Target hostname for placement constraint
+        type: str
+        default: ''
+        needs:
+          - swarm_placement_mode=replicated
+        extra: Constrains service to run on specific node by hostname

+ 86 - 3
library/helm/authentik/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: helm
 kind: helm
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -25,14 +24,21 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       release_name:
       release_name:
         default: authentik
         default: authentik
+      namespace:
+        type: str
+        description: Kubernetes namespace
+        default: authentik
   networking:
   networking:
     vars:
     vars:
       network_mode:
       network_mode:
+        type: str
+        description: Network mode for service
         default: ClusterIP
         default: ClusterIP
   authentik:
   authentik:
     title: Authentik Configuration
     title: Authentik Configuration
@@ -60,21 +66,98 @@ spec:
         description: Enable error reporting to Authentik developers
         description: Enable error reporting to Authentik developers
         default: false
         default: false
   database:
   database:
+    title: Database Configuration
+    toggle: database_enabled
     vars:
     vars:
       database_enabled:
       database_enabled:
+        type: bool
+        description: Enable database
         default: true
         default: true
       database_type:
       database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
         default: postgres
         default: postgres
+      database_host:
+        type: hostname
+        description: Database host
+        default: authentik-postgresql
+      database_port:
+        type: int
+        description: Database port
+        default: 5432
       database_name:
       database_name:
+        type: str
+        description: Database name
         default: authentik
         default: authentik
       database_user:
       database_user:
+        type: str
+        description: Database user
         default: authentik
         default: authentik
-      database_port:
-        default: 5432
       database_password:
       database_password:
+        type: str
         description: PostgreSQL database password
         description: PostgreSQL database password
         sensitive: true
         sensitive: true
+        autogenerated: true
+  email:
+    title: Email Configuration
+    toggle: email_enabled
+    vars:
+      email_enabled:
+        type: bool
+        description: Enable email notifications
+        default: false
+      email_host:
+        type: hostname
+        description: SMTP server hostname
+        default: smtp.example.com
+      email_port:
+        type: int
+        description: SMTP server port
+        default: 587
+      email_username:
+        type: str
+        description: SMTP username
+        default: ""
+      email_password:
+        type: str
+        description: SMTP password
+        sensitive: true
+        default: ""
+      email_from:
+        type: email
+        description: From email address
+        default: authentik@example.com
+      email_use_tls:
+        type: bool
+        description: Use TLS/STARTTLS for SMTP connection
+        default: true
   traefik:
   traefik:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
     vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik ingress
+        default: false
       traefik_host:
       traefik_host:
+        type: hostname
+        description: Traefik hostname
         default: authentik.home.arpa
         default: authentik.home.arpa
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS for Traefik ingress
+        default: false
+      traefik_tls_secret:
+        type: str
+        description: TLS secret name for Traefik ingress
+        default: authentik-tls
+      traefik_tls_certmanager:
+        type: bool
+        description: Use cert-manager for TLS certificate
+        default: false
+      certmanager_issuer:
+        type: str
+        description: Cert-manager issuer name
+        needs: traefik_tls_certmanager=true
+        default: letsencrypt-prod

+ 48 - 3
library/helm/certmanager/template.yaml

@@ -20,8 +20,55 @@ metadata:
     id: lets-encrypt
     id: lets-encrypt
   draft: true
   draft: true
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
+  general:
+    vars:
+      release_name:
+        type: str
+        description: Helm release name
+        default: cert-manager
+      namespace:
+        type: str
+        description: Kubernetes namespace
+        default: cert-manager
+  networking:
+    title: Networking Configuration
+    vars:
+      network_mode:
+        type: str
+        description: Network mode for service
+        default: ClusterIP
+  database:
+    title: Database Configuration
+    toggle: database_enabled
+    vars:
+      database_enabled:
+        type: bool
+        description: Enable database
+        default: false
+      database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
+        default: postgres
+      database_host:
+        type: hostname
+        description: Database host
+      database_port:
+        type: int
+        description: Database port
+        default: 5432
+      database_name:
+        type: str
+        description: Database name
+      database_user:
+        type: str
+        description: Database user
+      database_password:
+        type: str
+        description: Database password
+        sensitive: true
   dns:
   dns:
     title: DNS Configuration
     title: DNS Configuration
     vars:
     vars:
@@ -37,8 +84,6 @@ spec:
         description: Use only recursive nameservers for DNS01 challenges
         description: Use only recursive nameservers for DNS01 challenges
         type: bool
         type: bool
         default: true
         default: true
-  general:
-    vars:
       namespace:
       namespace:
         type: str
         type: str
         default: cert-manager
         default: cert-manager

+ 48 - 3
library/helm/longhorn/template.yaml

@@ -21,8 +21,55 @@ metadata:
     id: rancher-longhorn
     id: rancher-longhorn
   draft: true
   draft: true
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
+  general:
+    vars:
+      release_name:
+        type: str
+        description: Helm release name
+        default: longhorn
+      namespace:
+        type: str
+        description: Kubernetes namespace
+        default: longhorn-system
+  networking:
+    title: Networking Configuration
+    vars:
+      network_mode:
+        type: str
+        description: Network mode for service
+        default: ClusterIP
+  database:
+    title: Database Configuration
+    toggle: database_enabled
+    vars:
+      database_enabled:
+        type: bool
+        description: Enable database
+        default: false
+      database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
+        default: postgres
+      database_host:
+        type: hostname
+        description: Database host
+      database_port:
+        type: int
+        description: Database port
+        default: 5432
+      database_name:
+        type: str
+        description: Database name
+      database_user:
+        type: str
+        description: Database user
+      database_password:
+        type: str
+        description: Database password
+        sensitive: true
   backup:
   backup:
     title: Backup Configuration
     title: Backup Configuration
     toggle: backup_enabled
     toggle: backup_enabled
@@ -34,8 +81,6 @@ spec:
       backup_target:
       backup_target:
         description: Backup target URL (e.g., s3://bucket or nfs://server/path)
         description: Backup target URL (e.g., s3://bucket or nfs://server/path)
         type: str
         type: str
-  general:
-    vars:
       namespace:
       namespace:
         type: str
         type: str
         default: longhorn-system
         default: longhorn-system

+ 97 - 1
library/helm/netbox/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: helm
 kind: helm
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -21,6 +20,7 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-13'
   date: '2025-01-13'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -29,19 +29,46 @@ spec:
       namespace:
       namespace:
         default: netbox
         default: netbox
   database:
   database:
+    title: Database Configuration
+    toggle: database_enabled
     vars:
     vars:
       database_enabled:
       database_enabled:
+        type: bool
+        description: Enable database
         default: true
         default: true
       database_type:
       database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
         default: postgres
         default: postgres
       database_host:
       database_host:
+        type: hostname
+        description: Database host
         default: netbox-postgresql
         default: netbox-postgresql
       database_port:
       database_port:
+        type: int
+        description: Database port
         default: 5432
         default: 5432
       database_name:
       database_name:
+        type: str
+        description: Database name
         default: netbox
         default: netbox
       database_user:
       database_user:
+        type: str
+        description: Database user
         default: netbox
         default: netbox
+      database_password:
+        type: str
+        description: Database password
+        sensitive: true
+        autogenerated: true
+  networking:
+    title: Networking Configuration
+    vars:
+      network_mode:
+        type: str
+        description: Network mode for service
+        default: ClusterIP
   redis:
   redis:
     title: Redis Configuration
     title: Redis Configuration
     description: Configure Redis for caching and task queuing
     description: Configure Redis for caching and task queuing
@@ -64,10 +91,79 @@ spec:
         type: str
         type: str
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
+  email:
+    title: Email Configuration
+    toggle: email_enabled
+    vars:
+      email_enabled:
+        type: bool
+        description: Enable email notifications
+        default: false
+      email_host:
+        type: hostname
+        description: SMTP server hostname
+        default: smtp.example.com
+      email_port:
+        type: int
+        description: SMTP server port
+        default: 587
+      email_username:
+        type: str
+        description: SMTP username
+        default: ""
+      email_from:
+        type: email
+        description: From email address
+        default: netbox@example.com
+      email_use_tls:
+        type: bool
+        description: Use TLS/STARTTLS for SMTP connection
+        default: true
+      email_use_ssl:
+        type: bool
+        description: Use SSL for SMTP connection
+        default: false
   traefik:
   traefik:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
     vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik ingress
+        default: false
       traefik_host:
       traefik_host:
+        type: hostname
+        description: Traefik hostname
         default: netbox.home.arpa
         default: netbox.home.arpa
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS for Traefik ingress
+        default: false
+      traefik_tls_secret:
+        type: str
+        description: TLS secret name for Traefik ingress
+        default: netbox-tls
+      traefik_tls_certmanager:
+        type: bool
+        description: Use cert-manager for TLS certificate
+        default: false
+      certmanager_issuer:
+        type: str
+        description: Cert-manager issuer name
+        needs: traefik_tls_certmanager=true
+        default: letsencrypt-prod
+  volumes:
+    title: Volume Configuration
+    vars:
+      volumes_mode:
+        type: enum
+        description: Volume storage mode
+        options: [pvc, hostPath]
+        default: pvc
+      volumes_pvc_name:
+        type: str
+        description: PVC name for volumes
+        default: netbox-data
   netbox:
   netbox:
     title: NetBox Configuration
     title: NetBox Configuration
     description: Configure NetBox application settings
     description: Configure NetBox application settings

+ 63 - 1
library/helm/portainer/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: helm
 kind: helm
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -25,20 +24,83 @@ metadata:
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
   draft: true
   draft: true
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       release_name:
       release_name:
+        type: str
+        description: Helm release name
+        default: portainer
+      namespace:
+        type: str
+        description: Kubernetes namespace
         default: portainer
         default: portainer
   networking:
   networking:
     vars:
     vars:
       network_mode:
       network_mode:
+        type: str
+        description: Network mode for service
         default: ClusterIP
         default: ClusterIP
+  database:
+    title: Database Configuration
+    toggle: database_enabled
+    vars:
+      database_enabled:
+        type: bool
+        description: Enable database
+        default: false
+      database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
+        default: postgres
+      database_host:
+        type: hostname
+        description: Database host
+      database_port:
+        type: int
+        description: Database port
+        default: 5432
+      database_name:
+        type: str
+        description: Database name
+      database_user:
+        type: str
+        description: Database user
+      database_password:
+        type: str
+        description: Database password
+        sensitive: true
   traefik:
   traefik:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
     vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik ingress
+        default: false
       traefik_host:
       traefik_host:
+        type: hostname
+        description: Traefik hostname
         default: portainer.home.arpa
         default: portainer.home.arpa
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS for Traefik ingress
+        default: false
+      traefik_tls_secret:
+        type: str
+        description: TLS secret name for Traefik ingress
+        default: portainer-tls
   volumes:
   volumes:
+    title: Volume Configuration
     vars:
     vars:
+      volumes_mode:
+        type: enum
+        description: Volume storage mode
+        options: [pvc, hostPath]
+        default: pvc
       volumes_pvc_name:
       volumes_pvc_name:
+        type: str
+        description: PVC name for volumes
         default: portainer
         default: portainer

+ 48 - 3
library/helm/traefik/template.yaml

@@ -20,8 +20,55 @@ metadata:
     id: traefikproxy
     id: traefikproxy
   draft: true
   draft: true
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
+  general:
+    vars:
+      release_name:
+        type: str
+        description: Helm release name
+        default: traefik
+      namespace:
+        type: str
+        description: Kubernetes namespace
+        default: traefik
+  networking:
+    title: Networking Configuration
+    vars:
+      network_mode:
+        type: str
+        description: Network mode for service
+        default: LoadBalancer
+  database:
+    title: Database Configuration
+    toggle: database_enabled
+    vars:
+      database_enabled:
+        type: bool
+        description: Enable database
+        default: false
+      database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
+        default: postgres
+      database_host:
+        type: hostname
+        description: Database host
+      database_port:
+        type: int
+        description: Database port
+        default: 5432
+      database_name:
+        type: str
+        description: Database name
+      database_user:
+        type: str
+        description: Database user
+      database_password:
+        type: str
+        description: Database password
+        sensitive: true
   dashboard:
   dashboard:
     title: Dashboard IngressRoute
     title: Dashboard IngressRoute
     toggle: dashboard_ingressroute_enabled
     toggle: dashboard_ingressroute_enabled
@@ -41,8 +88,6 @@ spec:
         description: TLS secret name for dashboard
         description: TLS secret name for dashboard
         type: str
         type: str
         default: traefik-dashboard-tls
         default: traefik-dashboard-tls
-  general:
-    vars:
       release_name:
       release_name:
         type: str
         type: str
         default: traefik
         default: traefik

+ 47 - 1
library/kubernetes/certmanager-certificate/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -22,6 +21,7 @@ metadata:
   version: 1.16.2
   version: 1.16.2
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -33,6 +33,52 @@ spec:
         type: str
         type: str
         description: Name of secret to store the certificate
         description: Name of secret to store the certificate
         default: tls-secret
         default: tls-secret
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod
   dns:
   dns:
     title: DNS Settings
     title: DNS Settings
     vars:
     vars:

+ 51 - 1
library/kubernetes/certmanager-clusterissuer/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -19,11 +18,16 @@ metadata:
   version: 1.16.2
   version: 1.16.2
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       resource_name:
       resource_name:
         default: cloudflare-clusterissuer
         default: cloudflare-clusterissuer
+      namespace:
+        type: str
+        description: Namespace (ClusterIssuer is cluster-scoped, but needed for schema)
+        default: cert-manager
       acme_email:
       acme_email:
         type: email
         type: email
         description: Email address for ACME account registration
         description: Email address for ACME account registration
@@ -43,3 +47,49 @@ spec:
         type: str
         type: str
         description: Key name in secret containing Cloudflare API token
         description: Key name in secret containing Cloudflare API token
         default: api-token
         default: api-token
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/certmanager-issuer/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -22,6 +21,7 @@ metadata:
   version: 1.16.2
   version: 1.16.2
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -48,3 +48,49 @@ spec:
         type: str
         type: str
         description: Key name in secret containing Cloudflare API token
         description: Key name in secret containing Cloudflare API token
         default: api-token
         default: api-token
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-configmap/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -24,3 +24,49 @@ spec:
         default: app-config
         default: app-config
       namespace:
       namespace:
         default: default
         default: default
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 43 - 1
library/kubernetes/core-ingress/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -38,7 +38,49 @@ spec:
         type: int
         type: int
         description: Backend service port
         description: Backend service port
         default: 80
         default: 80
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
   traefik:
   traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
     vars:
     vars:
       traefik_enabled:
       traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
         default: false
         default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-ingressclass/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -30,3 +30,49 @@ spec:
         type: bool
         type: bool
         description: Set as default IngressClass
         description: Set as default IngressClass
         default: false
         default: false
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-persistentvolume/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -51,3 +51,49 @@ spec:
         type: str
         type: str
         description: Host path for local storage (e.g., /mnt/data)
         description: Host path for local storage (e.g., /mnt/data)
         default: /mnt/data
         default: /mnt/data
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-persistentvolumeclaim/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -41,3 +41,49 @@ spec:
           - ReadWriteMany
           - ReadWriteMany
           - ReadWriteOncePod
           - ReadWriteOncePod
         default: ReadWriteOnce
         default: ReadWriteOnce
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-secret/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -34,3 +34,49 @@ spec:
         default: ""
         default: ""
         sensitive: true
         sensitive: true
         autogenerated: true
         autogenerated: true
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-service/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -49,6 +49,52 @@ spec:
           - UDP
           - UDP
           - SCTP
           - SCTP
         default: TCP
         default: TCP
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod
       app_selector:
       app_selector:
         type: str
         type: str
         description: App label selector (e.g., app.kubernetes.io/name value)
         description: App label selector (e.g., app.kubernetes.io/name value)

+ 47 - 1
library/kubernetes/core-serviceaccount/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -24,3 +24,49 @@ spec:
         default: app-serviceaccount
         default: app-serviceaccount
       namespace:
       namespace:
         default: default
         default: default
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/core-storageclass/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   version: 1.31.0
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -40,3 +40,49 @@ spec:
           - Retain
           - Retain
           - Delete
           - Delete
         default: Delete
         default: Delete
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 39 - 3
library/kubernetes/traefik-ingressroute/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -19,6 +18,7 @@ metadata:
   version: 3.5.3
   version: 3.5.3
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -41,13 +41,49 @@ spec:
         type: int
         type: int
         description: Kubernetes service port
         description: Kubernetes service port
         default: 80
         default: 80
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
   traefik:
   traefik:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
     vars:
       traefik_enabled:
       traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
         default: true
         default: true
       traefik_host:
       traefik_host:
+        type: hostname
         description: Domain name for the IngressRoute
         description: Domain name for the IngressRoute
-  traefik_tls:
-    vars:
+      traefik_domain:
+        type: str
+        description: Traefik domain
       traefik_tls_enabled:
       traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
         default: true
         default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 46 - 3
library/kubernetes/traefik-ingressroutetcp/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: kubernetes
 kind: kubernetes
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -22,6 +21,7 @@ metadata:
   version: 3.5.3
   version: 3.5.3
   author: Christian Lempa
   author: Christian Lempa
   date: '2025-01-11'
   date: '2025-01-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -29,17 +29,60 @@ spec:
         default: app-tcp-route
         default: app-tcp-route
       namespace:
       namespace:
         default: default
         default: default
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
   traefik:
   traefik:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
     vars:
       traefik_enabled:
       traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
         default: true
         default: true
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
       traefik_entrypoint:
       traefik_entrypoint:
+        type: str
+        description: Traefik entrypoint for TCP routing
         default: tcp
         default: tcp
       traefik_service_name:
       traefik_service_name:
+        type: str
         description: Backend service name for TCP routing
         description: Backend service name for TCP routing
       traefik_service_port:
       traefik_service_port:
+        type: int
+        description: Backend service port for TCP routing
         default: 5432
         default: 5432
-  traefik_tls:
-    vars:
       traefik_tls_enabled:
       traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
         default: false
         default: false
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 47 - 1
library/kubernetes/traefik-middleware/template.yaml

@@ -20,7 +20,7 @@ metadata:
     id: traefik
     id: traefik
   draft: false
   draft: false
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
@@ -34,3 +34,49 @@ spec:
         type: enum
         type: enum
         default: redirectScheme
         default: redirectScheme
         options: [redirectScheme, stripPrefix, addPrefix, headers, rateLimit]
         options: [redirectScheme, stripPrefix, addPrefix, headers, rateLimit]
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 49 - 1
library/kubernetes/twingate-connector/template.yaml

@@ -18,12 +18,14 @@ metadata:
     id: twingate
     id: twingate
   draft: false
   draft: false
   next_steps: ""
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
       resource_name:
       resource_name:
         default: twingate-connector
         default: twingate-connector
+      namespace:
+        default: default
       image_tag:
       image_tag:
         type: str
         type: str
         description: Twingate connector image tag
         description: Twingate connector image tag
@@ -35,3 +37,49 @@ spec:
         type: bool
         type: bool
         description: Enable status notifications
         description: Enable status notifications
         default: true
         default: true
+  resources:
+    title: Resource Limits
+    toggle: resources_enabled
+    vars:
+      resources_enabled:
+        type: bool
+        description: Enable resource limits and requests
+        default: false
+      resources_cpu_limit:
+        type: str
+        description: CPU limit
+        default: 100m
+      resources_cpu_request:
+        type: str
+        description: CPU request
+        default: 50m
+      resources_memory_limit:
+        type: str
+        description: Memory limit
+        default: 128Mi
+      resources_memory_request:
+        type: str
+        description: Memory request
+        default: 64Mi
+  traefik:
+    title: Traefik Integration
+    toggle: traefik_enabled
+    vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
+        default: false
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
+      traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
+        default: true
+      traefik_tls_certresolver:
+        type: str
+        description: TLS certificate resolver
+        default: letsencrypt-prod

+ 4 - 1
library/packer/proxmox-iso-ubuntu/template.yaml

@@ -1,6 +1,5 @@
 ---
 ---
 kind: packer
 kind: packer
-schema: "1.0"
 metadata:
 metadata:
   icon:
   icon:
     provider: selfh
     provider: selfh
@@ -25,9 +24,13 @@ metadata:
   version: 1.11.2
   version: 1.11.2
   author: Christian Lempa
   author: Christian Lempa
   date: '2024-11-11'
   date: '2024-11-11'
+schema: "1.2"
 spec:
 spec:
   general:
   general:
     vars:
     vars:
+      playbook_name:
+        type: str
+        description: Name of the playbook
       image_name:
       image_name:
         default: ubuntu-server-noble
         default: ubuntu-server-noble
       vm_id:
       vm_id:

+ 0 - 14
library/schemas/ansible/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 229
library/schemas/compose/v1.0.json

@@ -1,229 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "toggle": "network_enabled",
-    "vars": [
-      {
-        "name": "network_enabled",
-        "description": "Enable custom network block",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge"
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "toggle": "ports_enabled",
-    "vars": [
-      {
-        "name": "ports_enabled",
-        "description": "Expose ports via 'ports' mapping",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "description": "Deploy service in Docker Swarm mode with replicas.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas in Swarm",
-        "type": "int",
-        "default": 1
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["global", "replicated"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Limit placement to specific node",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["postgres", "mysql"],
-        "default": "postgres"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است