First: if you're unsure or afraid of anything, ask for help! You can submit a work in progress (WIP) pull request, or file an issue with the parts you know. For questions and general discussion, use GitHub Discussions. We'll do our best to guide you in the right direction, and let you know if there are guidelines we will need to follow. We want people to be able to participate without fear of doing the wrong thing.
Below are our expectations for contributors. Following these guidelines gives us the best opportunity to work with you, by making sure we have the things we need in order to make it happen. Doing your best to follow it will speed up our ability to merge PRs and respond to issues.
- Fork and clone the repository.
- Create a feature branch.
- Implement your changes.
- Run
make testandmake lint. - Commit with
git commit -s(signs off on DCO). - Open a PR against
main.
For common issues during development, see Development Troubleshooting.
- Quick start
- Build the provider
- IDE support
- Devcontainer support
- Testing
- Provider implementation guidance
- Coding conventions
- Commit message conventions
- Developer Certificate of Origin (DCO)
- Submitting changes
- Using AI assistants and LLM agents
- Releasing
Tip
$GOPATH is the path to your Go workspace. If undefined, it defaults to $HOME/go on Linux and macOS, and %USERPROFILE%\go on Windows.
Note
The provider requires Go 1.25 or later to build.
-
Clone the repository to:
$GOPATH/src/github.com/bpg/terraform-provider-proxmox:mkdir -p "${GOPATH}/src/github.com/bpg" cd "${GOPATH}/src/github.com/bpg" git clone git@github.com:bpg/terraform-provider-proxmox
-
Enter the provider directory and build it:
cd "${GOPATH}/src/github.com/bpg/terraform-provider-proxmox" make build
-
To cross-compile the provider for all supported platforms:
make release-build
The compiled binaries will be placed in the
distdirectory. -
Documentation for Framework resources and data sources is auto-generated from schema definitions. To regenerate it, run:
make docs
Note:
make docsdoes not affect SDK resource docs (proxmoxtf/), which are manually maintained indocs/.
If you are using VS Code, feel free to copy settings.json from .vscode/settings.example.json.
Prerequisites:
- Docker (or Docker Desktop) installed on your machine
- VS Code Remote - Containers extension
To launch the devcontainer:
- Open the project in VS Code.
- Run Remote-Containers: Open Folder in Container from the Command Palette.
See Developing inside a Container for more details.
The project has a test suite that must pass for contributions to be accepted. When making changes:
-
Run all tests with:
make test -
Add or modify test cases to cover your changes.
-
Ensure all tests pass before submitting your PR.
Acceptance tests run against a real Proxmox instance and verify the provider's functionality end-to-end.
Where to put tests: place acceptance tests alongside the resource or data source implementation (same package/folder) whenever possible. The shared fwprovider/test/ directory is reserved for cross-resource integration tests or cases that require expensive Proxmox setup shared across multiple suites.
Functional coverage: acceptance tests must cover all major use cases for the resource — not just one basic scenario. Test each distinct operational mode (e.g., different targeting strategies, list attributes with multiple elements, compound fields, nested objects). PRs with insufficient functional test coverage will be rejected during review. See ADR-006 for details.
-
A running Proxmox instance (see Development Proxmox Setup)
-
Create a
testacc.envfile in the project root with:TF_ACC=1 PROXMOX_VE_API_TOKEN="root@pam!<token name>=<token value>" PROXMOX_VE_ENDPOINT="https://<pve instance>:8006/" PROXMOX_VE_SSH_AGENT="true" PROXMOX_VE_SSH_USERNAME="root"
Optional configuration:
# Override default node name and SSH settings PROXMOX_VE_ACC_NODE_NAME="pve1" PROXMOX_VE_ACC_NODE_SSH_ADDRESS="10.0.0.11" PROXMOX_VE_ACC_NODE_SSH_PORT="22" PROXMOX_VE_ACC_IFACE_NAME="enp1s0"
Some tests require multi node cluster and a ZFS datastore to run. To include these (otherwise skipped) tests add additional configuration corresponding to the cluster.
PROXMOX_VE_ACC_NODE_2_NAME="pve2"
PROXMOX_VE_ACC_ZFS_DATASTORE_ID="zfs"Run the full acceptance test suite with:
make testaccTo run a single test or a group of tests, use the helper script:
./testacc <test_name>For example, to run all VM-related tests: ./testacc TestAccResourceVM.*
Note
- Acceptance test coverage is still in development.
- Only some resources and data sources are currently tested.
- Some tests may require specific Proxmox configuration.
You can test the provider locally before submitting changes:
-
Create a provider override configuration in one of these locations:
Linux/macOS (
$HOME/.terraformrc):provider_installation { dev_overrides { "bpg/proxmox" = "/home/user/go/bin/" # Replace with your $GOPATH/bin } direct {} }
Windows (
%APPDATA%/terraform.rc):provider_installation { dev_overrides { "bpg/proxmox" = "C:\\Users\\user\\go\\bin" # Replace with your %GOPATH%/bin } direct {} }
-
Build and install the provider:
go install . -
Test your changes:
terraform plan # Preview changes terraform apply # Apply changes
Tip
After the initial setup, you only need to run go install . when rebuilding the provider.
New resources and data sources must be implemented using the Terraform Plugin Framework. The framework provider lives under the fwprovider/ directory. The legacy SDK implementation in proxmoxtf/ is feature-frozen; PRs that add new SDK-based resources or data sources will not be accepted.
See docs/adr/reference-examples.md for annotated walkthroughs and a new-resource checklist. Quick summary:
| Complexity | Reference | When to use |
|---|---|---|
| Basic CRUD | SDN VNet (fwprovider/cluster/sdn/vnet/) |
Start here for any new resource |
| Many optional fields | Replication (fwprovider/cluster/replication/) |
Split create/update, CheckDelete, attribute.*PtrFromValue |
| Sensitive attributes | Metrics Server (fwprovider/cluster/metrics/) |
Sensitive fields, bool-to-int conversion |
| Cross-field validation | ACL (fwprovider/access/) |
ConfigValidators, custom import ID parsing |
Architecture decisions are documented in docs/adr/.
Documentation for Framework resources and data sources is auto-generated from schema definitions:
- Write descriptive schema attributes — Add
Descriptionand/orMarkdownDescriptionfields to your schema attributes. These become the docs. - Optional: Create a template — For custom formatting, create a template in
/templates/resources/or/templates/data-sources/. - Add a
go:generatedirective — For new resources/data sources, add acpcommand inmain.goto copy the generated doc frombuild/docs-gen/todocs/. - Run
make docs— This generates documentation in/docs/from schemas and templates.
Important
Do not manually edit files in /docs/ for Framework resources. Your changes will be overwritten by make docs. Edit schema descriptions or templates instead.
Documentation for SDK resources (proxmoxtf/) is manually maintained — edit the docs/ files directly. These are not affected by make docs.
Description vs MarkdownDescription:
| Field | Format | Used for |
|---|---|---|
Description |
Plain text | CLI help, simple tooltips |
MarkdownDescription |
Markdown | Registry docs, rich formatting |
- If only one is set, it's used for both purposes.
- Use
MarkdownDescriptionwhen you need inline code (backticks), links, or HTML (<br>). - Keep descriptions concise: explain what the attribute does, valid values, and defaults.
Example:
schema.StringAttribute{
Description: "The name of the VM.",
MarkdownDescription: "The name of the VM. Must be a valid DNS name (`[a-zA-Z0-9-]+`).",
Optional: true,
}When to use templates:
- Adding usage examples beyond auto-generated ones
- Custom warnings, notes, or formatting
- Import instructions with specific syntax
See existing templates in /templates/ for examples.
Admonitions in docs:
Use Terraform registry admonition syntax in /docs/ files and templates:
| Symbol | Type | Usage |
|---|---|---|
-> |
Note | General information, tips |
~> |
Warning | Cautions, important caveats |
!> |
Danger | Critical warnings, "do not use" |
Example:
-> Consider using `proxmox_virtual_environment_download_file` resource instead.
~> Never commit proxy configurations or credentials to the repository.
!> **DO NOT USE** — This resource is experimental and will change.For more details, see the Terraform Plugin Framework documentation on descriptions.
- Keep validation logic consistent across framework components.
- Place acceptance tests alongside the implementation (same package/folder).
- Reuse shared helpers from
fwprovider/attribute/(e.g.,StringPtrFromValue,Int64PtrFromValue,CustomBoolPtrFromValue,CheckDelete) andfwprovider/validators/.
We expect all code contributions to follow these guidelines:
- Code must pass linting with
golangci-lint- Run
make lintto format and lint your code (includes formatting viagolangci-lint fmt). - The project uses
.golangci.ymlfor linting configuration.
- Run
We follow the Conventional Commits specification. Please use the following types for your commits:
feat: New featuresfix: Bug fixeschore: Maintenance tasks
These types are used to automatically generate the changelog. Other types will be ignored.
Use the scope field to indicate the area of the codebase being changed:
vm– Virtual Machine resourceslxc– Container resourcesprovider– Provider configuration and resourcescore– Core libraries and utilitiesdocs– Documentationci– Continuous Integration / Actions / GitHub Workflows
Guidelines:
- Use lowercase for descriptions.
- Do not end descriptions with a period.
- Keep the first line under 72 characters.
Example:
feat(vm): add support for the `clone` operation
All contributions must be signed off according to the Developer Certificate of Origin (DCO). The DCO is a lightweight way of certifying that you wrote or have the right to submit the code you are contributing. It provides legal protection for the project by ensuring contributors have the necessary rights to their contributions and agree to license them under the project's terms. You can find the full text here.
To sign off your commits, add a Signed-off-by line to your commit message:
feat(vm): add support for the `clone` operation
Signed-off-by: Random Developer <random@developer.example.org>
Note
- Name: Use your real name (preferred) or GitHub username if you prefer privacy.
- Email: Use a valid email address (GitHub's 'noreply' email is acceptable for privacy, see GitHub docs).
- Auto-sign: If your Git config has
user.nameanduser.emailset, usegit commit -sto automatically add the sign-off.
For more details about the DCO checker, see the DCO app repo.
Please keep PRs small and focused. Small PRs are easier to review, easier to test, and get merged faster.
Guidelines:
- One change per PR: a single fix/feature, or a refactor with no behavior change.
- Avoid multi-resource PRs: if you need to change multiple resources/data sources, split the work into separate PRs (you can stack them and link follow-ups).
- Do not mix concerns: avoid combining formatting-only changes, refactors, and behavior changes in the same PR.
- Iterate quickly: open a draft/WIP PR early if you want feedback on approach before polishing edge cases.
Proof of work is mandatory for all code changes. Every PR must include evidence that the change works as expected:
- Test output (unit tests, acceptance tests)
- Logs, screenshots, or terminal output demonstrating the fix/feature
- Any other relevant information that demonstrates the change works as expected
Warning
PRs without proof of work may be rejected. Trivial changes (typo fixes, documentation-only updates that don't affect code behavior) are exempt from this requirement.
If you use AI assistants, they are expected to generate a proof of work document as a .dev/*_REPORT.md file. Review this file and use its contents when completing the PR template.
- Create a new PR against the
mainbranch using the project's pull request template. - Ensure your PR title follows the Conventional Commits specification (we use this as the squash commit message).
- Include proof of work in the PR description (test results, logs, screenshots).
- All commits in a PR are typically squashed on merge.
We welcome contributions that use AI assistants, LLM agents, or AI-powered coding tools. These tools can help with code generation, testing, documentation, and other development tasks.
Allowed and encouraged:
- Using AI assistants (GitHub Copilot, Cursor, Claude, ChatGPT, etc.) to help write code
- Using LLM agents to automate repetitive tasks
- Leveraging AI for test generation, documentation, or debugging
- Any tool that helps you complete the task effectively
Contributor responsibility:
While AI tools can assist with contributions, the person submitting the change is fully responsible for:
- Code quality and correctness — Review all AI-generated code carefully. You are accountable for what you submit.
- DCO sign-off — By signing off (
git commit -s), you personally certify that you have the right to submit the code under the project's license, regardless of how it was generated. - Reproducible proof of work — See Proof of work requirements above.
- Understanding the change — Be prepared to explain and defend your contribution during code review.
Important
The DCO sign-off is a legal certification. When you sign off on a commit, you are affirming that you wrote or have the right to submit the code, and that you agree to license it under the project's terms. This applies equally to human-written and AI-assisted code.
For AI agents working on this repository:
- CLAUDE.md — Development guidelines and critical rules
- GEMINI.md — PR review instructions
- .dev/README.md — Detailed workflow with skills (
/bpg:start-issue,/bpg:ready,/bpg:debug-api,/bpg:prepare-pr,/bpg:resume)
The skills automate common workflows like setting up branches, running checklists, and preparing PR submissions.
We use release-please GitHub Action for automated release management. The process works as follows:
- The action creates a release PR based on commit messages.
- The PR includes an auto-generated changelog and version bump.
- Maintainers review and merge the release PR.
- The release is automatically published to:
- GitHub Releases
- Terraform Registry
We aim to release new versions every 1–2 weeks.