migrate
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/gethomepage/homepage:v1.12.3
|
||||
environment:
|
||||
<%- if traefik_enabled %>
|
||||
- HOMEPAGE_ALLOWED_HOSTS=<< traefik_host >>.<< traefik_domain >>
|
||||
<%- else %>
|
||||
- HOMEPAGE_ALLOWED_HOSTS=localhost:<< ports_http >>,127.0.0.1:<< ports_http >>
|
||||
<%- endif %>
|
||||
<%- if container_timezone %>
|
||||
- TZ=<< container_timezone >>
|
||||
<%- endif %>
|
||||
<%- if container_loglevel %>
|
||||
- LOG_LEVEL=<< container_loglevel >>
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
<%- endif %>
|
||||
<%- if not traefik_enabled %>
|
||||
ports:
|
||||
- << ports_http >>:3000
|
||||
<%- endif %>
|
||||
volumes:
|
||||
<%- if volume_mode == 'local' %>
|
||||
- << service_name >>_config:/app/config
|
||||
- << service_name >>_images:/app/images
|
||||
- << service_name >>_icons:/app/icons
|
||||
<%- elif volume_mode == 'mount' %>
|
||||
- << volume_mount_path >>/<< service_name >>/config:/app/config
|
||||
- << volume_mount_path >>/<< service_name >>/images:/app/images
|
||||
- << volume_mount_path >>/<< service_name >>/icons:/app/icons
|
||||
<%- elif volume_mode == 'nfs' %>
|
||||
- << service_name >>_config:/app/config
|
||||
- << service_name >>_images:/app/images
|
||||
- << service_name >>_icons:/app/icons
|
||||
<%- endif %>
|
||||
deploy:
|
||||
<%- if swarm_placement_mode == 'replicated' %>
|
||||
replicas: << swarm_replicas >>
|
||||
<%- if swarm_placement_host %>
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
<%- endif %>
|
||||
<%- else %>
|
||||
mode: global
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=<< traefik_network >>
|
||||
- traefik.http.services.<< service_name >>-web.loadbalancer.server.port=3000
|
||||
- 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 traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
|
||||
<%- if volume_mode == 'local' %>
|
||||
volumes:
|
||||
<< service_name >>_config:
|
||||
<< service_name >>_images:
|
||||
<< service_name >>_icons:
|
||||
<%- elif volume_mode == 'nfs' %>
|
||||
volumes:
|
||||
<< service_name >>_config:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>/config"
|
||||
<< service_name >>_images:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>/images"
|
||||
<< service_name >>_icons:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>/icons"
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,284 @@
|
||||
{
|
||||
"slug": "homepage-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Homepage",
|
||||
"description": "Modern, fully static, fast application dashboard with integrations for over 100 services and translations into multiple languages.",
|
||||
"tags": [
|
||||
"traefik",
|
||||
"volume_modes"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "homepage"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "v1.12.3",
|
||||
"source_dep_name": "ghcr.io/gethomepage/homepage",
|
||||
"source_dep_version": "v1.12.3"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "The service name",
|
||||
"required": true,
|
||||
"default": "homepage",
|
||||
"config": {
|
||||
"placeholder": "homepage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "The container timezone",
|
||||
"required": false,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_loglevel",
|
||||
"type": "enum",
|
||||
"title": "Log Level",
|
||||
"required": false,
|
||||
"config": {
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_mode",
|
||||
"type": "enum",
|
||||
"title": "Swarm Placement Mode",
|
||||
"required": true,
|
||||
"default": "replicated",
|
||||
"config": {
|
||||
"options": [
|
||||
"replicated",
|
||||
"global"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Swarm Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
},
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Swarm Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "The HTTP port",
|
||||
"required": true,
|
||||
"default": 3000,
|
||||
"needs": [
|
||||
"traefik_enabled=false"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "3000"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Entrypoint",
|
||||
"required": true,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "homepage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "TLS Entrypoint",
|
||||
"required": true,
|
||||
"default": "websecure",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Volume",
|
||||
"name": "volume",
|
||||
"items": [
|
||||
{
|
||||
"name": "volume_mode",
|
||||
"type": "enum",
|
||||
"title": "Volume Mode",
|
||||
"required": true,
|
||||
"default": "local",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"mount",
|
||||
"nfs"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_mount_path",
|
||||
"type": "str",
|
||||
"title": "Volume Mount Path",
|
||||
"required": true,
|
||||
"default": "/mnt/storage",
|
||||
"needs": [
|
||||
"volume_mode=mount"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/mnt/storage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_options",
|
||||
"type": "str",
|
||||
"title": "NFS Options",
|
||||
"required": false,
|
||||
"default": "nfsvers=4,soft,timeo=180,intr",
|
||||
"config": {
|
||||
"placeholder": "nfsvers=4,soft,timeo=180,intr"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_path",
|
||||
"type": "str",
|
||||
"title": "NFS Path",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/path/to/export"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_server",
|
||||
"type": "str",
|
||||
"title": "NFS Server",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "192.0.2.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
# Homepage configuration
|
||||
# See https://fontawesome.com/icons for icons options
|
||||
|
||||
title: "<< homer_title >>"
|
||||
subtitle: "<< homer_subtitle >>"
|
||||
logo: "<< homer_logo >>"
|
||||
# icon: "fas fa-home" # Optional icon instead of logo
|
||||
|
||||
header: true
|
||||
footer: false # Set to "<Message>" to enable footer with a custom message
|
||||
|
||||
# Optional theme customization
|
||||
theme: default # Options: default, sui
|
||||
# colors:
|
||||
# light:
|
||||
# highlight-primary: "#3367d6"
|
||||
# highlight-secondary: "#4285f4"
|
||||
# highlight-hover: "#5a95f5"
|
||||
# background: "#f5f5f5"
|
||||
# card-background: "#ffffff"
|
||||
# text: "#363636"
|
||||
# text-header: "#ffffff"
|
||||
# dark:
|
||||
# highlight-primary: "#3367d6"
|
||||
# highlight-secondary: "#4285f4"
|
||||
# highlight-hover: "#5a95f5"
|
||||
# background: "#131313"
|
||||
# card-background: "#2b2b2b"
|
||||
# text: "#eaeaea"
|
||||
# text-header: "#ffffff"
|
||||
|
||||
# Optional message displayed at the top
|
||||
# message:
|
||||
# style: "is-dark" # Options: is-dark, is-warning, is-info, is-success, is-danger
|
||||
# title: "Welcome!"
|
||||
# icon: "fa fa-grin"
|
||||
# content: "This is your Homer dashboard. <br /> Add your services below."
|
||||
|
||||
# Optional navbar links
|
||||
# links:
|
||||
# - name: "GitHub"
|
||||
# icon: "fab fa-github"
|
||||
# url: "https://github.com"
|
||||
# target: "_blank" # optional: open in new tab
|
||||
# - name: "Documentation"
|
||||
# icon: "fas fa-book"
|
||||
# url: "https://github.com/bastienwirtz/homer/blob/main/docs/configuration.md"
|
||||
|
||||
# Services
|
||||
# First level array represents a group.
|
||||
# Leave only an "items" key if not using groups (group name, icon & tagstyle are optional)
|
||||
services:
|
||||
- name: "Applications"
|
||||
icon: "fas fa-cloud"
|
||||
# items:
|
||||
# - name: "Example App"
|
||||
# logo: "assets/tools/sample.png" # or use "icon: fas fa-server"
|
||||
# subtitle: "Description of the app"
|
||||
# tag: "app" # Optional tag
|
||||
# tagstyle: "is-success" # Optional: is-success, is-warning, is-info, is-danger
|
||||
# url: "https://example.com"
|
||||
# target: "_blank" # optional: open in new tab
|
||||
|
||||
# - name: "Monitoring"
|
||||
# icon: "fas fa-chart-line"
|
||||
# items:
|
||||
# - name: "Grafana"
|
||||
# icon: "fas fa-chart-area"
|
||||
# subtitle: "Metrics & dashboards"
|
||||
# url: "https://grafana.example.com"
|
||||
@@ -0,0 +1,60 @@
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/b4bz/homer:v26.4.2
|
||||
<%- if container_timezone %>
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
<%- endif %>
|
||||
<%- if not traefik_enabled %>
|
||||
ports:
|
||||
- target: 8080
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif %>
|
||||
volumes:
|
||||
- ./assets:/www/assets
|
||||
deploy:
|
||||
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
|
||||
<%- if 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 authentik_enabled %>
|
||||
- traefik.http.routers.<< service_name >>-http.middlewares=<< authentik_traefik_middleware >>
|
||||
<%- endif %>
|
||||
<%- 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 >>
|
||||
<%- if authentik_enabled %>
|
||||
- traefik.http.routers.<< service_name >>-https.middlewares=<< authentik_traefik_middleware >>
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,259 @@
|
||||
{
|
||||
"slug": "homer-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Homer",
|
||||
"description": "Simple static homepage for your server to keep your services on hand, configured through a single YAML file.",
|
||||
"tags": [
|
||||
"traefik",
|
||||
"authentik"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "homer"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "v26.4.2",
|
||||
"source_dep_name": "docker.io/b4bz/homer",
|
||||
"source_dep_version": "v26.4.2"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "homer",
|
||||
"config": {
|
||||
"placeholder": "homer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": false,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "homer_title",
|
||||
"type": "str",
|
||||
"title": "Dashboard title",
|
||||
"required": false,
|
||||
"default": "Dashboard",
|
||||
"config": {
|
||||
"placeholder": "Dashboard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "homer_subtitle",
|
||||
"type": "str",
|
||||
"title": "Dashboard subtitle",
|
||||
"required": false,
|
||||
"default": "Dashboard",
|
||||
"config": {
|
||||
"placeholder": "Dashboard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "homer_logo",
|
||||
"type": "str",
|
||||
"title": "Logo Path",
|
||||
"required": false,
|
||||
"default": "logo-file.png",
|
||||
"description": "Logo file path (relative to assets/)",
|
||||
"config": {
|
||||
"placeholder": "logo-file.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 8080,
|
||||
"config": {
|
||||
"placeholder": "8080"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Entrypoint",
|
||||
"required": true,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "dashboard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik Tls",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "TLS Entrypoint",
|
||||
"required": true,
|
||||
"default": "websecure",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Docker Swarm",
|
||||
"name": "swarm",
|
||||
"items": [
|
||||
{
|
||||
"name": "swarm_placement_mode",
|
||||
"type": "enum",
|
||||
"title": "Swarm Placement Mode",
|
||||
"required": true,
|
||||
"default": "replicated",
|
||||
"config": {
|
||||
"options": [
|
||||
"replicated",
|
||||
"global"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Swarm Replicas",
|
||||
"required": true,
|
||||
"default": 1,
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
],
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Swarm Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Authentik SSO",
|
||||
"name": "authentik",
|
||||
"toggle": "authentik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "authentik_traefik_middleware",
|
||||
"type": "str",
|
||||
"title": "Authentik Traefik Middleware",
|
||||
"required": true,
|
||||
"default": "middleware@file",
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "middleware@file"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "authentik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Authentik SSO",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/moghtech/komodo-core:2.1.2
|
||||
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:
|
||||
- target: 9120
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif %>
|
||||
<%- if environment_enabled %>
|
||||
environment:
|
||||
KOMODO_DATABASE_ADDRESS: "<< environment_database_address >>"
|
||||
KOMODO_DATABASE_DB_NAME: "<< environment_database_name >>"
|
||||
<%- if environment_database_username %>
|
||||
KOMODO_DATABASE_USERNAME: "<< environment_database_username >>"
|
||||
<%- endif %>
|
||||
<%- if environment_database_password %>
|
||||
KOMODO_DATABASE_PASSWORD: "<< environment_database_password >>"
|
||||
<%- endif %>
|
||||
<%- if environment_jwt_secret %>
|
||||
KOMODO_JWT_SECRET: "<< environment_jwt_secret >>"
|
||||
<%- endif %>
|
||||
LOG_LEVEL: "<< environment_log_level >>"
|
||||
<%- endif %>
|
||||
volumes:
|
||||
<%- if volume_mode == 'mount' %>
|
||||
- << volume_mount_path >>/data:/app/data:rw
|
||||
- << volume_mount_path >>/repos:/app/repos:rw
|
||||
<%- elif volume_mode == 'local' or volume_mode == 'nfs' %>
|
||||
- << service_name >>-data:/app/data
|
||||
- << service_name >>-repos:/app/repos
|
||||
<%- endif %>
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
<%- if resources_enabled %>
|
||||
resources:
|
||||
limits:
|
||||
cpus: '<< resources_cpu_limit >>'
|
||||
memory: << resources_memory_limit >>
|
||||
reservations:
|
||||
cpus: '<< resources_cpu_reservation >>'
|
||||
memory: << resources_memory_reservation >>
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=<< traefik_network >>
|
||||
- traefik.http.services.<< service_name >>-web.loadBalancer.server.port=9120
|
||||
- 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 >>-repos:
|
||||
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 >>-repos:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>/repos"
|
||||
<%- 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 >>
|
||||
<%- else %>
|
||||
driver: overlay
|
||||
attachable: true
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,460 @@
|
||||
{
|
||||
"slug": "komodo-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Komodo",
|
||||
"description": "Build and deployment automation tool for managing Docker deployments, stacks, and builds across multiple servers. Features real-time container monitoring, batch operations, and a web-based management interface.",
|
||||
"tags": [
|
||||
"traefik",
|
||||
"deployment",
|
||||
"automation"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "komodo"
|
||||
},
|
||||
"draft": true,
|
||||
"version": {
|
||||
"name": "2.1.2",
|
||||
"source_dep_name": "ghcr.io/moghtech/komodo-core",
|
||||
"source_dep_version": "2.1.2"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "komodo",
|
||||
"config": {
|
||||
"placeholder": "komodo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_hostname",
|
||||
"type": "str",
|
||||
"title": "Container Hostname",
|
||||
"required": false,
|
||||
"default": "komodo",
|
||||
"config": {
|
||||
"placeholder": "komodo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_mode",
|
||||
"type": "enum",
|
||||
"title": "Network Mode",
|
||||
"required": false,
|
||||
"default": "bridge",
|
||||
"config": {
|
||||
"options": [
|
||||
"bridge",
|
||||
"macvlan",
|
||||
"host"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_ipv4_address",
|
||||
"type": "str",
|
||||
"title": "IPv4 Address",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "192.0.2.10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_external",
|
||||
"type": "bool",
|
||||
"title": "External Network",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "volume_mode",
|
||||
"type": "enum",
|
||||
"title": "Volume Mode",
|
||||
"required": false,
|
||||
"default": "local",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"mount",
|
||||
"nfs"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_options",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Options",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "rw,nolock,soft"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_mount_path",
|
||||
"type": "str",
|
||||
"title": "Volume Mount Path",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=mount"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/path/to/storage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_server",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Server",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "192.0.2.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_path",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Path",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/path/to/export"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_subnet",
|
||||
"type": "str",
|
||||
"title": "Subnet",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "192.0.2.0/24"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_name",
|
||||
"type": "str",
|
||||
"title": "Network Name",
|
||||
"required": false,
|
||||
"default": "komodo_network",
|
||||
"config": {
|
||||
"placeholder": "komodo_network"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_parent_interface",
|
||||
"type": "str",
|
||||
"title": "Parent Interface",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "eth0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_gateway",
|
||||
"type": "str",
|
||||
"title": "Gateway",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "192.0.2.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Entrypoint",
|
||||
"required": true,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "komodo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "TLS Entrypoint",
|
||||
"required": true,
|
||||
"default": "websecure",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 9120,
|
||||
"needs": [
|
||||
"traefik_enabled=false",
|
||||
"network_mode=bridge"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "9120"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Resource Limits",
|
||||
"name": "resources",
|
||||
"toggle": "resources_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "resources_enabled",
|
||||
"type": "bool",
|
||||
"title": "Resources Enabled",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "resources_cpu_limit",
|
||||
"type": "str",
|
||||
"title": "Resources Cpu Limit",
|
||||
"required": true,
|
||||
"default": 1,
|
||||
"config": {
|
||||
"placeholder": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resources_cpu_reservation",
|
||||
"type": "str",
|
||||
"title": "Resources Cpu Reservation",
|
||||
"required": true,
|
||||
"default": 0.25,
|
||||
"config": {
|
||||
"placeholder": "0.25"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resources_memory_limit",
|
||||
"type": "str",
|
||||
"title": "Resources Memory Limit",
|
||||
"required": true,
|
||||
"default": "1G",
|
||||
"config": {
|
||||
"placeholder": "1G"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resources_memory_reservation",
|
||||
"type": "str",
|
||||
"title": "Resources Memory Reservation",
|
||||
"required": true,
|
||||
"default": "512M",
|
||||
"config": {
|
||||
"placeholder": "512M"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Environment Variables",
|
||||
"name": "environment",
|
||||
"toggle": "environment_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "environment_enabled",
|
||||
"type": "bool",
|
||||
"title": "Environment",
|
||||
"required": false,
|
||||
"default": true,
|
||||
"description": "Configure environment variables (required)"
|
||||
},
|
||||
{
|
||||
"name": "environment_database_address",
|
||||
"type": "str",
|
||||
"title": "Database Address",
|
||||
"required": false,
|
||||
"default": "mongodb://database:27017",
|
||||
"description": "Database connection address (MongoDB or FerretDB)",
|
||||
"needs": [
|
||||
"environment_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "mongodb://database:27017"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "environment_database_name",
|
||||
"type": "str",
|
||||
"title": "Database name",
|
||||
"required": false,
|
||||
"default": "komodo",
|
||||
"needs": [
|
||||
"environment_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "komodo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "environment_database_username",
|
||||
"type": "str",
|
||||
"title": "DB User",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Database username (optional)",
|
||||
"needs": [
|
||||
"environment_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "komodo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "environment_database_password",
|
||||
"type": "secret",
|
||||
"title": "DB Password",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Database password (optional)",
|
||||
"needs": [
|
||||
"environment_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "environment_jwt_secret",
|
||||
"type": "secret",
|
||||
"title": "JWT Secret",
|
||||
"required": false,
|
||||
"description": "JWT secret for authentication (auto-generated if empty)",
|
||||
"needs": [
|
||||
"environment_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"autogenerated": {
|
||||
"length": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "environment_log_level",
|
||||
"type": "enum",
|
||||
"title": "Log level",
|
||||
"required": false,
|
||||
"default": "info",
|
||||
"needs": [
|
||||
"environment_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
services:
|
||||
<%- if queue_enabled and not queue_redis_external -%>
|
||||
redis:
|
||||
image: redis:8-alpine
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
<%- if network_mode == 'bridge' -%>
|
||||
networks:
|
||||
- << network_name >>
|
||||
<%- else -%>
|
||||
network_mode: << network_mode >>
|
||||
<%- endif -%>
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
|
||||
<%- endif -%>
|
||||
<< service_name >>:
|
||||
image: n8nio/n8n:2.20.0
|
||||
environment:
|
||||
- N8N_LOG_LEVEL=<< container_loglevel >>
|
||||
- GENERIC_TIMEZONE=<< container_timezone >>
|
||||
- TZ=<< container_timezone >>
|
||||
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
|
||||
- N8N_RUNNERS_ENABLED=true
|
||||
<%- if traefik_enabled -%>
|
||||
- N8N_HOST=<< traefik_host >>.<< traefik_domain >>
|
||||
<%- if traefik_tls_enabled -%>
|
||||
- N8N_PROTOCOL=https
|
||||
- N8N_EDITOR_BASE_URL=https://<< traefik_host >>.<< traefik_domain >>
|
||||
<%- else -%>
|
||||
- N8N_PROTOCOL=http
|
||||
- N8N_EDITOR_BASE_URL=http://<< traefik_host >>.<< traefik_domain >>
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
- NODE_ENV=production
|
||||
<%- if database_enabled -%>
|
||||
<%- if database_type == 'postgres' -%>
|
||||
- DB_TYPE=postgresdb
|
||||
- DB_POSTGRESDB_HOST=<< database_host >>
|
||||
- DB_POSTGRESDB_PORT=<< database_port >>
|
||||
- DB_POSTGRESDB_DATABASE=<< database_name >>
|
||||
- DB_POSTGRESDB_USER=<< database_user >>
|
||||
- DB_POSTGRESDB_PASSWORD_FILE=/run/secrets/<< database_password_secret_name >>
|
||||
<%- elif database_type == 'mysql' -%>
|
||||
- DB_TYPE=mysqldb
|
||||
- DB_MYSQLDB_HOST=<< database_host >>
|
||||
- DB_MYSQLDB_PORT=<< database_port >>
|
||||
- DB_MYSQLDB_DATABASE=<< database_name >>
|
||||
- DB_MYSQLDB_USER=<< database_user >>
|
||||
- DB_MYSQLDB_PASSWORD_FILE=/run/secrets/<< database_password_secret_name >>
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
- N8N_ENCRYPTION_KEY_FILE=/run/secrets/<< encryption_key_secret_name >>
|
||||
<%- if webhook_url -%>
|
||||
- WEBHOOK_URL=<< webhook_url >>
|
||||
<%- endif -%>
|
||||
- N8N_PROXY_HOPS=<< proxy_hops >>
|
||||
<%- if metrics_enabled -%>
|
||||
- N8N_METRICS=true
|
||||
<%- if metrics_detailed -%>
|
||||
- N8N_METRICS_INCLUDE_WORKFLOW_ID_LABELS=true
|
||||
- N8N_METRICS_INCLUDE_NODE_TYPE_LABEL=true
|
||||
- N8N_METRICS_INCLUDE_API_ENDPOINTS=true
|
||||
- N8N_METRICS_INCLUDE_API_STATUS_CODE_LABELS=true
|
||||
- N8N_METRICS_INCLUDE_CREDENTIAL_TYPE_LABEL=true
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
- EXECUTIONS_DATA_SAVE_ON_ERROR=<< execution_save_on_error >>
|
||||
- EXECUTIONS_DATA_SAVE_ON_SUCCESS=<< execution_save_on_success >>
|
||||
<%- if queue_enabled -%>
|
||||
- EXECUTIONS_MODE=queue
|
||||
- QUEUE_BULL_REDIS_HOST=<< queue_redis_host >>
|
||||
- QUEUE_BULL_REDIS_PORT=<< queue_redis_port >>
|
||||
- QUEUE_HEALTH_CHECK_ACTIVE=true
|
||||
<%- if metrics_enabled -%>
|
||||
- N8N_METRICS_INCLUDE_QUEUE_METRICS=true
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- data:/home/node/.n8n
|
||||
<%- if network_mode == 'bridge' -%>
|
||||
networks:
|
||||
<%- if traefik_enabled -%>
|
||||
- << traefik_network >>
|
||||
<%- endif -%>
|
||||
- << network_name >>
|
||||
<%- else -%>
|
||||
network_mode: << network_mode >>
|
||||
<%- endif -%>
|
||||
<%- if not traefik_enabled and network_mode == 'bridge' -%>
|
||||
ports:
|
||||
- target: 5678
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif -%>
|
||||
<%- if queue_enabled and not queue_redis_external -%>
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
<%- endif -%>
|
||||
<%- if traefik_enabled -%>
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
<%- if network_mode == 'bridge' -%>
|
||||
- traefik.docker.network=<< traefik_network >>
|
||||
<%- endif -%>
|
||||
<%- if traefik_webhook_host -%>
|
||||
- traefik.http.routers.<< service_name >>.rule=Host(`<< traefik_host >>.<< traefik_domain >>`) || Host(`<< traefik_webhook_host >>`)
|
||||
<%- else -%>
|
||||
- traefik.http.routers.<< service_name >>.rule=Host(`<< traefik_host >>.<< traefik_domain >>`)
|
||||
<%- endif -%>
|
||||
<%- if traefik_tls_enabled -%>
|
||||
- traefik.http.routers.<< service_name >>.entrypoints=<< traefik_tls_entrypoint >>
|
||||
- traefik.http.routers.<< service_name >>.tls=true
|
||||
- traefik.http.routers.<< service_name >>.tls.certresolver=<< traefik_tls_certresolver >>
|
||||
<%- else -%>
|
||||
- traefik.http.routers.<< service_name >>.entrypoints=<< traefik_entrypoint >>
|
||||
<%- endif -%>
|
||||
- traefik.http.services.<< service_name >>-web.loadbalancer.server.port=5678
|
||||
- traefik.http.routers.<< service_name >>.service=<< service_name >>-web
|
||||
<%- endif -%>
|
||||
deploy:
|
||||
replicas: << swarm_replicas >>
|
||||
<%- if swarm_placement_host -%>
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
<%- endif -%>
|
||||
<%- if traefik_enabled -%>
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=<< traefik_network >>
|
||||
<%- if traefik_webhook_host -%>
|
||||
- traefik.http.routers.<< service_name >>.rule=Host(`<< traefik_host >>.<< traefik_domain >>`) || Host(`<< traefik_webhook_host >>`)
|
||||
<%- else -%>
|
||||
- traefik.http.routers.<< service_name >>.rule=Host(`<< traefik_host >>.<< traefik_domain >>`)
|
||||
<%- endif -%>
|
||||
<%- if traefik_tls_enabled -%>
|
||||
- traefik.http.routers.<< service_name >>.entrypoints=<< traefik_tls_entrypoint >>
|
||||
- traefik.http.routers.<< service_name >>.tls=true
|
||||
- traefik.http.routers.<< service_name >>.tls.certresolver=<< traefik_tls_certresolver >>
|
||||
<%- else -%>
|
||||
- traefik.http.routers.<< service_name >>.entrypoints=<< traefik_entrypoint >>
|
||||
<%- endif -%>
|
||||
- traefik.http.services.<< service_name >>-web.loadbalancer.server.port=5678
|
||||
- traefik.http.routers.<< service_name >>.service=<< service_name >>-web
|
||||
<%- endif -%>
|
||||
secrets:
|
||||
- << encryption_key_secret_name >>
|
||||
<%- if database_enabled -%>
|
||||
- << database_password_secret_name >>
|
||||
<%- endif -%>
|
||||
<%- if queue_enabled and queue_embedded_worker -%>
|
||||
|
||||
<< service_name >>-worker:
|
||||
image: n8nio/n8n:2.20.0
|
||||
command: worker
|
||||
environment:
|
||||
- N8N_LOG_LEVEL=<< container_loglevel >>
|
||||
- GENERIC_TIMEZONE=<< container_timezone >>
|
||||
- TZ=<< container_timezone >>
|
||||
<%- if database_enabled -%>
|
||||
<%- if database_type == 'postgres' -%>
|
||||
- DB_TYPE=postgresdb
|
||||
- DB_POSTGRESDB_HOST=<< database_host >>
|
||||
- DB_POSTGRESDB_PORT=<< database_port >>
|
||||
- DB_POSTGRESDB_DATABASE=<< database_name >>
|
||||
- DB_POSTGRESDB_USER=<< database_user >>
|
||||
- DB_POSTGRESDB_PASSWORD_FILE=/run/secrets/<< database_password_secret_name >>
|
||||
<%- elif database_type == 'mysql' -%>
|
||||
- DB_TYPE=mysqldb
|
||||
- DB_MYSQLDB_HOST=<< database_host >>
|
||||
- DB_MYSQLDB_PORT=<< database_port >>
|
||||
- DB_MYSQLDB_DATABASE=<< database_name >>
|
||||
- DB_MYSQLDB_USER=<< database_user >>
|
||||
- DB_MYSQLDB_PASSWORD_FILE=/run/secrets/<< database_password_secret_name >>
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
- N8N_ENCRYPTION_KEY_FILE=/run/secrets/<< encryption_key_secret_name >>
|
||||
- EXECUTIONS_MODE=queue
|
||||
- QUEUE_BULL_REDIS_HOST=<< queue_redis_host >>
|
||||
- QUEUE_BULL_REDIS_PORT=<< queue_redis_port >>
|
||||
- QUEUE_HEALTH_CHECK_ACTIVE=true
|
||||
<%- if metrics_enabled -%>
|
||||
- N8N_METRICS=true
|
||||
<%- if metrics_detailed -%>
|
||||
- N8N_METRICS_INCLUDE_WORKFLOW_ID_LABELS=true
|
||||
- N8N_METRICS_INCLUDE_NODE_TYPE_LABEL=true
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- data:/home/node/.n8n
|
||||
<%- if network_mode == 'bridge' -%>
|
||||
networks:
|
||||
- << network_name >>
|
||||
<%- else -%>
|
||||
network_mode: << network_mode >>
|
||||
<%- endif -%>
|
||||
<%- if not queue_redis_external -%>
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
<%- endif -%>
|
||||
deploy:
|
||||
replicas: 1
|
||||
<%- if swarm_placement_host -%>
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
<%- endif -%>
|
||||
secrets:
|
||||
- << encryption_key_secret_name >>
|
||||
<%- if database_enabled -%>
|
||||
- << database_password_secret_name >>
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
|
||||
volumes:
|
||||
data:
|
||||
driver: local
|
||||
<%- if queue_enabled and not queue_redis_external -%>
|
||||
redis_data:
|
||||
driver: local
|
||||
<%- endif -%>
|
||||
|
||||
<%- if network_mode == 'bridge' -%>
|
||||
networks:
|
||||
<< network_name >>:
|
||||
<%- if network_external -%>
|
||||
external: true
|
||||
<%- else -%>
|
||||
driver: overlay
|
||||
attachable: true
|
||||
<%- endif -%>
|
||||
<%- if traefik_enabled -%>
|
||||
<< traefik_network >>:
|
||||
<%- if traefik_network_external -%>
|
||||
external: true
|
||||
<%- else -%>
|
||||
driver: overlay
|
||||
attachable: true
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
<%- endif -%>
|
||||
|
||||
secrets:
|
||||
<< encryption_key_secret_name >>:
|
||||
external: true
|
||||
<%- if database_enabled -%>
|
||||
<< database_password_secret_name >>:
|
||||
external: true
|
||||
<%- endif -%>
|
||||
@@ -0,0 +1,562 @@
|
||||
{
|
||||
"slug": "n8n-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "N8N",
|
||||
"description": "Source-available workflow automation tool that connects apps and services to automate tasks through a visual drag-and-drop node editor.",
|
||||
"tags": [
|
||||
"traefik",
|
||||
"database"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "n8n"
|
||||
},
|
||||
"draft": true,
|
||||
"version": {
|
||||
"name": "2.20.0",
|
||||
"source_dep_name": "n8nio/n8n",
|
||||
"source_dep_version": "2.20.0"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "n8n",
|
||||
"config": {
|
||||
"placeholder": "n8n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": false,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_loglevel",
|
||||
"type": "enum",
|
||||
"title": "Log Level",
|
||||
"required": false,
|
||||
"config": {
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Tls Entrypoint",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_password_secret_name",
|
||||
"type": "str",
|
||||
"title": "DB Password Secret",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "n8n-db-password"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "encryption_key_secret_name",
|
||||
"type": "str",
|
||||
"title": "Encryption Key Secret",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "n8n-encryption-key"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Entrypoint",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=false"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Queue Mode",
|
||||
"name": "queue",
|
||||
"toggle": "queue_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "queue_enabled",
|
||||
"type": "bool",
|
||||
"title": "Queue Mode",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Enable queue mode (requires Redis)"
|
||||
},
|
||||
{
|
||||
"name": "queue_redis_external",
|
||||
"type": "bool",
|
||||
"title": "External Redis",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"needs": [
|
||||
"queue_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "queue_redis_host",
|
||||
"type": "str",
|
||||
"title": "Redis host",
|
||||
"required": false,
|
||||
"default": "redis",
|
||||
"needs": [
|
||||
"queue_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "redis"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "queue_redis_port",
|
||||
"type": "int",
|
||||
"title": "Redis port",
|
||||
"required": false,
|
||||
"default": 6379,
|
||||
"needs": [
|
||||
"queue_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "6379"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "queue_embedded_worker",
|
||||
"type": "bool",
|
||||
"title": "Embedded Worker",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Include embedded worker in this deployment",
|
||||
"needs": [
|
||||
"queue_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Database",
|
||||
"name": "database",
|
||||
"toggle": "database_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "database_enabled",
|
||||
"type": "bool",
|
||||
"title": "External Database",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "database_type",
|
||||
"type": "enum",
|
||||
"title": "Database type",
|
||||
"required": false,
|
||||
"default": "postgres",
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"options": [
|
||||
"postgres",
|
||||
"mysql"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_host",
|
||||
"type": "str",
|
||||
"title": "Database host",
|
||||
"required": false,
|
||||
"default": "postgres",
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "postgres"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_port",
|
||||
"type": "int",
|
||||
"title": "Database port",
|
||||
"required": false,
|
||||
"default": 5432,
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "5432"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_name",
|
||||
"type": "str",
|
||||
"title": "Database name",
|
||||
"required": false,
|
||||
"default": "n8n",
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "n8n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_user",
|
||||
"type": "str",
|
||||
"title": "Database username",
|
||||
"required": false,
|
||||
"default": "n8n",
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "n8n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_password",
|
||||
"type": "secret",
|
||||
"title": "Database password",
|
||||
"required": false,
|
||||
"needs": [
|
||||
"database_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Security",
|
||||
"name": "security",
|
||||
"items": [
|
||||
{
|
||||
"name": "encryption_key",
|
||||
"type": "secret",
|
||||
"title": "Encryption Key",
|
||||
"required": false,
|
||||
"config": {
|
||||
"autogenerated": {
|
||||
"length": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "proxy_hops",
|
||||
"type": "int",
|
||||
"title": "Proxy Hops",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"description": "Number of proxy hops (X-Forwarded-For)",
|
||||
"config": {
|
||||
"placeholder": "1",
|
||||
"unit": "hops"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Webhooks",
|
||||
"name": "webhooks",
|
||||
"items": [
|
||||
{
|
||||
"name": "webhook_url",
|
||||
"type": "str",
|
||||
"title": "Webhook base URL",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Base URL used for webhooks.",
|
||||
"config": {
|
||||
"placeholder": "https://n8n.home.arpa/"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Metrics",
|
||||
"name": "metrics",
|
||||
"toggle": "metrics_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "metrics_enabled",
|
||||
"type": "bool",
|
||||
"title": "Prometheus",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "metrics_detailed",
|
||||
"type": "bool",
|
||||
"title": "Detailed Metrics",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Include detailed metrics (workflows, nodes, API endpoints)",
|
||||
"needs": [
|
||||
"metrics_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Execution Settings",
|
||||
"name": "execution",
|
||||
"items": [
|
||||
{
|
||||
"name": "execution_save_on_error",
|
||||
"type": "enum",
|
||||
"title": "Save on Error",
|
||||
"required": false,
|
||||
"default": "all",
|
||||
"description": "Save execution data on error",
|
||||
"config": {
|
||||
"options": [
|
||||
"all",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "execution_save_on_success",
|
||||
"type": "enum",
|
||||
"title": "Save on Success",
|
||||
"required": false,
|
||||
"default": "none",
|
||||
"description": "Save execution data on success",
|
||||
"config": {
|
||||
"options": [
|
||||
"all",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Network",
|
||||
"name": "network",
|
||||
"items": [
|
||||
{
|
||||
"name": "network_mode",
|
||||
"type": "enum",
|
||||
"title": "Network Mode",
|
||||
"required": false,
|
||||
"default": "bridge",
|
||||
"config": {
|
||||
"options": [
|
||||
"bridge",
|
||||
"host"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_name",
|
||||
"type": "str",
|
||||
"title": "Network Name",
|
||||
"required": false,
|
||||
"default": "n8n_network",
|
||||
"config": {
|
||||
"placeholder": "n8n_network"
|
||||
},
|
||||
"needs": [
|
||||
"network_mode=bridge"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "network_external",
|
||||
"type": "bool",
|
||||
"title": "External Network",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"needs": [
|
||||
"network_mode=bridge"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik Enabled",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"needs": [
|
||||
"network_mode=bridge"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "n8n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_webhook_host",
|
||||
"type": "str",
|
||||
"title": "Webhook Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Separate hostname for webhooks (optional)",
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "hooks.n8n.home.arpa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Traefik network name",
|
||||
"required": false,
|
||||
"default": "traefik",
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network_external",
|
||||
"type": "bool",
|
||||
"title": "External Traefik Network",
|
||||
"required": false,
|
||||
"default": true,
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "External HTTP port",
|
||||
"required": false,
|
||||
"default": 5678,
|
||||
"needs": [
|
||||
"traefik_enabled=false",
|
||||
"network_mode=bridge"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "5678"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Swarm",
|
||||
"name": "swarm",
|
||||
"items": [
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 20,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Target hostname for placement constraint",
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
services:
|
||||
<< service_name >>-app:
|
||||
image: docker.io/library/nextcloud:33.0.3-apache
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
|
||||
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
|
||||
- REDIS_HOST=<< service_name >>-redis
|
||||
<%- if database_type == 'mysql' %>
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- MYSQL_DATABASE=<< database_name >>
|
||||
- MYSQL_USER=<< database_user >>
|
||||
- MYSQL_HOST=<< service_name >>-db
|
||||
<%- elif database_type == 'postgres' %>
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=<< database_name >>
|
||||
- POSTGRES_USER=<< database_user >>
|
||||
- POSTGRES_HOST=<< service_name >>-db
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
- NEXTCLOUD_TRUSTED_DOMAINS=<< traefik_host >>.<< traefik_domain >>
|
||||
- OVERWRITEHOST=<< traefik_host >>.<< traefik_domain >>
|
||||
<%- if traefik_tls_enabled %>
|
||||
- OVERWRITEPROTOCOL=https
|
||||
<%- else %>
|
||||
- OVERWRITEPROTOCOL=http
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- if not traefik_enabled %>
|
||||
ports:
|
||||
- target: 80
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif %>
|
||||
volumes:
|
||||
- nextcloud-data:/var/www/html
|
||||
networks:
|
||||
- << service_name >>-backend
|
||||
<%- if traefik_enabled %>
|
||||
- << traefik_network >>
|
||||
<%- endif %>
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
- << service_name >>-redis
|
||||
deploy:
|
||||
replicas: << swarm_replicas >>
|
||||
<%- 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 >>-web-http.rule=Host(`<< traefik_host >>.<< traefik_domain >>`)
|
||||
- traefik.http.routers.<< service_name >>-web-http.entrypoints=<< traefik_entrypoint >>
|
||||
- traefik.http.routers.<< service_name >>-web-http.service=<< service_name >>-web
|
||||
<%- if traefik_tls_enabled %>
|
||||
- traefik.http.routers.<< service_name >>-web-https.rule=Host(`<< traefik_host >>.<< traefik_domain >>`)
|
||||
- traefik.http.routers.<< service_name >>-web-https.entrypoints=<< traefik_tls_entrypoint >>
|
||||
- traefik.http.routers.<< service_name >>-web-https.tls=true
|
||||
- traefik.http.routers.<< service_name >>-web-https.tls.certresolver=<< traefik_tls_certresolver >>
|
||||
- traefik.http.routers.<< service_name >>-web-https.service=<< service_name >>-web
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
|
||||
<< service_name >>-cron:
|
||||
image: docker.io/library/nextcloud:33.0.3-apache
|
||||
entrypoint: /cron.sh
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
- REDIS_HOST=<< service_name >>-redis
|
||||
<%- if database_type == 'mysql' %>
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- MYSQL_DATABASE=<< database_name >>
|
||||
- MYSQL_USER=<< database_user >>
|
||||
- MYSQL_HOST=<< service_name >>-db
|
||||
<%- elif database_type == 'postgres' %>
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=<< database_name >>
|
||||
- POSTGRES_USER=<< database_user >>
|
||||
- POSTGRES_HOST=<< service_name >>-db
|
||||
<%- endif %>
|
||||
volumes:
|
||||
- nextcloud-data:/var/www/html
|
||||
networks:
|
||||
- << service_name >>-backend
|
||||
depends_on:
|
||||
- << service_name >>-app
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
<< service_name >>-redis:
|
||||
image: docker.io/library/redis:8-alpine
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- nextcloud-redis:/data
|
||||
networks:
|
||||
- << service_name >>-backend
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
<< service_name >>-db:
|
||||
<%- if database_type == 'mysql' %>
|
||||
# See compatibility matrix for Nextcloud 31
|
||||
# https://docs.nextcloud.com/server/31/admin_manual/installation/system_requirements.html
|
||||
image: docker.io/library/mariadb:10.11.16
|
||||
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
- MYSQL_RANDOM_ROOT_PASSWORD=true
|
||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||
- MYSQL_DATABASE=<< database_name >>
|
||||
- MYSQL_USER=<< database_user >>
|
||||
volumes:
|
||||
- nextcloud-db:/var/lib/mysql
|
||||
networks:
|
||||
- << service_name >>-backend
|
||||
<%- elif database_type == 'postgres' %>
|
||||
image: docker.io/library/postgres:17.9
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
- POSTGRES_USER=<< database_user >>
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=<< database_name >>
|
||||
volumes:
|
||||
- nextcloud-db:/var/lib/postgresql/data
|
||||
networks:
|
||||
- << service_name >>-backend
|
||||
<%- endif %>
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
volumes:
|
||||
nextcloud-data:
|
||||
driver: local
|
||||
nextcloud-db:
|
||||
driver: local
|
||||
nextcloud-redis:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
<< service_name >>-backend:
|
||||
driver: overlay
|
||||
attachable: true
|
||||
<%- if traefik_enabled %>
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,239 @@
|
||||
{
|
||||
"slug": "nextcloud-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Nextcloud",
|
||||
"description": "Self-hosted file sync and share platform, similar to Dropbox, with built-in collaboration tools, calendar, contacts, and extensible app ecosystem.",
|
||||
"tags": [
|
||||
"traefik"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "nextcloud"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "33.0.3-apache",
|
||||
"source_dep_name": "docker.io/library/nextcloud",
|
||||
"source_dep_version": "33.0.3-apache"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Database",
|
||||
"name": "database",
|
||||
"items": [
|
||||
{
|
||||
"name": "database_type",
|
||||
"type": "enum",
|
||||
"title": "Database Type",
|
||||
"required": false,
|
||||
"default": "postgres",
|
||||
"config": {
|
||||
"options": [
|
||||
"postgres",
|
||||
"mysql"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "database_name",
|
||||
"type": "str",
|
||||
"title": "Database Name",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "database_user",
|
||||
"type": "str",
|
||||
"title": "Database User",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "database_password",
|
||||
"type": "secret",
|
||||
"title": "Database Password",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "nextcloud",
|
||||
"config": {
|
||||
"placeholder": "nextcloud"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Entrypoint",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Tls Entrypoint",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=true"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Swarm Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 80,
|
||||
"config": {
|
||||
"placeholder": "80"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=false"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Nextcloud",
|
||||
"name": "nextcloud",
|
||||
"items": [
|
||||
{
|
||||
"name": "admin_user",
|
||||
"type": "str",
|
||||
"title": "Nextcloud admin username",
|
||||
"required": false,
|
||||
"default": "admin",
|
||||
"config": {
|
||||
"placeholder": "admin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "secret",
|
||||
"title": "Nextcloud admin password",
|
||||
"required": false,
|
||||
"config": {
|
||||
"autogenerated": {
|
||||
"length": 32
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "nextcloud"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/library/nginx:1.30.0-alpine
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
<%- endif %>
|
||||
<%- if not traefik_enabled %>
|
||||
ports:
|
||||
- target: 80
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
- target: 443
|
||||
published: << ports_https >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif %>
|
||||
# volumes:
|
||||
# - ./config/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
# - ./data:/usr/share/nginx/html:ro
|
||||
deploy:
|
||||
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 %>
|
||||
<%- 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 >>-web-http.rule=Host(`<< traefik_host >>.<< traefik_domain >>`)
|
||||
- traefik.http.routers.<< service_name >>-web-http.entrypoints=<< traefik_entrypoint >>
|
||||
- traefik.http.routers.<< service_name >>-web-http.service=<< service_name >>-web
|
||||
<%- if traefik_tls_enabled %>
|
||||
- traefik.http.routers.<< service_name >>-web-https.rule=Host(`<< traefik_host >>.<< traefik_domain >>`)
|
||||
- traefik.http.routers.<< service_name >>-web-https.entrypoints=<< traefik_tls_entrypoint >>
|
||||
- traefik.http.routers.<< service_name >>-web-https.tls=true
|
||||
- traefik.http.routers.<< service_name >>-web-https.tls.certresolver=<< traefik_tls_certresolver >>
|
||||
- traefik.http.routers.<< service_name >>-web-https.service=<< service_name >>-web
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,9 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
access_log on;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
this is a test website...
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"slug": "nginx-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Nginx",
|
||||
"description": "High-performance web server, reverse proxy, and load balancer known for stability, low resource consumption, and simple configuration.",
|
||||
"tags": [
|
||||
"traefik"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "simple-icons",
|
||||
"id": "nginx"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "1.30.0-alpine",
|
||||
"source_dep_name": "docker.io/library/nginx",
|
||||
"source_dep_version": "1.30.0-alpine"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "nginx",
|
||||
"config": {
|
||||
"placeholder": "nginx"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Tls Entrypoint",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"description": "Number of replicas for Swarm mode",
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 20,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "The placement host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_mode",
|
||||
"type": "enum",
|
||||
"title": "The placement mode",
|
||||
"required": false,
|
||||
"default": "replicated",
|
||||
"description": "Placement mode for the service.",
|
||||
"config": {
|
||||
"options": [
|
||||
"replicated",
|
||||
"global"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 8080,
|
||||
"config": {
|
||||
"placeholder": "8080"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=false"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ports_https",
|
||||
"type": "int",
|
||||
"title": "HTTPS Port",
|
||||
"required": false,
|
||||
"default": 8443,
|
||||
"config": {
|
||||
"placeholder": "8443"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=false"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik Enabled",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": false,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "nginx"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Entrypoint",
|
||||
"required": false,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"name": "traefik-tls",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<< webpassword >>
|
||||
@@ -0,0 +1,157 @@
|
||||
---
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/pihole/pihole:2026.04.1
|
||||
|
||||
<%- if container_hostname %>
|
||||
hostname: << container_hostname >>
|
||||
<%- endif %>
|
||||
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
- PIHOLE_UID=<< user_uid >>
|
||||
- PIHOLE_GID=<< user_gid >>
|
||||
- WEBPASSWORD_FILE=<< service_name >>_webpassword
|
||||
<%- if network_mode == 'bridge' %>
|
||||
- FTLCONF_dns_listeningMode=all
|
||||
<%- endif %>
|
||||
|
||||
<%- if network_mode == 'host' %>
|
||||
network_mode: host
|
||||
<%- elif network_mode == 'bridge' or network_mode == 'macvlan' or traefik_enabled %>
|
||||
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 == '' or network_mode == 'bridge' or traefik_enabled %>
|
||||
ports:
|
||||
<%- if not traefik_enabled %>
|
||||
- target: 80
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
- target: 443
|
||||
published: << ports_https >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif %>
|
||||
- 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
|
||||
<%- endif %>
|
||||
|
||||
volumes:
|
||||
<%- if volume_mode == 'mount' %>
|
||||
- << volume_mount_path >>/dnsmasq:/etc/dnsmasq.d:rw
|
||||
- << volume_mount_path >>/pihole:/etc/pihole:rw
|
||||
<%- else %>
|
||||
- << service_name >>-dnsmasq:/etc/dnsmasq.d
|
||||
- << service_name >>-pihole:/etc/pihole
|
||||
<%- endif %>
|
||||
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_TIME
|
||||
|
||||
secrets:
|
||||
- << service_name >>_webpassword
|
||||
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
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=<< 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 %>
|
||||
|
||||
|
||||
secrets:
|
||||
<< service_name >>_webpassword:
|
||||
file: ./.env.secret.webpassword
|
||||
|
||||
|
||||
<%- if volume_mode == 'local' %>
|
||||
volumes:
|
||||
<< service_name >>-dnsmasq:
|
||||
driver: local
|
||||
<< service_name >>-pihole:
|
||||
driver: local
|
||||
<%- elif volume_mode == 'nfs' %>
|
||||
volumes:
|
||||
<< service_name >>-dnsmasq:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>/dnsmasq"
|
||||
<< service_name >>-pihole:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>/pihole"
|
||||
<%- endif %>
|
||||
|
||||
|
||||
<%- if network_mode == 'bridge' or network_mode == 'macvlan' or traefik_enabled %>
|
||||
networks:
|
||||
<%- if network_mode == 'bridge' or network_mode == 'macvlan' %>
|
||||
<< 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 >>
|
||||
<%- else %>
|
||||
driver: overlay
|
||||
attachable: true
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- if traefik_enabled %>
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,407 @@
|
||||
{
|
||||
"slug": "pihole-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Pihole",
|
||||
"description": "Network-wide DNS-based ad and tracker blocker that acts as a DNS sinkhole. Filters content at the DNS level for all devices on your network.",
|
||||
"tags": [
|
||||
"traefik",
|
||||
"network",
|
||||
"volume"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "pi-hole"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "2026.04.1",
|
||||
"source_dep_name": "docker.io/pihole/pihole",
|
||||
"source_dep_version": "2026.04.1"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "pihole",
|
||||
"config": {
|
||||
"placeholder": "pihole"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_hostname",
|
||||
"type": "str",
|
||||
"title": "Container Hostname",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "user_uid",
|
||||
"type": "int",
|
||||
"title": "User Uid",
|
||||
"required": false,
|
||||
"default": 1000,
|
||||
"config": {
|
||||
"placeholder": "1000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "user_gid",
|
||||
"type": "int",
|
||||
"title": "User Gid",
|
||||
"required": false,
|
||||
"default": 1000,
|
||||
"config": {
|
||||
"placeholder": "1000"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Admin Settings",
|
||||
"name": "admin-settings",
|
||||
"items": [
|
||||
{
|
||||
"name": "webpassword",
|
||||
"type": "secret",
|
||||
"title": "Admin Password",
|
||||
"required": false,
|
||||
"config": {
|
||||
"autogenerated": {
|
||||
"length": 32
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_dns",
|
||||
"type": "int",
|
||||
"title": "DNS Port",
|
||||
"required": true,
|
||||
"default": 53,
|
||||
"config": {
|
||||
"placeholder": "53"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 80,
|
||||
"config": {
|
||||
"placeholder": "80"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ports_https",
|
||||
"type": "int",
|
||||
"title": "HTTPS Port",
|
||||
"required": false,
|
||||
"default": 443,
|
||||
"config": {
|
||||
"placeholder": "443"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ports_ntp",
|
||||
"type": "int",
|
||||
"title": "External NTP port",
|
||||
"required": true,
|
||||
"default": 123,
|
||||
"config": {
|
||||
"placeholder": "123"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "pihole"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Entrypoint",
|
||||
"required": false,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Tls Entrypoint",
|
||||
"required": false,
|
||||
"default": "websecure",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Network",
|
||||
"name": "network",
|
||||
"items": [
|
||||
{
|
||||
"name": "network_mode",
|
||||
"type": "enum",
|
||||
"title": "Network Mode",
|
||||
"required": false,
|
||||
"default": "bridge",
|
||||
"config": {
|
||||
"options": [
|
||||
"bridge",
|
||||
"host",
|
||||
"macvlan"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_name",
|
||||
"type": "str",
|
||||
"title": "Network Name",
|
||||
"required": false,
|
||||
"default": "pihole_network",
|
||||
"config": {
|
||||
"placeholder": "pihole_network"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_ipv4_address",
|
||||
"type": "str",
|
||||
"title": "IPv4 Address",
|
||||
"required": true,
|
||||
"default": "IP_ADDRESS",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "IP_ADDRESS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_parent_interface",
|
||||
"type": "str",
|
||||
"title": "Parent Interface",
|
||||
"required": true,
|
||||
"default": "eth0",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "eth0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_subnet",
|
||||
"type": "str",
|
||||
"title": "Subnet",
|
||||
"required": true,
|
||||
"default": "IP_RANGE",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "IP_RANGE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_macvlan_gateway",
|
||||
"type": "str",
|
||||
"title": "Gateway",
|
||||
"required": true,
|
||||
"default": "GATEWAY",
|
||||
"needs": [
|
||||
"network_mode=macvlan"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "GATEWAY"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_external",
|
||||
"type": "bool",
|
||||
"title": "External Network",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Docker Swarm",
|
||||
"name": "swarm",
|
||||
"items": [
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Swarm Placement Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Volume",
|
||||
"name": "volume",
|
||||
"items": [
|
||||
{
|
||||
"name": "volume_mode",
|
||||
"type": "enum",
|
||||
"title": "Volume Mode",
|
||||
"required": true,
|
||||
"default": "local",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"mount",
|
||||
"nfs"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_mount_path",
|
||||
"type": "str",
|
||||
"title": "Volume Mount Path",
|
||||
"required": true,
|
||||
"default": "/data",
|
||||
"needs": [
|
||||
"volume_mode=mount"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/data"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_server",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Server",
|
||||
"required": true,
|
||||
"default": "NFS_SERVER",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "NFS_SERVER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_path",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Path",
|
||||
"required": true,
|
||||
"default": "/export",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/export"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_options",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Options",
|
||||
"required": true,
|
||||
"default": "rw,nolock,soft",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "rw,nolock,soft"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/portainer/portainer-ce:2.41.0-alpine
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
<%- endif %>
|
||||
ports:
|
||||
<%- if not traefik_enabled %>
|
||||
- "<< ports_http >>:9000"
|
||||
- "<< ports_https >>:9443"
|
||||
<%- endif %>
|
||||
- "<< ports_edge >>:8000"
|
||||
volumes:
|
||||
- /run/docker.sock:/var/run/docker.sock
|
||||
<%- if volume_mode == 'mount' %>
|
||||
- << volume_mount_path >>/data:/data
|
||||
<%- else %>
|
||||
- << service_name >>_data:/data
|
||||
<%- 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=9000
|
||||
- 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
|
||||
<%- elif volume_mode == 'nfs' %>
|
||||
volumes:
|
||||
<< 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 %>
|
||||
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,266 @@
|
||||
{
|
||||
"slug": "portainer",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Portainer",
|
||||
"description": "Web-based management UI for Docker and Kubernetes environments. Simplifies container, image, network, and volume management through an intuitive interface.",
|
||||
"tags": [
|
||||
"traefik",
|
||||
"volumes"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "portainer"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "2.41.0-alpine",
|
||||
"source_dep_name": "docker.io/portainer/portainer-ce",
|
||||
"source_dep_version": "2.41.0-alpine"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "portainer",
|
||||
"config": {
|
||||
"placeholder": "portainer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Target hostname for placement constraint",
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 9000,
|
||||
"config": {
|
||||
"placeholder": "9000"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=false"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ports_https",
|
||||
"type": "int",
|
||||
"title": "HTTPS Port",
|
||||
"required": false,
|
||||
"default": 9443,
|
||||
"config": {
|
||||
"placeholder": "9443"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=false"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ports_edge",
|
||||
"type": "int",
|
||||
"title": "Edge Port",
|
||||
"required": true,
|
||||
"default": 8000,
|
||||
"config": {
|
||||
"placeholder": "8000"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "portainer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Entrypoint",
|
||||
"required": false,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"name": "traefik-tls",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Tls Entrypoint",
|
||||
"required": false,
|
||||
"default": "websecure",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Volume",
|
||||
"name": "volume",
|
||||
"items": [
|
||||
{
|
||||
"name": "volume_mode",
|
||||
"type": "enum",
|
||||
"title": "Volume Mode",
|
||||
"required": true,
|
||||
"default": "local",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"mount",
|
||||
"nfs"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_mount_path",
|
||||
"type": "str",
|
||||
"title": "Volume Mount Path",
|
||||
"required": true,
|
||||
"default": "/data",
|
||||
"needs": [
|
||||
"volume_mode=mount"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/data"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_server",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Server",
|
||||
"required": true,
|
||||
"default": "NFS_SERVER",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "NFS_SERVER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_path",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Path",
|
||||
"required": true,
|
||||
"default": "/export",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/export"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_options",
|
||||
"type": "str",
|
||||
"title": "Volume Nfs Options",
|
||||
"required": true,
|
||||
"default": "rw,nolock,soft",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "rw,nolock,soft"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/library/postgres:18.3
|
||||
hostname: << container_hostname >>
|
||||
environment:
|
||||
- POSTGRES_INITDB_ARGS=<< postgres_initdb_args >>
|
||||
<%- if postgres_host_auth_method %>
|
||||
- POSTGRES_HOST_AUTH_METHOD=<< postgres_host_auth_method >>
|
||||
<%- endif %>
|
||||
- POSTGRES_USER=<< database_user >>
|
||||
- POSTGRES_PASSWORD=<< database_password >>
|
||||
- POSTGRES_DB=<< database_name >>
|
||||
- TZ=<< container_timezone >>
|
||||
<%- if network_mode == 'bridge' or network_mode == '' %>
|
||||
networks:
|
||||
<< network_name >>:
|
||||
<%- endif %>
|
||||
<%- if network_mode == 'bridge' or network_mode == '' %>
|
||||
ports:
|
||||
- target: 5432
|
||||
published: << ports_postgres >>
|
||||
protocol: tcp
|
||||
mode: host
|
||||
<%- endif %>
|
||||
volumes:
|
||||
<%- if volume_mode == 'mount' %>
|
||||
- << volume_mount_path >>:/var/lib/postgresql:rw
|
||||
<%- else %>
|
||||
- << service_name >>-data:/var/lib/postgresql
|
||||
<%- endif %>
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U << database_user >>"]
|
||||
start_period: 30s
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
<%- if swarm_placement_host %>
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
<%- endif %>
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
||||
<%- if volume_mode == 'local' %>
|
||||
volumes:
|
||||
<< service_name >>-data:
|
||||
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 >>"
|
||||
<%- endif %>
|
||||
|
||||
<%- if network_mode == 'bridge' or network_mode == '' %>
|
||||
networks:
|
||||
<< network_name >>:
|
||||
<%- if network_external %>
|
||||
external: true
|
||||
<%- else %>
|
||||
driver: overlay
|
||||
attachable: true
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,238 @@
|
||||
{
|
||||
"slug": "postgres-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "PostgreSQL",
|
||||
"description": "Powerful open-source object-relational database system with over 35 years of active development, known for reliability, feature robustness, and performance.",
|
||||
"tags": [],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "postgresql"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "18.3",
|
||||
"source_dep_name": "docker.io/library/postgres",
|
||||
"source_dep_version": "18.3"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "postgres",
|
||||
"config": {
|
||||
"placeholder": "postgres"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_hostname",
|
||||
"type": "str",
|
||||
"title": "Container Hostname",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "postgres_initdb_args",
|
||||
"type": "str",
|
||||
"title": "Postgres Initdb Args",
|
||||
"required": true,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "--data-checksums"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "postgres_host_auth_method",
|
||||
"type": "str",
|
||||
"title": "Host Auth",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "scram-sha-256"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "The placement host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_postgres",
|
||||
"type": "int",
|
||||
"title": "PostgreSQL port",
|
||||
"required": false,
|
||||
"default": 5432,
|
||||
"config": {
|
||||
"placeholder": "5432"
|
||||
},
|
||||
"needs": [
|
||||
"network_mode=bridge"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Network",
|
||||
"name": "network",
|
||||
"items": [
|
||||
{
|
||||
"name": "network_mode",
|
||||
"type": "enum",
|
||||
"title": "Network Mode",
|
||||
"required": false,
|
||||
"default": "bridge",
|
||||
"config": {
|
||||
"options": [
|
||||
"bridge",
|
||||
"host"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_name",
|
||||
"type": "str",
|
||||
"title": "Network Name",
|
||||
"required": false,
|
||||
"default": "postgres_network",
|
||||
"config": {
|
||||
"placeholder": "postgres_network"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "network_external",
|
||||
"type": "bool",
|
||||
"title": "External Network",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Volume",
|
||||
"name": "volume",
|
||||
"items": [
|
||||
{
|
||||
"name": "volume_mode",
|
||||
"type": "enum",
|
||||
"title": "Volume Mode",
|
||||
"required": false,
|
||||
"default": "local",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"mount",
|
||||
"nfs"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_mount_path",
|
||||
"type": "str",
|
||||
"title": "Bind Path",
|
||||
"required": false,
|
||||
"default": "/var/lib/postgresql/data",
|
||||
"config": {
|
||||
"placeholder": "/var/lib/postgresql/data"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=mount"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_server",
|
||||
"type": "str",
|
||||
"title": "NFS Server",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "192.0.2.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_path",
|
||||
"type": "str",
|
||||
"title": "NFS Path",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "/path/to/export"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_options",
|
||||
"type": "str",
|
||||
"title": "NFS Options",
|
||||
"required": false,
|
||||
"default": "rw",
|
||||
"config": {
|
||||
"placeholder": "rw"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Database",
|
||||
"name": "database",
|
||||
"items": [
|
||||
{
|
||||
"name": "database_name",
|
||||
"type": "str",
|
||||
"title": "Database Name",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "database_user",
|
||||
"type": "str",
|
||||
"title": "Database User",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "database_password",
|
||||
"type": "secret",
|
||||
"title": "Database password",
|
||||
"required": true,
|
||||
"config": {
|
||||
"autogenerated": {
|
||||
"length": 32
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/mend/renovate-ce:14.5.0-full
|
||||
hostname: << container_hostname >>
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
<%- endif %>
|
||||
<%- if not traefik_enabled %>
|
||||
ports:
|
||||
- "<< ports_http >>:8080"
|
||||
<%- endif %>
|
||||
environment:
|
||||
- MEND_RNV_ACCEPT_TOS=y
|
||||
- MEND_RNV_LICENSE_KEY=<< license_key >>
|
||||
- MEND_RNV_PLATFORM=<< renovate_platform >>
|
||||
- MEND_RNV_ENDPOINT=<< renovate_endpoint >>
|
||||
- MEND_RNV_GITLAB_PAT=<< git_token >>
|
||||
- MEND_RNV_WEBHOOK_SECRET=<< webhook_secret >>
|
||||
- MEND_RNV_SERVER_PORT=8080
|
||||
- RENOVATE_AUTODISCOVER=<< renovate_autodiscover | lower >>
|
||||
<%- if container_timezone %>
|
||||
- TZ=<< container_timezone >>
|
||||
<%- endif %>
|
||||
<%- if container_loglevel %>
|
||||
- LOG_LEVEL=<< container_loglevel >>
|
||||
<%- endif %>
|
||||
deploy:
|
||||
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 %>
|
||||
<%- if traefik_enabled %>
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=<< traefik_network >>
|
||||
- traefik.http.services.<< service_name >>.loadbalancer.server.port=8080
|
||||
- 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.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 %>
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
<%- if traefik_enabled %>
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
external: true
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,301 @@
|
||||
{
|
||||
"slug": "renovate-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Renovate",
|
||||
"description": "Self-hosted Mend Renovate CE worker for GitLab that scans repositories and opens dependency update merge requests.",
|
||||
"tags": [
|
||||
"traefik"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "mend-renovate"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "14.5.0-full",
|
||||
"source_dep_name": "ghcr.io/mend/renovate-ce",
|
||||
"source_dep_version": "14.5.0-full"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "renovate",
|
||||
"config": {
|
||||
"placeholder": "renovate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_hostname",
|
||||
"type": "str",
|
||||
"title": "Container Hostname",
|
||||
"required": false,
|
||||
"default": "renovate",
|
||||
"config": {
|
||||
"placeholder": "renovate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": false,
|
||||
"default": "UTC",
|
||||
"config": {
|
||||
"placeholder": "UTC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_loglevel",
|
||||
"type": "enum",
|
||||
"title": "Log Level",
|
||||
"required": false,
|
||||
"config": {
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "str",
|
||||
"title": "Cert Resolver",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "cloudflare"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Tls Entrypoint",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"config": {
|
||||
"placeholder": "websecure"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true",
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Renovate Settings",
|
||||
"name": "renovate-settings",
|
||||
"items": [
|
||||
{
|
||||
"name": "renovate_platform",
|
||||
"type": "enum",
|
||||
"title": "Git Platform",
|
||||
"required": false,
|
||||
"default": "gitlab",
|
||||
"config": {
|
||||
"options": [
|
||||
"gitlab"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "renovate_endpoint",
|
||||
"type": "str",
|
||||
"title": "Git Endpoint",
|
||||
"required": false,
|
||||
"default": "https://gitlab.com/api/v4/",
|
||||
"config": {
|
||||
"placeholder": "https://gitlab.com/api/v4/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "renovate_autodiscover",
|
||||
"type": "bool",
|
||||
"title": "Auto-discover repositories",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Authentication",
|
||||
"name": "authentication",
|
||||
"items": [
|
||||
{
|
||||
"name": "git_token",
|
||||
"type": "secret",
|
||||
"title": "Git Token",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "license_key",
|
||||
"type": "secret",
|
||||
"title": "License Key",
|
||||
"required": true,
|
||||
"description": "Mend Renovate CE License Key"
|
||||
},
|
||||
{
|
||||
"name": "webhook_secret",
|
||||
"type": "secret",
|
||||
"title": "Webhook Secret",
|
||||
"required": false,
|
||||
"default": "renovate",
|
||||
"description": "Webhook secret for platform integration",
|
||||
"config": {
|
||||
"placeholder": "renovate"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Ports",
|
||||
"name": "ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": false,
|
||||
"default": 8080,
|
||||
"config": {
|
||||
"placeholder": "8080"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik",
|
||||
"name": "traefik",
|
||||
"toggle": "traefik_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_enabled",
|
||||
"type": "bool",
|
||||
"title": "Traefik Enabled",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": false,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_host",
|
||||
"type": "str",
|
||||
"title": "Host",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "renovate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_domain",
|
||||
"type": "str",
|
||||
"title": "Domain",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "home.arpa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_entrypoint",
|
||||
"type": "str",
|
||||
"title": "Traefik Entrypoint",
|
||||
"required": false,
|
||||
"default": "web",
|
||||
"config": {
|
||||
"placeholder": "web"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Traefik TLS",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"name": "traefik-tls",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Swarm",
|
||||
"name": "swarm",
|
||||
"items": [
|
||||
{
|
||||
"name": "swarm_placement_mode",
|
||||
"type": "enum",
|
||||
"title": "Swarm Placement Mode",
|
||||
"required": false,
|
||||
"default": "replicated",
|
||||
"config": {
|
||||
"options": [
|
||||
"replicated",
|
||||
"global"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Swarm Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
],
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Swarm Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<%- if traefik_tls_certresolver == 'route53' %>
|
||||
[default]
|
||||
aws_access_key_id = << traefik_tls_acme_token >>
|
||||
aws_secret_access_key = << traefik_tls_acme_secret_key >>
|
||||
<%- endif %>
|
||||
@@ -0,0 +1 @@
|
||||
<%- if traefik_tls_acme_consumer_key %><< traefik_tls_acme_consumer_key >><%- endif %>
|
||||
@@ -0,0 +1 @@
|
||||
<%- if traefik_tls_acme_token and traefik_tls_certresolver != 'route53' %><< traefik_tls_acme_token >><%- endif %>
|
||||
@@ -0,0 +1 @@
|
||||
<%- if traefik_tls_acme_secret_key and traefik_tls_certresolver != 'route53' %><< traefik_tls_acme_secret_key >><%- endif %>
|
||||
@@ -0,0 +1,189 @@
|
||||
---
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/library/traefik:v3.6.15
|
||||
command:
|
||||
- "--global.checkNewVersion=false"
|
||||
- "--global.sendAnonymousUsage=false"
|
||||
- "--log.level=<< container_loglevel >>"
|
||||
- "--ping=true"
|
||||
- "--ping.entryPoint=ping"
|
||||
<%- if accesslog_enabled %>
|
||||
- "--accesslog=true"
|
||||
<%- endif %>
|
||||
<%- if dashboard_enabled %>
|
||||
- "--api.dashboard=true"
|
||||
- "--api.insecure=true"
|
||||
<%- endif %>
|
||||
<%- if prometheus_enabled %>
|
||||
- "--metrics.prometheus=true"
|
||||
- "--metrics.prometheus.entryPoint=metrics"
|
||||
- "--metrics.prometheus.addRoutersLabels=true"
|
||||
<%- endif %>
|
||||
- "--entrypoints.ping.address=:8082"
|
||||
<%- if prometheus_enabled %>
|
||||
- "--entrypoints.metrics.address=:9090"
|
||||
<%- endif %>
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.web.http.encodedCharacters.allowEncodedSlash=true"
|
||||
<%- if traefik_tls_enabled and traefik_tls_redirect %>
|
||||
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
|
||||
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
|
||||
<%- endif %>
|
||||
<%- if traefik_tls_enabled %>
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--entrypoints.websecure.http.encodedCharacters.allowEncodedSlash=true"
|
||||
- "--certificatesresolvers.<< traefik_tls_certresolver >>.acme.email=<< traefik_tls_acme_email >>"
|
||||
- "--certificatesresolvers.<< traefik_tls_certresolver >>.acme.caServer=https://acme-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.<< traefik_tls_certresolver >>.acme.storage=/var/traefik/certs/acme.json"
|
||||
- "--certificatesresolvers.<< traefik_tls_certresolver >>.acme.dnsChallenge.provider=<< traefik_tls_certresolver >>"
|
||||
- "--certificatesresolvers.<< traefik_tls_certresolver >>.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
|
||||
- "--tls.options.default.minVersion=<< traefik_tls_min_version >>"
|
||||
<%- endif %>
|
||||
<%- if traefik_tls_secure_ciphers %>
|
||||
- "--tls.options.default.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 %>
|
||||
<%- if traefik_tls_skipverify %>
|
||||
- "--serversTransport.insecureSkipVerify=true"
|
||||
<%- endif %>
|
||||
- "--providers.swarm.endpoint=unix:///var/run/docker.sock"
|
||||
- "--providers.swarm.exposedByDefault=false"
|
||||
- "--providers.swarm.network=<< traefik_network >>"
|
||||
ports:
|
||||
- target: 80
|
||||
published: << ports_http >>
|
||||
protocol: tcp
|
||||
mode: << ports_publish_mode >>
|
||||
- target: 443
|
||||
published: << ports_https >>
|
||||
protocol: tcp
|
||||
mode: << ports_publish_mode >>
|
||||
<%- if dashboard_enabled %>
|
||||
- target: 8080
|
||||
published: << ports_dashboard >>
|
||||
protocol: tcp
|
||||
mode: << ports_publish_mode >>
|
||||
<%- endif %>
|
||||
<%- if prometheus_enabled %>
|
||||
- target: 9090
|
||||
published: << ports_metrics >>
|
||||
protocol: tcp
|
||||
mode: << ports_publish_mode >>
|
||||
<%- endif %>
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
<%- if volume_mode == 'mount' %>
|
||||
- << volume_mount_path >>:/var/traefik/certs:rw
|
||||
<%- elif volume_mode == 'local' or volume_mode == 'nfs' %>
|
||||
- << service_name >>_certs:/var/traefik/certs:rw
|
||||
<%- endif %>
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
<%- if traefik_tls_enabled %>
|
||||
<%- if traefik_tls_certresolver == 'cloudflare' %>
|
||||
- CF_DNS_API_TOKEN_FILE=/run/secrets/<< service_name >>_token
|
||||
<%- elif traefik_tls_certresolver == 'porkbun' %>
|
||||
- PORKBUN_API_KEY_FILE=/run/secrets/<< service_name >>_token
|
||||
- PORKBUN_SECRET_API_KEY_FILE=/run/secrets/<< service_name >>_token_key
|
||||
<%- elif traefik_tls_certresolver == 'route53' %>
|
||||
- AWS_SHARED_CREDENTIALS_FILE=/run/secrets/<< service_name >>_aws_credentials
|
||||
- AWS_REGION=<< traefik_tls_acme_region >>
|
||||
<%- elif traefik_tls_certresolver == 'digitalocean' %>
|
||||
- DO_AUTH_TOKEN_FILE=/run/secrets/<< service_name >>_token
|
||||
<%- elif traefik_tls_certresolver == 'godaddy' %>
|
||||
- GODADDY_API_KEY_FILE=/run/secrets/<< service_name >>_token
|
||||
- GODADDY_API_SECRET_FILE=/run/secrets/<< service_name >>_token_key
|
||||
<%- elif traefik_tls_certresolver == 'azure' %>
|
||||
- AZURE_CLIENT_ID_FILE=/run/secrets/<< service_name >>_token
|
||||
- AZURE_CLIENT_SECRET_FILE=/run/secrets/<< service_name >>_token_key
|
||||
- AZURE_TENANT_ID=<< traefik_tls_acme_tenant_id >>
|
||||
- AZURE_SUBSCRIPTION_ID=<< traefik_tls_acme_subscription_id >>
|
||||
- AZURE_RESOURCE_GROUP=<< traefik_tls_acme_resource_group >>
|
||||
<%- elif traefik_tls_certresolver == 'namecheap' %>
|
||||
- NAMECHEAP_API_KEY_FILE=/run/secrets/<< service_name >>_token
|
||||
- NAMECHEAP_API_USER=<< traefik_tls_acme_username >>
|
||||
<%- elif traefik_tls_certresolver == 'ovh' %>
|
||||
- OVH_ENDPOINT=<< traefik_tls_acme_endpoint >>
|
||||
- OVH_APPLICATION_KEY_FILE=/run/secrets/<< service_name >>_token
|
||||
- OVH_APPLICATION_SECRET_FILE=/run/secrets/<< service_name >>_token_key
|
||||
- OVH_CONSUMER_KEY_FILE=/run/secrets/<< service_name >>_consumer_key
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:8082/ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
networks:
|
||||
- << traefik_network >>
|
||||
<%- if traefik_tls_enabled %>
|
||||
secrets:
|
||||
<%- if traefik_tls_certresolver == 'route53' %>
|
||||
- << service_name >>_aws_credentials
|
||||
<%- else %>
|
||||
- << service_name >>_token
|
||||
<%- if traefik_tls_certresolver == 'azure' or traefik_tls_certresolver == 'godaddy' or traefik_tls_certresolver == 'ovh' or traefik_tls_certresolver == 'porkbun' %>
|
||||
- << service_name >>_token_key
|
||||
<%- endif %>
|
||||
<%- if traefik_tls_certresolver == 'ovh' %>
|
||||
- << service_name >>_consumer_key
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
deploy:
|
||||
mode: << swarm_placement_mode >>
|
||||
<%- if swarm_placement_mode == 'replicated' %>
|
||||
replicas: << swarm_replicas >>
|
||||
<%- endif %>
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
<%- if swarm_placement_host %>
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
<%- endif %>
|
||||
restart_policy:
|
||||
condition: any
|
||||
|
||||
<%- if traefik_tls_enabled %>
|
||||
secrets:
|
||||
<%- if traefik_tls_certresolver == 'route53' %>
|
||||
<< service_name >>_aws_credentials:
|
||||
file: ./.env.secret.aws_credentials
|
||||
<%- else %>
|
||||
<< service_name >>_token:
|
||||
file: ./.env.secret.token
|
||||
<%- if traefik_tls_certresolver == 'azure' or traefik_tls_certresolver == 'godaddy' or traefik_tls_certresolver == 'ovh' or traefik_tls_certresolver == 'porkbun' %>
|
||||
<< service_name >>_token_key:
|
||||
file: ./.env.secret.token_key
|
||||
<%- endif %>
|
||||
<%- if traefik_tls_certresolver == 'ovh' %>
|
||||
<< service_name >>_consumer_key:
|
||||
file: ./.env.secret.consumer_key
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
<%- endif %>
|
||||
|
||||
networks:
|
||||
<< traefik_network >>:
|
||||
<%- if traefik_network_external %>
|
||||
external: true
|
||||
<%- else %>
|
||||
driver: overlay
|
||||
attachable: true
|
||||
name: << traefik_network >>
|
||||
<%- endif %>
|
||||
|
||||
<%- if volume_mode == 'local' %>
|
||||
volumes:
|
||||
<< service_name >>_certs:
|
||||
driver: local
|
||||
<%- elif volume_mode == 'nfs' %>
|
||||
volumes:
|
||||
<< service_name >>_certs:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=<< volume_nfs_server >>,nfsvers=4,<< volume_nfs_options >>
|
||||
device: ":<< volume_nfs_path >>"
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,513 @@
|
||||
{
|
||||
"slug": "traefik-swarm",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Traefik",
|
||||
"description": "Swarm-only Traefik reverse proxy and load balancer with Docker Swarm service discovery, optional Let's Encrypt DNS challenge TLS, dashboard, and metrics support. For Traefik-managed ACME certificates, run a single replica; Traefik OSS ACME storage is not safe for active-active writes from multiple instances. References: Traefik Swarm provider https://doc.traefik.io/traefik/providers/swarm/ and Traefik ACME storage notes https://doc.traefik.io/traefik/https/acme/.",
|
||||
"tags": [
|
||||
"reverse-proxy",
|
||||
"traefik"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "devicon",
|
||||
"id": "traefikproxy",
|
||||
"color": "sky"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "v3.6.15",
|
||||
"source_dep_name": "docker.io/library/traefik",
|
||||
"source_dep_version": "v3.6.15"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"name": "general",
|
||||
"title": "General",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "traefik",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": true,
|
||||
"default": "UTC",
|
||||
"config": {
|
||||
"placeholder": "UTC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_loglevel",
|
||||
"type": "enum",
|
||||
"title": "Log Level",
|
||||
"required": false,
|
||||
"default": "info",
|
||||
"description": "Traefik log level.",
|
||||
"config": {
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ports",
|
||||
"title": "Ports",
|
||||
"items": [
|
||||
{
|
||||
"name": "ports_http",
|
||||
"type": "int",
|
||||
"title": "HTTP Port",
|
||||
"required": true,
|
||||
"default": 80,
|
||||
"description": "Published port for the web entrypoint.",
|
||||
"config": {
|
||||
"placeholder": "80"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ports_https",
|
||||
"type": "int",
|
||||
"title": "HTTPS Port",
|
||||
"required": true,
|
||||
"default": 443,
|
||||
"description": "Published port for the websecure entrypoint.",
|
||||
"config": {
|
||||
"placeholder": "443"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ports_dashboard",
|
||||
"type": "int",
|
||||
"title": "Dashboard Port",
|
||||
"required": true,
|
||||
"default": 8080,
|
||||
"description": "Published port for the insecure dashboard/API.",
|
||||
"config": {
|
||||
"placeholder": "8080"
|
||||
},
|
||||
"needs": [
|
||||
"dashboard_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ports_metrics",
|
||||
"type": "int",
|
||||
"title": "Metrics Port",
|
||||
"required": true,
|
||||
"default": 9090,
|
||||
"description": "Published port for Prometheus metrics.",
|
||||
"config": {
|
||||
"placeholder": "9090"
|
||||
},
|
||||
"needs": [
|
||||
"prometheus_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ports_publish_mode",
|
||||
"type": "enum",
|
||||
"title": "Publish Mode",
|
||||
"required": true,
|
||||
"default": "host",
|
||||
"description": "Swarm port publishing mode. Host mode is recommended for edge proxies.",
|
||||
"config": {
|
||||
"options": [
|
||||
"host",
|
||||
"ingress"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik",
|
||||
"title": "Traefik",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_network",
|
||||
"type": "str",
|
||||
"title": "Network",
|
||||
"required": true,
|
||||
"default": "traefik",
|
||||
"description": "Overlay network Traefik uses to reach routed Swarm services.",
|
||||
"config": {
|
||||
"placeholder": "traefik"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "traefik_network_external",
|
||||
"type": "bool",
|
||||
"title": "External Network",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "accesslog_enabled",
|
||||
"type": "bool",
|
||||
"title": "Access Log",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "dashboard_enabled",
|
||||
"type": "bool",
|
||||
"title": "Dashboard",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Enable the insecure Traefik dashboard/API. Do not expose this in production."
|
||||
},
|
||||
{
|
||||
"name": "prometheus_enabled",
|
||||
"type": "bool",
|
||||
"title": "Prometheus",
|
||||
"required": false,
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik-tls",
|
||||
"title": "Traefik TLS",
|
||||
"toggle": "traefik_tls_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "traefik_tls_enabled",
|
||||
"type": "bool",
|
||||
"title": "TLS",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_certresolver",
|
||||
"type": "enum",
|
||||
"title": "DNS Provider",
|
||||
"required": true,
|
||||
"default": "cloudflare",
|
||||
"description": "ACME DNS challenge provider.",
|
||||
"config": {
|
||||
"options": [
|
||||
"cloudflare",
|
||||
"porkbun",
|
||||
"godaddy",
|
||||
"digitalocean",
|
||||
"route53",
|
||||
"azure",
|
||||
"namecheap",
|
||||
"ovh"
|
||||
]
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_email",
|
||||
"type": "str",
|
||||
"title": "ACME Email",
|
||||
"required": true,
|
||||
"description": "Email address used for ACME registration.",
|
||||
"config": {
|
||||
"placeholder": "admin@example.com"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_token",
|
||||
"type": "secret",
|
||||
"title": "API Token / ID",
|
||||
"required": true,
|
||||
"description": "DNS provider API token or access/client ID. Stored as a Swarm secret.",
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=azure,cloudflare,digitalocean,godaddy,namecheap,ovh,porkbun,route53"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_secret_key",
|
||||
"type": "secret",
|
||||
"title": "Secret Key",
|
||||
"required": true,
|
||||
"description": "DNS provider secret key. Stored as a Swarm secret.",
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=azure,godaddy,ovh,porkbun,route53"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_consumer_key",
|
||||
"type": "secret",
|
||||
"title": "Consumer Key",
|
||||
"required": true,
|
||||
"description": "OVH consumer key. Stored as a Swarm secret.",
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=ovh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_username",
|
||||
"type": "str",
|
||||
"title": "Username",
|
||||
"required": true,
|
||||
"description": "Namecheap API username.",
|
||||
"config": {
|
||||
"placeholder": "namecheap-user"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=namecheap"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_region",
|
||||
"type": "str",
|
||||
"title": "AWS Region",
|
||||
"required": true,
|
||||
"default": "us-east-1",
|
||||
"description": "AWS region for Route53.",
|
||||
"config": {
|
||||
"placeholder": "us-east-1"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=route53"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_endpoint",
|
||||
"type": "str",
|
||||
"title": "OVH Endpoint",
|
||||
"required": false,
|
||||
"default": "ovh-eu",
|
||||
"description": "OVH API endpoint.",
|
||||
"config": {
|
||||
"placeholder": "ovh-eu"
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=ovh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_tenant_id",
|
||||
"type": "str",
|
||||
"title": "Azure Tenant ID",
|
||||
"required": true,
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=azure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_subscription_id",
|
||||
"type": "str",
|
||||
"title": "Azure Subscription ID",
|
||||
"required": true,
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=azure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_acme_resource_group",
|
||||
"type": "str",
|
||||
"title": "Azure Resource Group",
|
||||
"required": true,
|
||||
"description": "Azure DNS resource group.",
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true",
|
||||
"traefik_tls_certresolver=azure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_redirect",
|
||||
"type": "bool",
|
||||
"title": "HTTP Redirect",
|
||||
"required": false,
|
||||
"default": true,
|
||||
"description": "Redirect all HTTP traffic to HTTPS.",
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_min_version",
|
||||
"type": "enum",
|
||||
"title": "Minimum TLS Version",
|
||||
"required": false,
|
||||
"default": "VersionTLS12",
|
||||
"config": {
|
||||
"options": [
|
||||
"VersionTLS12",
|
||||
"VersionTLS13"
|
||||
]
|
||||
},
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_secure_ciphers",
|
||||
"type": "bool",
|
||||
"title": "Strict Ciphers",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "traefik_tls_skipverify",
|
||||
"type": "bool",
|
||||
"title": "Skip Backend Verify",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "Skip TLS verification for backend servers.",
|
||||
"needs": [
|
||||
"traefik_tls_enabled=true"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "swarm",
|
||||
"title": "Docker Swarm",
|
||||
"items": [
|
||||
{
|
||||
"name": "swarm_placement_mode",
|
||||
"type": "enum",
|
||||
"title": "Placement Mode",
|
||||
"required": true,
|
||||
"default": "replicated",
|
||||
"description": "Swarm deployment mode. Traefik is constrained to manager nodes because the Swarm provider reads service state through the local Docker socket. Use replicated with one replica when Traefik manages ACME certificates. Global mode runs one task per eligible manager node, but Traefik OSS cannot safely coordinate active-active ACME writes to a shared acme.json. See https://doc.traefik.io/traefik/providers/swarm/ and https://doc.traefik.io/traefik/https/acme/.",
|
||||
"config": {
|
||||
"options": [
|
||||
"global",
|
||||
"replicated"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"description": "Number of replicas when placement mode is replicated. Keep this at 1 when Traefik manages ACME certificates; use multiple replicas only with external/static certificate management.",
|
||||
"config": {
|
||||
"placeholder": "1",
|
||||
"unit": "replicas",
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"step": 1
|
||||
},
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Optional manager-node hostname constraint. The selected node must be a Swarm manager.",
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "volume",
|
||||
"title": "Volume",
|
||||
"items": [
|
||||
{
|
||||
"name": "volume_mode",
|
||||
"type": "enum",
|
||||
"title": "Volume Mode",
|
||||
"required": true,
|
||||
"default": "local",
|
||||
"description": "Storage mode for ACME certificate data. Shared storage allows file access from multiple nodes, but it does not make Traefik-managed ACME safe with multiple active Traefik writers. Use one Traefik replica for ACME, or use external/static certificate management for multi-replica Traefik. See https://doc.traefik.io/traefik/https/acme/.",
|
||||
"config": {
|
||||
"options": [
|
||||
"local",
|
||||
"mount",
|
||||
"nfs"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "volume_mount_path",
|
||||
"type": "str",
|
||||
"title": "Bind Mount Path",
|
||||
"required": true,
|
||||
"default": "/data/traefik/certs",
|
||||
"description": "Host path used for certificate storage.",
|
||||
"config": {
|
||||
"placeholder": "/data/traefik/certs"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=mount"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_server",
|
||||
"type": "str",
|
||||
"title": "NFS Server",
|
||||
"required": true,
|
||||
"default": "NFS_SERVER",
|
||||
"config": {
|
||||
"placeholder": "NFS_SERVER"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_path",
|
||||
"type": "str",
|
||||
"title": "NFS Path",
|
||||
"required": true,
|
||||
"default": "/export/traefik/certs",
|
||||
"config": {
|
||||
"placeholder": "/export/traefik/certs"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "volume_nfs_options",
|
||||
"type": "str",
|
||||
"title": "NFS Options",
|
||||
"required": true,
|
||||
"default": "rw,nolock,soft",
|
||||
"config": {
|
||||
"placeholder": "rw,nolock,soft"
|
||||
},
|
||||
"needs": [
|
||||
"volume_mode=nfs"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
services:
|
||||
<< service_name >>:
|
||||
image: docker.io/twingate/connector:1.88.0
|
||||
hostname: << container_hostname >>
|
||||
environment:
|
||||
- TZ=<< container_timezone >>
|
||||
- TWINGATE_NETWORK=<< twingate_network >>
|
||||
- TWINGATE_ACCESS_TOKEN=<< twingate_access_token >>
|
||||
- TWINGATE_REFRESH_TOKEN=<< twingate_refresh_token >>
|
||||
- TWINGATE_LOG_ANALYTICS=v2
|
||||
- TWINGATE_LOG_LEVEL=<< twingate_log_level >>
|
||||
<%- if twingate_dns %>
|
||||
- TWINGATE_DNS=<< twingate_dns >>
|
||||
<%- endif %>
|
||||
sysctls:
|
||||
net.ipv4.ping_group_range: "0 2147483647"
|
||||
deploy:
|
||||
<%- if swarm_placement_mode == 'replicated' %>
|
||||
mode: replicated
|
||||
replicas: << swarm_replicas >>
|
||||
<%- if swarm_placement_host %>
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == << swarm_placement_host >>
|
||||
<%- endif %>
|
||||
<%- else %>
|
||||
mode: global
|
||||
<%- endif %>
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
<%- if resources_enabled %>
|
||||
resources:
|
||||
limits:
|
||||
cpus: '<< resources_cpu_limit >>'
|
||||
memory: << resources_memory_limit >>
|
||||
reservations:
|
||||
cpus: '<< resources_cpu_reservation >>'
|
||||
memory: << resources_memory_reservation >>
|
||||
<%- endif %>
|
||||
@@ -0,0 +1,206 @@
|
||||
{
|
||||
"slug": "twingate-connector",
|
||||
"kind": "swarm",
|
||||
"metadata": {
|
||||
"name": "Twingate_Connector",
|
||||
"description": "Lightweight agent that establishes secure zero-trust connections between your private network and the Twingate service, allowing authorized users to access internal resources without a VPN.",
|
||||
"tags": [],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "twingate"
|
||||
},
|
||||
"draft": false,
|
||||
"version": {
|
||||
"name": "1.88.0",
|
||||
"source_dep_name": "docker.io/twingate/connector",
|
||||
"source_dep_version": "1.88.0"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "General",
|
||||
"name": "general",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Service Name",
|
||||
"required": false,
|
||||
"default": "twingate",
|
||||
"config": {
|
||||
"placeholder": "twingate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_hostname",
|
||||
"type": "str",
|
||||
"title": "Container Hostname",
|
||||
"required": false,
|
||||
"default": "twingate-connector",
|
||||
"config": {
|
||||
"placeholder": "twingate-connector"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "container_timezone",
|
||||
"type": "str",
|
||||
"title": "Container Timezone",
|
||||
"required": true,
|
||||
"config": {
|
||||
"placeholder": "Europe/Berlin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_mode",
|
||||
"type": "enum",
|
||||
"title": "Swarm Placement Mode",
|
||||
"required": true,
|
||||
"default": "replicated",
|
||||
"config": {
|
||||
"options": [
|
||||
"replicated",
|
||||
"global"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swarm_replicas",
|
||||
"type": "int",
|
||||
"title": "Swarm Replicas",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"step": 1,
|
||||
"placeholder": "1",
|
||||
"unit": "replicas"
|
||||
},
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "swarm_placement_host",
|
||||
"type": "str",
|
||||
"title": "Swarm Placement Host",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"needs": [
|
||||
"swarm_placement_mode=replicated"
|
||||
],
|
||||
"config": {
|
||||
"placeholder": "swarm-node-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Twingate Configuration",
|
||||
"name": "twingate",
|
||||
"items": [
|
||||
{
|
||||
"name": "twingate_network",
|
||||
"type": "str",
|
||||
"title": "Network Name",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "twingate_access_token",
|
||||
"type": "secret",
|
||||
"title": "Access Token",
|
||||
"required": true,
|
||||
"description": "Connector access token from Twingate."
|
||||
},
|
||||
{
|
||||
"name": "twingate_refresh_token",
|
||||
"type": "secret",
|
||||
"title": "Refresh Token",
|
||||
"required": true,
|
||||
"description": "Connector refresh token from Twingate."
|
||||
},
|
||||
{
|
||||
"name": "twingate_log_level",
|
||||
"type": "int",
|
||||
"title": "Log Level",
|
||||
"required": false,
|
||||
"default": 1,
|
||||
"description": "Log level (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)",
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 4,
|
||||
"step": 1,
|
||||
"placeholder": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "twingate_dns",
|
||||
"type": "str",
|
||||
"title": "DNS Server",
|
||||
"required": false,
|
||||
"default": "",
|
||||
"description": "Local DNS server IP (optional, leave empty to use default)",
|
||||
"config": {
|
||||
"placeholder": "192.0.2.53"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Resource Limits",
|
||||
"name": "resources",
|
||||
"toggle": "resources_enabled",
|
||||
"items": [
|
||||
{
|
||||
"name": "resources_enabled",
|
||||
"type": "bool",
|
||||
"title": "Resources Enabled",
|
||||
"required": false,
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "resources_cpu_limit",
|
||||
"type": "str",
|
||||
"title": "Resources Cpu Limit",
|
||||
"required": true,
|
||||
"default": 1,
|
||||
"config": {
|
||||
"placeholder": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resources_cpu_reservation",
|
||||
"type": "str",
|
||||
"title": "Resources Cpu Reservation",
|
||||
"required": true,
|
||||
"default": 0.25,
|
||||
"config": {
|
||||
"placeholder": "0.25"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resources_memory_limit",
|
||||
"type": "str",
|
||||
"title": "Resources Memory Limit",
|
||||
"required": true,
|
||||
"default": "1G",
|
||||
"config": {
|
||||
"placeholder": "1G"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resources_memory_reservation",
|
||||
"type": "str",
|
||||
"title": "Resources Memory Reservation",
|
||||
"required": true,
|
||||
"default": "512M",
|
||||
"config": {
|
||||
"placeholder": "512M"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user