README
¶
Terraform Provider for evroc
Official Terraform provider for the evroc Cloud Platform
Manage your evroc infrastructure as code with Terraform or OpenTofu
Declaratively manage your evroc cloud infrastructure — provision VMs, configure networks, manage storage, and control access. Version control your infrastructure, preview changes before applying, and collaborate with your team.
OpenTofu compatible: This provider works with both Terraform and OpenTofu. All examples below use
terraformcommands, buttofuworks identically.
Capabilities
| Resource | What you can manage |
|---|---|
| Compute | Virtual machines, disks, disk attachments, placement groups |
| Networking | Public IPs, security groups |
| Storage | S3-compatible buckets and service accounts |
| IAM | Projects, permission sets, service accounts, role bindings |
Requirements
- Terraform 1.0+ or OpenTofu 1.9+
- evroc cloud account with API access
- Go 1.25+ (for building from source only)
Installation
Option 1: From Registry (Recommended)
The provider is published on both the OpenTofu Registry and the Terraform Registry. No manual download needed — just declare it in your configuration.
Configure your project — create a main.tf file:
terraform {
required_providers {
evroc = {
source = "evroc-oss/evroc"
}
}
}
provider "evroc" {}
Then initialize the provider:
terraform init
This downloads and installs the provider from the registry. No infrastructure is created yet — you'll define resources in the next sections, then iterate with terraform plan and terraform apply to preview and apply changes.
Upgrading the Provider
To upgrade to a newer version of the provider, update the version constraint in your main.tf:
terraform {
required_providers {
evroc = {
source = "evroc-oss/evroc"
}
}
}
Then run:
terraform init -upgrade
This fetches the new version and updates the lock file (.terraform.lock.hcl). Review the CHANGELOG before upgrading for any breaking changes.
Tip: Use
terraform providers lockto pre-generate lock file entries for multiple platforms (useful for CI/CD and team collaboration).
Option 2: Download from GitHub Releases
For air-gapped environments or when you need a specific binary.
Linux / macOS
# Fetch latest version automatically
VERSION=$(curl -s https://api.github.com/repos/evroc-oss/terraform-provider-evroc/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')
OS="linux" # or: darwin
ARCH="amd64" # or: arm64
# Download and extract
curl -LO "https://github.com/evroc-oss/terraform-provider-evroc/releases/download/v${VERSION}/terraform-provider-evroc_${VERSION}_${OS}_${ARCH}.zip"
unzip terraform-provider-evroc_${VERSION}_${OS}_${ARCH}.zip
# Install to the local plugin directory
mkdir -p ~/.terraform.d/plugins/evroc-oss/evroc/${VERSION}/${OS}_${ARCH}/
mv terraform-provider-evroc_v${VERSION} ~/.terraform.d/plugins/evroc-oss/evroc/${VERSION}/${OS}_${ARCH}/
Windows
$VERSION = (Invoke-RestMethod -Uri "https://api.github.com/repos/evroc-oss/terraform-provider-evroc/releases/latest").tag_name -replace '^v',''
New-Item -ItemType Directory -Force -Path "$env:APPDATA\terraform.d\plugins\evroc-oss\evroc\$VERSION\windows_amd64"
Move-Item terraform-provider-evroc_v$VERSION.exe "$env:APPDATA\terraform.d\plugins\evroc-oss\evroc\$VERSION\windows_amd64\"
Option 3: Build from Source
For development or when you need the latest unreleased changes.
git clone https://github.com/evroc-oss/terraform-provider-evroc.git
cd terraform-provider-evroc
make install
This builds the provider and installs it to ~/.terraform.d/plugins/github.com/evroc-oss/evroc/<VERSION>/linux_amd64/ (or %APPDATA%\terraform.d\plugins\ on Windows), where <VERSION> is the Makefile's VERSION variable.
Configure Terraform to use the local build — create (or update) ~/.terraformrc (Linux/macOS) or %APPDATA%\terraform.rc (Windows) with a dev_overrides block. For OpenTofu, use ~/.tofurc or %APPDATA%\tofu.rc instead.
provider_installation {
dev_overrides {
"evroc-oss/evroc" = "/home/<your-user>/.terraform.d/plugins/evroc-oss/evroc/<VERSION>/linux_amd64"
}
direct {}
}
The version in the path must match the version used by
make install. Check theVERSIONvariable in the Makefile for the current default. If you override it (e.g.make install VERSION=1.0.0), update the path accordingly.
Adjust the path for your OS/architecture (e.g., darwin_arm64 for Apple Silicon). On Windows, use forward slashes: C:/Users/<your-user>/AppData/Roaming/terraform.d/plugins/....
Important: When using
dev_overrides, skipterraform initand go directly toterraform plan/terraform apply.
Use the same main.tf as Option 1 above, but omit the version constraint (dev_overrides bypasses version checks).
Quick Start
1. Authenticate with evroc
The provider supports service account authentication (recommended for CI/CD) and token-based authentication. Credentials are resolved in this order:
- Explicit provider attributes (in the
provider "evroc" {}block) - Environment variables (
EVROC_SERVICE_ACCOUNT_ID,EVROC_TOKEN, etc.) - evroc CLI config file (
~/.evroc/config.yaml)
Option A: Use the evroc CLI (Recommended)
Install the evroc CLI and log in:
evroc login
This creates ~/.evroc/config.yaml with your credentials, project, and region. The Terraform provider reads this file automatically — no further configuration needed. Just use an empty provider block:
provider "evroc" {}
Tip: If you already use the evroc CLI, you're all set. The provider reads the same
~/.evroc/config.yamlthatevroc logincreates. No additional setup is required.
Option B: Environment variables
Set credentials directly via environment variables. This is useful for CI/CD pipelines or when using service accounts:
# Service account authentication (recommended for CI/CD)
export EVROC_SERVICE_ACCOUNT_ID="sa-cicd-pipeline"
export EVROC_SERVICE_ACCOUNT_SECRET="<base64-encoded JWK or path to key file>"
export EVROC_PROJECT="your-project-uuid"
export EVROC_REGION="se-sto"
# OR token-based authentication (extract refresh_token from ~/.evroc/config.yaml after `evroc login`)
export EVROC_REFRESH_TOKEN="your-refresh-token"
export EVROC_PROJECT="your-project-uuid"
export EVROC_REGION="se-sto"
Then use an empty provider block:
provider "evroc" {}
Creating a service account: See the
examples/service-account/directory for a complete walkthrough — create a service account, assign roles, generate credentials, and configure your CI/CD runner.
Important: Service account credentials have an expiration date (
expires_at) and the private key is only returned once at creation time. Store it securely. Plan for credential rotation before expiry.
Option C: Explicit provider attributes
# Service account authentication (recommended for CI/CD)
provider "evroc" {
service_account_id = var.evroc_sa_id
service_account_secret = var.evroc_sa_secret
project = "your-project-id"
region = "se-sto"
organization = "your-organization-id" # Only needed for IAM project creation
}
# OR token-based authentication (refresh_token from ~/.evroc/config.yaml after `evroc login`)
provider "evroc" {
refresh_token = var.evroc_refresh_token
project = "your-project-id"
region = "se-sto"
organization = "your-organization-id" # Only needed for IAM project creation
}
Option D: Custom config file (for CI/CD or service accounts)
Point the provider at a dedicated config file. This is useful for CI/CD pipelines or service account credentials that you don't want in ~/.evroc/config.yaml (which is managed by evroc login):
provider "evroc" {
config_file = "/path/to/my-terraform-config.yaml"
}
The config file format:
auth:
# Service account authentication (recommended for CI/CD):
service_account_id: "sa-cicd-pipeline"
service_account_secret: "<base64-encoded JWK or path to key file>"
# OR token-based authentication:
# refresh_token: "your-refresh-token"
context:
project: "your-project-uuid"
region: "se-sto"
organization: "your-organization-uuid" # Optional, only for IAM project creation
Note: Do not edit
~/.evroc/config.yamlmanually — that file is managed byevroc login. If you need a custom config, create a separate file and reference it withconfig_file.
Finding your IDs: Your organization and project IDs are visible in the evroc console under the project settings page. You can also extract them from the console URL:
https://cloud.evroc.com/?rgFullPath=%2F{organization-id}%2F{project-id}
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^
Note: The console and CLI use id and name for what Terraform calls
nameanddisplay_nameon theevroc_projectresource.
2. Create Your First VM
Create a file named main.tf:
terraform {
required_providers {
evroc = {
source = "evroc-oss/evroc"
}
}
}
# Credentials are read automatically from ~/.evroc/config.yaml (created by `evroc login`)
provider "evroc" {}
# Query available disk images and compute profiles (optional)
data "evroc_disk_images" "available" {}
data "evroc_compute_profiles" "available" {}
# Create a security group allowing SSH access
resource "evroc_security_group" "allow_ssh" {
name = "allow-ssh"
rule {
name = "allow-ssh"
direction = "Ingress"
protocol = "TCP"
port = 22
remote_ip = "0.0.0.0/0"
}
rule {
name = "allow-all-egress"
direction = "Egress"
protocol = "TCP"
port = 0 # 0 means all ports
remote_ip = "0.0.0.0/0"
}
}
# Create a public IP for the VM
resource "evroc_public_ip" "vm" {
name = "vm-public-ip"
}
# Create a boot disk with Ubuntu 24.04
resource "evroc_disk" "boot" {
name = "vm-boot-disk"
size = 20
image = data.evroc_disk_images.available.ubuntu_minimal_24_04_1
zone = "a"
}
# Create the virtual machine
resource "evroc_virtual_machine" "web" {
name = "web-server"
flavor = data.evroc_compute_profiles.available.a1a_s
boot_disk = evroc_disk.boot.fqid
zone = "a"
# Attach public IP
public_ip = evroc_public_ip.vm.fqid
# Attach security group
security_groups = [evroc_security_group.allow_ssh.fqid]
# Add your SSH public key
ssh_keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@example.com"
]
# Custom cloud-init replaces the default, so you must include the SSH user
# setup to keep SSH access working. Add your packages/files after the user block.
cloud_config_user_data = <<-EOF
## template: jinja
#cloud-config
ssh_pwauth: false
manage_etc_hosts: localhost
users:
- name: evroc-user
gecos: evroc VM user
lock_passwd: true
sudo: ALL=(ALL) NOPASSWD:ALL
groups:
- sudo
shell: /bin/bash
{% if public_ssh_keys %}
ssh_authorized_keys:
{% for pubkey in public_ssh_keys %}
- {{ pubkey }}
{% endfor %}
{% endif %}
package_update: true
packages:
- nginx
write_files:
- path: /var/www/html/index.html
content: "<h1>Hello from evroc!</h1>"
EOF
}
# Output the public IP address and SSH command
output "web_server_ip" {
value = evroc_virtual_machine.web.public_ipv4_address
description = "Public IP address of the web server"
}
output "ssh_command" {
value = "ssh evroc-user@${evroc_virtual_machine.web.public_ipv4_address}"
description = "SSH command to connect to the VM"
}
3. Deploy Your Infrastructure
# Preview what will be created
# Preview what will be created
terraform plan
# Apply the configuration to create resources
terraform apply
# When prompted, type 'yes' to confirm
After a few minutes, your VM will be running! You can SSH into it:
# Get the SSH command from the output
# Get the SSH command from Terraform output
terraform output -raw ssh_command
# Or manually
ssh evroc-user@$(terraform output -raw web_server_ip)
4. Clean Up
When you're done testing:
# Destroy all resources
# Destroy all resources created by Terraform
terraform destroy
Examples
Complete, production-ready examples in the examples/ directory:
- basic - Complete VM with public IP and security group (great starting point)
- virtual-machine - Simple VM with nginx
- complete - Full production setup with web server and cloud-init
- k3s-cluster - Kubernetes cluster with control plane and workers
- networking - Security groups and public IP management
- multi-project - Security policy shared across multiple projects using provider aliases
- storage - S3-compatible buckets with service accounts
- disk - Disk creation and management
- disk-attachment - Hot-attach disks to running VMs
- placement-groups - VM placement strategies for high availability
- loadbalancer - HA k3s control plane behind an L4 load balancer across 3 zones
- service-account - IAM service accounts with role bindings and credentials for CI/CD
- public-ip - Public IP allocation
- project - Project management
Documentation
Provider Configuration
The provider supports multiple authentication methods (see Quick Start for details).
Environment variable reference:
| Provider Attribute | Environment Variable | Notes |
|---|---|---|
service_account_id |
EVROC_SERVICE_ACCOUNT_ID |
Service account auth (recommended for CI/CD) |
service_account_secret |
EVROC_SERVICE_ACCOUNT_SECRET |
Base64-encoded JWK or path to key file |
token |
EVROC_TOKEN |
Access token |
refresh_token |
EVROC_REFRESH_TOKEN |
For automatic token renewal |
project |
EVROC_PROJECT |
Required |
region |
EVROC_REGION |
Defaults to se-sto |
organization |
EVROC_ORGANIZATION |
Only for IAM project creation |
config_file |
EVROC_CONFIG_FILE |
Path to SDK config YAML |
api_endpoint |
EVROC_API_ENDPOINT |
Defaults to https://api.cloud.evroc.com |
Remote State Backend (evroc S3)
You can use an evroc S3-compatible bucket to store your state remotely. This enables team collaboration and state locking. Works with both OpenTofu and Terraform.
1. Create a bucket and service account (via Terraform or the console), then configure the backend:
terraform {
backend "s3" {
bucket = "<bucket-name>"
key = "terraform.tfstate"
region = "se-sto"
endpoints = {
s3 = "https://s3.se-sto.evroc.com"
}
access_key = "<access-key>"
secret_key = "<secret-key>"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
skip_requesting_account_id = true
skip_s3_checksum = true
use_path_style = true
}
}
2. Alternatively, set credentials via environment variables to keep them out of your configuration:
export AWS_ACCESS_KEY_ID="<access-key>"
export AWS_SECRET_ACCESS_KEY="<secret-key>"
Then omit access_key and secret_key from the backend block.
Note: The
skip_*flags are required because evroc S3 is not AWS — they disable AWS-specific validation that would otherwise fail.
Resources
| Resource | Description |
|---|---|
evroc_virtual_machine |
Virtual machine instances with networking |
evroc_disk |
Persistent block storage volumes |
evroc_hotswap_disk_attachment |
Attach disks to VMs (hot-attach supported) |
evroc_public_ip |
Public IPv4 addresses |
evroc_security_group |
Network firewall rules (ingress/egress) |
evroc_placement_group |
VM placement strategies (spread) |
evroc_bucket |
S3-compatible object storage |
evroc_bucket_service_account |
S3 access credentials |
evroc_project |
Project management |
evroc_permission_set |
IAM permission sets |
evroc_loadbalancer |
Layer 4 (TCP) load balancer with backend pool |
evroc_service_account |
IAM service accounts for programmatic API access |
evroc_service_account_credential |
Credentials (JWK key pairs) for service accounts |
evroc_role_binding |
Bind IAM roles to users or service accounts |
Data Sources
| Data Source | Description |
|---|---|
evroc_disk_images |
List available OS images with named attributes |
evroc_compute_profiles |
List VM sizes/flavors with named attributes |
evroc_virtual_machine |
Look up existing VMs |
evroc_disk |
Look up existing disks |
evroc_hotswap_disk_attachment |
Look up existing disk attachments |
evroc_public_ip |
Look up existing public IPs |
evroc_security_group |
Look up existing security groups |
evroc_placement_group |
Look up existing placement groups |
evroc_bucket |
Look up existing buckets |
evroc_bucket_service_account |
Look up existing bucket service accounts |
evroc_bucket_service_account_secret |
Retrieve S3 credentials for a bucket service account |
evroc_project |
Look up existing projects |
evroc_permission_set |
Look up existing permission sets |
evroc_loadbalancer |
Look up existing load balancers |
evroc_service_account |
Look up existing IAM service accounts |
evroc_service_account_credential |
Look up existing service account credentials |
evroc_roles |
List available IAM roles |
Key Fields Reference
Zone (Required)
All disk and VM resources require a zone field:
zone = "a"- Zone azone = "b"- Zone bzone = "c"- Zone c
Image Names
Use data source for current images:
data "evroc_disk_images" "available" {}
resource "evroc_disk" "boot" {
image = data.evroc_disk_images.available.ubuntu_minimal_24_04_1
# Other options: ubuntu_22_04_1, rocky_9_6_1, opensuse_15_6_1, etc.
}
VM Flavors
Use data source for available sizes:
data "evroc_compute_profiles" "available" {}
resource "evroc_virtual_machine" "vm" {
flavor = data.evroc_compute_profiles.available.a1a_s
# Other options: a1a_m, a1a_l, c1a_s, m1a_s, etc.
}
Security Group Rules
resource "evroc_security_group" "example" {
name = "example-sg"
rule {
name = "allow-https"
direction = "Ingress" # or "Egress"
protocol = "TCP" # or "UDP"
port = 443 # 0 means all ports
remote_ip = "0.0.0.0/0"
}
}
Testing
See TESTING.md for comprehensive testing documentation.
Importing Existing Infrastructure
Already have evroc resources deployed? You can bring them under management without recreating anything.
Option A: Automated discovery (recommended)
Use the included script to enumerate all resources in your project and generate import blocks:
# Requires: evroc CLI installed and authenticated (evroc login)
./scripts/generate-imports.sh ./my-project
# Output:
# my-project/provider.tf - Provider configuration
# my-project/imports.tf - Import blocks for all discovered resources
# Then generate the .tf configuration:
cd my-project
terraform plan -generate-config-out=generated.tf
# Review generated.tf, adjust as needed, then:
terraform apply
Set EVROC_CLI if the binary isn't in your PATH:
EVROC_CLI=/path/to/evroc ./scripts/generate-imports.sh ./my-project
Option B: Manual import (single resources)
For importing individual resources, use the native import block:
import {
to = evroc_virtual_machine.web
id = "my-vm-name"
}
Then run:
terraform plan -generate-config-out=generated.tf
The provider's Read function is called and the full resource block is written into generated.tf.
Features
- Declarative Infrastructure - Define your desired state, the tool handles the rest
- Plan Before Apply - Preview changes before making them
- Dependency Management - Automatic resource dependency resolution
- State Management - Track infrastructure state and detect drift
- Import Existing Resources - Bring existing evroc resources under Terraform management
- Parallel Execution - Create/update/delete resources concurrently when possible
- Type Safety - Validate configuration before deployment
- Service Account Auth - JWT-based authentication for CI/CD pipelines and automation
- Token Auto-Refresh - Automatic token refresh using refresh tokens
- Resource Waiters - Built-in waiting for async operations (VM/disk creation)
Security
All evroc Terraform Provider releases are cryptographically signed and attested to ensure authenticity and integrity.
Release Security
Every release includes:
- GPG Signatures - Required by Terraform Registry, signs the SHA256SUMS file (
*.sig) - Cosign Signatures - Keyless signing using GitHub OIDC (
*.cosign.sig) - SBOM - Software Bill of Materials for dependency transparency
- SLSA Provenance - Build integrity attestations proving official build process
Verify Before Use
Quick verification with Cosign (recommended):
# Fetch latest version automatically
VERSION="v$(curl -s https://api.github.com/repos/evroc-oss/terraform-provider-evroc/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')"
BASE_URL="https://github.com/evroc-oss/terraform-provider-evroc/releases/download/${VERSION}"
# Download checksums and signature
curl -LO "${BASE_URL}/terraform-provider-evroc_${VERSION#v}_SHA256SUMS"
curl -LO "${BASE_URL}/terraform-provider-evroc_${VERSION#v}_SHA256SUMS.cosign.sig"
curl -LO "${BASE_URL}/terraform-provider-evroc_${VERSION#v}_SHA256SUMS.pem"
# Verify (requires cosign: brew install cosign)
cosign verify-blob \
terraform-provider-evroc_${VERSION#v}_SHA256SUMS \
--signature terraform-provider-evroc_${VERSION#v}_SHA256SUMS.cosign.sig \
--certificate terraform-provider-evroc_${VERSION#v}_SHA256SUMS.pem \
--certificate-identity-regexp="^https://github.com/evroc-oss/terraform-provider-evroc/" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"
For complete verification instructions, see docs/VERIFICATION.md
Reporting Security Issues
If you discover a security vulnerability, please contact security@evroc.com. Do not open public issues for security vulnerabilities.
Repository Layout
.
├── main.go # Provider entry point
├── internal/provider/ # Provider implementation
│ ├── provider.go # Provider configuration and client setup
│ ├── resource_*.go # Resource implementations
│ ├── data_source_*.go # Data source implementations
│ ├── resource_*_test.go # Acceptance tests per resource
│ ├── helpers.go # SDK builder helper functions
│ ├── utils.go # Shared utilities
│ └── validators.go # Input validators
├── docs/ # Generated documentation (tfplugindocs)
│ ├── resources/ # Resource documentation
│ └── data-sources/ # Data source documentation
├── examples/ # Terraform example configurations
├── scripts/ # Build and release scripts
├── .github/workflows/ # GitHub Actions CI/CD
├── .goreleaser.yml # GoReleaser configuration
├── CHANGELOG.md # Version history (Keep a Changelog)
├── TESTING.md # Acceptance testing guide
└── LICENSE # Apache 2.0
Development
Building from Source
# Clone the repository
git clone https://github.com/evroc-oss/terraform-provider-evroc.git
cd terraform-provider-evroc
# Download dependencies
make deps
# Build the provider
make build
# Run tests
make test
# Run linters
make lint
# Install locally for testing (see Installation > Option 1 for full setup)
make install
# Run acceptance tests (requires evroc credentials)
make testacc
Available Make Targets
make build # Build the provider binary
make install # Install locally for testing
make test # Run unit tests
make testacc # Run acceptance tests
make fmt # Format code
make lint # Run linters
make vet # Run go vet
make clean # Clean build artifacts
make deps # Download Go dependencies
make docs # Generate documentation (requires tfplugindocs)
make coverage # Run tests with coverage report
Contributing
This project does not accept external contributions. If you encounter a bug or have a feature request, please report it through evroc support.
Support
Support level: Best-effort — evroc will address issues as time permits, with no guaranteed SLA. All issues should be reported through evroc support channels.
- Support: support@evroc.com
- Documentation: docs/
- Examples: examples/
- Go SDK: github.com/evroc-oss/evroc-go-sdk
Versioning and Deprecation
This project follows Semantic Versioning.
- Breaking changes only occur in major version releases.
- Deprecated features are announced at least one minor version in advance.
- Deprecation notices are documented in the CHANGELOG and may include runtime warnings.
- Security fixes are provided for the current major version and one prior major version.
If this project reaches end-of-life, the README will be updated with archived status and a final release will be made.
License
Apache License 2.0 - see LICENSE file
Documentation
¶
There is no documentation for this package.