Forked from kwonghung-YIP/backup-docker-secrets.sh
Last active
September 8, 2026 23:59
-
-
Save dargmuesli/3d5176e96b7174f9a5539c798155f9e7 to your computer and use it in GitHub Desktop.
Shell script for export all secrets defined in docker swarm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Dumps every swarm secret into a tar by mounting them all into a throwaway service. | |
| # The tar holds plaintext secrets: encrypt it before moving it off this host. | |
| set -euo pipefail | |
| umask 077 | |
| service_name="backup-all-secrets" | |
| out_dir="${1:-.}" | |
| tar_file="backup_$(date +"%Y%m%d-%H%M%S").tar" | |
| mapfile -t secret_list < <(docker secret ls --format '{{ .Name }}') | |
| # Docker only creates /run/secrets once it mounts something there, so an empty list would break the tar. | |
| (( ${#secret_list[@]} )) || { echo "no secrets to back up" >&2; exit 0; } | |
| # Runs on every exit path so an interrupted run never leaves a container holding all secrets. | |
| cleanup() { docker service rm "$service_name" >/dev/null 2>&1 || true; } | |
| trap cleanup EXIT | |
| # node.id is exact, unlike node.hostname, which matches whatever name the node used when it joined the swarm. | |
| node_id=$(docker info --format '{{ .Swarm.NodeID }}') | |
| args=(--name "$service_name" --constraint "node.id==$node_id" --restart-condition none) | |
| for secret in "${secret_list[@]}"; do | |
| args+=(--secret "$secret") | |
| done | |
| docker service create "${args[@]}" nginx >/dev/null | |
| container_id=$(docker ps --filter "label=com.docker.swarm.service.name=$service_name" \ | |
| --filter status=running --format '{{ .ID }}' | head -n1) | |
| [[ -n $container_id ]] || { echo "backup task never started" >&2; exit 1; } | |
| mkdir -p "$out_dir" | |
| docker exec -w /usr/local "$container_id" sh -c "tar -cf '$tar_file' -C /run/secrets ." | |
| docker cp "$container_id:/usr/local/$tar_file" "$out_dir/" | |
| # /run/secrets carries only name and value, so labels and driver settings are captured separately. | |
| docker secret inspect "${secret_list[@]}" > "$out_dir/${tar_file%.tar}.metadata.json" | |
| # docker cp preserves the container-side mode, so tighten it here rather than relying on umask. | |
| chmod 600 "$out_dir/$tar_file" "$out_dir/${tar_file%.tar}.metadata.json" | |
| echo "$out_dir/$tar_file" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment