xcad пре 5 месеци
родитељ
комит
208b6ab6ef

+ 7 - 1
library/compose/pihole/.env.pihole.j2

@@ -1,5 +1,5 @@
 # Pi-hole Configuration
-# Contains sensitive application secrets and configuration
+# Contains application configuration
 
 # Timezone
 TZ={{ container_timezone }}
@@ -9,7 +9,13 @@ PIHOLE_UID={{ user_uid }}
 PIHOLE_GID={{ user_gid }}
 
 # Web Interface Admin Password
+{% if swarm_enabled %}
+# In swarm mode, password is loaded from Docker secret (use secret name, not path)
+WEBPASSWORD_FILE={{ webpassword_secret_name }}
+{% else %}
+# In compose mode, password is stored directly
 FTLCONF_webserver_api_password={{ webpassword }}
+{% endif %}
 
 # DNS Listening Mode
 {% if network_mode == 'bridge' %}

+ 1 - 0
library/compose/pihole/.env.secret.j2

@@ -0,0 +1 @@
+{{ webpassword }}

+ 96 - 2
library/compose/pihole/compose.yaml.j2

@@ -1,12 +1,14 @@
 services:
   {{ service_name }}:
+    {% if not swarm_enabled %}
     container_name: {{ container_name }}
+    {% endif %}
     image: docker.io/pihole/pihole:2025.08.0
     env_file:
       - .env.pihole
-    {% if network_mode == 'host' %}
+    {% if network_enabled == 'true' and network_mode == 'host' %}
     network_mode: host
-    {% elif traefik_enabled or network_mode == 'macvlan' %}
+    {% elif traefik_enabled or network_enabled == 'true' %}
     networks:
       {% if traefik_enabled %}
       {{ traefik_network }}:
@@ -21,18 +23,78 @@ services:
     {% if network_mode not in ['host', 'macvlan'] %}
     ports:
       {% if not traefik_enabled %}
+      {% if swarm_enabled %}
+      - target: 443
+        published: {{ ports_https }}
+        protocol: tcp
+        mode: host
+      {% else %}
       - "{{ ports_https }}:443/tcp"
       {% endif %}
+      {% endif %}
+      {% if swarm_enabled %}
+      - target: 53
+        published: {{ ports_dns }}
+        protocol: tcp
+        mode: host
+      - target: 53
+        published: {{ ports_dns }}
+        protocol: udp
+        mode: host
+      - target: 123
+        published: {{ ports_ntp }}
+        protocol: udp
+        mode: host
+      {% else %}
       - "{{ ports_dns }}:53/tcp"
       - "{{ ports_dns }}:53/udp"
       - "{{ ports_ntp }}:123/udp"
+      {% endif %}
     {% endif %}
     volumes:
+      {% if not swarm_enabled %}
+      - config_dnsmasq:/etc/dnsmasq.d
+      - config_pihole:/etc/pihole
+      {% else %}
+      {% if swarm_volume_mode == 'mount' %}
+      - {{ swarm_volume_mount_path }}/dnsmasq:/etc/dnsmasq.d:rw
+      - {{ swarm_volume_mount_path }}/pihole:/etc/pihole:rw
+      {% elif swarm_volume_mode == 'local' %}
+      - config_dnsmasq:/etc/dnsmasq.d
+      - config_pihole:/etc/pihole
+      {% elif swarm_volume_mode == 'nfs' %}
       - config_dnsmasq:/etc/dnsmasq.d
       - config_pihole:/etc/pihole
+      {% endif %}
+      {% endif %}
     cap_add:
       - NET_ADMIN
       - SYS_TIME
+    {% if swarm_enabled %}
+    secrets:
+      - {{ webpassword_secret_name }}
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.hostname == {{ swarm_placement_host }}
+      {% if traefik_enabled %}
+      labels:
+        - traefik.enable=true
+        - 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.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.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 %}
+    {% else %}
     {% if traefik_enabled %}
     labels:
       - traefik.enable=true
@@ -49,12 +111,39 @@ services:
       {% endif %}
     {% endif %}
     restart: {{ restart_policy }}
+    {% endif %}
 
+{% if swarm_enabled %}
+{% if swarm_volume_mode in ['local', 'nfs'] %}
+volumes:
+  config_dnsmasq:
+    {% if swarm_volume_mode == 'nfs' %}
+    driver: local
+    driver_opts:
+      type: nfs
+      o: addr={{ swarm_volume_nfs_server }},{{ swarm_volume_nfs_options }}
+      device: ":{{ swarm_volume_nfs_path }}/dnsmasq"
+    {% endif %}
+  config_pihole:
+    {% if swarm_volume_mode == 'nfs' %}
+    driver: local
+    driver_opts:
+      type: nfs
+      o: addr={{ swarm_volume_nfs_server }},{{ swarm_volume_nfs_options }}
+      device: ":{{ swarm_volume_nfs_path }}/pihole"
+    {% endif %}
+{% endif %}
+
+secrets:
+  {{ webpassword_secret_name }}:
+    file: ./.env.secret
+{% else %}
 volumes:
   config_dnsmasq:
     driver: local
   config_pihole:
     driver: local
+{% endif %}
 
 {% if network_mode != 'host' and (network_mode in ['bridge', 'macvlan'] or traefik_enabled) %}
 networks:
@@ -72,7 +161,12 @@ networks:
     external: true
   {% elif network_mode == 'bridge' and not network_external %}
   {{ network_name }}:
+    {% if swarm_enabled %}
+    driver: overlay
+    attachable: true
+    {% else %}
     driver: bridge
+    {% endif %}
   {% endif %}
   {% if traefik_enabled %}
   {{ traefik_network }}:

+ 30 - 3
library/compose/pihole/template.yaml

@@ -22,6 +22,27 @@ metadata:
     - ad-blocking
   draft: false
   next_steps: |
+    {% if swarm_enabled -%}
+    1. Create Docker Swarm secret for admin password:
+       echo "{{ webpassword }}" | docker secret create {{ webpassword_secret_name }} -
+       (Or use the generated .env.secret file)
+
+    2. Deploy to Swarm:
+       docker stack deploy -c compose.yaml pihole
+
+    3. Verify deployment:
+       docker service ls
+       docker service logs pihole_{{ service_name }}
+
+    4. Access web interface:
+       {% if network_mode == 'macvlan' -%}https://{{ network_macvlan_ipv4_address }}/admin/login
+       {%- elif traefik_enabled == True -%}https://{{ traefik_host }}/admin/login
+       {%- else -%}https://localhost:{{ ports_https }}/admin/login{%- endif %}
+
+    5. Login password: Stored in Docker secret '{{ webpassword_secret_name }}'
+
+    6. Configure devices to use your swarm node's IP address as DNS server
+    {% else -%}
     1. Start: docker compose up -d
 
     2. Access web interface:
@@ -32,6 +53,7 @@ metadata:
     3. Login password: {{ webpassword }}
 
     4. Configure devices to use your host's IP address as DNS server
+    {% endif -%}
 spec:
   general:
     vars:
@@ -54,14 +76,11 @@ spec:
       traefik_host:
         default: "pihole.home.arpa"
   network:
-    required: true
     vars:
       network_mode:
         extra: "If you need DHCP functionality, use 'host' or 'macvlan' mode"
       network_name:
         default: "pihole_network"
-      network_external:
-        default: false
   ports:
     needs: "network_mode=bridge"
     vars:
@@ -78,3 +97,11 @@ spec:
         description: "External NTP port"
         type: int
         default: 123
+  swarm:
+    vars:
+      swarm_placement_host:
+        required: true
+      webpassword_secret_name:
+        description: "Docker Swarm secret name for admin password"
+        type: str
+        default: "pihole_webpassword"