{"slug":"terraform-overview","title":"Terraform Provider Overview","description":"The official DanubeData Terraform provider allows you to manage your cloud infrastructure using Infrastructure as Code (IaC). Deploy VPS instances, databases, caches, storage buckets, and more with ve...","section":"Terraform","url":"https://docs.danubedata.ro/terraform-overview","markdown_url":"https://docs.danubedata.ro/terraform-overview.md","breadcrumbs":[{"title":"Terraform","slug":null},{"title":"Overview","slug":"terraform-overview"}],"headings":[{"level":1,"title":"Terraform Provider Overview","id":"terraform-provider-overview"},{"level":2,"title":"Why Use Terraform?","id":"why-use-terraform"},{"level":2,"title":"Quick Start","id":"quick-start"},{"level":3,"title":"1. Install Terraform","id":"1-install-terraform"},{"level":3,"title":"2. Get Your API Token","id":"2-get-your-api-token"},{"level":3,"title":"3. Configure the Provider","id":"3-configure-the-provider"},{"level":3,"title":"4. Initialize and Apply","id":"4-initialize-and-apply"},{"level":2,"title":"Provider Configuration","id":"provider-configuration"},{"level":3,"title":"Authentication Methods","id":"authentication-methods"},{"level":2,"title":"Available Resources","id":"available-resources"},{"level":2,"title":"Available Data Sources","id":"available-data-sources"},{"level":2,"title":"Supported Datacenters","id":"supported-datacenters"},{"level":2,"title":"State Management","id":"state-management"},{"level":3,"title":"Using DanubeData Object Storage as Backend","id":"using-danubedata-object-storage-as-backend"},{"level":2,"title":"Importing Existing Resources","id":"importing-existing-resources"},{"level":2,"title":"Best Practices","id":"best-practices"},{"level":3,"title":"Give Each Environment Its Own State","id":"give-each-environment-its-own-state"},{"level":3,"title":"Use One Project per Environment","id":"use-one-project-per-environment"},{"level":3,"title":"Mark Sensitive Outputs","id":"mark-sensitive-outputs"},{"level":3,"title":"Use Terraform Cloud for Team Collaboration","id":"use-terraform-cloud-for-team-collaboration"},{"level":2,"title":"Troubleshooting","id":"troubleshooting"},{"level":3,"title":"Authentication Errors","id":"authentication-errors"},{"level":3,"title":"Provider Not Found","id":"provider-not-found"},{"level":3,"title":"Resource Timeouts","id":"resource-timeouts"},{"level":2,"title":"Next Steps","id":"next-steps"},{"level":2,"title":"Support","id":"support"}],"format":"markdown","word_count":1463,"content":"# Terraform Provider Overview\n\nThe official DanubeData Terraform provider allows you to manage your cloud infrastructure using Infrastructure as Code (IaC). Deploy VPS instances, databases, caches, storage buckets, and more with version-controlled, reproducible configurations.\n\n## Why Use Terraform?\n\n- **Version Control**: Track infrastructure changes in Git alongside your application code\n- **Reproducible Deployments**: Deploy identical environments across dev, staging, and production\n- **Team Collaboration**: Share configurations and collaborate with pull requests\n- **Drift Detection**: Detect and fix configuration drift automatically\n- **Cost Visibility**: Preview costs before deployment with `terraform plan`\n\n## Quick Start\n\n### 1. Install Terraform\n\nDownload and install Terraform from [terraform.io](https://www.terraform.io/downloads):\n\n```bash\n# macOS with Homebrew\nbrew tap hashicorp/tap\nbrew install hashicorp/tap/terraform\n\n# Ubuntu/Debian\nwget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg\necho \"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/hashicorp.list\nsudo apt update && sudo apt install terraform\n\n# Verify installation\nterraform version\n```\n\n### 2. Get Your API Token\n\n1. Log in to your DanubeData dashboard\n2. Navigate to **Settings > API Tokens**\n3. Click **Create New Token**\n4. Select the permissions you need (at minimum: read/write for resources you want to manage)\n5. Copy the token - it's shown only once!\n\n### 3. Configure the Provider\n\nCreate a new directory for your Terraform configuration:\n\n```bash\nmkdir my-infrastructure\ncd my-infrastructure\n```\n\nCreate a `main.tf` file:\n\n```hcl\nterraform {\n  required_providers {\n    danubedata = {\n      source  = \"AdrianSilaghi/danubedata\"\n      version = \"~> 0.1\"\n    }\n  }\n}\n\nprovider \"danubedata\" {\n  # API token is read from DANUBEDATA_API_TOKEN environment variable\n}\n```\n\nSet your API token as an environment variable:\n\n```bash\nexport DANUBEDATA_API_TOKEN=\"your-api-token-here\"\n```\n\n### 4. Initialize and Apply\n\n```bash\n# Initialize the provider\nterraform init\n\n# Preview changes\nterraform plan\n\n# Apply changes\nterraform apply\n```\n\n## Provider Configuration\n\nThe provider supports the following configuration options:\n\n| Attribute | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `api_token` | string | Yes | Your DanubeData API token. Can also be set via `DANUBEDATA_API_TOKEN` environment variable. |\n| `base_url` | string | No | API endpoint URL. Defaults to `https://danubedata.ro/api/v1`. Can be set via `DANUBEDATA_BASE_URL` environment variable. |\n\n### Authentication Methods\n\n**Recommended: Environment Variable**\n\n```bash\nexport DANUBEDATA_API_TOKEN=\"your-api-token\"\n```\n\n```hcl\nprovider \"danubedata\" {}\n```\n\n**Alternative: Direct Configuration** (not recommended for production)\n\n```hcl\nprovider \"danubedata\" {\n  api_token = \"your-api-token\"  # Don't commit this to version control!\n}\n```\n\n**Using Terraform Variables**\n\n```hcl\nvariable \"danubedata_token\" {\n  type      = string\n  sensitive = true\n}\n\nprovider \"danubedata\" {\n  api_token = var.danubedata_token\n}\n```\n\nThen set the variable:\n```bash\nexport TF_VAR_danubedata_token=\"your-api-token\"\n```\n\n## Available Resources\n\nThe provider includes the following resource types:\n\n| Resource | Description |\n|----------|-------------|\n| `danubedata_vps` | Virtual machines with shared or dedicated CPU |\n| `danubedata_database` | Managed MySQL, PostgreSQL, and MariaDB databases |\n| `danubedata_database_replica` | Read replicas for a managed database |\n| `danubedata_cache` | Redis, Valkey, and Dragonfly cache instances |\n| `danubedata_parameter_group` | Reusable database/cache configuration presets |\n| `danubedata_serverless` | Scale-to-zero serverless containers |\n| `danubedata_static_site` | Static site hosting |\n| `danubedata_static_site_domain` | Custom domain for a static site |\n| `danubedata_storage_bucket` | S3-compatible object storage buckets |\n| `danubedata_storage_access_key` | Access keys for object storage |\n| `danubedata_ssh_key` | SSH keys for VPS authentication |\n| `danubedata_firewall` | Network security rules |\n| `danubedata_vps_snapshot` | Point-in-time VPS backups |\n| `danubedata_database_snapshot` | Point-in-time database backups |\n| `danubedata_cache_snapshot` | Point-in-time cache backups |\n\nSee [Terraform Resources](https://docs.danubedata.ro/terraform-resources) for detailed documentation.\n\n## Available Data Sources\n\nThe provider includes these data sources for querying existing resources:\n\n| Data Source | Description |\n|-------------|-------------|\n| `danubedata_vpss` | List existing VPS instances |\n| `danubedata_vps_images` | List available OS images |\n| `danubedata_databases` | List existing databases |\n| `danubedata_database_providers` | List available database engines |\n| `danubedata_database_snapshots` | List database snapshots |\n| `danubedata_caches` | List existing cache instances |\n| `danubedata_cache_providers` | List available cache providers |\n| `danubedata_cache_snapshots` | List cache snapshots |\n| `danubedata_parameter_groups` | List parameter groups |\n| `danubedata_serverless_containers` | List serverless containers |\n| `danubedata_static_sites` | List static sites |\n| `danubedata_storage_buckets` | List storage buckets |\n| `danubedata_storage_access_keys` | List storage access keys |\n| `danubedata_ssh_keys` | List existing SSH keys |\n| `danubedata_firewalls` | List firewalls |\n| `danubedata_vps_snapshots` | List VPS snapshots |\n\nSee [Terraform Data Sources](https://docs.danubedata.ro/terraform-data-sources) for detailed documentation.\n\n## Supported Datacenters\n\nAll resources are deployed to our single datacenter:\n\n| Code | Location | Country |\n|------|----------|---------|\n| `fsn1` | Falkenstein | Germany |\n\n## State Management\n\nTerraform tracks your infrastructure state in a state file. The state — not your API token — records which resources Terraform already manages, so it is what decides whether a plan creates, changes or destroys something. For team collaboration, use a remote backend.\n\n### Using DanubeData Object Storage as Backend\n\n```hcl\nterraform {\n  backend \"s3\" {\n    bucket = \"terraform-state\"\n    key    = \"my-project/terraform.tfstate\"\n    region = \"fsn1\"\n\n    endpoints = { s3 = \"https://s3.danubedata.ro\" }\n\n    use_path_style              = true\n    use_lockfile                = true\n    skip_credentials_validation = true\n    skip_requesting_account_id  = true\n    skip_metadata_api_check     = true\n    skip_region_validation      = true\n    skip_s3_checksum            = true\n  }\n}\n```\n\nThe `skip_*` flags are required: our object storage is S3-compatible but is not AWS, so the AWS-specific credential, account-ID and metadata lookups have to be turned off. `use_lockfile = true` enables state locking against the bucket itself, with no DynamoDB table, so two CI runs cannot write the state at once — it needs Terraform 1.10 or later.\n\nSet S3 credentials from a storage access key:\n```bash\nexport AWS_ACCESS_KEY_ID=\"your-access-key\"\nexport AWS_SECRET_ACCESS_KEY=\"your-secret-key\"\n```\n\n## Importing Existing Resources\n\nYou can import existing DanubeData resources into Terraform management:\n\n```bash\n# Import a VPS instance\nterraform import danubedata_vps.my_server 12345\n\n# Import a database\nterraform import danubedata_database.my_db 67890\n\n# Import a storage bucket\nterraform import danubedata_storage_bucket.my_bucket abc123\n```\n\nFind resource IDs in the DanubeData dashboard or via the API.\n\n## Best Practices\n\n### Give Each Environment Its Own State\n\nSeparate environments need separate state. An API token decides which project a call goes to, but it does not change what Terraform already believes it manages — that comes from the state file.\n\n> **Do not point one root module at several environments by changing a variable.** If your state already holds a `production` resource and you re-run it with `environment = \"test\"`, Terraform does not create something new: it compares the config against the resource it already tracks and plans to replace it. Attributes such as `name`, `engine` and `database_name` cannot be changed on a running instance, so the plan comes back as `1 to add, 1 to destroy` — and the resource it destroys is the live production one.\n\nGive each environment its own root module, its own state key and its own token:\n\n```\nmodules/stack/       shared resource definitions, taking env as a variable\nenvs/prod/           key prod/terraform.tfstate,  production token\nenvs/test/           key test/terraform.tfstate,  test token\n```\n\nEach environment directory holds only a backend block, a provider block and a call to the shared module:\n\n```hcl\n# envs/test/main.tf\nterraform {\n  backend \"s3\" {\n    bucket = \"my-tfstate\"\n    key    = \"test/terraform.tfstate\"\n    # ...remaining backend settings as above\n  }\n}\n\nprovider \"danubedata\" {}   # token from DANUBEDATA_API_TOKEN\n\nmodule \"stack\" {\n  source = \"../../modules/stack\"\n  env    = \"test\"\n}\n```\n\nNow `terraform apply` in `envs/test/` starts from an empty state and creates the test resources, while production is untouched — because a different state file describes it.\n\nResource names are unique per project rather than globally, so the same name can be used in every environment and only values that must differ, such as a database's initial database name, need to include `var.env`.\n\nTerraform workspaces are an alternative, but the API token still has to change per environment through the shell environment, so separate root modules are harder to get wrong.\n\n### Use One Project per Environment\n\nCreate a separate project (team) for each environment and issue each one its own API token, scoped to that project. Projects are the isolation boundary on our side: separate Kubernetes namespace, separate quotas and separate billing lines.\n\n### Mark Sensitive Outputs\n\n```hcl\noutput \"database_password\" {\n  value     = danubedata_database.main.password\n  sensitive = true\n}\n```\n\n### Use Terraform Cloud for Team Collaboration\n\nFor larger teams, consider using Terraform Cloud for:\n- Remote state management\n- Policy enforcement\n- VCS integration\n- Cost estimation\n\n## Troubleshooting\n\n### Authentication Errors\n\nIf you see \"401 Unauthorized\":\n1. Verify your API token is correct\n2. Check the token has the required permissions\n3. Ensure the `DANUBEDATA_API_TOKEN` environment variable is set\n\n### Provider Not Found\n\nIf Terraform can't find the provider:\n```bash\nterraform init -upgrade\n```\n\n### Resource Timeouts\n\nFor long-running operations, configure timeouts:\n\n```hcl\nresource \"danubedata_vps\" \"app\" {\n  # ...\n\n  timeouts {\n    create = \"10m\"\n    update = \"10m\"\n    delete = \"5m\"\n  }\n}\n```\n\n## Next Steps\n\n- [Terraform Resources](https://docs.danubedata.ro/terraform-resources) - Detailed resource documentation\n- [Terraform Data Sources](https://docs.danubedata.ro/terraform-data-sources) - Query existing resources\n- [Terraform Examples](https://docs.danubedata.ro/terraform-examples) - Real-world configuration examples\n- [Terraform Registry](https://registry.terraform.io/providers/AdrianSilaghi/danubedata/latest) - Official provider documentation\n\n## Support\n\n- **Documentation**: [registry.terraform.io/providers/AdrianSilaghi/danubedata](https://registry.terraform.io/providers/AdrianSilaghi/danubedata/latest/docs)\n- **GitHub Issues**: Report bugs and request features\n- **Contact Support**: Reach out to our support team for help\n","prev":{"title":"Failure Codes","slug":"failure-codes","url":"https://docs.danubedata.ro/failure-codes","markdown_url":"https://docs.danubedata.ro/failure-codes.md","json_url":"https://docs.danubedata.ro/failure-codes.json"},"next":{"title":"Resources","slug":"terraform-resources","url":"https://docs.danubedata.ro/terraform-resources","markdown_url":"https://docs.danubedata.ro/terraform-resources.md","json_url":"https://docs.danubedata.ro/terraform-resources.json"},"index_url":"https://docs.danubedata.ro/index.json"}