ℹ️ For all that are currently using the
suitdeer/syncthing4swarm-docker image, please switch tosyncthing4swarm/syncthing4swarm-docker image. (My pull request repository was merged into the main repository 😄)
Update the
syncthing4swarm.yamlfile inside theSwarmPilotfolder.Replace the the line
image: suitdeer/syncthing4swarm:latestwith
image: syncthing4swarm/syncthing4swarm:latestUpdate the syncthing4swarm docker service:
cd SwarmPilot sudo docker stack deploy --resolve-image=always -c syncthing4swarm.yaml syncthing4swarm
For all that are new (after 07.03.2026) you do not need to do anything 😄
Deploy your Swarm cluster with one script — automatically
SwarmPilot helps you to deploy a high available docker swarm cluster from 1 to 9 nodes with the following components:
Docker is a technology that bundles a software program with all the other software that application needs to run, such as an operating system, third-party software libraries, etc. Software bundled like this is called a container.
Used for managing a virtual IP address for all cluster nodes
Ensures persistent volume synchronization
It provides an intuitive graphical user interface and extensive API for managing resources such as containers, images, and networks via a
Web interface: https://<virtual_ip>:9443
Used for a central reverse proxy and SSL termination for other docker services on this cluster.
Web Interface: http://<virtual_ip>:81
Web Interface: https://<virtual_ip>/dashboard/ Dashboard authentication: Basic Auth (username and password are requested during installation)
- Ubuntu Server installed on all nodes
- SSH access on all nodes
- Root access on all nodes
- Additional unused IP address for keepalived (virtual IP of the docker swarm cluster)
sshpassmust be installed on all nodes:sudo apt install sshpass
Run only on one node:
# Clone the repository
git clone https://github.com/SuitDeer/SwarmPilot.git
cd SwarmPilot
# Deploy to Swarm
sudo chmod +x swarmpilot.sh
sudo ./swarmpilot.shsetup-demo-video.mp4
Please use the reverse_proxy overlay network for your stacks if you need ssl termination via Nginx Proxy Manager or Traefik.
Example:
If your stack containers need persistent volumes please first create the root directory in the syced syncthind directory:
sudo mkdir /var/syncthing/data/<FOLDER_NAME>Instructions for setting up a Service with Nginx Proxy Manager
services:
webserver:
image: nginxdemos/hello
volumes:
- /var/syncthing/data/<FOLDER_NAME>:/var/www/html
networks:
- reverse_proxy
ports:
- 8082:80
networks:
reverse_proxy:
external: trueSince both the Nginx Proxy Manager container and your new service stack are connected to the same overlay network reverse_proxy, you should reference containers in Nginx Proxy Manager by their service names.
services:
webserver: <---- This is the service-name of the container
...............
Instructions for setting up a Service with Traefik
Please edit app.example.com to your liking
services:
webserver:
image: nginxdemos/hello
volumes:
- /var/syncthing/data/<FOLDER_NAME>:/var/www/html
networks:
- reverse_proxy
ports:
- 8082:80
deploy:
labels:
# Enable Traefik routing for this service
- traefik.enable=true
# Define the router
- traefik.http.routers.webapp.rule=Host(`app.example.com`)
- traefik.http.routers.webapp.entrypoints=websecure
- traefik.http.routers.webapp.tls.certresolver=letsencrypt
# Define the service (required for Swarm)
- traefik.http.services.webapp.loadbalancer.server.port=8082
# Health check for load balancing
- traefik.http.services.webapp.loadbalancer.healthcheck.path=/
- traefik.http.services.webapp.loadbalancer.healthcheck.interval=10s
networks:
reverse_proxy:
external: truecd SwarmPilot
sudo docker stack deploy --resolve-image=always -c syncthing4swarm.yaml syncthing4swarmcd SwarmPilot
sudo docker stack deploy --resolve-image=always -c portainer.yaml portainercd SwarmPilot
sudo docker stack deploy --resolve-image=always -c nginxproxymanager.yaml nginxproxymanagercd SwarmPilot
sudo docker stack deploy --resolve-image=always -c traefik.yaml traefikThe swarmpilot.sh script automates the entire cluster setup process through the following steps:
- Local Node IP: The IP address of the node running the script
- Node Count: Number of nodes in the cluster (1-9, including the local node)
- Remote Node Information: For each remote node, the script collects:
- IP address
- Username
- Password (validated for length 8-128 characters)
- Verifies
sshpassis installed on the local node - Checks
sshpassinstallation on all remote nodes - Ensures SSH connectivity to all nodes
- Updates package lists
- Installs required dependencies (ca-certificates, curl)
- Adds Docker GPG key and repository
- Installs Docker Engine, CLI, containerd.io, and Docker plugins
- Enables and starts Docker service
- Validates installation with hello-world test
- Initializes Docker Swarm on the local node with the specified advertise address
- Retrieves the manager join token
- Joins all remote nodes to the swarm using the join token
- Prompts for virtual IP address for the cluster
- Calculates priorities for each node (local node: 255, remote nodes: 254, 253, etc.)
- Installs and configures keepalived on all nodes:
- Detects network interface automatically
- Creates keepalived configuration with unicast peers
- Sets state (MASTER for local node, BACKUP for remote nodes)
- Enables and starts keepalived service
- Configures automatic failover between nodes
- For clusters with more than 1 node: creates
/var/syncthing/dataon all nodes - On the local node: creates
syncthing4swarm.yamland deploys the Syncthing4Swarm stack - On remote nodes: prepares the required syncthing directory
- For single-node clusters: skips Syncthing4Swarm setup
- Waits until Syncthing4Swarm containers report healthy on all nodes
- Creates portainer data directory
- Creates portainer.yaml configuration file
- Deploys Portainer stack
- Exposes Portainer on ports 9443 (HTTPS) and 8000 (HTTP)
- Publishes the Portainer dashboard at
https://<virtual_ip>:9443
- Prompts the user to choose
TraefikorNginx Proxy Manager - If
Traefikis selected, the script:- Prompts for a valid email address for Let's Encrypt ACME
- Prompts for dashboard username and password
- Generates a password hash for Traefik Basic Auth
- Creates the shared overlay network
reverse_proxy(if needed) - Creates
traefik.yamland deploys the Traefik stack - Exposes ports 80 (HTTP) and 443 (HTTPS)
- Publishes the Traefik dashboard at
https://<virtual_ip>/dashboard/(protected by Basic Auth)
- If
Nginx Proxy Manageris selected, the script:- Creates required Nginx Proxy Manager data directories
- Creates the shared overlay network
reverse_proxy(if needed) - Creates
nginxproxymanager.yamland deploys the Nginx Proxy Manager stack - Exposes ports 80 (HTTP), 81 (Web UI), and 443 (HTTPS)
- Publishes the Nginx Proxy Manager dashboard at
http://<virtual_ip>:81
