# ============================================================================= # SeaweedFS Terraform core module - input variables # # This module is a PURE RENDERER. It creates zero cloud resources. It takes a # per-node address map plus configuration and emits, per node, the rendered # `weed` argv, systemd unit, cloud-init, and config files. Both the per-cloud # infra wrappers (consume cloud_init/systemd_unit) and the local test harness # (consume argv/config_files) read its `nodes` output. # # Flag names below are verified against the real `weed` binary, not the chart. # Notably: volume uses -mserver for the master list; gRPC is -port.grpc # (auto = http+10000); minFreeSpacePercent is a string. # ============================================================================= variable "weed_binary" { description = "Path to the weed executable on the target host." type = string default = "/usr/bin/weed" } variable "cluster_name" { description = "Logical cluster name (WEED_CLUSTER_DEFAULT)." type = string default = "sw" } variable "log_level" { description = "Global glog verbosity (-v)." type = number default = 1 } variable "log_to_stderr" { description = "Log to stderr (journald) instead of -logdir. Recommended on systemd." type = bool default = true } variable "monitoring_enabled" { description = "Gate the -metricsPort/-metrics.address flags. When false the metrics port is not bound, matching the chart." type = bool default = false } variable "enable_security" { description = "Emit the security.toml [grpc] mTLS block and reference per-component certs. Independent of JWT." type = bool default = false } # ---------------------------------------------------------------------------- # Security / secrets (the core only references paths + renders security.toml; # cert/secret material is generated by the wrapper, never defaulted here). # ---------------------------------------------------------------------------- variable "security" { description = "mTLS + JWT signing configuration. Secret values must be supplied (never defaulted in module code)." type = object({ cert_dir = optional(string, "/usr/local/share/ca-certificates") allowed_wildcard_domain = optional(string, "") allowed_common_names = optional(string, "") jwt_signing_key = optional(string, "") jwt_signing_read_key = optional(string, "") jwt_filer_signing_key = optional(string, "") jwt_filer_signing_read_key = optional(string, "") }) default = {} sensitive = true } variable "hardening" { description = "systemd hardening directives (OpenShift SCC analogs). Relax per field if needed." type = object({ run_as_user = optional(string, "seaweedfs") no_new_privileges = optional(bool, true) protect_system = optional(bool, true) cap_drop_all = optional(bool, true) }) default = {} } variable "env_file" { description = "Path to the systemd EnvironmentFile holding secret env (DB creds, S3 admin key) fetched at boot. Optional (-prefixed in the unit, so a missing file is tolerated)." type = string default = "/etc/seaweedfs/weed.env" } variable "render_secret_files" { description = <<-EOT When true (default), secret-bearing config (security.toml, S3 identity JSON) is written directly into cloud-init user_data. Convenient for the local test harness and simple deployments. Set to false to keep secrets OUT of user_data (and out of the cloud metadata service): the files are then exposed only via the secret_files_by_node output, and the wrapper is expected to deliver them from a secret store via boot_fetch_script. EOT type = bool default = true } variable "boot_fetch_script" { description = "Optional shell script written to /opt/seaweedfs/fetch-secrets.sh (root, 0755) and run before the weed unit starts. Used by wrappers to pull certs/secrets from a cloud secret store at boot." type = string default = "" } # ---------------------------------------------------------------------------- # Master (Raft quorum). Keyed `nodes` map -> for_each, never count. # ---------------------------------------------------------------------------- variable "master" { description = "Master tier. nodes is a map keyed by stable node id (m0/m1/m2)." type = object({ enabled = optional(bool, true) nodes = optional(map(object({ address = string port = optional(number) grpc_port = optional(number) data_dir = optional(string) disk_mounts = optional(list(object({ mountpoint = string fstype = optional(string, "ext4") devices = optional(list(string), []) })), []) })), {}) port = optional(number, 9333) grpc_port = optional(number, null) # null => weed auto = port+10000 metrics_port = optional(number, 9327) metrics_ip = optional(string, "") ip_bind = optional(string, "0.0.0.0") data_dir = optional(string, "/var/lib/seaweedfs/master") default_replication = optional(string, "000") volume_size_limit_mb = optional(number, 1000) volume_preallocate = optional(bool, false) garbage_threshold = optional(number, null) disable_http = optional(bool, false) raft_hashicorp = optional(bool, false) resume_state = optional(bool, true) # deliberate deviation: binary default false election_timeout = optional(string, "10s") heartbeat_interval = optional(string, "300ms") white_list = optional(string, "") extra_args = optional(list(string), []) }) default = {} } # ---------------------------------------------------------------------------- # Volume (stateful disk owners). Keyed `nodes` map. # ---------------------------------------------------------------------------- variable "volume" { description = "Volume tier. Each node owns one or more data dirs (-> -dir / -max)." type = object({ enabled = optional(bool, true) nodes = optional(map(object({ address = string port = optional(number) grpc_port = optional(number) public_url = optional(string) rack = optional(string) data_center = optional(string) data_dirs = optional(list(object({ path = string max_volumes = optional(number, 0) # 0 => auto on non-windows }))) idx_dir = optional(string) disk_mounts = optional(list(object({ mountpoint = string fstype = optional(string, "ext4") devices = optional(list(string), []) })), []) })), {}) port = optional(number, 8080) metrics_port = optional(number, 9327) metrics_ip = optional(string, "") ip_bind = optional(string, "0.0.0.0") data_dirs = optional(list(object({ path = string max_volumes = optional(number, 0) })), [{ path = "/data", max_volumes = 0 }]) idx_dir = optional(string, "") read_mode = optional(string, "proxy") compaction_mbps = optional(number, 50) min_free_space_percent = optional(string, "1") file_size_limit_mb = optional(number, null) index = optional(string, "memory") images_fix_orientation = optional(bool, false) white_list = optional(string, "") extra_args = optional(list(string), []) }) default = {} } # ---------------------------------------------------------------------------- # Filer (+ optional embedded S3). Keyed `nodes` map. # ---------------------------------------------------------------------------- variable "filer" { description = "Filer tier. Default leveldb2-replicated HA (each filer has its own store)." type = object({ enabled = optional(bool, true) nodes = optional(map(object({ address = string port = optional(number) grpc_port = optional(number) data_dir = optional(string) disk_mounts = optional(list(object({ mountpoint = string fstype = optional(string, "ext4") devices = optional(list(string), []) })), []) })), {}) port = optional(number, 8888) metrics_port = optional(number, 9327) metrics_ip = optional(string, "") ip_bind = optional(string, "0.0.0.0") data_dir = optional(string, "/var/lib/seaweedfs/filer") # -defaultStoreDir for leveldb2 default_replica_placement = optional(string, "000") dir_list_limit = optional(number, 100000) max_mb = optional(number, null) disable_dir_listing = optional(bool, false) disable_http = optional(bool, false) encrypt_volume_data = optional(bool, false) rack = optional(string, "") data_center = optional(string, "") filer_group = optional(string, "") extra_env = optional(map(string), {}) extra_args = optional(list(string), []) s3 = optional(object({ enabled = optional(bool, false) port = optional(number, 8333) https_port = optional(number, 0) domain_name = optional(string, "") config_path = optional(string, "/etc/seaweedfs/s3_config.json") }), {}) }) default = {} } # ---------------------------------------------------------------------------- # S3 gateway (standalone). Keyed `nodes` map (stateless, but kept keyed for # parity; wrappers may instead drive an ASG). # ---------------------------------------------------------------------------- variable "s3" { description = "Standalone S3 gateway tier." type = object({ enabled = optional(bool, false) nodes = optional(map(object({ address = string port = optional(number) grpc_port = optional(number) })), {}) port = optional(number, 8333) https_port = optional(number, 0) iceberg_port = optional(number, null) metrics_port = optional(number, 9327) ip_bind = optional(string, "0.0.0.0") domain_name = optional(string, "") filer_address = optional(string, "") # override; else first filer node config_path = optional(string, "/etc/seaweedfs/s3_config.json") audit_log_config_path = optional(string, "") cert_file = optional(string, "") key_file = optional(string, "") cacert_file = optional(string, "") verify_client_cert = optional(bool, false) extra_args = optional(list(string), []) }) default = {} } # ---------------------------------------------------------------------------- # S3 identities -> rendered into the s3 config JSON (non-admin only; the admin # credential is delivered via EnvironmentFile, never the JSON). # ---------------------------------------------------------------------------- variable "s3_identities" { description = "Non-admin S3 identities rendered into the config JSON. Admin key goes in the EnvironmentFile, not here." type = list(object({ name = string access_key = string secret_key = string actions = list(string) })) default = [] sensitive = true } # ---------------------------------------------------------------------------- # All-in-one (single `weed server` process). # ---------------------------------------------------------------------------- variable "all_in_one" { description = "All-in-one tier (weed server). Mutually exclusive with the distributed tiers." type = object({ enabled = optional(bool, false) nodes = optional(map(object({ address = string data_dir = optional(string) disk_mounts = optional(list(object({ mountpoint = string fstype = optional(string, "ext4") devices = optional(list(string), []) })), []) })), {}) data_dir = optional(string, "/data") ip_bind = optional(string, "0.0.0.0") master_port = optional(number, 9333) volume_port = optional(number, 8080) filer_port = optional(number, 8888) default_replication = optional(string, "000") volume_size_limit_mb = optional(number, 1000) idle_timeout = optional(number, 30) metrics_port = optional(number, 9324) disable_http = optional(bool, false) s3 = optional(object({ enabled = optional(bool, false) port = optional(number, 8333) config_path = optional(string, "/etc/seaweedfs/s3/s3_config.json") domain_name = optional(string, "") }), {}) extra_args = optional(list(string), []) }) default = {} }