xcad 6 месяцев назад
Родитель
Сommit
928cdd2704

+ 28 - 0
AGENTS.md

@@ -245,6 +245,17 @@ spec:
         default: latest
 ```
 
+### Template Metadata Versioning
+
+**Template Version Field:**
+The `metadata.version` field in `template.yaml` should reflect the version of the underlying application or resource:
+- **Compose templates**: Match the Docker image version (e.g., `nginx:1.25.3` → `version: 1.25.3`)
+- **Terraform templates**: Match the provider version (e.g., AWS provider 5.23.0 → `version: 5.23.0`)
+- **Other templates**: Match the primary application/tool version being deployed
+- Use `latest` or increment template-specific version (e.g., `0.1.0`, `0.2.0`) only when no specific application version applies
+
+**Rationale:** This helps users identify which version of the application/provider the template is designed for and ensures template versions track upstream changes.
+
 ### Template Schema Versioning
 
 Templates and modules use schema versioning to ensure compatibility. Each module defines a supported schema version, and templates declare which schema version they use.
@@ -324,6 +335,23 @@ class ComposeModule(Module):
 3. User `config.yaml` (overrides template and module defaults)
 4. CLI `--var` (highest priority)
 
+**Template Variable Overrides:**
+Template `spec` variables can:
+- **Override module defaults**: Only specify properties that differ from module spec (e.g., change `default` value)
+- **Create new variables**: Define template-specific variables not in module spec
+- **Minimize duplication**: Do NOT re-specify `type`, `description`, or other properties if they remain unchanged from module spec
+
+**Example:**
+```yaml
+# Module spec defines: service_name (type: str, no default)
+# Template spec overrides:
+spec:
+  general:
+    vars:
+      service_name:
+        default: whoami  # Only override the default, type already defined in module
+```
+
 **Variable Types:**
 - `str` (default), `int`, `float`, `bool`
 - `email` - Email validation with regex

+ 2 - 2
cli/core/module/config_commands.py

@@ -160,8 +160,8 @@ def config_list(module_instance) -> None:
         return
 
     # Display defaults using DisplayManager
-    module_instance.display.info(
-        f"[bold]Defaults for module '{module_instance.name}':[/bold]\n"
+    module_instance.display.heading(
+        f"Defaults for module '{module_instance.name}':"
     )
 
     # Convert defaults to display format (rows for table)

+ 15 - 33
library/compose/traefik/compose.yaml.j2

@@ -3,7 +3,10 @@ services:
     image: docker.io/library/traefik:v3.5.3
     {% if not swarm_enabled %}
     container_name: {{ container_name }}
+    security_opt:
+      - no-new-privileges:true
     {% endif %}
+    hostname: {{ container_hostname }}
     ports:
       - "{{ ports_http }}:80"
       - "{{ ports_https }}:443"
@@ -24,23 +27,21 @@ services:
       - traefik_certs:/var/traefik/certs/:rw
       {% endif %}
       {% endif %}
-      {% if traefik_tls_enabled %}
-      {% if not swarm_enabled %}
+      {% if traefik_tls_enabled and not swarm_enabled %}
       - ./.env.secret:/.env.secret:ro
       {% endif %}
     env_file:
       - ./.env
-    {% endif %}
     {% if swarm_enabled %}
     configs:
       - source: traefik_config
         target: /etc/traefik/traefik.yaml
       - source: traefik_middlewares
         target: /etc/traefik/files/middlewares.yaml
-      - source: traefik_tls
-        target: /etc/traefik/files/tls.yaml
-      - source: traefik_external_services
-        target: /etc/traefik/files/external-services.yaml
+      - source: traefik_routers
+        target: /etc/traefik/files/routers.yaml
+      - source: traefik_services
+        target: /etc/traefik/files/services.yaml
     {% endif %}
     environment:
       - TZ={{ container_timezone }}
@@ -50,15 +51,8 @@ services:
       timeout: 5s
       retries: 3
       start_period: 10s
-    {% if network_mode == 'host' %}
-    network_mode: host
-    {% else %}
     networks:
-      {{ traefik_network }}:
-        {% if network_mode == 'macvlan' %}
-        ipv4_address: {{ network_macvlan_ipv4_address }}
-        {% endif %}
-    {% endif %}
+      - {{ traefik_network }}
     {% if swarm_enabled %}
     {% if traefik_tls_enabled %}
     secrets:
@@ -88,7 +82,7 @@ volumes:
     driver: local
     driver_opts:
       type: nfs
-      o: addr={{ swarm_volume_nfs_server }},{{ swarm_volume_nfs_options }}
+      o: addr={{ swarm_volume_nfs_server }},nfsvers=4,{{ swarm_volume_nfs_options }}
       device: ":{{ swarm_volume_nfs_path }}"
     {% endif %}
 {% endif %}
@@ -98,10 +92,10 @@ configs:
     file: ./config/traefik.yaml
   traefik_middlewares:
     file: ./config/files/middlewares.yaml
-  traefik_tls:
-    file: ./config/files/tls.yaml
-  traefik_external_services:
-    file: ./config/files/external-services.yaml
+  traefik_routers:
+    file: ./config/files/routers.yaml
+  traefik_services:
+    file: ./config/files/services.yaml
 
 {% if traefik_tls_enabled %}
 secrets:
@@ -110,28 +104,16 @@ secrets:
 {% endif %}
 {% endif %}
 
-{% if network_mode != 'host' %}
 networks:
   {{ traefik_network }}:
-    {% if network_external %}
+    {% if traefik_network_external %}
     external: true
     {% else %}
     {% if swarm_enabled %}
     driver: overlay
     attachable: 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 }}
-    {% else %}
     driver: bridge
     {% endif %}
-    {% endif %}
     name: {{ traefik_network }}
     {% endif %}
-{% endif %}

+ 0 - 73
library/compose/traefik/config/files/external-services.yaml

@@ -1,73 +0,0 @@
----
-# Example: External Service Configuration
-# This is a commented example showing how to proxy to external services
-# Uncomment and customize for your needs
-
-# http:
-#   routers:
-#     # Example: Proxmox Router
-#     proxmox-router:
-#       rule: "Host(`proxmox.example.com`)"
-#       service: proxmox-service
-#       priority: 10
-#       entryPoints:
-#         - websecure
-#       tls:
-#         certResolver: cloudflare
-#       middlewares:
-#         # Optional: Add authentication
-#         # - authentik@file
-#         # Optional: Add custom headers
-#         # - custom-headers@file
-#
-#     # Example: Router for a local service (Home Assistant, etc.)
-#     homeassistant-router:
-#       rule: "Host(`homeassistant.example.com`)"
-#       service: homeassistant-service
-#       entryPoints:
-#         - websecure
-#       tls:
-#         certResolver: cloudflare
-#
-#     # Example: Router with path-based routing
-#     api-router:
-#       rule: "Host(`example.com`) && PathPrefix(`/api`)"
-#       service: api-service
-#       priority: 20
-#       entryPoints:
-#         - websecure
-#       tls:
-#         certResolver: cloudflare
-#       middlewares:
-#         - rate-limit@file
-#
-#   services:
-#     # Example: Proxmox Service (HTTPS backend)
-#     proxmox-service:
-#       loadBalancer:
-#         servers:
-#           - url: "https://192.168.1.100:8006"
-#         serversTransport: insecure-transport
-#
-#     # Example: Home Assistant Service (HTTP backend)
-#     homeassistant-service:
-#       loadBalancer:
-#         servers:
-#           - url: "http://192.168.1.50:8123"
-#
-#     # Example: API Service with multiple backends (load balancing)
-#     api-service:
-#       loadBalancer:
-#         servers:
-#           - url: "http://192.168.1.10:8080"
-#           - url: "http://192.168.1.11:8080"
-#         sticky:
-#           cookie:
-#             name: api-sticky
-#             httpOnly: true
-#
-# # Example: Server Transport for insecure backends (skip TLS verification)
-# # Useful for services with self-signed certificates
-# serversTransports:
-#   insecure-transport:
-#     insecureSkipVerify: true

+ 27 - 35
library/compose/traefik/config/files/middlewares.yaml.j2

@@ -2,9 +2,9 @@
 # Traefik Dynamic Middleware Configuration
 # This file is watched by Traefik and changes are applied automatically
 
+{% if authentik_enabled -%}
 http:
   middlewares:
-{% if authentik_enabled %}
     # Authentik Forward Auth Middleware
     # Use this middleware in your service labels: traefik.http.routers.myservice.middlewares={{ traefik_authentik_middleware_name }}@file
     {{ traefik_authentik_middleware_name }}:
@@ -24,43 +24,35 @@ http:
           - X-authentik-meta-app
           - X-authentik-meta-version
 
-{% endif %}
-    # Example: Custom Headers Middleware
-    # Uncomment and customize as needed
-    # custom-headers:
+    # Example 1: Security headers
+    # security-headers:
     #   headers:
-    #     customRequestHeaders:
-    #       X-Custom-Header: "value"
-    #     customResponseHeaders:
-    #       X-Custom-Response: "value"
-
-    # Example: Rate Limiting Middleware
-    # Uncomment and customize as needed
+    #     frameDeny: true
+    #     browserXssFilter: true
+    #     contentTypeNosniff: true
+    #     stsSeconds: 31536000
+    #
+    # Example 2: Rate limiting
     # rate-limit:
     #   rateLimit:
     #     average: 100
     #     burst: 50
-    #     period: 1s
-
-    # Example: IP Whitelist Middleware
-    # Uncomment and customize as needed
-    # ip-whitelist:
-    #   ipWhiteList:
-    #     sourceRange:
-    #       - "192.168.1.0/24"
-    #       - "10.0.0.0/8"
-
-    # Example: Basic Auth Middleware
-    # Uncomment and customize as needed
-    # Generate passwords with: htpasswd -nb user password
-    # basic-auth:
-    #   basicAuth:
-    #     users:
-    #       - "admin:$apr1$..."
+{% else -%}
+# Uncomment and customize the examples below as needed
 
-    # Example: Redirect Scheme Middleware
-    # Uncomment and customize as needed
-    # redirect-to-https:
-    #   redirectScheme:
-    #     scheme: https
-    #     permanent: true
+# http:
+#   middlewares:
+#     # Example 1: Security headers
+#     security-headers:
+#       headers:
+#         frameDeny: true
+#         browserXssFilter: true
+#         contentTypeNosniff: true
+#         stsSeconds: 31536000
+#
+#     # Example 2: Rate limiting
+#     rate-limit:
+#       rateLimit:
+#         average: 100
+#         burst: 50
+{% endif -%}

+ 27 - 0
library/compose/traefik/config/files/routers.yaml

@@ -0,0 +1,27 @@
+---
+# Traefik Dynamic Router Configuration
+# Define routers to route traffic to services
+# Uncomment and customize the examples below
+
+# http:
+#   routers:
+#     # Example 1: Simple host-based routing with HTTPS
+#     my-app:
+#       rule: "Host(`app.example.com`)"
+#       service: my-app-service
+#       entryPoints:
+#         - websecure
+#       tls:
+#         certResolver: cloudflare
+#
+#     # Example 2: Path-based routing with middleware
+#     api:
+#       rule: "Host(`example.com`) && PathPrefix(`/api`)"
+#       service: api-service
+#       priority: 10
+#       entryPoints:
+#         - websecure
+#       tls:
+#         certResolver: cloudflare
+#       middlewares:
+#         - rate-limit@file

+ 28 - 0
library/compose/traefik/config/files/services.yaml

@@ -0,0 +1,28 @@
+---
+# Traefik Dynamic Service Configuration
+# Define backend services that routers connect to
+# Uncomment and customize the examples below
+
+# http:
+#   services:
+#     # Example 1: Single backend server
+#     my-app-service:
+#       loadBalancer:
+#         servers:
+#           - url: "http://192.168.1.100:8080"
+#
+#     # Example 2: Load balanced service with multiple backends
+#     api-service:
+#       loadBalancer:
+#         servers:
+#           - url: "http://192.168.1.10:8080"
+#           - url: "http://192.168.1.11:8080"
+#         sticky:
+#           cookie:
+#             name: api-sticky
+#             httpOnly: true
+#
+# # Server Transport for HTTPS backends with self-signed certificates
+# serversTransports:
+#   insecure:
+#     insecureSkipVerify: true

+ 0 - 96
library/compose/traefik/config/files/tls.yaml

@@ -1,96 +0,0 @@
----
-# Traefik TLS Configuration
-# This file is watched by Traefik and changes are applied automatically
-
-# TLS Options Configuration
-# Define custom TLS settings for different security requirements
-tls:
-  options:
-    # Example: Modern TLS Configuration (Recommended)
-    # Uncomment and customize as needed
-    # modern:
-    #   minVersion: VersionTLS13
-    #   cipherSuites:
-    #     - TLS_AES_128_GCM_SHA256
-    #     - TLS_AES_256_GCM_SHA384
-    #     - TLS_CHACHA20_POLY1305_SHA256
-    #   curvePreferences:
-    #     - CurveP521
-    #     - CurveP384
-
-    # Example: Intermediate TLS Configuration (Balanced)
-    # Good balance between security and compatibility
-    # intermediate:
-    #   minVersion: VersionTLS12
-    #   cipherSuites:
-    #     - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-    #     - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-    #     - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    #   curvePreferences:
-    #     - CurveP521
-    #     - CurveP384
-    #   sniStrict: true
-
-    # Example: Old TLS Configuration (Maximum Compatibility)
-    # Use only if you need to support very old clients
-    # old:
-    #   minVersion: VersionTLS10
-    #   maxVersion: VersionTLS13
-
-  # Certificate Stores
-  # Define custom certificate stores for dynamic certificates
-  # stores:
-  #   default:
-  #     defaultCertificate:
-  #       certFile: /path/to/cert.pem
-  #       keyFile: /path/to/key.pem
-
-  # Dynamic Certificates
-  # Load certificates from files (alternative to ACME)
-  # certificates:
-  #   - certFile: /path/to/domain1.cert
-  #     keyFile: /path/to/domain1.key
-  #     stores:
-  #       - default
-  #   - certFile: /path/to/domain2.cert
-  #     keyFile: /path/to/domain2.key
-
-# Server Transports
-# Configure how Traefik communicates with backend services
-# serversTransports:
-#   # Example: Skip TLS Verification for Self-Signed Certificates
-#   # Useful for internal services with self-signed certs
-#   insecure:
-#     insecureSkipVerify: true
-#
-#   # Example: Custom Root CA
-#   # Use a custom CA to verify backend certificates
-#   custom-ca:
-#     rootCAs:
-#       - /path/to/ca.crt
-#
-#   # Example: Client Certificate Authentication
-#   # Use client certificates to authenticate to backend
-#   mtls:
-#     certificates:
-#       - certFile: /path/to/client.crt
-#         keyFile: /path/to/client.key
-
-# Usage Examples:
-#
-# 1. Apply TLS options to a router:
-#    http:
-#      routers:
-#        my-router:
-#          rule: "Host(`example.com`)"
-#          tls:
-#            options: modern@file
-#
-# 2. Use custom server transport:
-#    http:
-#      services:
-#        my-service:
-#          loadBalancer:
-#            servers:
-#              - url: "https://backend:443"
-#            serversTransport: insecure@file

+ 48 - 9
library/compose/traefik/config/traefik.yaml.j2

@@ -12,16 +12,32 @@ log:
 accesslog: {}
 {% endif %}
 
+ping:
+  entryPoint: ping
+
 {% if dashboard_enabled %}
 api:
   dashboard: true
   insecure: true
 {% endif %}
 
+{% if prometheus_enabled %}
+metrics:
+  prometheus:
+    entryPoint: metrics
+    addRoutersLabels: true
+{% endif %}
+
 entryPoints:
+  ping:
+    address: :8082
+  {% if prometheus_enabled %}
+  metrics:
+    address: :9090
+  {% endif %}
   {{ traefik_entrypoint }}:
     address: :80
-    {% if traefik_tls_enabled and tls_redirect %}
+    {% if traefik_tls_enabled and traefik_tls_redirect %}
     http:
       redirections:
         entryPoint:
@@ -35,28 +51,51 @@ entryPoints:
 
 {% if traefik_tls_enabled %}
 certificatesResolvers:
-  {{ traefik_tls_certresolver | default('cloudflare') }}:
+  {{ traefik_tls_certresolver }}:
     acme:
       email: {{ traefik_tls_acme_email }}
       storage: /var/traefik/certs/acme.json
       caServer: "https://acme-v02.api.letsencrypt.org/directory"
       dnsChallenge:
-        provider: {{ traefik_tls_acme_provider | default('cloudflare') }}
+        provider: {{ traefik_tls_acme_provider }}
         resolvers:
           - 1.1.1.1:53
           - 8.8.8.8:53
+
+tls:
+  options:
+    default:
+      minVersion: {{ traefik_tls_min_version }}
+      {% if traefik_tls_secure_ciphers %}
+      cipherSuites:
+        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+      {% endif %}
+{% endif %}
+
+{% if traefik_tls_skipverify %}
+http:
+  serversTransports:
+    insecure:
+      insecureSkipVerify: true
 {% endif %}
 
-# NOTE: If using self-signed certificates in your backend services, uncomment the following section
-# to disable certificate verification (not recommended for production use).
-# ---
-# serversTransport:
-#   insecureSkipVerify: true
 
 providers:
+  {% if swarm_enabled %}
+  swarm:
+    endpoint: "unix:///var/run/docker.sock"
+    exposedByDefault: false
+    network: {{ traefik_network }}
+  {% else %}
   docker:
     exposedByDefault: false
-    network: {{ network_name }}
+    network: {{ traefik_network }}
+  {% endif %}
   file:
     directory: /etc/traefik/files
     watch: true

+ 46 - 4
library/compose/traefik/template.yaml

@@ -29,9 +29,10 @@ spec:
         default: "traefik"
       container_name:
         default: "traefik"
+      container_hostname:
+        default: "traefik"
   ports:
-    title: "Ports"
-    description: "Configure external port mappings"
+    needs: []
     vars:
       ports_http:
         type: "int"
@@ -50,12 +51,21 @@ spec:
         extra: "Only used when dashboard is enabled"
   traefik:
     title: "Settings"
+    needs: []
     vars:
       traefik_network:
         type: "str"
         description: "Traefik network name"
         default: "traefik"
         extra: "Network that Traefik uses to connect to services"
+      traefik_network_external:
+        type: "bool"
+        description: "Use existing Docker network (external)"
+        default: false
+      traefik_entrypoint:
+        type: "str"
+        description: "HTTP entrypoint (non-TLS)"
+        default: "web"
       dashboard_enabled:
         type: "bool"
         description: "Enable Traefik dashboard"
@@ -65,14 +75,27 @@ spec:
         type: "bool"
         description: "Enable Traefik access log"
         default: false
+      prometheus_enabled:
+        type: "bool"
+        description: "Enable Prometheus metrics"
+        default: false
+        extra: "Exposes metrics on internal port 9090 (not publicly exposed)"
   traefik_tls:
     title: "TLS Settings"
-    needs: null
+    needs: []
     vars:
       traefik_tls_enabled:
         type: "bool"
         description: "Enable HTTPS/TLS with ACME"
         default: false
+      traefik_tls_entrypoint:
+        type: "str"
+        description: "TLS entrypoint"
+        default: "websecure"
+      traefik_tls_certresolver:
+        type: "str"
+        description: "Traefik certificate resolver name"
+        default: "cloudflare"
       traefik_tls_acme_provider:
         type: "enum"
         description: "ACME DNS challenge provider"
@@ -89,11 +112,30 @@ spec:
         description: "Email address for ACME (Let's Encrypt) registration"
         default: "admin@example.com"
         extra: "Required for Let's Encrypt certificate requests"
-      tls_redirect:
+      traefik_tls_redirect:
         type: "bool"
         description: "Redirect all HTTP traffic to HTTPS"
         default: true
+      traefik_tls_min_version:
+        type: "enum"
+        description: "Minimum TLS version"
+        default: "VersionTLS12"
+        options:
+          - "VersionTLS12"
+          - "VersionTLS13"
+        extra: "TLS 1.2 is recommended for compatibility, TLS 1.3 for maximum security"
+      traefik_tls_secure_ciphers:
+        type: "bool"
+        description: "Enable strict cipher suites (recommended)"
+        default: true
+        extra: "Enforces modern, secure cipher suites"
+      traefik_tls_skipverify:
+        type: "bool"
+        description: "Skip TLS verification for backend servers"
+        default: false
+        extra: "WARNING: Only enable for self-signed certificates in trusted environments"
   swarm:
+    needs: []
     vars:
       traefik_tls_acme_secret_name:
         type: "str"

+ 38 - 28
library/compose/whoami/compose.yaml.j2

@@ -1,41 +1,51 @@
 services:
-  {{ service_name | default('whoami') }}:
-    image: traefik/whoami
-    container_name: {{ container_name | default('whoami') }}
+  {{ service_name }}:
+    image: traefik/whoami:v1.11.0
+    {% if not swarm_enabled %}
+    container_name: {{ container_name }}
+    restart: {{ restart_policy }}
+    {% endif %}
+    hostname: {{ container_hostname }}
     {% if swarm_enabled %}
     deploy:
-      replicas: {{ swarm_replicas | default(1) }}
+      mode: {{ swarm_placement_mode }}
+      {% if swarm_placement_mode == "replicated" %}
+      replicas: {{ swarm_replicas }}
+      {% endif %}
+      {% if swarm_placement_host %}
+      placement:
+        constraints:
+          - node.hostname == {{ swarm_placement_host }}
+      {% endif %}
       restart_policy:
         condition: on-failure
-    {% endif %}
-    {% if ports_enabled %}
-    ports:
-      - "{{ ports_http | default(8080) }}:80"
-      - "{{ ports_https | default(8443) }}:443"
-    {% endif %}
-    {% if network_enabled %}
-    networks:
-      - {{ network_name | default("bridge") }}
-    {% endif %}
-    {% if traefik_enabled %}
+      labels:
+        - traefik.enable=true
+        - traefik.http.services.{{ service_name }}.loadbalancer.server.port=80
+        - traefik.http.routers.{{ service_name }}-http.rule=Host(`{{ traefik_host }}`)
+        - traefik.http.routers.{{ service_name }}-http.entrypoints={{ traefik_entrypoint }}
+        {% if traefik_tls_enabled %}
+        - traefik.http.routers.{{ service_name }}-https.rule=Host(`{{ traefik_host }}`)
+        - 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 %}
+    {% else %}
     labels:
       - traefik.enable=true
-      - traefik.http.services.{{ service_name | default("whoami") }}.loadbalancer.server.port=80
-      - traefik.http.routers.{{ service_name | default("whoami") }}-http.rule=Host(`{{ traefik_host }}`)
-      - traefik.http.routers.{{ service_name | default("whoami") }}-http.entrypoints={{ traefik_entrypoint | default("web") }}
+      - traefik.http.services.{{ service_name }}.loadbalancer.server.port=80
+      - traefik.http.routers.{{ service_name }}-http.rule=Host(`{{ traefik_host }}`)
+      - traefik.http.routers.{{ service_name }}-http.entrypoints={{ traefik_entrypoint }}
       {% if traefik_tls_enabled %}
-      - traefik.http.routers.{{ service_name | default("whoami") }}-https.rule=Host(`{{ traefik_host }}`)
-      - traefik.http.routers.{{ service_name | default("whoami") }}-https.entrypoints={{ traefik_tls_entrypoint | default("websecure") }}
-      - traefik.http.routers.{{ service_name | default("whoami") }}-https.tls=true
-      - traefik.http.routers.{{ service_name | default("whoami") }}-https.tls.certresolver={{ traefik_tls_certresolver }}
+      - traefik.http.routers.{{ service_name }}-https.rule=Host(`{{ traefik_host }}`)
+      - 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 %}
-    restart: {{ restart_policy | default("unless-stopped") }}
+    networks:
+      - {{ traefik_network }}
 
-{% if network_enabled %}
 networks:
-  {{ network_name | default("bridge") }}:
-    {% if network_external %}
+  {{ traefik_network }}:
     external: true
-    {% endif %}
-{% endif %}

+ 22 - 17
library/compose/whoami/template.yaml

@@ -1,5 +1,6 @@
 ---
 kind: compose
+schema: "1.1"
 metadata:
   name: Whoami
   description: >
@@ -12,27 +13,31 @@ metadata:
     Documentation: https://traefik.io/docs/
 
     GitHub: https://github.com/traefik/whoami
-  version: 0.1.0
+  version: 1.11.0
   author: Christian Lempa
-  date: '2025-09-28'
+  date: '2025-10-30'
   tags:
     - reverse-proxy
     - testing
-  draft: true
+    - traefik
+    - swarm
+  draft: false
 spec:
-  ports:
-    vars:
-      ports_http:
-        description: "Host port for HTTP (80)"
-        type: int
-        default: 80
-      ports_https:
-        description: "Host port for HTTPS (443)"
-        type: int
-        default: 443
   general:
     vars:
-      whoami_version:
-        type: str
-        description: Whoami version
-        default: latest
+      service_name:
+        default: whoami
+      container_name:
+        default: whoami
+      container_hostname:
+        default: whoami
+  traefik:
+    required: true
+    needs: []
+    vars:
+      traefik_host:
+        default: whoami.localhost
+  traefik_tls:
+    needs: []
+  swarm:
+    needs: []