terraform-provider-remnawave

command module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 4 Imported by: 0

README

Terraform Provider for Remnawave

CI Terraform Registry Latest Release Go Version Context7

A community Terraform provider for Remnawave — a modern proxy management panel built on top of Xray-core. Manage VPN users, nodes, hosts, squads, billing, subscription pages, and more as infrastructure-as-code.


Table of Contents

Why Terraform + Remnawave?

Without Terraform With this provider
Create users one-by-one in the web UI Define hundreds of users in HCL, terraform apply
Manual config drift between nodes Version-controlled, reproducible node configs
No audit trail for changes Git history + Terraform plan/apply logs
Onboarding = manual clicks Onboarding = terraform init && terraform apply

Compatibility

The provider supports Remnawave panel v2.7.x and v2.8.x. The acceptance test suite runs against both versions in CI on every push to main and every pull request — see the full CI matrix.

Remnawave version Status
v2.8.0 ✅ Tested (primary)
v2.7.4 ✅ Tested (matrix)

The client auto-detects the backend version via /api/system/metadata on the first API-token operation and adapts API calls where contracts differ between versions. No configuration is required.

Quick Start

terraform {
  required_providers {
    remnawave = {
      source  = "batonogov/remnawave"
      version = "~> 0.4.0"
    }
  }
}

provider "remnawave" {
  endpoint  = "https://panel.example.com"
  api_token = var.remnawave_api_token
}

# ─── VPN user with 10 GB traffic limit ───
resource "remnawave_user" "john" {
  username            = "john-doe"
  expire_at           = "2027-01-01T00:00:00.000Z"
  traffic_limit_bytes = 10737418240 # 10 GB
  traffic_limit_strategy = "MONTH"
  description         = "Managed by Terraform"
}

# ─── Xray node ───
resource "remnawave_config_profile" "default" {
  name   = "default-profile"
  config = file("xray-config.json")
}

resource "remnawave_node" "de-fra-01" {
  name                 = "de-fra-01"
  address              = "1.2.3.4"
  port                 = 443
  config_profile_uuid  = remnawave_config_profile.default.uuid
  config_profile_inbounds = [remnawave_config_profile.default.inbounds[0].uuid]
}

# ─── Connection host ───
resource "remnawave_host" "de-fra-01-vless" {
  remark                  = "🇩🇪 Frankfurt"
  address                 = "vpn.example.com"
  port                    = 443
  inbound = {
    config_profile_uuid         = remnawave_config_profile.default.uuid
    config_profile_inbound_uuid = remnawave_config_profile.default.inbounds[0].uuid
  }
}

# ─── Monitor system health ───
data "remnawave_system_stats" "current" {}

output "online_users" {
  value = data.remnawave_system_stats.current.online_now
}

Authentication

The provider supports two authentication methods:

Generate a token in the panel under API Keys and pass it via the api_token attribute or the REMNAWAVE_API_TOKEN environment variable. This is a static JWT — no login round-trip, works with scoped permissions.

provider "remnawave" {
  endpoint  = "https://panel.example.com"
  api_token = var.remnawave_api_token
}
Username / Password

If no API token is provided, the provider logs in via POST /api/auth/login and obtains a JWT automatically. The token is refreshed on 401 responses.

provider "remnawave" {
  endpoint = "https://panel.example.com"
  username = "admin"
  password = var.remnawave_password
}

Note: Username/password auth requires setting proxy_headers = true or NODE_ENV=dev on the backend — Remnawave's ProxyCheckMiddleware requires X-Forwarded-For/X-Forwarded-Proto headers for browser-originated requests.

Provider Configuration

All provider attributes can be supplied through environment variables — the provider block may be empty when the environment is configured. Explicit HCL values take precedence over environment variables.

Attribute Env var Type Description
endpoint REMNAWAVE_ENDPOINT string Base URL of the panel, e.g. https://panel.example.com
api_token REMNAWAVE_API_TOKEN string (sensitive) Pre-generated API token (JWT). If set, username/password are ignored
username REMNAWAVE_USERNAME string Admin username for login
password REMNAWAVE_PASSWORD string (sensitive) Admin password for login
insecure_skip_verify REMNAWAVE_INSECURE_SKIP_VERIFY bool Skip TLS certificate verification (true/false)
request_timeout REMNAWAVE_REQUEST_TIMEOUT string HTTP client timeout (default 30s)
proxy_headers REMNAWAVE_PROXY_HEADERS bool Send X-Forwarded-For/Proto headers (bypass ProxyCheckMiddleware)

Resources

The provider exposes 24 resources across 6 functional areas:

Core VPN Management
Resource Description
remnawave_user VPN user with traffic limits, expiration, VLESS/Trojan/Shadowsocks credentials
remnawave_node Xray server node with traffic tracking, tags, consumption multipliers
remnawave_host Connection endpoint (host) for VPN subscriptions
remnawave_config_profile Xray config profile with inbounds, routing, sniffing
Access Control & Routing
Resource Description
remnawave_external_squad External squad (managed by name)
remnawave_internal_squad Internal squad with inbounds and accessible nodes
remnawave_subscription_template Subscription template (XRAY_JSON, MIHOMO, CLASH, SINGBOX, etc.)
remnawave_subscription_settings Subscription page settings (singleton)
remnawave_subpage_config Subscription page config (i18n, theme, blocks)
Panel & Branding
Resource Description
remnawave_panel_settings Panel branding, auth, passkey settings (singleton)
remnawave_snippet Xray config snippet (reusable JSON fragments)
remnawave_node_plugin Node plugin (e.g. torrent blocker)
Infrastructure Billing
Resource Description
remnawave_infra_provider Infrastructure billing provider
remnawave_billing_node Infrastructure billing node (recurring billing)
remnawave_billing_history Infrastructure billing history record (one-time payment)
API & Access Tokens
Resource Description
remnawave_api_token API token with scopes and expiration
remnawave_passkey WebAuthn passkey (import-only — cannot be created via Terraform)
Metadata & Devices
Resource Description
remnawave_user_metadata Free-form key-value metadata for a user
remnawave_node_metadata Free-form key-value metadata for a node
remnawave_hwid_device HWID device entry for device-limit enforcement
Imperative Actions

These resources trigger one-shot operations on terraform apply. Use the triggers attribute to force re-execution when external values change.

Resource Description
remnawave_node_action Enable / disable / restart / reset traffic on a node
remnawave_user_action Enable / disable / reset traffic / revoke subscription on a user
remnawave_host_bulk_action Bulk enable / disable / delete hosts
remnawave_drop_connections Drop active connections for a user

Data Sources

23 data sources for reading panel state:

Inventory
Data Source Description
remnawave_nodes List all nodes with status and online user counts
remnawave_users List all users with status and tags
remnawave_hosts List all hosts
remnawave_config_profiles List all config profiles
remnawave_host_tags List all unique host tags
remnawave_passkeys List WebAuthn passkeys for the current admin
System & Health
Data Source Description
remnawave_system_health Panel system health (raw JSON)
remnawave_system_stats CPU, memory, uptime, user status counts, online stats
remnawave_system_recap Monthly/total summary: users, traffic, nodes, version
remnawave_system_bandwidth_stats System-level bandwidth statistics
remnawave_system_nodes_stats System-level per-node statistics
Bandwidth & Metrics
Data Source Description
remnawave_nodes_metrics Per-node live metrics: users online, inbounds/outbounds
remnawave_bandwidth_stats Per-node bandwidth usage by date range
remnawave_bandwidth_stats_user Per-user bandwidth usage by date range
remnawave_bandwidth_realtime Realtime bandwidth metrics per node
Subscriptions
Data Source Description
remnawave_subscriptions Fetch subscription by UUID/username/short UUID
remnawave_subscription_request_history Subscription request history
remnawave_subscription_request_history_stats Subscription request statistics
remnawave_connection_keys Per-protocol connection keys for a user
Other
Data Source Description
remnawave_keygen Panel public key for node setup
remnawave_user_ips Fetch IPs a user is currently connected from
remnawave_hwid_stats HWID device statistics
remnawave_hwid_top_users Top users by HWID device count

Examples

Browse the examples/ directory for complete, copy-paste-ready configurations:

examples/
├── resources/
│   ├── remnawave_user/            # User with traffic limit + tag
│   ├── remnawave_node_action/     # Periodic traffic reset via triggers
│   ├── remnawave_host_bulk_action/# Bulk enable/disable/delete
│   ├── remnawave_user_action/     # Enable/disable/reset/revoke
│   └── remnawave_passkey/         # Import + manage existing passkeys
└── data-sources/
    ├── remnawave_users/           # List all users
    ├── remnawave_system_stats/    # Dashboard metrics
    └── remnawave_passkeys/        # List passkeys

Full documentation for every resource and data source is on the Terraform Registry and in docs/.

Importing Existing Resources

Resources created outside Terraform (e.g. via the web UI) can be imported into Terraform state:

# Import a user by UUID
terraform import remnawave_user.john 550e8400-e29b-41d4-a716-446655440000

# Import a node by UUID
terraform import remnawave_node.de-fra-01 550e8400-e29b-41d4-a716-446655440001

# Import a passkey (import-only resource)
terraform import remnawave_passkey.admin 550e8400-e29b-41d4-a716-446655440002

All resources that support import accept the UUID as the import ID.

Versioning & Upgrades

This provider follows Semantic Versioning. Breaking changes are reserved for major releases (e.g. 1.0.0).

Upgrading
# Upgrade to the latest version
terraform init -upgrade

Review the CHANGELOG for breaking changes and migration notes before upgrading across major versions.

Version Constraints
terraform {
  required_providers {
    remnawave = {
      source  = "batonogov/remnawave"
      version = "~> 0.4" # Allow 0.4.x patches
    }
  }
}

Development

Requirements
Tool Version
Go 1.24+ (see go.mod)
Terraform CLI 1.12+
Task Latest (optional, for task commands)
Docker Required for acceptance tests
Build & Test
# Build the provider binary
go build -o terraform-provider-remnawave

# Format code
gofmt -w provider/*.go

# Lint
golangci-lint run

# Unit tests (no Docker needed)
go test ./provider/... -race -cover

# Acceptance tests (starts Remnawave panel via Docker Compose)
task test:acc

See Taskfile.yml and AGENTS.md for the full list of commands and development conventions.

Acceptance Tests

Acceptance tests run against a real Remnawave panel via Docker Compose (docker-compose.yaml). The compose file spins up:

  • remnawave/backend panel (port 3000)
  • PostgreSQL 18
  • Valkey (Redis) 9
# Run the complete Docker lifecycle + test suite
task test:acc

# Override the Remnawave version under test
REMNAWAVE_VERSION=2.9.0 REMNAWAVE_DIGEST=sha256:<digest> task test:acc

All compose images are pinned by sha256 digest for reproducibility.

Regenerating Documentation

Documentation is auto-generated from provider schemas via tfplugindocs:

task docs       # Format examples + regenerate Registry docs
task docs:check # Validate and detect stale generated docs (CI gate)

Contributing

Contributions are welcome! Please:

  1. Open an issue to discuss the change before starting work.
  2. Follow Conventional Commits for commit messages (feat:, fix:, docs:, test:, chore:).
  3. Add or update tests for any changed behavior.
  4. Run gofmt, golangci-lint, and the relevant test suite before submitting a pull request.
  5. Ensure CI is green — acceptance tests run against both Remnawave v2.7.4 and v2.8.0.
Security

If you believe you have found a security issue, please report it privately rather than opening a public issue.

License

MIT © 2026 Fedor Batonogov

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL