Proxmox Provider¶
This provider for Terraform / OpenTofu is used for interacting with resources supported by Proxmox VE. The provider needs to be configured with the proper endpoint and credentials before it can be used.
Use the navigation to the left to read about the available resources.
Getting Started¶
To use this provider, you only need:
- API access to your Proxmox VE server (endpoint URL + username/password or API token)
- That's it for most use cases!
Info
SSH access is optional. Most resources work entirely through the Proxmox API. See When is SSH Required? for specific cases that need SSH.
Example Usage¶
Minimal configuration (no SSH):
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
# TODO: use terraform variable or remove the line, and use PROXMOX_VE_USERNAME environment variable
username = "root@pam"
# TODO: use terraform variable or remove the line, and use PROXMOX_VE_PASSWORD environment variable
password = "the-password-set-during-installation-of-proxmox-ve"
# because self-signed TLS certificate is in use
insecure = true
}
With SSH access (only if needed for snippets or certain file uploads):
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
username = "root@pam"
password = "the-password-set-during-installation-of-proxmox-ve"
insecure = true
ssh {
agent = true
# username = "root" # required when using api_token
}
}
Warning
When using API token authentication, the SSH password cannot be inherited from the provider password field (since there is none). You must ensure that either ssh-agent has the appropriate keys loaded, or explicitly configure password or private_key in the ssh block.
Authentication¶
The provider supports three authentication methods (in order of precedence):
- API Token — recommended for production and CI/CD
- Auth Ticket — for automated scripts with TOTP support
- Username/Password — simplest, good for development
Danger
Hard-coding credentials into any Terraform configuration is not recommended. Use environment variables or a .tfvars file (add to .gitignore) instead.
Authentication Methods Comparison¶
| Method | Use Case | Pros | Cons | Security Level |
|---|---|---|---|---|
| API Token | Production, CI/CD | - No password needed - Fine-grained permissions - Revocable |
- Some operations not supported - Requires SSH username config |
High |
| Auth Ticket | Automated scripts | - Short-lived - No password storage - TOTP support |
- More complex setup - Needs periodic renewal |
High |
| Username/Password | Development, Testing | - Full API support - Simple setup |
- Password in config/env - Not revocable individually |
Medium |
Quick Examples¶
Here are examples for each authentication method:
API Token (Recommended for Production):
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
api_token = "terraform@pve!provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Username/Password (Development/Testing):
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
insecure = true
username = "username@realm"
password = "a-strong-password"
}
Auth Ticket (Automated Scripts):
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
auth_ticket = "PVE:username@realm:12345678::some_base64_payload=="
csrf_prevention_token = "12345678:some_blob"
}
A better approach is to extract these values into Terraform variables and reference them instead:
provider "proxmox" {
endpoint = var.virtual_environment_endpoint
# Choose one authentication method:
api_token = var.virtual_environment_api_token
# OR
username = var.virtual_environment_username
password = var.virtual_environment_password
# OR
auth_ticket = var.virtual_environment_auth_ticket
csrf_prevention_token = var.virtual_environment_csrf_prevention_token
}
The variable values can be provided via a separate .tfvars file (add it to .gitignore).
See the Terraform documentation for more information.
Security Best Practices¶
- Use API tokens in production — they're revocable and support fine-grained permissions
- Never commit credentials to version control — use environment variables or
.tfvarsfiles (in.gitignore) - Use HTTPS with valid certificates — only set
insecure = truein development environments - Apply least privilege — create tokens/users with minimal required permissions
- Rotate credentials regularly
Environment Variables¶
Credentials can also be provided via environment variables instead of static arguments. For example:
export PROXMOX_VE_USERNAME="username@realm"
export PROXMOX_VE_PASSWORD='a-strong-password'
terraform plan
See the Argument Reference section for the supported variable names and use cases.
API Token Authentication¶
API tokens allow password-less authentication with the Proxmox API. If you already have a token, use it like this:
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
api_token = "user@realm!tokenid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Creating an API Token on the Proxmox Server¶
You can create an API Token via the Proxmox UI or the command line on the Proxmox host:
-
Create a user:
-
Create a role for the user (you can skip this step if you want to use any of the existing roles):
pveum role add Terraform -privs "Realm.AllocateUser, VM.PowerMgmt, VM.GuestAgent.Unrestricted, Sys.Console, Sys.Audit, Sys.AccessNetwork, VM.Config.Cloudinit, VM.Replicate, Pool.Allocate, SDN.Audit, Realm.Allocate, SDN.Use, Mapping.Modify, VM.Config.Memory, VM.GuestAgent.FileSystemMgmt, VM.Allocate, SDN.Allocate, VM.Console, VM.Clone, VM.Backup, Datastore.AllocateTemplate, VM.Snapshot, VM.Config.Network, Sys.Incoming, Sys.Modify, VM.Snapshot.Rollback, VM.Config.Disk, Datastore.Allocate, VM.Config.CPU, VM.Config.CDROM, Group.Allocate, Datastore.Audit, VM.Migrate, VM.GuestAgent.FileWrite, Mapping.Use, Datastore.AllocateSpace, Sys.Syslog, VM.Config.Options, Pool.Audit, User.Modify, VM.Config.HWType, VM.Audit, Sys.PowerMgmt, VM.GuestAgent.Audit, Mapping.Audit, VM.GuestAgent.FileRead, Permissions.Modify"Warning
The list of available privileges has changed in PVE 9.0. The above list is only an example (and likely too permissive for most use cases). Please review and adjust to your needs. Refer to the privileges documentation for more details.
-
Assign the role to the previously created user:
-
Create an API token for the user:
Info
Make sure you copy the token value, as it will not be displayed again.
Refer to the PVE User Management documentation for more details.
The command outputs a table with the token ID and secret. Concatenate them into a single string (e.g., user@realm!tokenid=secret) for the api_token field or the PROXMOX_VE_API_TOKEN environment variable:
provider "proxmox" {
endpoint = var.virtual_environment_endpoint
api_token = "terraform@pve!provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
insecure = true
ssh {
agent = true
username = "terraform"
}
}
Info
Not all Proxmox API operations are supported via API Token.
You may see errors like
error creating container: received an HTTP 403 response - Reason: Permission check failed (changing feature flags for privileged container is only allowed for root@pam) or
error creating VM: received an HTTP 500 response - Reason: only root can set 'arch' config or
Permission check failed (user != root@pam) when using API Token authentication, even when Administrator role or the root@pam user is used with the token.
The workaround is to use password authentication for those operations.
Info
You can also configure additional Proxmox users and roles using virtual_environment_user and virtual_environment_role resources of the provider.
Pre-Authentication, or Passing an Authentication Ticket into the provider¶
It is possible to generate a session ticket with the API, and to pass the ticket and csrf_prevention_token into the provider using environment variables PROXMOX_VE_AUTH_TICKET and PROXMOX_VE_CSRF_PREVENTION_TOKEN (or provider's arguments auth_ticket and csrf_prevention_token). See more details in the Proxmox Wiki.
An example of using curl and jq to query the Proxmox API to get a Proxmox session ticket; it is also very easy to pass in a TOTP password this way:
#!/usr/bin/bash
## assume vars are set: PROXMOX_VE_ENDPOINT, PROXMOX_VE_USERNAME, PROXMOX_VE_PASSWORD
## end-goal: automatically set PROXMOX_VE_AUTH_TICKET and PROXMOX_VE_CSRF_PREVENTION_TOKEN
_user_totp_password='123456' ## optional TOTP password
proxmox_api_ticket_path='api2/json/access/ticket' ## cannot have double "//" - ensure endpoint ends with a "/" and this string does not begin with a "/", or vice-versa
## call the auth api endpoint
resp=$( curl -q -s -k --data-urlencode "username=${PROXMOX_VE_USERNAME}" --data-urlencode "password=${PROXMOX_VE_PASSWORD}" "${PROXMOX_VE_ENDPOINT}${proxmox_api_ticket_path}" )
auth_ticket=$( jq -r '.data.ticket' <<<"${resp}" )
resp_csrf=$( jq -r '.data.CSRFPreventionToken' <<<"${resp}" )
## check if the response payload needs a TFA (totp) passed, call the auth-api endpoint again
if [[ $(jq -r '.data.NeedTFA' <<<"${resp}") == 1 ]]; then
resp=$( curl -q -s -k -H "CSRFPreventionToken: ${resp_csrf}" --data-urlencode "username=${PROXMOX_VE_USERNAME}" --data-urlencode "tfa-challenge=${auth_ticket}" --data-urlencode "password=totp:${_user_totp_password}" "${PROXMOX_VE_ENDPOINT}${proxmox_api_ticket_path}" )
auth_ticket=$( jq -r '.data.ticket' <<<"${resp}" )
resp_csrf=$( jq -r '.data.CSRFPreventionToken' <<<"${resp}" )
fi
export PROXMOX_VE_AUTH_TICKET="${auth_ticket}"
export PROXMOX_VE_CSRF_PREVENTION_TOKEN="${resp_csrf}"
terraform plan
SSH Connection¶
Info
SSH is optional for most users. The provider primarily uses the Proxmox API. SSH is only needed for specific edge cases listed below.
When is SSH Required?¶
SSH connection is only required for these specific operations:
| Operation | Resource | Why SSH is needed |
|---|---|---|
| Upload snippets | proxmox_virtual_environment_file |
Proxmox API doesn't support snippet uploads |
| Upload certain file types | proxmox_virtual_environment_file |
Some content types require direct node access |
Import disks via source_file.path |
proxmox_virtual_environment_vm |
Local file transfer to node |
Configure idmap entries |
proxmox_virtual_environment_container |
Proxmox API doesn't support lxc[n] parameters |
SSH is NOT required for:
- Creating, modifying, or deleting VMs and Containers
- Managing storage, networks, pools, users, or any other resources
- Importing disks using
import_fromattribute (uses API) - Downloading files using
proxmox_virtual_environment_download_file(uses API)
If you don't need the operations listed above, you can skip the SSH configuration entirely.
SSH Configuration¶
If you need SSH access, the connection is configured via the optional ssh block in the provider block:
provider "proxmox" {
endpoint = "https://10.0.0.2:8006/"
username = "username@realm"
password = "a-strong-password"
insecure = true
ssh {
agent = true
}
}
If no ssh block is provided, the provider will attempt to connect to the target node using the credentials provided in the username and password arguments (or PROXMOX_VE_USERNAME and PROXMOX_VE_PASSWORD environment variables).
Note that the target node is identified by the node argument in the resource, and may be different from the Proxmox API endpoint.
Please refer to the Argument Reference section to view the available arguments of the ssh block.
Warning
Important: The SSH password is only inherited from the provider's password field when using username/password authentication. When using API token authentication, there is no password to inherit. In this case, you must provide SSH credentials explicitly: either configure ssh-agent with the appropriate keys, or set password or private_key in the ssh block (or their corresponding environment variables).
SSH Agent¶
The provider does not use OS-specific SSH configuration files, such as ~/.ssh/config.
Instead, it uses the SSH protocol directly, and supports the SSH_AUTH_SOCK environment variable (or agent_socket argument) to connect to the SSH agent.
This allows the provider to use the SSH agent configured by the user, and to support multiple SSH agents running on the same machine.
You can find more details on the SSH Agent here.
The SSH agent authentication takes precedence over the private_key and password authentication.
Info
By default on Windows, the provider will assume the SSH agent is at \\.\pipe\openssh-ssh-agent.
SSH Private Key¶
When an SSH agent is not available (for example, in CI/CD pipelines without SSH agent forwarding), you can use the private_key argument in the ssh block (or the PROXMOX_VE_SSH_PRIVATE_KEY environment variable) to provide the private key directly.
The private key must not be encrypted, and must be in PEM format.
You can provide the private key from a file:
Alternatively, heredoc syntax can supply the private key as a string (not recommended due to security risks). The <<- format ignores indentation:
provider "proxmox" {
// ...
ssh {
agent = false
private_key = <<-EOF
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
<SKIPPED>
DMUWUEaH7yMCKl7uCZ9xAAAAAAECAwQF
-----END OPENSSH PRIVATE KEY-----
EOF
}
}
SSH User¶
By default, the provider will use the same username for the SSH connection as the one used for the Proxmox API connection (when using PAM authentication).
This can be overridden by specifying the username argument in the ssh block (or alternatively a username in the PROXMOX_VE_SSH_USERNAME environment variable):
Info
When using API Token or non-PAM authentication for Proxmox API, the username field in the ssh block (or alternatively a username in PROXMOX_VE_USERNAME or PROXMOX_VE_SSH_USERNAME environment variable) is required.
This is because the provider needs to know which PAM user to use for the SSH connection.
When using a non-root user for the SSH connection, the user must have the sudo privilege on the target node without requiring a password.
Info
If you run clustered Proxmox VE, you will need to configure the sudo privilege for the user on all nodes in the cluster.
Info
sudo may not be installed by default on Proxmox VE nodes. You can install it via the command line on the Proxmox host: apt install sudo
You can configure the sudo privilege for the user via the command line on the Proxmox host.
In the example below, we create a user terraform and assign the sudo privilege to it. Run the following commands on the Proxmox node in the root shell:
-
Create a new system user:
-
Configure the
Add the following lines to the file:sudoprivilege for the user, by adding a new sudoers file to the/etc/sudoers.ddirectory:If you use theterraform ALL=(root) NOPASSWD: /usr/sbin/pvesm terraform ALL=(root) NOPASSWD: /usr/sbin/qm terraform ALL=(root) NOPASSWD: /usr/bin/tee /var/lib/vz/snippets/[a-zA-Z0-9_][a-zA-Z0-9_.-]*idmapattribute onproxmox_virtual_environment_container, the provider edits the container configuration file via SSH. Add the following rules to allowsedandteeaccess to the LXC configuration directory:If you're using a different datastore for snippets, not the defaultterraform ALL=(root) NOPASSWD: /usr/bin/sed -i * /etc/pve/lxc/*.conf terraform ALL=(root) NOPASSWD: /usr/bin/tee -a /etc/pve/lxc/*.conflocal, you should add the datastore's mount point to the sudoers file as well, for example: You can find the mount point of the datastore by runningpvesh get /storage/<name>on the Proxmox node.Warning
Security Warning: Do not use wildcard patterns like
/var/lib/vz/*in sudoers rules fortee. Such patterns allow path traversal attacks (e.g.,/var/lib/vz/../../../etc/sudoers.d/malicious) that can lead to privilege escalation. Always restrict to specific subdirectories with strict filename patterns as shown above. -
Copy your SSH public key to the
~/.ssh/authorized_keysfile of theterraformuser on the target node. -
Test the SSH connection and password-less
You should be able to connect to the target node and see the output containingsudo:APIVER <number>on the screen without being prompted for your password.
Alternatively, if pam_ssh_agent_auth is configured on the target node, the agent_forwarding option can forward the SSH agent to the remote server. This allows sudo without a password by validating the public SSH key configured for pam_ssh_agent_auth.
Node IP address used for SSH connection¶
To make the SSH connection, the provider needs to resolve the target node name to an IP address. The following methods are used to resolve the node name, in the specified order:
- Enumerate the node's network interfaces via the Proxmox API, and identify the first interface that:
- Has an IPv4 address with IPv4 gateway configured, or
- Has an IPv6 address with IPv6 gateway configured, or
- Has an IPv4 address
- Resolve the Proxmox node name (usually a shortname) via DNS using the system DNS resolver of the machine running Terraform.
In some cases, this may not be the desired behavior — for example, when the node has multiple network interfaces and the one that should be used for SSH is not the first one.
To override the node IP address used for SSH connection, you can use the optional node blocks in the ssh block, and specify the desired IP address (or FQDN) for each node.
For example:
provider "proxmox" {
// ...
ssh {
// ...
node {
name = "pve1"
address = "192.168.10.1"
}
node {
name = "pve2"
address = "192.168.10.2"
}
}
}
SSH Connection via SOCKS5 Proxy¶
The provider supports SSH connection to the target node via a SOCKS5 proxy.
To enable the SOCKS5 proxy, specify the socks5_server argument in the ssh block:
provider "proxmox" {
// ...
ssh {
// ...
socks5_server = "ip-or-fqdn-of-socks5-server:port"
socks5_username = "username" # optional
socks5_password = "password" # optional
}
}
If enabled, this method will be used for all SSH connections to the target nodes in the cluster.
VM and Container ID Assignment¶
When creating VMs and Containers, you can specify the optional vm_id attribute to set the ID. If omitted, the provider generates a unique ID automatically.
The Proxmox API requires unique IDs within the cluster but doesn't support reserving IDs before resource creation. The provider uses file-based locking to prevent duplicates, but conflicts can still occur when multiple provider instances create resources simultaneously.
To reduce conflicts, set random_vm_ids = true in the provider block. This generates random IDs (checked for uniqueness via the API) instead of sequential ones.
Temporary Directory¶
Using proxmox_virtual_environment_file with .iso files or disk images can require a large amount of space in the temporary directory of the computer running Terraform.
Consider pointing tmp_dir to a directory with enough space, especially if the default temporary directory is limited by the system memory (e.g. tmpfs mounted on /tmp).
A better approach is to use the proxmox_virtual_environment_download_file resource to download files directly to the target node without buffering to the local machine.
Environment Variables Summary¶
All provider arguments can be configured via environment variables. This is the recommended approach for credentials.
API Connection (required):
| Environment Variable | Description |
|---|---|
PROXMOX_VE_ENDPOINT |
API endpoint URL (e.g., https://pve.example.com:8006/) |
Authentication (one method required):
| Environment Variable | Description |
|---|---|
PROXMOX_VE_API_TOKEN |
API token (recommended for production) |
PROXMOX_VE_USERNAME |
Username with realm (e.g., root@pam) |
PROXMOX_VE_PASSWORD |
Password for username/password auth |
PROXMOX_VE_AUTH_TICKET |
Pre-authenticated session ticket |
PROXMOX_VE_CSRF_PREVENTION_TOKEN |
CSRF token (used with auth ticket) |
API Options (optional):
| Environment Variable | Description |
|---|---|
PROXMOX_VE_INSECURE |
Skip TLS verification (true/false) |
PROXMOX_VE_MIN_TLS |
Minimum TLS version (1.0, 1.1, 1.2, 1.3) |
PROXMOX_VE_TMPDIR |
Custom temporary directory |
SSH Connection (optional — only if SSH is required):
| Environment Variable | Description |
|---|---|
PROXMOX_VE_SSH_USERNAME |
SSH username |
PROXMOX_VE_SSH_PASSWORD |
SSH password |
PROXMOX_VE_SSH_PRIVATE_KEY |
SSH private key (PEM format) |
PROXMOX_VE_SSH_AGENT |
Use SSH agent (true/false) |
PROXMOX_VE_SSH_AUTH_SOCK |
SSH agent socket path |
PROXMOX_VE_SSH_AGENT_FORWARDING |
Enable SSH agent forwarding |
PROXMOX_VE_SSH_SOCKS5_SERVER |
SOCKS5 proxy server address |
PROXMOX_VE_SSH_SOCKS5_USERNAME |
SOCKS5 proxy username |
PROXMOX_VE_SSH_SOCKS5_PASSWORD |
SOCKS5 proxy password |
Argument Reference¶
In addition to generic provider arguments (e.g. alias and version), the following arguments are supported in the Proxmox provider block:
endpoint- (Required) The endpoint for the Proxmox Virtual Environment API (can also be sourced fromPROXMOX_VE_ENDPOINT). Usually this ishttps://<your-cluster-endpoint>:8006/. Do not include/api2/jsonat the end.insecure- (Optional) Whether to skip the TLS verification step (can also be sourced fromPROXMOX_VE_INSECURE). If omitted, defaults tofalse.-
min_tls- (Optional) The minimum required TLS version for API calls (can also be sourced fromPROXMOX_VE_MIN_TLS). Supported values:1.0|1.1|1.2|1.3. If omitted, defaults to1.3. -
auth_ticket- (Optional) The auth ticket from an external auth call (can also be sourced fromPROXMOX_VE_AUTH_TICKET). To be used in conjunction withcsrf_prevention_token, takes precedence overapi_tokenandusernamewithpassword. For example,PVE:username@realm:12345678::some_base64_payload==. -
csrf_prevention_token- (Optional) The CSRF Prevention Token from an external auth call (can also be sourced fromPROXMOX_VE_CSRF_PREVENTION_TOKEN). For example,12345678:some_blob. -
api_token- (Optional) The API Token for the Proxmox Virtual Environment API (can also be sourced fromPROXMOX_VE_API_TOKEN). Takes precedence overusernamewithpassword. For example,username@realm!for-terraform-provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. -
otp- (Optional, Deprecated) The one-time password for the Proxmox Virtual Environment API (can also be sourced fromPROXMOX_VE_OTP). -
username- (Required) The username and realm for the Proxmox Virtual Environment API (can also be sourced fromPROXMOX_VE_USERNAME). For example,root@pam. -
password- (Required) The password for the Proxmox Virtual Environment API (can also be sourced fromPROXMOX_VE_PASSWORD). -
ssh- (Optional) The SSH connection configuration to a Proxmox node. This is a block, whose fields are documented below.username- (Optional) The username to use for the SSH connection. Defaults to the username used for the Proxmox API connection. Can also be sourced fromPROXMOX_VE_SSH_USERNAME. Required when using API Token.password- (Optional) The password to use for the SSH connection. Defaults to the password used for the Proxmox API connection when using username/password authentication. Default has no effect when using API token authentication, as there is no password to inherit. Can also be sourced fromPROXMOX_VE_SSH_PASSWORD.agent- (Optional) Whether to use the SSH agent for the SSH authentication. Defaults tofalse. Can also be sourced fromPROXMOX_VE_SSH_AGENT.agent_socket- (Optional) The path to the SSH agent socket. Defaults to the value of theSSH_AUTH_SOCKenvironment variable. Can also be sourced fromPROXMOX_VE_SSH_AUTH_SOCK.agent_forwarding- (Optional) Whether to enable SSH agent forwarding. Defaults to the value of thePROXMOX_VE_SSH_AGENT_FORWARDINGenvironment variable, orfalseif not set.private_key- (Optional) The private key to use for the SSH connection. Can also be sourced fromPROXMOX_VE_SSH_PRIVATE_KEY. The private key must be in PEM format.socks5_server- (Optional) The address of the SOCKS5 proxy server to use for the SSH connection. Can also be sourced fromPROXMOX_VE_SSH_SOCKS5_SERVER.socks5_username- (Optional) The username to use for the SOCKS5 proxy server. Can also be sourced fromPROXMOX_VE_SSH_SOCKS5_USERNAME.socks5_password- (Optional) The password to use for the SOCKS5 proxy server. Can also be sourced fromPROXMOX_VE_SSH_SOCKS5_PASSWORD.node- (Optional) The node configuration for the SSH connection. Can be specified multiple times to provide configuration for multiple nodes.
tmp_dir- (Optional) Use a custom temporary directory. (can also be sourced fromPROXMOX_VE_TMPDIR)random_vm_ids- (Optional) Use random VM IDs for VMs and Containers whenvm_idattribute is not specified. Defaults tofalse.random_vm_id_start- (Optional) The start of the range for random VM IDs. Defaults to10000.random_vm_id_end- (Optional) The end of the range for random VM IDs. Defaults to99999.