README
ΒΆ
Terraform Provider for Portainer
Portainer Terraform Provider
A Terraform provider to manage Portainer resources via its REST API using Terraform.
It supports provisioning and configuration of Portainer users and will be extended to support other objects such as teams, stacks, endpoints, and access control.
Requirements
- Terraform v0.13+
- Portainer 2.x with admin API key support enabled
- Go 1.21+ (if building from source)
Building and Installing
make build
Provider Support
| Provider | Provider Support Status |
|---|---|
| Terraform | |
| OpenTofu |
Example Provider Configuration
provider "portainer" {
endpoint = "https://portainer.example.com"
api_key = "your-api-key"
skip_ssl_verify = true # optional (default value is `false`)
}
Authentication
- Static API key
Static credentials can be provided by adding the api_key variables in-line in the Portainer provider block:
π Authentication: This provider supports only API keys via the
X-API-Keyheader. JWT tokens curentlly are not supported in this provider.
Usage:
provider "portainer" {
api_key = "your-api-key"
}
Environment variables
You can provide your configuration via the environment variables representing your minio credentials:
$ export PORTAINER_ENDPOINT="https://portainer.example.com"
$ export PORTAINER_API_KEY="your-api-key"
$ export PORTAINER_SKIP_SSL_VERIFY=true
Arguments Reference
| Name | Type | Required | Description |
|---|---|---|---|
endpoint |
string | β yes | The URL of the Portainer instance. /api will be appended automatically if missing. |
api_key |
string | β yes | API key used to authenticate requests. |
skip_ssl_verify |
boolean | β no | Set to true to skip TLS certificate verification (useful for self-signed certs). Default: false |
Usage
See our examples per resources in docs.
π§© Supported Resources
| Resource | Documentation | Example | Status | Terraform Import | E2E Tests |
|---|---|---|---|---|---|
portainer_user |
user.md | example | |||
portainer_team |
team.md | example | |||
portainer_team_membership |
team_membership.md | example | |||
portainer_environment |
environment.md | example | |||
portainer_tag |
tag.md | example | |||
portainer_endpoint_group |
endpoint_group.md | example | |||
portainer_registry |
registry.md | example | |||
portainer_backup |
backup.md | example | |||
portainer_backup_s3 |
backup_s3.md | example | |||
portainer_auth |
auth.md | example | |||
portainer_edge_group |
edge_group.md | example | |||
portainer_edge_stack |
edge_stack.md | example | |||
portainer_edge_job |
edge_job.md | example | |||
portainer_stack |
stack.md | example | |||
portainer_custom_template |
custom_template.md | example | |||
portainer_container_exec |
container_exec.md | example | |||
portainer_docker_network |
docker_network.md | example | |||
portainer_docker_image |
docker_image.md | example | |||
portainer_docker_volume |
docker_volume.md | example | |||
portainer_docker_secret |
docker_secret.md | example | |||
portainer_docker_config |
docker_config.md | example | |||
portainer_open_amt |
open_amt.md | example | |||
portainer_settings |
settings.md | example | |||
portainer_endpoint_settings |
endpoint_settings.md | example | |||
portainer_portainer_endpoint_service_update |
endpoint_service_update.md | example | |||
portainer_endpoint_snapshot |
endpoint_snapshot.md | example | |||
portainer_endpoint_association |
endpoint_association.md | example | |||
portainer_ssl |
ssl.md | example | |||
portainer_webhook |
webhook.md | example | |||
portainer_webhook_execute |
webhook_execute.md | example | |||
portainer_resource_control |
resource_control.md | example | |||
portainer_licenses |
licenses.md | example | |||
portainer_cloud_credentials |
cloud_credentials.md | example | |||
portainer_kubernetes_delete_object |
kubernetes_delete_object.md | example | |||
portainer_kubernetes_helm |
kubernetes_helm.md | example | |||
portainer_kubernetes_ingresscontrollers |
kubernetes_ingresscontrollers.md | example | |||
portainer_kubernetes_namespace_ingresscontrollers |
kubernetes_namespace_ingresscontrollers.md | example | |||
portainer_kubernetes_namespace_system |
kubernetes_namespace_system.md | example | |||
portainer_kubernetes_namespace |
kubernetes_namespace.md | example | |||
portainer_kubernetes_cronjob |
kubernetes_cronjob.md | example | |||
portainer_kubernetes_job |
kubernetes_job.md | example | |||
portainer_kubernetes_service_accounts |
kubernetes_service_account.md | example | |||
portainer_kubernetes_configmaps |
kubernetes_configmaps.md | example | |||
portainer_kubernetes_secret |
kubernetes_secret.md | example | |||
portainer_kubernetes_service |
kubernetes_service.md | example | |||
portainer_kubernetes_role |
kubernetes_role.md | example | |||
portainer_kubernetes_rolebinding |
kubernetes_rolebinding.md | example | |||
portainer_kubernetes_clusterrole |
kubernetes_clusterrole.md | example | |||
portainer_kubernetes_clusterrolebinding |
kubernetes_clusterrolebinding.md | example | |||
portainer_kubernetes_application |
kubernetes_application.md | example | |||
portainer_kubernetes_ingress |
kubernetes_ingress.md | example | |||
portainer_kubernetes_volume |
kubernetes_volume.md | example | |||
portainer_kubernetes_storage |
kubernetes_storage.md | example |
π‘ Missing a resource?
Is there a Portainer resource you'd like to see supported?
π Open an issue and weβll consider it for implementation β or even better, submit a Pull Request to contribute directly!
π See CONTRIBUTING.md for guidelines.
β»οΈ Terraform Import Guide
You can import existing Portainer-managed resources into Terraform using the terraform import command. This is useful for adopting GitOps practices or migrating manually created resources into code.
β General Syntax
terraform import <RESOURCE_TYPE>.<NAME> <ID>
<RESOURCE_TYPE>β the Terraform resource type, e.g., portainer_tag<NAME>β the local name you've chosen in your .tf file<ID>β the Portainer object ID (usually numeric)
π Example: Import an existing tag
Let's say you already have a tag with ID 3 in Portainer. First, define it in your configuration:
resource "portainer_tag" "existing_tag" {
name = "production"
}
Then run the import:
terraform import portainer_tag.existing_tag 3
Terraform will fetch the current state of the resource and start managing it. You can now safely plan and apply updates from Terraform.
π¦ Auto-generate Terraform configuration
After a successful import, you can automatically generate the resource definition from the Terraform state:
./generate-tf.sh
This script reads the current Terraform state and generates a file named generated.tf with the proper configuration of the imported resources. You can copy or refactor the output into your main Terraform files.
βΉοΈ Note: Only resources with import support listed as β in the table above can be imported.
β Daily End-to-End Testing
To ensure maximum reliability and functionality of this provider, automated end-to-end tests are executed every day via GitHub Actions.
These tests run against a real Portainer instance (started using docker compose) and validate the majority of supported resources using real Terraform plans and applies.
π‘ This helps catch regressions early and ensures the provider remains fully operational and compatible with the Portainer API.
π Workflows
The project uses GitHub Actions to automate validation and testing of the provider.
- Validate and lint documentation files (
README.mdanddocs/) - Initialize, test and check the Portainer provider with Terraform and OpenTofu
- Publish the new version of the Portainer Terraform provider to Terraform Registry
- Run daily E2E Terraform tests against a live Portainer instance spun up via Docker Compose (
make up) at 07:00 UTC
π§ͺ Localy Testing
To test the provider locally, start the Portainer Web UI using Docker Compose:
make up
Then open http://localhost:9000 in your browser.
π Predefined Test Credentials for Login (use also E2E tests)
Thanks to the portainer_data directory included in this repository, a test user and token are preloaded when you launch the local Portainer instance:
| Field | Value |
|---|---|
| Username | admin |
| Password | password123456789 |
| API Token | ptr_xrP7XWqfZEOoaCJRu5c8qKaWuDtVc2Zb07Q5g22YpS8= |
You can now apply your Terraform templates and observe changes live in the UI.
βΈοΈ Testing Kubernetes Resources Locally
If you want to test Kubernetes-related resources, you can spin up a local Kubernetes cluster with k3d, deploy the Portainer Agent into it, and connect Portainer to that environment:
make install-k3d # Install k3d CLI
make k3d-up # Create a local k3d cluster
make k8s-deploy-agent # Deploy Portainer Agent into Kubernetes
make k3d-connect-portainer # Connect Portainer container to the k3d network
make k3d-export-ip # Export Kubernetes IP into terraform.tfvars
Then you can apply your Kubernetes environemnt from directory e2e-tests/environment run by:
cd e2e-tests/environment
terraform init
terraform apply
and than Kubernetes-related Terraform templates under e2e-tests/kubernetes* (or a similar directory):
cd e2e-tests/kubernetes*
terraform init
terraform apply
Testing a new version of the Portainer provider
After making changes to the provider source code, follow these steps: Build the provider binary:
make build
Install the binary into the local Terraform plugin directory:
make install-plugin
Update your main.tf to use the local provider source Add the following to your Terraform configuration:
terraform {
required_providers {
portainer = {
source = "localdomain/local/portainer"
}
}
}
Now you're ready to test your provider against the local Portainer instance.
Roadmap
See the open issues for a list of proposed features (and known issues). See CONTRIBUTING for more information.
License
This module is 100% Open Source and all versions of this provider starting from v2.0.0 are distributed under the AGPL-3.0 License. See LICENSE for more information.
Acknowledgements
Documentation
ΒΆ
There is no documentation for this package.