Skip to content

Instantly share code, notes, and snippets.

@Wonno
Last active September 24, 2025 17:42
Show Gist options
  • Select an option

  • Save Wonno/2b9f4229bf08f9cbf52f083d83683564 to your computer and use it in GitHub Desktop.

Select an option

Save Wonno/2b9f4229bf08f9cbf52f083d83683564 to your computer and use it in GitHub Desktop.
Portainer: Stack creation via API and local compose.yml and stack.env
#!/usr/bin/env bash
# Create Stack in Portainer using API
#
# - compose.yml
# - stack.env
set -euo pipefail
which curl || (echo "Missing 'curl'"; exit 1)
which jq || (echo "Missing 'jq'"; exit 1)
which jo || (echo "Missing 'jo'"; exit 1)
# read values from config file
if [[ -e portainer.config ]] ; then
source portainer.config
fi
if [[ -z "${PORTAINER_USER-}" ]]; then
read -rp "Portainer-User: " PORTAINER_USER
echo
fi
if [[ -z "${PORTAINER_PASSWORD-}" ]]; then
read -srp "Portainer-Password: " PORTAINER_PASSWORD
echo
fi
if [[ -z "${PORTAINER_URL-}" ]]; then
read -rp "Portainer-URL: " PORTAINER_URL
echo
fi
if [[ -z "${PORTAINER_ENDPOINTNAME-}" ]]; then
read -rp "Endpoint-Name: " PORTAINER_ENDPOINTNAME
echo
fi
if [[ -z "${PORTAINER_STACKNAME-}" ]]; then
read -rp "Stack-Name: " PORTAINER_STACKNAME
echo
fi
# Get Bearer Token
PORTAINER_TOKEN=$(curl --silent --fail --show-error \
--request POST "${PORTAINER_URL}/api/auth" \
--data "$(jo username="${PORTAINER_USER}" password="${PORTAINER_PASSWORD}")" \
| jq -r '.jwt')
# Fetch ID by name
PORTAINER_ENDPOINTID=$(curl --silent --fail --show-error \
--request GET "${PORTAINER_URL}/api/endpoints" \
--header "Authorization: Bearer ${PORTAINER_TOKEN}" \
| jq --arg name "${PORTAINER_ENDPOINTNAME}" '.[] | select (.Name==$name).Id ')
declare -A properties
# Read File "stack.env" into associative array; skip empty lines; skip commented lines
while IFS='=' read -r key value; do
properties["$key"]="$value"
done < <(
# shellcheck disable=SC2002
cat stack.env \
| tr -s '\n' \
| grep -Ev "^[[:space:]]*#.*"
)
# Convert associative array to JSON array with name value pairs
STACKENV=$(for key in "${!properties[@]}"; do
jo -- -s name="${key}" -s value="${properties[$key]}"
done | jo -a -p)
# Create the Portainer stack
curl --silent --fail --show-error \
--request POST "${PORTAINER_URL}/api/stacks/create/standalone/file" \
--header 'cookie: wonnoauthenticator=rjs3fsK5L2rA0uV9Aoou;' \
--header "Authorization: Bearer ${PORTAINER_TOKEN}" \
--form "Name=${PORTAINER_STACKNAME}" \
--form "endpointId=${PORTAINER_ENDPOINTID}" \
--form "Env=${STACKENV}" \
--form "file=@compose.yaml"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment