9.6 KiB
9.6 KiB
🐳 Portainer API Management Guide
Complete guide for managing homelab infrastructure via Portainer API
📋 Overview
This guide covers how to interact with the Portainer API for managing the homelab infrastructure, including GitOps deployments, container management, and system monitoring.
🔗 API Access Information
Primary Portainer Instance
- URL: https://192.168.0.200:9443
- API Endpoint: https://192.168.0.200:9443/api
- Version: 2.39.0 (Portainer Enterprise Edition)
- Instance ID: dc043e05-f486-476e-ada3-d19aaea0037d
Authentication
Portainer supports two authentication methods:
Option A — API Access Token (recommended):
# Tokens starting with ptr_ use the X-API-Key header (NOT Bearer)
export PORTAINER_TOKEN="<your-portainer-api-token>"
curl -k -H "X-API-Key: $PORTAINER_TOKEN" https://192.168.0.200:9443/api/stacks
Option B — JWT (username/password):
TOKEN=$(curl -k -s -X POST https://192.168.0.200:9443/api/auth \
-H "Content-Type: application/json" \
-d '{"Username":"admin","Password":"YOUR_PASSWORD"}' | jq -r '.jwt')
curl -k -H "Authorization: Bearer $TOKEN" https://192.168.0.200:9443/api/stacks
Note:
ptr_API tokens must useX-API-Key, notAuthorization: Bearer. UsingBearerwith aptr_token returns{"message":"Invalid JWT token"}.
Endpoint IDs
| Endpoint | ID |
|---|---|
| Atlantis | 2 |
| Calypso | 443397 |
| Concord NUC | 443398 |
| Homelab VM | 443399 |
| RPi5 | 443395 |
🚀 GitOps Management
Check GitOps Stack Status
# List all stacks with Git config
curl -k -s -H "X-API-Key: $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/stacks | \
jq '[.[] | select(.GitConfig.URL) | {id:.Id, name:.Name, status:.Status, file:.GitConfig.ConfigFilePath, credId:.GitConfig.Authentication.GitCredentialID}]'
# Get specific stack details
curl -k -H "X-API-Key: $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/stacks/{stack_id}
Trigger GitOps Deployment
# Redeploy stack from Git (pass creds inline to bypass saved credential cache)
curl -k -X PUT -H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
"https://192.168.0.200:9443/api/stacks/{stack_id}/git/redeploy?endpointId={endpoint_id}" \
-d '{"pullImage":true,"prune":false,"repositoryAuthentication":true,"repositoryUsername":"vish","repositoryPassword":"YOUR_GITEA_TOKEN"}'
Manage Git Credentials
# The saved Git credential used by most stacks is "portainer-homelab" (credId: 1)
# List saved credentials:
curl -k -s -H "X-API-Key: $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/users/1/gitcredentials | jq '.'
# Update the saved credential (e.g. after rotating the Gitea token):
curl -k -s -X PUT \
-H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
"https://192.168.0.200:9443/api/users/1/gitcredentials/1" \
-d '{"name":"portainer-homelab","username":"vish","password":"YOUR_NEW_GITEA_TOKEN"}'
Scan Containers for Broken Credentials
# Useful after a sanitization commit — finds any REDACTED values in running container envs
python3 << 'EOF'
import json, urllib.request, ssl
ctx = ssl.create_default_context(); ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
token = "REDACTED_TOKEN"
base = "https://192.168.0.200:9443/api"
endpoints = {"atlantis":2,"calypso":443397,"nuc":443398,"homelab":443399,"rpi5":443395}
def api(p):
req = urllib.request.Request(f"{base}{p}", headers={"X-API-Key": token})
with urllib.request.urlopen(req, context=ctx) as r: return json.loads(r.read())
for ep_name, ep_id in endpoints.items():
for c in api(f"/endpoints/{ep_id}/docker/containers/json?all=true"):
info = api(f"/endpoints/{ep_id}/docker/containers/{c['Id'][:12]}/json")
hits = [e for e in (info.get("Config",{}).get("Env") or []) if "REDACTED" in e]
if hits: print(f"[{ep_name}] {c['Names'][0]}"); [print(f" {h}") for h in hits]
EOF
📊 Container Management
List All Containers
# Get all containers across all endpoints
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/containers/json?all=true
Container Health Checks
# Check container status
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/containers/{container_id}/json | \
jq '.State.Health.Status'
# Get container logs
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/containers/{container_id}/logs?stdout=1&stderr=1&tail=100
🖥️ System Information
Endpoint Status
# List all endpoints (servers)
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints
# Get system information
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/system/info
Resource Usage
# Get system stats
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/system/df
# Container resource usage
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/containers/{container_id}/stats?stream=false
🔧 Automation Scripts
Health Check Script
#!/bin/bash
# portainer-health-check.sh
PORTAINER_URL="https://192.168.0.200:9443"
TOKEN="$PORTAINER_TOKEN"
echo "🔍 Checking Portainer API status..."
STATUS=$(curl -k -s "$PORTAINER_URL/api/status" | jq -r '.Version')
echo "✅ Portainer Version: $STATUS"
echo "🐳 Checking container health..."
CONTAINERS=$(curl -k -s -H "Authorization: Bearer $TOKEN" \
"$PORTAINER_URL/api/endpoints/1/docker/containers/json" | \
jq -r '.[] | select(.State=="running") | .Names[0]' | wc -l)
echo "✅ Running containers: $CONTAINERS"
echo "📊 Checking GitOps stacks..."
STACKS=$(curl -k -s -H "Authorization: Bearer $TOKEN" \
"$PORTAINER_URL/api/stacks" | \
jq -r '.[] | select(.Status==1) | .Name' | wc -l)
echo "✅ Active stacks: $STACKS"
GitOps Deployment Script
#!/bin/bash
# deploy-stack.sh
STACK_NAME="$1"
PORTAINER_URL="https://192.168.0.200:9443"
TOKEN="$PORTAINER_TOKEN"
if [[ -z "$STACK_NAME" ]]; then
echo "Usage: $0 <stack_name>"
exit 1
fi
echo "🚀 Deploying stack: $STACK_NAME"
# Find stack ID
STACK_ID=$(curl -k -s -H "Authorization: Bearer $TOKEN" \
"$PORTAINER_URL/api/stacks" | \
jq -r ".[] | select(.Name==\"$STACK_NAME\") | .Id")
if [[ -z "$STACK_ID" ]]; then
echo "❌ Stack not found: $STACK_NAME"
exit 1
fi
# Trigger redeploy
curl -k -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
"$PORTAINER_URL/api/stacks/$STACK_ID/git/redeploy" \
-d '{"RepositREDACTED_APP_PASSWORD":"main","PullImage":true}'
echo "✅ Deployment triggered for stack: $STACK_NAME"
📈 Monitoring Integration
Prometheus Metrics
# Get Portainer metrics (if enabled)
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/containers/json | \
jq '[.[] | {name: .Names[0], state: .State, status: .Status}]'
Alerting Integration
# Check for unhealthy containers
UNHEALTHY=$(curl -k -s -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/endpoints/1/docker/containers/json | \
jq -r '.[] | select(.State != "running") | .Names[0]')
if [[ -n "$UNHEALTHY" ]]; then
echo "⚠️ Unhealthy containers detected:"
echo "$UNHEALTHY"
fi
🔐 Security Best Practices
API Token Management
- Rotation: Rotate API tokens regularly (monthly)
- Scope: Use least-privilege tokens when possible
- Storage: Store tokens securely (environment variables, secrets management)
Network Security
- TLS: Always use HTTPS endpoints
- Firewall: Restrict API access to authorized networks
- Monitoring: Log all API access for security auditing
🚨 Troubleshooting
Common Issues
Authentication Failures
# Check token validity
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/users/me
Connection Issues
# Test basic connectivity
curl -k -s https://192.168.0.200:9443/api/status
# Check certificate issues
openssl s_client -connect 192.168.0.200:9443 -servername atlantis.vish.local
GitOps Sync Issues
# Check stack deployment logs
curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \
https://192.168.0.200:9443/api/stacks/{stack_id}/logs
📚 API Documentation
Official Resources
- Portainer API Docs: https://docs.portainer.io/api/
- Swagger UI: https://192.168.0.200:9443/api/docs/
- API Reference: Available in Portainer web interface
Useful Endpoints
/api/status- System status/api/endpoints- Managed environments/api/stacks- GitOps stacks/api/containers- Container management/api/images- Image management/api/volumes- Volume management/api/networks- Network management
🔄 Integration with Homelab
GitOps Workflow
- Code Change: Update compose files in Git repository
- Webhook: Git webhook triggers Portainer sync (optional)
- Deployment: Portainer pulls changes and redeploys
- Verification: API checks confirm successful deployment
Monitoring Integration
- Health Checks: Regular API calls to verify system health
- Metrics Collection: Export container metrics to Prometheus
- Alerting: Trigger alerts on deployment failures or container issues
Last Updated: February 14, 2026
Portainer Version: 2.33.7
API Version: Compatible with Portainer EE
Status: ✅ Active and Operational