Просмотр исходного кода

Merge release/v0.1.3 into main

xcad 1 месяц назад
Родитель
Сommit
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]
 
+## [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
 
 ### Fixed

+ 1 - 1
cli/__init__.py

@@ -2,6 +2,6 @@
 Boilerplates CLI - A sophisticated command-line tool for managing infrastructure boilerplates.
 """
 
-__version__ = "0.1.2"
+__version__ = "0.1.3"
 __author__ = "Christian Lempa"
 __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("Tags")
         table.add_column("Version", no_wrap=True)
-        table.add_column("Schema", no_wrap=True)
         table.add_column("Library", no_wrap=True)
 
         settings = self.settings
@@ -102,7 +101,6 @@ class TableDisplay:
             tags_list = template.metadata.tags or []
             tags = ", ".join(tags_list) if tags_list 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
             library_name = template.metadata.library or ""
@@ -111,7 +109,7 @@ class TableDisplay:
             color = "yellow" if library_type == "static" else "blue"
             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)
 

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

@@ -67,7 +67,6 @@ class TemplateDisplay:
 
         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
-        schema = template.schema_version if hasattr(template, "schema_version") else "1.0"
         description = template.metadata.description or settings.TEXT_NO_DESCRIPTION
 
         # 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="cyan")
         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(icon + " ", 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)
 
 
+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):
     """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
 
 from .config import ConfigManager
-from .exceptions import DuplicateTemplateError, LibraryError, TemplateNotFoundError
+from .exceptions import DuplicateTemplateError, LibraryError, TemplateDraftError, TemplateNotFoundError
 
 logger = logging.getLogger(__name__)
 
@@ -53,17 +53,22 @@ class Library:
             return False
 
     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:
             module_name: The module name (e.g., 'compose', 'terraform')
             template_id: The template ID to find
 
         Returns:
-            Path to the template directory if found
+            Path to the template directory if found and not draft
 
         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}'")
 
@@ -75,23 +80,28 @@ class Library:
             (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)
 
+        # 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}")
         return template_path, self.name
 
     def find(self, module_name: str, sort_results: bool = False) -> list[tuple[Path, str]]:
         """Find templates in this library for a specific module.
 
-        Excludes templates marked as draft.
+        Includes all templates (both published and draft).
 
         Args:
             module_name: The module name (e.g., 'compose', 'terraform')
             sort_results: Whether to return results sorted alphabetically
 
         Returns:
-            List of Path objects representing template directories (excluding drafts)
+            List of Path objects representing template directories (including drafts)
 
         Raises:
             FileNotFoundError: If the module directory is not found in this library
@@ -111,7 +121,7 @@ class Library:
         try:
             for item in module_path.iterdir():
                 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
 
                     # Check for duplicate within same library
@@ -120,8 +130,6 @@ class Library:
 
                     seen_ids[template_id] = True
                     template_dirs.append((item, self.name))
-                elif has_template:
-                    logger.debug(f"Skipping draft template: {item.name}")
         except PermissionError as e:
             raise LibraryError(
                 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)
                             logger.debug(f"Found template '{base_id}' in library '{requested_lib}'")
                             return template_path, lib_name
-                        except TemplateNotFoundError:
+                        except (TemplateNotFoundError, TemplateDraftError):
                             logger.debug(f"Template '{base_id}' not found in library '{requested_lib}'")
                             return None
 
@@ -268,6 +276,9 @@ class LibraryManager:
             except TemplateNotFoundError:
                 # Continue searching in next library
                 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")
         return None

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

@@ -17,7 +17,11 @@ from ..exceptions import (
     TemplateValidationError,
 )
 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 .helpers import (
     apply_cli_overrides,
@@ -83,14 +87,34 @@ def list_templates(module_instance, raw: bool = False) -> list:
                 tags_list = template.metadata.tags or []
                 tags = ", ".join(tags_list) if tags_list 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_type = template.metadata.library_type or "git"
                 # Format library with icon and color
                 icon = IconManager.UI_LIBRARY_STATIC if library_type == "static" else IconManager.UI_LIBRARY_GIT
                 color = "yellow" if library_type == "static" else "blue"
                 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(
                 columns=[
@@ -98,7 +122,7 @@ def list_templates(module_instance, raw: bool = False) -> list:
                     {"name": "Name"},
                     {"name": "Tags"},
                     {"name": "Version", "no_wrap": True},
-                    {"name": "Schema", "no_wrap": True},
+                    {"name": "Status", "no_wrap": True},
                     {"name": "Library", "no_wrap": True},
                 ],
                 rows=filtered_templates,
@@ -129,14 +153,34 @@ def search_templates(module_instance, query: str) -> list:
             tags_list = template.metadata.tags or []
             tags = ", ".join(tags_list) if tags_list 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_type = template.metadata.library_type or "git"
             # Format library with icon and color
             icon = IconManager.UI_LIBRARY_STATIC if library_type == "static" else IconManager.UI_LIBRARY_GIT
             color = "yellow" if library_type == "static" else "blue"
             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(
             columns=[
@@ -144,7 +188,7 @@ def search_templates(module_instance, query: str) -> list:
                 {"name": "Name"},
                 {"name": "Tags"},
                 {"name": "Version", "no_wrap": True},
-                {"name": "Schema", "no_wrap": True},
+                {"name": "Status", "no_wrap": True},
                 {"name": "Library", "no_wrap": True},
             ],
             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_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_vars = template.variables.reset_disabled_bool_variables()
         if reset_vars:
@@ -347,7 +388,6 @@ def _prepare_template(
     apply_cli_overrides(template, var)
 
     if template.variables:
-        template.variables.sort_sections()
         reset_vars = template.variables.reset_disabled_bool_variables()
         if reset_vars:
             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)
 
-                # Validate schema version compatibility
-                template._validate_schema_version(self.schema_version, self.name)
-
                 # If template ID needs qualification, set qualified ID
                 if needs_qualification:
                     template.set_qualified_id()
@@ -115,9 +112,6 @@ class Module(ABC):
         try:
             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 "." in 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.
 """
 
-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_collection import VariableCollection
 from .variable_section import VariableSection
 
 __all__ = [
+    "TEMPLATE_STATUS_DRAFT",
+    "TEMPLATE_STATUS_INVALID",
+    "TEMPLATE_STATUS_PUBLISHED",
     "Template",
     "TemplateErrorHandler",
     "TemplateFile",

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

@@ -1,14 +1,12 @@
 from __future__ import annotations
 
 import base64
-import importlib
 import logging
 import os
 import re
 import secrets
 import string
 from dataclasses import dataclass, field
-from functools import lru_cache
 from pathlib import Path
 from typing import Any, Literal
 
@@ -29,7 +27,6 @@ from jinja2.exceptions import (
 from jinja2.sandbox import SandboxedEnvironment
 
 from ..exceptions import (
-    IncompatibleSchemaVersionError,
     RenderErrorContext,
     TemplateLoadError,
     TemplateRenderError,
@@ -37,11 +34,15 @@ from ..exceptions import (
     TemplateValidationError,
     YAMLParseError,
 )
-from ..version import is_compatible
 from .variable_collection import VariableCollection
 
 logger = logging.getLogger(__name__)
 
+# Template Status Constants
+TEMPLATE_STATUS_PUBLISHED = "published"
+TEMPLATE_STATUS_DRAFT = "draft"
+TEMPLATE_STATUS_INVALID = "invalid"
+
 
 class TemplateErrorHandler:
     """Handles parsing and formatting of template rendering errors.
@@ -314,8 +315,6 @@ class Template:
         self.library_type = library_type
 
         # Initialize caches for lazy loading
-        self.__module_specs: dict | None = None
-        self.__merged_specs: dict | None = None
         self.__jinja_env: Environment | None = None
         self.__used_variables: set[str] | None = None
         self.__variables: VariableCollection | None = None
@@ -350,12 +349,6 @@ class Template:
             # Validate 'kind' field (always needed)
             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
             # This significantly improves performance when listing many templates
 
@@ -389,80 +382,36 @@ class Template:
                 return path
         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:
-            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:
         """Collects all TemplateFile objects in the template directory."""
@@ -537,8 +486,6 @@ class Template:
     def _filter_specs_to_used(
         self,
         used_variables: set,
-        merged_specs: dict,
-        _module_specs: dict,
         template_specs: dict,
     ) -> dict:
         """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:
                 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)
         # We keep sensitive variables that are either:
         # 1. Actually used in template files, OR
         # 2. Explicitly defined in the template spec (even if not yet used)
         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
         filtered_specs = {}
@@ -569,36 +516,6 @@ class Template:
 
         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
     def _validate_kind(template_data: dict) -> None:
         """Validate that template has required 'kind' field.
@@ -865,20 +782,6 @@ class Template:
         """Get the spec section from template YAML data."""
         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
     def jinja_env(self) -> Environment:
         if self.__jinja_env is None:
@@ -894,17 +797,35 @@ class Template:
     @property
     def variables(self) -> VariableCollection:
         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
-            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
             filtered_specs = self._filter_specs_to_used(
                 self.used_variables,
-                self.merged_specs,
-                self.module_specs,
                 self.template_specs,
             )
 
             self.__variables = VariableCollection(filtered_specs)
-            # Sort sections: required first, then enabled, then disabled
-            self.__variables.sort_sections()
         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:
                 variable = self._variable_map.get(var_name)
                 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
 
                 # 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
-from collections import OrderedDict
 
 from ...core.module import Module
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 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):
     """Ansible module."""
 
     name = "ansible"
     description = "Manage Ansible configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 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
-from collections import OrderedDict
 from typing import Annotated
 
 from typer import Argument, Option
@@ -9,85 +8,16 @@ from typer import Argument, Option
 from ...core.module import Module
 from ...core.module.base_commands import validate_templates
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 from .validate import run_docker_validation
 
 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):
     """Docker Compose module with extended validation."""
 
     name = "compose"
     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
         self,

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

@@ -1,87 +1,18 @@
-"""Helm module with multi-schema support."""
+"""Helm module."""
 
 import logging
-from collections import OrderedDict
 
 from ...core.module import Module
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 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):
     """Helm module."""
 
     name = "helm"
     description = "Manage Helm configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 registry.register(HelmModule)

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

@@ -1,88 +1,18 @@
-"""Kubernetes module with multi-schema support."""
+"""Kubernetes module."""
 
 import logging
-from collections import OrderedDict
 
 from ...core.module import Module
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 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):
     """Kubernetes module."""
 
     name = "kubernetes"
     description = "Manage Kubernetes configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 registry.register(KubernetesModule)

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

@@ -1,87 +1,18 @@
-"""Packer module with multi-schema support."""
+"""Packer module."""
 
 import logging
-from collections import OrderedDict
 
 from ...core.module import Module
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 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):
     """Packer module."""
 
     name = "packer"
     description = "Manage Packer configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 registry.register(PackerModule)

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

@@ -1,88 +1,18 @@
-"""Terraform module with multi-schema support."""
+"""Terraform module."""
 
 import logging
-from collections import OrderedDict
 
 from ...core.module import Module
 from ...core.registry import registry
-from ...core.schema import has_schema, list_versions, load_schema
 
 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):
     """Terraform module."""
 
     name = "terraform"
     description = "Manage Terraform configurations"
-    schema_version = "1.0"  # Current schema version supported by this module
-    schemas = SCHEMAS  # Available schema versions
 
 
 registry.register(TerraformModule)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -2,23 +2,37 @@
 kind: compose
 metadata:
   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.
+
     It features advanced DNS filtering, parental controls, safe browsing, and HTTPS/DNS-over-TLS/DNS-over-QUIC support.
+
     ## Prerequisites
+
     - :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`.
+
     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.
+
     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,
+
     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
+
     - **Project:** https://adguard.com/adguard-home/overview.html
+
     - **Documentation:** https://github.com/AdguardTeam/AdGuardHome/wiki
-    - **GitHub:** https://github.com/AdguardTeam/AdGuardHome
+
+    - **GitHub:** https://github.com/AdguardTeam/AdGuardHome'
   icon:
     provider: selfh
     id: adguard-home
@@ -29,46 +43,86 @@ metadata:
     - traefik
     - network
     - volume
-  next_steps:
-schema: 1.2
+  next_steps: null
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         default: adguardhome
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       initial_setup:
         description: Enable initial setup wizard on port 3000 (only used without Traefik)
         type: bool
         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:
     vars:
       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:
         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:
     vars:
       ports_http:
         default: 80
       ports_https:
         default: 443
+      ports_dns:
+        type: int
+        default: 53
+        required: true
       ports_initial:
         description: Initial setup wizard port (only when Traefik is disabled)
         type: int
         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:
         description: DNS over TLS Port
         type: int
@@ -78,4 +132,64 @@ spec:
         description: DNSCrypt Port
         type: int
         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 {
     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_timeout        = "5s"
+    mount_out        = "5s"
   }
   netclass {
     ignored_devices = "^(veth.*|cali.*|[a-f0-9]{15})$"

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

@@ -20,12 +20,25 @@ metadata:
     provider: selfh
     id: grafana
   next_steps:
-schema: 1.2
+schema: "1.2"
 spec:
   general:
     vars:
       service_name:
         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:
     title: Log Collection
     toggle: logs_enabled
@@ -69,12 +82,42 @@ spec:
         type: bool
         default: true
   ports:
+    title: Ports
     vars:
       ports_webui:
         description: Port for Alloy web UI
         type: int
         default: 12345
   traefik:
+    title: Traefik
+    toggle: traefik_enabled
     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:
         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
 metadata:
   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.
+
     This configuration enables OAuth-based SSO, allowing users to log in using their Authentik
+
     credentials, enhancing security and user experience.
+
     ## Prerequisites
+
     - :warning: The `authentik_secret_key` must be generated using the following command
+
     according to the official documentation.
+
     ```bash
-    echo "$(openssl rand -base64 60 | tr -d '\n')"
+
+    echo "$(openssl rand -base64 60 | tr -d ''\n'')"
+
     ```
+
     ## References
+
     * **Project:** https://goauthentik.io/
+
     * **Documentation:** https://goauthentik.io/docs/
-    * **GitHub:** https://github.com/goauthentik/authentik
+
+    * **GitHub:** https://github.com/goauthentik/authentik'
   icon:
     provider: selfh
     id: authentik
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
+
     Username: akadmin
+
     Password: {{ authentik_admin_password }}
-    ```
+
+    ```'
   version: 2025.10.3
   author: Christian Lempa
   date: '2025-12-16'
   tags:
     - traefik
     - volume
-schema: "1.2"
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         default: authentik
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   database:
     vars:
-      database_name:
-        default: authentik
+      database_password:
+        description: Database password
+        type: str
+        sensitive: true
+        required: true
       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:
     vars:
       ports_http:
@@ -54,6 +91,18 @@ spec:
     vars:
       traefik_host:
         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:
     description: Configure Authentik application settings
     required: true
@@ -72,3 +121,79 @@ spec:
       authentik_error_reporting:
         description: Enable error reporting to Authentik developers
         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
 metadata:
   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,
+
     TSIG authentication for secure zone transfers, and DNSSEC support.
+
     ## References
+
     * **Project:** https://www.isc.org/bind/
-    * **Documentation:** https://bind9.readthedocs.io/
+
+    * **Documentation:** https://bind9.readthedocs.io/'
   version: 9.20-24.10_edge
   author: Christian Lempa
-  date: "2025-10-02"
+  date: '2025-10-02'
   tags:
     - network
     - volume
@@ -19,7 +23,7 @@ metadata:
     provider: selfh
     id: bind-9
   draft: true
-schema: "1.2"
+schema: '1.2'
 spec:
   dns_security:
     title: dns_security
@@ -42,8 +46,93 @@ spec:
         type: str
         sensitive: 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:
     vars:
       service_name:
         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
     id: 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.
+
     It offers a wide range of monitoring capabilities, including server, network, cloud,
+
     and application monitoring, with an emphasis on ease of use and scalability.
+
     ## References
+
     * **Project:** https://checkmk.com/
+
     * **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
+
     Username: cmkadmin
+
     Password: {{ cmk_password }}
-    ```
+
+    ```'
   version: 2.4.0-latest
   author: Christian Lempa
   date: '2025-12-10'
   tags:
     - traefik
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         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:
         type: str
         description: CheckMK admin password
@@ -46,6 +72,18 @@ spec:
     vars:
       traefik_host:
         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:
     vars:
       ports_http:
@@ -55,3 +93,18 @@ spec:
         type: int
         default: 5000
         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
     id: 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.
+
     ## Prerequisites
+
     * **Project:** https://dockge.com/
+
     * **Documentation:** https://docs.dockge.com/
-    * **GitHub:** https://github.com/dockge/dockge
+
+    * **GitHub:** https://github.com/dockge/dockge'
   version: 1.5.0
   author: Christian Lempa
   date: '2025-09-28'
   tags:
     - traefik
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         default: dockge
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       stacks_path:
         type: str
         description: Docker Compose Path
@@ -32,6 +47,28 @@ spec:
     vars:
       traefik_host:
         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:
     vars:
       ports_http:

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

@@ -2,18 +2,27 @@
 kind: compose
 metadata:
   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.
+
     ## Prerequisites
+
     - :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
+
     are recommended for larger installations.
+
     ## References
+
     - **Project:** https://gitea.io/
+
     - **Documentation:** https://docs.gitea.io/
-    - **GitHub:** https://github.com/go-gitea/gitea
+
+    - **GitHub:** https://github.com/go-gitea/gitea'
   icon:
     provider: selfh
     id: gitea
@@ -22,23 +31,62 @@ metadata:
   date: '2025-12-19'
   tags:
     - traefik
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         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:
-        description: "Public URL"
+        description: Public URL
         type: str
-        needs: ["traefik_enabled=false"]
-        default: "https://git.example.com"
+        needs:
+          - traefik_enabled=false
+        default: https://git.example.com
   database:
     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:
         default: gitea
       database_user:
         default: gitea
+      database_password:
+        type: str
+        sensitive: true
+        required: true
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
   ports:
     vars:
       ports_http:
@@ -49,3 +97,25 @@ spec:
     vars:
       traefik_host:
         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
   next_steps: ""
 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 }}
-{% 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:
   {{ 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 }}
-    {% endif %}
     shm_size: '256m'
-    environment:
-      - 
+    env_file: .env
     {% if traefik_enabled %}
     networks:
       {{ traefik_network }}:
@@ -16,26 +13,15 @@ services:
       - "{{ ports_http }}:80"
       {% endif %}
       - "{{ ports_ssh }}:22"
-      {% if registry_enabled %}
+      {% if registry_enabled and not traefik_enabled %}
       - "{{ ports_registry }}:5000"
       {% endif %}
     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
-      {% endif %}
       - {{ service_name }}_config:/etc/gitlab
       - {{ service_name }}_logs:/var/log/gitlab
       - {{ service_name }}_data:/var/opt/gitlab
-      {% endif %}
-    {% if traefik_enabled and not swarm_enabled %}
+    {% if traefik_enabled  %}
     labels:
       - traefik.enable=true
       - traefik.docker.network={{ traefik_network }}
@@ -53,84 +39,18 @@ services:
       {% 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.rule=Host(`{{ traefik_registry_host }}`.{{ traefik_domain }}`)
       - 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.rule=Host(`{{ traefik_registry_host }}`.{{ traefik_domain }}`)
       - 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 %}
-    {#
-      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:
   {{ service_name }}_config:
     driver: local
@@ -138,51 +58,7 @@ volumes:
     driver: local
   {{ service_name }}_data:
     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 %}
 networks:
   {{ traefik_network }}:

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

@@ -1,9 +1,8 @@
 ---
 kind: compose
-schema: "1.2"
 metadata:
   name: GitLab
-  description: |
+  description: |-
     A **complete DevOps platform** that provides Git repository management, CI/CD pipelines,
     issue tracking, and container registry in a single application.
     ## Prerequisites
@@ -24,48 +23,58 @@ metadata:
   icon:
     provider: selfh
     id: gitlab
-  version: 18.5.4-ce.0
+  version: 18.6.1-ce.0
   author: Christian Lempa
   date: '2025-12-11'
   tags:
     - traefik
-    - swarm
-  next_steps: |
+  next_steps: |-
     ## Post-Installation Steps
     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:
   general:
     vars:
       service_name:
-        default: "gitlab"
+        type: str
+        description: Docker service name
+        default: gitlab
       external_url:
         type: str
         description: External URL for GitLab
@@ -79,68 +88,156 @@ spec:
         description: Initial root user password (only used on first initialization)
         sensitive: 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:
         type: int
         description: Default GitLab UI theme (2 = dark mode)
         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:
         type: int
         description: Default color mode (2 = dark mode)
         default: 2
-        extra: "1 = Light, 2 = Dark"
+        extra: 1 = Light, 2 = Dark
       disable_usage_data:
         type: bool
         description: Disable product usage metrics upload to GitLab
         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:
     vars:
+      ports_http:
+        default: 80
       ports_ssh:
         default: 2424
       ports_registry:
         type: int
         description: Container Registry port
         default: 5000
-  network:
+  registry:
+    description: GitLab Container Registry configuration
+    toggle: registry_enabled
     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:
     vars:
       traefik_host:
         default: gitlab.home.arpa
       traefik_registry_host:
-        needs: ["registry_enabled=true"]
+        needs:
+          - registry_enabled=true
         default: registry.home.arpa
         type: str
         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:
-      registry_enabled:
+      traefik_tls_certresolver:
+        type: str
+        default: cloudflare
+        required: true
+      traefik_tls_enabled:
         type: bool
-        description: Enable GitLab Container Registry
         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
-        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:
-      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
-        description: Enable Prometheus monitoring
         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
 metadata:
   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.
+
     ## Prerequisites
+
     - **Project:** https://grafana.com/
+
     - **Documentation:** https://grafana.com/docs/grafana/latest/
-    - **GitHub:** https://github.com/grafana/grafana
+
+    - **GitHub:** https://github.com/grafana/grafana'
   icon:
     provider: selfh
     id: grafana
-  next_steps: |-
-    Log in with the initial admin user:
+  next_steps: 'Log in with the initial admin user:
+
     ```bash
+
     Username: admin
+
     Password: admin
-    ```
+
+    ```'
   version: 12.3.1
   author: Christian Lempa
   date: '2025-12-16'
   tags:
     - traefik
     - authentik
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         default: grafana
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
     vars:
       ports_http:
@@ -40,10 +57,44 @@ spec:
         default: https://auth.home.arpa
       authentik_slug:
         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:
     vars:
       traefik_host:
         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:
     vars:
       database_type:
@@ -54,3 +105,32 @@ spec:
         default: grafana
       database_user:
         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
 metadata:
   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.
 
+
     Project: https://gethomepage.dev/
+
     Documentation: https://gethomepage.dev/latest/
-    GitHub: https://github.com/gethomepage/homepage
+
+    GitHub: https://github.com/gethomepage/homepage'
   version: v1.8.0
   author: Christian Lempa
   date: '2025-12-12'
@@ -20,8 +23,8 @@ metadata:
     provider: simpleicons
     id: homepage
   draft: true
-  next_steps: ""
-schema: "1.2"
+  next_steps: ''
+schema: '1.2'
 spec:
   general:
     vars:
@@ -31,6 +34,24 @@ spec:
         default: homepage
       service_name:
         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:
     vars:
       ports_http:
@@ -39,3 +60,100 @@ spec:
     vars:
       traefik_host:
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: 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
 
     Documentation: https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md
+
+    '
   version: v25.11.1
   author: Christian Lempa
   date: '2025-12-11'
@@ -21,60 +22,155 @@ metadata:
     - swarm
     - authentik
   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:
   general:
     vars:
       service_name:
-        default: "homer"
+        default: homer
       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:
-        description: "Dashboard title"
+        description: Dashboard title
         type: str
-        default: "My Dashboard"
+        default: My Dashboard
       homer_subtitle:
-        description: "Dashboard subtitle"
+        description: Dashboard subtitle
         type: str
-        default: "Homer"
+        default: Homer
       homer_logo:
-        description: "Logo file path (relative to assets/)"
+        description: Logo file path (relative to assets/)
         type: str
-        default: "logo.png"
+        default: logo.png
   ports:
     vars:
       ports_http:
-        description: "Host port for HTTP (8080)"
+        description: Host port for HTTP (8080)
         type: int
         default: 8080
   traefik:
     vars:
       traefik_host:
         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
     id: 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.
+
     ## References
+
     * **Project:** https://www.influxdata.com/
+
     * **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
+
     Username: {{ influxdb_init_username }}
+
     Password: {{ influxdb_init_password }}
-    ```
+
+    ```'
   version: 2.8.0-alpine
   author: Christian Lempa
   date: '2025-12-11'
   tags:
     - traefik
   draft: true
-schema: "1.2"
+schema: '1.2'
 spec:
   ports:
     vars:
       ports_http:
-        description: "Host port for HTTP API (8086)"
+        description: Host port for HTTP API (8086)
         type: int
         default: 8086
   influxdb:
-    description: "InfluxDB initialization settings"
+    description: InfluxDB initialization settings
     required: true
     vars:
       influxdb_init_username:
-        description: "Initial admin username"
+        description: Initial admin username
         type: str
-        default: "admin"
+        default: admin
         required: true
       influxdb_init_password:
-        description: "Initial admin password"
+        description: Initial admin password
         type: str
         sensitive: true
         autogenerated: 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:
     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:
         type: str
         description: Influxdb version

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

@@ -1,24 +1,35 @@
 ---
 kind: compose
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: 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,
+
     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.
+
     ## Important Notes
+
     * Requires MongoDB or FerretDB for data storage (database not included in this template)
+
     * Requires Periphery agent on managed servers for remote operations
+
     * Web interface and API accessible through configured ports
+
     ## References
+
     * **Project:** https://github.com/moghtech/komodo
+
     * **Documentation:** https://github.com/moghtech/komodo/tree/main/docsite/docs
+
     * **Docker Hub:** https://hub.docker.com/r/moghtech/komodo
+
+    '
   draft: true
   version: latest
   author: Christian Lempa
@@ -28,107 +39,278 @@ metadata:
     - swarm
     - deployment
     - automation
-  next_steps: |
-    ### 1. Prerequisites
+  next_steps: '### 1. Prerequisites
+
     * Deploy MongoDB or FerretDB database
+
     * Configure database connection in environment variables
+
     * Install Periphery agent on servers you want to manage
+
     ### 2. Deploy the Service
+
     {% if swarm_enabled -%}
+
     Deploy to Docker Swarm:
+
     ```bash
+
     docker stack deploy -c compose.yaml komodo
+
     ```
+
     {% else -%}
+
     Start Komodo 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 -%}
+
     * Complete initial setup and create admin user
+
     ### 4. Install Periphery Agent
+
     On each server you want to manage:
+
     ```bash
+
     curl -sSL https://raw.githubusercontent.com/moghtech/komodo/main/scripts/setup-periphery.py | python3
+
     ```
+
     ### 5. Configure Servers
+
     * Add servers to Komodo through the web interface
+
     * Configure API keys for programmatic access
+
     * Start managing deployments, stacks, and builds
+
+    '
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
-        default: "komodo"
+        default: komodo
       container_name:
-        default: "komodo"
+        default: komodo
       container_hostname:
-        default: "komodo"
+        default: komodo
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   traefik:
     vars:
       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:
     vars:
       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:
     vars:
       ports_http:
-        description: "External HTTP port (web interface and API)"
+        description: External HTTP port (web interface and API)
         type: int
         default: 9120
-        needs: ["traefik_enabled=false", "network_mode=bridge"]
+        needs:
+          - traefik_enabled=false
+          - network_mode=bridge
   volume:
     vars:
       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:
-    title: "Environment Variables"
+    title: Environment Variables
     toggle: environment_enabled
     required: true
     vars:
       environment_enabled:
         type: bool
         default: true
-        description: "Configure environment variables (required)"
+        description: Configure environment variables (required)
       environment_database_address:
         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:
         type: str
-        default: "komodo"
-        description: "Database name"
-        needs: "environment_enabled=true"
+        default: komodo
+        description: Database name
+        needs: environment_enabled=true
       environment_database_username:
         type: str
-        default: ""
-        description: "Database username (optional)"
-        needs: "environment_enabled=true"
+        default: ''
+        description: Database username (optional)
+        needs: environment_enabled=true
       environment_database_password:
         type: str
-        default: ""
+        default: ''
         sensitive: true
-        description: "Database password (optional)"
-        needs: "environment_enabled=true"
+        description: Database password (optional)
+        needs: environment_enabled=true
       environment_jwt_secret:
         type: str
-        default: ""
+        default: ''
         sensitive: 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:
         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
     id: 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.
+
     ## References
+
     * **Project:** https://grafana.com/oss/loki/
+
     * **Documentation:** https://grafana.com/docs/loki/latest/
-    * **GitHub:** https://github.com/grafana/loki
+
+    * **GitHub:** https://github.com/grafana/loki'
   version: 3.6.3
   author: Christian Lempa
   date: '2025-12-11'
   tags:
     - traefik
     - authentik
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         default: loki
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       data_retention_days:
-        description: "Number of days to retain logs"
+        description: Number of days to retain logs
         type: int
         default: 7
   ports:
@@ -36,3 +49,25 @@ spec:
     vars:
       traefik_host:
         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'
   tags: []
   draft: true
-schema: 1.2
+schema: "1.2"
 spec:
   general:
     vars:
       service_name:
         default: mariadb
+      restart_policy:
+        type: enum
+        options: [unless-stopped, always, on-failure, "no"]
+        default: unless-stopped
+        required: true
   ports:
     vars:
       ports_mariadb:
@@ -36,3 +41,15 @@ spec:
         type: int
         default: 3306
         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
     id: 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.
+
     With its user-friendly interface, you can create complex workflows by simply dragging
+
     and dropping nodes that represent different actions and triggers.
+
     ## Prerequisites
+
     - :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
+
     database like PostgreSQL or MySQL for better performance and reliability. This is also
+
     required when using Queue Mode.
+
     - :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
+
     setups where multiple n8n instances work together. It also supports Queue Monitoring
+
     (when Prometheus metrics are enabled).
+
     ## Resources
+
     - **Project**: https://n8n.io/
+
     - **Documentation**: https://docs.n8n.io/
+
     - **GitHub**: https://github.com/n8n-io/n8n
+
+    '
   version: 8-alpine
   author: Christian Lempa
   date: '2025-12-17'
@@ -30,185 +47,236 @@ metadata:
     - traefik
     - database
   draft: true
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
-        default: "n8n"
+        default: n8n
       container_name:
-        default: "n8n-server"
+        default: n8n-server
       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:
-    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
-    needs: "database_enabled=true"
+    needs: database_enabled=true
     vars:
       queue_enabled:
         type: bool
-        description: "Enable queue mode (requires Redis)"
+        description: Enable queue mode (requires Redis)
         default: false
-        extra: "Required for multiple workers and scaled deployments"
+        extra: Required for multiple workers and scaled deployments
       queue_redis_external:
         type: bool
-        description: "Use external Redis instance"
+        description: Use external Redis instance
         default: false
-        needs: "queue_enabled"
+        needs: queue_enabled
       queue_redis_host:
         type: str
-        description: "Redis host"
-        default: "redis"
-        needs: "queue_enabled"
+        description: Redis host
+        default: redis
+        needs: queue_enabled
       queue_redis_port:
         type: int
-        description: "Redis port"
+        description: Redis port
         default: 6379
-        needs: "queue_enabled"
+        needs: queue_enabled
       queue_embedded_worker:
         type: bool
-        description: "Include embedded worker in this deployment"
+        description: Include embedded worker in this deployment
         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:
-    title: "Database"
-    description: "External database configuration"
+    title: Database
+    description: External database configuration
     vars:
       database_enabled:
         type: bool
-        description: "Use external database"
+        description: Use external database
         default: false
       database_type:
         type: enum
-        description: "Database type"
+        description: Database type
         options:
-          - "postgres"
-          - "mysql"
-        default: "postgres"
-        needs: "database_enabled"
+          - postgres
+          - mysql
+        default: postgres
+        needs: database_enabled
       database_host:
         type: str
-        description: "Database host"
-        default: "postgres"
-        needs: "database_enabled"
+        description: Database host
+        default: postgres
+        needs: database_enabled
       database_port:
         type: int
-        description: "Database port"
+        description: Database port
         default: 5432
-        needs: "database_enabled"
+        needs: database_enabled
       database_name:
         type: str
-        description: "Database name"
-        default: "n8n"
-        needs: "database_enabled"
+        description: Database name
+        default: n8n
+        needs: database_enabled
       database_user:
         type: str
-        description: "Database username"
-        default: "n8n"
-        needs: "database_enabled"
+        description: Database username
+        default: n8n
+        needs: database_enabled
       database_password:
         type: str
-        description: "Database password"
+        description: Database password
         sensitive: true
-        needs: "database_enabled"
+        needs: database_enabled
+      database_external:
+        type: bool
+        default: false
+        description: Use external database
   security:
-    title: "Security"
+    title: Security
     vars:
       encryption_key:
         type: str
-        description: "N8N encryption key for credentials"
+        description: N8N encryption key for credentials
         sensitive: true
         autogenerated: true
-        extra: "Keep this secure! Used to encrypt stored credentials."
+        extra: Keep this secure! Used to encrypt stored credentials.
       proxy_hops:
         type: int
-        description: "Number of proxy hops (X-Forwarded-For)"
+        description: Number of proxy hops (X-Forwarded-For)
         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:
-    title: "Webhooks"
-    description: "Webhook configuration for external triggers"
+    title: Webhooks
+    description: Webhook configuration for external triggers
     vars:
       webhook_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:
-    title: "Metrics"
-    description: "Prometheus metrics configuration"
+    title: Metrics
+    description: Prometheus metrics configuration
     vars:
       metrics_enabled:
         type: bool
-        description: "Enable Prometheus metrics"
+        description: Enable Prometheus metrics
         default: false
       metrics_detailed:
         type: bool
-        description: "Include detailed metrics (workflows, nodes, API endpoints)"
+        description: Include detailed metrics (workflows, nodes, API endpoints)
         default: false
-        needs: "metrics_enabled"
+        needs: metrics_enabled
   execution:
-    title: "Execution Settings"
+    title: Execution Settings
     vars:
       execution_save_on_error:
         type: enum
-        description: "Save execution data on error"
+        description: Save execution data on error
         options:
-          - "all"
-          - "none"
-        default: "all"
+          - all
+          - none
+        default: all
       execution_save_on_success:
         type: enum
-        description: "Save execution data on success"
+        description: Save execution data on success
         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:
     vars:
       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:
-        default: "n8n_network"
+        default: n8n_network
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
   traefik:
     vars:
       traefik_enabled:
-        needs: "network_mode=bridge"
+        needs: network_mode=bridge
       traefik_host:
-        default: "n8n.home.arpa"
+        default: n8n.home.arpa
       traefik_webhook_host:
         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:
         type: str
-        description: "Traefik network name"
-        default: "traefik"
-        needs: "traefik_enabled"
+        description: Traefik network name
+        default: traefik
+        needs: traefik_enabled
       traefik_network_external:
         type: bool
-        description: "Use external Traefik network"
+        description: Use external Traefik network
         default: true
-        needs: "traefik_enabled"
+        needs: traefik_enabled
+      traefik_domain:
+        type: str
+        default: home.arpa
+        required: true
   ports:
     vars:
       ports_http:
-        description: "External HTTP port"
+        description: External HTTP port
         type: int
         default: 5678
-        needs: ["traefik_enabled=false", "network_mode=bridge"]
+        needs:
+          - traefik_enabled=false
+          - network_mode=bridge
   swarm:
     vars:
       swarm_enabled:
-        needs: "network_mode=bridge"
+        needs: network_mode=bridge
       swarm_replicas:
         type: int
-        description: "Number of server replicas"
+        description: Number of server replicas
         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
 metadata:
   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
+
     automation capabilities.
+
     ## References
+
     - **Project:** https://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
   author: Christian Lempa
   date: '2025-12-12'
@@ -21,13 +27,16 @@ metadata:
     provider: selfh
     id: netbox
   draft: false
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
+
     Username: admin
+
     Password: admin
-    ```
-schema: 1.2
+
+    ```'
+schema: '1.2'
 spec:
   database:
     vars:
@@ -35,16 +44,70 @@ spec:
         default: netbox
       database_user:
         default: netbox
+      database_host:
+        type: str
+        required: true
+      database_password:
+        type: str
+        sensitive: true
+        required: true
       redis_password:
         description: Redis password for authentication
         type: str
         sensitive: true
         autogenerated: 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:
     vars:
       service_name:
         default: netbox
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   netbox:
     title: NetBox Configuration
     description: Configure NetBox application settings
@@ -70,3 +133,25 @@ spec:
     vars:
       traefik_host:
         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
-schema: "1.2"
 metadata:
   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/
@@ -14,6 +12,8 @@ metadata:
     Documentation: https://docs.nextcloud.com/
 
     GitHub: https://github.com/nextcloud/server
+
+    '
   icon:
     provider: selfh
     id: nextcloud
@@ -23,38 +23,114 @@ metadata:
   tags:
     - traefik
   draft: true
+schema: '1.2'
 spec:
   database:
     required: true
     vars:
       database_type:
-        description: "Database type (Nextcloud supports PostgreSQL or MySQL/MariaDB)"
+        description: Database type (Nextcloud supports PostgreSQL or MySQL/MariaDB)
         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:
     vars:
       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
-        default: "192.168.1.252"
-        needs: "network_mode=macvlan"
+        default: 192.168.1.252
+        needs: network_mode=macvlan
   ports:
     vars:
       ports_http:
-        description: "Host port for HTTP"
+        description: Host port for HTTP
         type: int
         default: 80
   nextcloud:
-    description: "Configure Nextcloud application settings"
+    description: Configure Nextcloud application settings
     vars:
       admin_user:
-        description: "Nextcloud admin username"
+        description: Nextcloud admin username
         type: str
-        default: "admin"
+        default: admin
       admin_password:
-        description: "Nextcloud admin password"
+        description: Nextcloud admin password
         type: str
         sensitive: 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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: 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.
 
+
     ## Prerequisites
+
     * **Project:** https://nginx.org/
+
     * **Documentation:** https://nginx.org/en/docs/
-    * **GitHub:** https://github.com/nginx/nginx
 
+    * **GitHub:** https://github.com/nginx/nginx'
   version: 1.28.1-alpine
   author: Christian Lempa
   date: '2025-12-24'
@@ -22,19 +25,24 @@ metadata:
     - traefik
     - swarm
   draft: true
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
-        default: "nginx"
+        default: nginx
       restart_policy:
         type: enum
-        options: ["unless-stopped", "always", "on-failure", "no"]
-        default: "unless-stopped"
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
       container_name:
-        default: "nginx"
+        default: nginx
       container_timezone:
-        default: "UTC"
+        default: UTC
   ports:
     vars:
       ports_http:
@@ -51,28 +59,31 @@ spec:
         type: bool
         default: false
       traefik_network:
-        default: "traefik"
+        default: traefik
       traefik_host:
-        default: "nginx"
+        default: nginx
       traefik_domain:
-        default: "home.arpa"
+        default: home.arpa
       traefik_entrypoint:
-        default: "web"
+        default: web
       traefik_tls_entrypoint:
-        default: "websecure"
+        default: websecure
       traefik_tls_enabled:
         type: bool
         default: true
       traefik_tls_certresolver:
-        default: "cloudflare"
+        default: cloudflare
   network:
     vars:
       network_mode:
         type: enum
-        options: ["bridge", "host", "macvlan"]
-        default: "bridge"
+        options:
+          - bridge
+          - host
+          - macvlan
+        default: bridge
       network_name:
-        default: "bridge"
+        default: bridge
   swarm:
     vars:
       swarm_enabled:
@@ -82,3 +93,11 @@ spec:
         description: Number of replicas for Swarm mode
         type: int
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: open-webui
   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/
@@ -18,6 +16,8 @@ metadata:
     Documentation: https://docs.openwebui.io/
 
     GitHub: https://github.com/openwebui/openwebui
+
+    '
   version: 0.6.41
   author: Christian Lempa
   date: '2025-12-11'
@@ -25,6 +25,7 @@ metadata:
     - traefik
     - authentik
   draft: true
+schema: '1.2'
 spec:
   general:
     vars:
@@ -32,6 +33,19 @@ spec:
         default: openwebui
       container_name:
         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:
         type: str
         description: Ollama API base URL
@@ -40,6 +54,28 @@ spec:
     vars:
       traefik_host:
         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:
     vars:
       ports_http:
@@ -66,3 +102,19 @@ spec:
         type: bool
         description: Merge OAuth accounts by email
         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
     - database
   draft: true
-schema: 1.2
+schema: "1.2"
 spec:
   general:
     vars:
       service_name:
         default: passbolt
+      container_timezone:
+        type: str
   traefik:
     vars:
       traefik_host:

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

@@ -1,22 +1,31 @@
 ---
 kind: compose
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: pi-hole
   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.
+
     Supports custom blocklists, whitelists, and seamless integration with existing network infrastructure.
+
     ## Prerequisites
+
     - :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.
+
     ## References
+
     - **Project:** https://pi-hole.net/
+
     - **Documentation:** https://docs.pi-hole.net/
+
     - **GitHub:** https://github.com/pi-hole/pi-hole
+
+    '
   version: 2025.11.1
   author: Christian Lempa
   date: '2025-12-11'
@@ -25,12 +34,16 @@ metadata:
     - swarm
     - network
     - volume
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
+
     Username: admin
+
     Password: {{ webpassword }}
-    ```
+
+    ```'
+schema: '1.2'
 spec:
   general:
     vars:
@@ -38,17 +51,41 @@ spec:
         default: pihole
       container_name:
         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:
-    description: "Admin Pi-hole Settings"
+    description: Admin Pi-hole Settings
     required: true
     vars:
       webpassword:
-        description: "Web interface admin password"
+        description: Web interface admin password
         type: str
         sensitive: true
         autogenerated: true
   ports:
     vars:
+      ports_dns:
+        description: DNS port for Pi-hole
+        type: int
+        default: 53
+        required: true
       ports_http:
         description: HTTP port for Pi-hole
         type: int
@@ -58,7 +95,7 @@ spec:
         type: int
         default: 443
       ports_ntp:
-        description: "External NTP port"
+        description: External NTP port
         type: int
         default: 123
         required: true
@@ -66,14 +103,64 @@ spec:
     vars:
       traefik_host:
         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:
     vars:
       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:
-        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:
     vars:
       swarm_placement_host:
@@ -84,3 +171,45 @@ spec:
         description: Number of replicas for Swarm mode
         type: int
         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
     id: 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,
+
     making it easier to deploy and monitor applications.
+
     ## References
+
     - **Project:** https://www.portainer.io/
+
     - **Documentation:** https://docs.portainer.io/
-    - **GitHub:** https://github.com/portainer/portainer
+
+    - **GitHub:** https://github.com/portainer/portainer'
   version: 2.37.0-alpine
   author: Christian Lempa
   date: '2025-12-12'
@@ -20,12 +25,23 @@ metadata:
     - traefik
     - swarm
     - volumes
-schema: 1.2
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
         default: portainer
+      container_timezone:
+        type: str
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   ports:
     vars:
       ports_http:
@@ -33,7 +49,7 @@ spec:
       ports_https:
         default: 9443
       ports_edge:
-        description: "Host port for Edge agent (8000)"
+        description: Host port for Edge agent (8000)
         type: int
         default: 8000
         required: true
@@ -41,3 +57,78 @@ spec:
     vars:
       traefik_host:
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: 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.
 
 
@@ -16,19 +14,35 @@ metadata:
     Documentation: https://www.postgresql.org/docs/
 
     GitHub: https://github.com/postgres/postgres
+
+    '
   version: 18.1
   author: Christian Lempa
   date: '2025-12-11'
   tags:
     - swarm
   draft: true
+schema: '1.2'
 spec:
   general:
     vars:
       service_name:
-        default: "postgres"
+        default: postgres
       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:
     vars:
       ports_postgres:
@@ -38,27 +52,43 @@ spec:
   traefik:
     vars:
       traefik_host:
-        default: "postgres"
+        default: postgres
   network:
     vars:
       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:
-        default: "postgres_network"
+        default: postgres_network
+      network_external:
+        type: bool
+        default: false
+        description: Whether the network is external
   swarm:
     vars:
       swarm_replicas:
         description: Number of replicas for Swarm mode
         type: int
         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:
     vars:
       volume_mode:
         description: Volume mounting mode (local, mount, nfs)
         type: str
-        default: "local"
+        default: local
         options:
           - local
           - mount
@@ -66,16 +96,28 @@ spec:
       volume_mount_path:
         description: Path for bind mounts when volume_mode is 'mount'
         type: str
-        default: "/var/lib/postgresql/data"
+        default: /var/lib/postgresql/data
       volume_nfs_server:
         description: NFS server address when volume_mode is 'nfs'
         type: str
-        default: ""
+        default: ''
       volume_nfs_path:
         description: NFS path when volume_mode is 'nfs'
         type: str
-        default: ""
+        default: ''
       volume_nfs_options:
         description: NFS mount options when volume_mode is 'nfs'
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: 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.
-    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
+
     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/
 
+
     Documentation: https://prometheus.io/docs/
 
+
     GitHub: https://github.com/prometheus/prometheus
+
+    '
   version: v3.8.1
   author: Christian Lempa
   date: '2025-12-16'
@@ -26,52 +36,73 @@ metadata:
     - traefik
     - swarm
     - 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:
   general:
     vars:
       service_name:
         default: prometheus
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   metrics:
     title: Metrics & Storage
     description: Configure data retention and storage settings
     vars:
       metrics_retention_time:
         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:
         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:
         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
-        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:
     vars:
       ports_http:
         default: 9090
-
   traefik:
     vars:
       traefik_host:
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
@@ -29,6 +28,7 @@ metadata:
     - traefik
     - swarm
   draft: true
+schema: "1.2"
 spec:
   general:
     vars:
@@ -44,6 +44,9 @@ spec:
         default: "renovate"
       container_timezone:
         default: "UTC"
+      container_loglevel:
+        type: enum
+        options: [debug, info, warn, error]
   renovate_settings:
     title: "Renovate Settings"
     required: true

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

@@ -5,32 +5,45 @@ metadata:
     provider: selfh
     id: 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
+
     inventories, and schedule automated tasks. Perfect for teams who want a
+
     user-friendly way to execute and monitor Ansible automation.
+
     ## Prerequisites
+
     - :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
+
     are recommended for larger installations.
+
     ## References
+
     - **Project:** https://www.semaphoreui.com/
+
     - **Documentation:** https://docs.semaphoreui.com/
-    - **GitHub:** https://github.com/semaphoreui/semaphore
+
+    - **GitHub:** https://github.com/semaphoreui/semaphore'
   version: v2.16.47
   author: Christian Lempa
   date: '2025-12-17'
   tags:
     - traefik
     - database
-  next_steps: |-
-    Log in with your initial admin user:
+  next_steps: 'Log in with your initial admin user:
+
     ```bash
+
     Username: {{ admin_user }}
+
     Password: {{ admin_pass }}
-    ```
-schema: 1.2
+
+    ```'
+schema: '1.2'
 spec:
   general:
     vars:
@@ -38,35 +51,44 @@ spec:
         default: semaphoreui
       container_name:
         default: semaphoreui
+      restart_policy:
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
       secret_key:
-        description: "Secret key for encrypting access keys"
+        description: Secret key for encrypting access keys
         type: str
         sensitive: true
         autogenerated: true
         required: true
       admin_user:
-        description: "Administrator username"
+        description: Administrator username
         type: str
         required: true
         default: admin
       admin_name:
-        description: "Administrator full name"
+        description: Administrator full name
         type: str
         required: true
         default: Administrator
       admin_email:
-        description: "Administrator email address"
+        description: Administrator email address
         type: str
         required: true
         default: admin@home.arpa
       admin_pass:
-        description: "Administrator password"
+        description: Administrator password
         type: str
         sensitive: true
         autogenerated: true
         required: true
       ansible_host_key_checking:
-        description: "Enable Ansible SSH host key checking"
+        description: Enable Ansible SSH host key checking
         type: bool
   ports:
     vars:
@@ -76,6 +98,28 @@ spec:
     vars:
       traefik_host:
         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:
     vars:
       database_type:
@@ -87,3 +131,14 @@ spec:
         default: semaphore
       database_user:
         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
 metadata:
   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
+
     - **Project:** https://traefik.io/
+
     - **Documentation:** https://doc.traefik.io/traefik/
-    - **GitHub:** https://github.com/traefik/traefik
+
+    - **GitHub:** https://github.com/traefik/traefik'
   version: v3.6.5
   author: Christian Lempa
   date: '2025-12-17'
@@ -19,22 +23,38 @@ metadata:
     provider: simpleicons
     id: traefikproxy
   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:
   general:
     vars:
       service_name:
         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:
     vars:
       ports_dashboard:
@@ -42,7 +62,8 @@ spec:
         type: int
         default: 8080
         required: true
-        needs: [dashboard_enabled=true]
+        needs:
+          - dashboard_enabled=true
         extra: Only used when dashboard is enabled
       ports_http:
         default: 80
@@ -89,44 +110,58 @@ spec:
         type: str
         default: us-east-1
         required: true
-        needs: [traefik_tls_certresolver=route53]
+        needs:
+          - traefik_tls_certresolver=route53
       traefik_tls_acme_resource_group:
         description: Azure Resource Group
         type: str
         required: true
-        needs: [traefik_tls_certresolver=azure]
+        needs:
+          - traefik_tls_certresolver=azure
       traefik_tls_acme_secret_key:
         description: DNS provider secret key
         type: str
         sensitive: 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
       traefik_tls_acme_subscription_id:
         description: Azure Subscription ID
         type: str
         required: true
-        needs: [traefik_tls_certresolver=azure]
+        needs:
+          - traefik_tls_certresolver=azure
       traefik_tls_acme_tenant_id:
         description: Azure Tenant ID
         type: str
         required: true
-        needs: [traefik_tls_certresolver=azure]
+        needs:
+          - traefik_tls_certresolver=azure
       traefik_tls_acme_token:
         description: DNS provider API token
         type: str
         sensitive: 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
       traefik_tls_acme_username:
         description: Namecheap API username
         type: str
         required: true
-        needs: [traefik_tls_certresolver=namecheap]
+        needs:
+          - traefik_tls_certresolver=namecheap
       traefik_tls_certresolver:
         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
       traefik_tls_enabled:
         description: Enable HTTPS/TLS with ACME
@@ -134,7 +169,9 @@ spec:
       traefik_tls_min_version:
         description: Minimum TLS version
         type: enum
-        options: [VersionTLS12, VersionTLS13]
+        options:
+          - VersionTLS12
+          - VersionTLS13
         extra: TLS 1.2 is recommended for compatibility, TLS 1.3 for maximum security
       traefik_tls_redirect:
         description: Redirect all HTTP traffic to HTTPS
@@ -148,3 +185,63 @@ spec:
         description: Skip TLS verification for backend servers
         type: bool
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
     id: twingate
   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/
@@ -18,12 +16,15 @@ metadata:
     Documentation: https://docs.twingate.com/docs/architecture/connectors
 
     GitHub: https://github.com/twingate/twingate-connector
+
+    '
   version: 1.80.0
   author: Christian Lempa
   date: '2025-11-11'
   tags:
     - swarm
   draft: true
+schema: '1.2'
 spec:
   general:
     vars:
@@ -33,10 +34,21 @@ spec:
         default: twingate_connector
       container_hostname:
         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:
         type: str
         description: Twingate Connector version
-        default: "1.79.0"
+        default: 1.79.0
   twingate:
     title: Twingate Configuration
     required: true
@@ -44,7 +56,7 @@ spec:
       twingate_network:
         type: str
         description: Your Twingate network name
-        prompt: "Enter your Twingate network name"
+        prompt: Enter your Twingate network name
       twingate_log_level:
         type: int
         description: Log level (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
@@ -52,4 +64,50 @@ spec:
       twingate_dns:
         type: str
         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
-schema: "1.2"
 metadata:
   icon:
     provider: selfh
@@ -21,6 +20,7 @@ metadata:
   date: '2025-10-31'
   tags: []
   draft: true
+schema: "1.2"
 spec:
   general:
     vars:

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

@@ -28,7 +28,72 @@ spec:
     vars:
       service_name:
         default: whoami
+      restart_policy:
+        description: Container restart policy
+        type: enum
+        options:
+          - unless-stopped
+          - always
+          - on-failure
+          - 'no'
+        default: unless-stopped
+        required: true
   traefik:
     vars:
       traefik_host:
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -25,14 +24,21 @@ metadata:
   author: Christian Lempa
   date: '2025-01-11'
   draft: true
+schema: "1.2"
 spec:
   general:
     vars:
       release_name:
         default: authentik
+      namespace:
+        type: str
+        description: Kubernetes namespace
+        default: authentik
   networking:
     vars:
       network_mode:
+        type: str
+        description: Network mode for service
         default: ClusterIP
   authentik:
     title: Authentik Configuration
@@ -60,21 +66,98 @@ spec:
         description: Enable error reporting to Authentik developers
         default: false
   database:
+    title: Database Configuration
+    toggle: database_enabled
     vars:
       database_enabled:
+        type: bool
+        description: Enable database
         default: true
       database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
         default: postgres
+      database_host:
+        type: hostname
+        description: Database host
+        default: authentik-postgresql
+      database_port:
+        type: int
+        description: Database port
+        default: 5432
       database_name:
+        type: str
+        description: Database name
         default: authentik
       database_user:
+        type: str
+        description: Database user
         default: authentik
-      database_port:
-        default: 5432
       database_password:
+        type: str
         description: PostgreSQL database password
         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:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik ingress
+        default: false
       traefik_host:
+        type: hostname
+        description: Traefik hostname
         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
   draft: true
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 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:
     title: DNS Configuration
     vars:
@@ -37,8 +84,6 @@ spec:
         description: Use only recursive nameservers for DNS01 challenges
         type: bool
         default: true
-  general:
-    vars:
       namespace:
         type: str
         default: cert-manager

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

@@ -21,8 +21,55 @@ metadata:
     id: rancher-longhorn
   draft: true
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 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:
     title: Backup Configuration
     toggle: backup_enabled
@@ -34,8 +81,6 @@ spec:
       backup_target:
         description: Backup target URL (e.g., s3://bucket or nfs://server/path)
         type: str
-  general:
-    vars:
       namespace:
         type: str
         default: longhorn-system

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

@@ -1,6 +1,5 @@
 ---
 kind: helm
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -21,6 +20,7 @@ metadata:
   author: Christian Lempa
   date: '2025-01-13'
   draft: true
+schema: "1.2"
 spec:
   general:
     vars:
@@ -29,19 +29,46 @@ spec:
       namespace:
         default: netbox
   database:
+    title: Database Configuration
+    toggle: database_enabled
     vars:
       database_enabled:
+        type: bool
+        description: Enable database
         default: true
       database_type:
+        type: enum
+        description: Database type
+        options: [postgres, mysql]
         default: postgres
       database_host:
+        type: hostname
+        description: Database host
         default: netbox-postgresql
       database_port:
+        type: int
+        description: Database port
         default: 5432
       database_name:
+        type: str
+        description: Database name
         default: netbox
       database_user:
+        type: str
+        description: Database user
         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:
     title: Redis Configuration
     description: Configure Redis for caching and task queuing
@@ -64,10 +91,79 @@ spec:
         type: str
         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_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:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik ingress
+        default: false
       traefik_host:
+        type: hostname
+        description: Traefik hostname
         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:
     title: NetBox Configuration
     description: Configure NetBox application settings

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

@@ -1,6 +1,5 @@
 ---
 kind: helm
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -25,20 +24,83 @@ metadata:
   author: Christian Lempa
   date: '2025-01-11'
   draft: true
+schema: "1.2"
 spec:
   general:
     vars:
       release_name:
+        type: str
+        description: Helm release name
+        default: portainer
+      namespace:
+        type: str
+        description: Kubernetes namespace
         default: portainer
   networking:
     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
   traefik:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
+      traefik_enabled:
+        type: bool
+        description: Enable Traefik ingress
+        default: false
       traefik_host:
+        type: hostname
+        description: Traefik hostname
         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:
+    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: portainer

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

@@ -20,8 +20,55 @@ metadata:
     id: traefikproxy
   draft: true
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 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:
     title: Dashboard IngressRoute
     toggle: dashboard_ingressroute_enabled
@@ -41,8 +88,6 @@ spec:
         description: TLS secret name for dashboard
         type: str
         default: traefik-dashboard-tls
-  general:
-    vars:
       release_name:
         type: str
         default: traefik

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

@@ -1,6 +1,5 @@
 ---
 kind: kubernetes
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -22,6 +21,7 @@ metadata:
   version: 1.16.2
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -33,6 +33,52 @@ spec:
         type: str
         description: Name of secret to store the certificate
         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:
     title: DNS Settings
     vars:

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

@@ -1,6 +1,5 @@
 ---
 kind: kubernetes
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -19,11 +18,16 @@ metadata:
   version: 1.16.2
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
       resource_name:
         default: cloudflare-clusterissuer
+      namespace:
+        type: str
+        description: Namespace (ClusterIssuer is cluster-scoped, but needed for schema)
+        default: cert-manager
       acme_email:
         type: email
         description: Email address for ACME account registration
@@ -43,3 +47,49 @@ spec:
         type: str
         description: Key name in secret containing Cloudflare 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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -22,6 +21,7 @@ metadata:
   version: 1.16.2
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -48,3 +48,49 @@ spec:
         type: str
         description: Key name in secret containing Cloudflare 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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -24,3 +24,49 @@ spec:
         default: app-config
       namespace:
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -38,7 +38,49 @@ spec:
         type: int
         description: Backend service port
         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:
+    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-ingressclass/template.yaml

@@ -1,6 +1,5 @@
 ---
 kind: kubernetes
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -30,3 +30,49 @@ spec:
         type: bool
         description: Set as default IngressClass
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -51,3 +51,49 @@ spec:
         type: str
         description: Host path for local storage (e.g., /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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -41,3 +41,49 @@ spec:
           - ReadWriteMany
           - ReadWriteOncePod
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -34,3 +34,49 @@ spec:
         default: ""
         sensitive: 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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -49,6 +49,52 @@ spec:
           - UDP
           - SCTP
         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:
         type: str
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -24,3 +24,49 @@ spec:
         default: app-serviceaccount
       namespace:
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -17,6 +16,7 @@ metadata:
   version: 1.31.0
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -40,3 +40,49 @@ spec:
           - Retain
           - 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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -19,6 +18,7 @@ metadata:
   version: 3.5.3
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -41,13 +41,49 @@ spec:
         type: int
         description: Kubernetes service port
         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:
+    title: Traefik Configuration
+    toggle: traefik_enabled
     vars:
       traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
         default: true
       traefik_host:
+        type: hostname
         description: Domain name for the IngressRoute
-  traefik_tls:
-    vars:
+      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

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

@@ -1,6 +1,5 @@
 ---
 kind: kubernetes
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -22,6 +21,7 @@ metadata:
   version: 3.5.3
   author: Christian Lempa
   date: '2025-01-11'
+schema: "1.2"
 spec:
   general:
     vars:
@@ -29,17 +29,60 @@ spec:
         default: app-tcp-route
       namespace:
         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 Configuration
+    toggle: traefik_enabled
     vars:
       traefik_enabled:
+        type: bool
+        description: Enable Traefik integration
         default: true
+      traefik_host:
+        type: hostname
+        description: Traefik host
+      traefik_domain:
+        type: str
+        description: Traefik domain
       traefik_entrypoint:
+        type: str
+        description: Traefik entrypoint for TCP routing
         default: tcp
       traefik_service_name:
+        type: str
         description: Backend service name for TCP routing
       traefik_service_port:
+        type: int
+        description: Backend service port for TCP routing
         default: 5432
-  traefik_tls:
-    vars:
       traefik_tls_enabled:
+        type: bool
+        description: Enable TLS
         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
   draft: false
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
   general:
     vars:
@@ -34,3 +34,49 @@ spec:
         type: enum
         default: redirectScheme
         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
   draft: false
   next_steps: ""
-schema: "1.0"
+schema: "1.2"
 spec:
   general:
     vars:
       resource_name:
         default: twingate-connector
+      namespace:
+        default: default
       image_tag:
         type: str
         description: Twingate connector image tag
@@ -35,3 +37,49 @@ spec:
         type: bool
         description: Enable status notifications
         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
-schema: "1.0"
 metadata:
   icon:
     provider: selfh
@@ -25,9 +24,13 @@ metadata:
   version: 1.11.2
   author: Christian Lempa
   date: '2024-11-11'
+schema: "1.2"
 spec:
   general:
     vars:
+      playbook_name:
+        type: str
+        description: Name of the playbook
       image_name:
         default: ubuntu-server-noble
       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
-      }
-    ]
-  }
-]

Некоторые файлы не были показаны из-за большого количества измененных файлов