dokploy_libsql (Resource)
A Dokploy libsql service: a distributed SQLite (sqld) database.
~> A replica (sqld_node = "replica") requires sqld_primary_url and cannot set an external port. A primary (sqld_node unset or "primary") must not set sqld_primary_url. Dokploy rejects all three violations at apply time. The provider rejects them earlier, at plan time.
~> A replica does not replicate without command on Dokploy v0.30.5. Dokploy stores the role and the URL and passes them to the container as SQLD_NODE and SQLD_PRIMARY_URL. It also starts sqld with a fixed command that bypasses the image entrypoint, and sqld reads neither variable. The container then runs as a second primary. Set command to sqld --db-path iku.db --http-listen-addr 0.0.0.0:8080 --admin-listen-addr 0.0.0.0:5000 --primary-grpc-url http://<primary app_name>:5001. Verified on the rig (2026-09-05): with that command, a row written on the primary reads back from the replica.
Example Usage
resource "dokploy_libsql" "example" {
name = "edge-db"
environment_id = dokploy_project.example.production_environment_id
database_user = "libsql"
database_password = var.db_password # use a sensitive variable
docker_image = "ghcr.io/tursodatabase/libsql-server:v0.24.32"
external_port = 8080
external_admin_port = 8081
external_grpc_port = 8082
# The Docker Swarm service specification. Set swarm.mode or replicas, not
# both. Durations are in nanoseconds.
# swarm = {
# mode = { replicated = { replicas = 1 } }
# placement = { constraints = ["node.labels.tier == db"] }
# }
}
# A replica follows a primary in the same environment. On Dokploy v0.30.5 the
# role and the URL alone do not make the container replicate; the command
# override does. Do not add --grpc-listen-addr to a replica command.
resource "dokploy_libsql" "replica" {
name = "edge-db-replica"
environment_id = dokploy_project.example.production_environment_id
database_user = "libsql"
database_password = var.db_password
sqld_node = "replica"
sqld_primary_url = "http://${dokploy_libsql.example.app_name}:5001"
command = "sqld --db-path iku.db --http-listen-addr 0.0.0.0:8080 --admin-listen-addr 0.0.0.0:5000 --primary-grpc-url http://${dokploy_libsql.example.app_name}:5001"
}Schema
Required
database_user(String) LibSQL database user.environment_id(String) Id of the environment that holds this service. Usedokploy_project.production_environment_idfor the default environment.name(String) Display name of the libsql service.
Optional
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
app_name_prefix(String) Prefix of the Dokploy app name. Dokploy appends-<suffix>(six random lowercase characters) at create and never changes the app name afterwards. Defaults toname. Use lowercase letters, digits, dots, underscores, and hyphens; 56 characters at most. A change replaces the resource. After an import the provider derives the value fromapp_name.command(String) Override the container command. A replica needs it on Dokploy v0.30.5:sqld --db-path iku.db --http-listen-addr 0.0.0.0:8080 --admin-listen-addr 0.0.0.0:5000 --primary-grpc-url http://<primary app_name>:5001. Do not add--grpc-listen-addrto a replica command;sqldrejects it next to--primary-grpc-url.cpu_limit(String) Hard CPU limit in nano-CPUs, as a whole number in a string:"1000000000"is one CPU,"500000000"half a CPU. Dokploy reads the value withparseInt, so a Docker-style suffix such as512mdeploys as 512 bytes and a fraction such as0.5sets no limit. Use a whole number.cpu_reservation(String) Reserved CPU in nano-CPUs, as a whole number in a string:"250000000"is a quarter CPU. Dokploy reads the value withparseInt, so a Docker-style suffix such as512mdeploys as 512 bytes and a fraction such as0.5sets no limit. Use a whole number.database_password(String, Sensitive) LibSQL database password. Set this attribute ordatabase_password_wo.database_password_wo(String, Sensitive, Write-only) Write-only form ofdatabase_password. Terraform keeps it out of the plan and the state. It needs Terraform 1.11 or later. Set exactly one ofdatabase_passwordanddatabase_password_wo. A new value reaches the server only whendatabase_password_wo_versionchanges.database_password_wo_version(Number) Version ofdatabase_password_wo. Change it to send the currentdatabase_password_wovalue to the server. A version change starts a redeploy. It needsdatabase_password_wo.deploy_on_change(Boolean) Deploy after a create, and after a change to an attribute that starts a deploy. Defaults totrue.deployment_timeout(String) The maximum wait for a deploy to reach a terminal status, as a Go duration string. Defaults to"15m". On timeout, the apply fails, but the deploy continues on the server.description(String) Free-form description.detach_dokploy_network(Boolean) Detach the shareddokploy-networkfrom this service. Defaults tofalse. It has an effect only together withnetwork_ids, and it applies on the next deploy.docker_image(String) LibSQL Docker image, for exampleghcr.io/tursodatabase/libsql-server:v0.24.32. That tag is also the server default when you omit the attribute, and it exists in the registry.enable_namespaces(Boolean) Enable sqld namespaces, the multi-database mode. Defaults tofalse.env(String) Extra environment variables in the native Dokploy multilineKEY=valueformat. Use Terraform sensitive variables for secret values. An omitted value and""both read back as null. Omit the attribute to clear it.external_admin_port(Number) Host port for the libsql admin interface. Not permitted whensqld_nodeisreplica.external_grpc_port(Number) Host port for the libsql gRPC replication interface. Not permitted whensqld_nodeisreplica.external_port(Number) Host port for the libsql HTTP interface. Not permitted whensqld_nodeisreplica.memory_limit(String) Hard memory limit in bytes, as a whole number in a string:"536870912"is 512 MiB. Dokploy reads the value withparseInt, so a Docker-style suffix such as512mdeploys as 512 bytes and a fraction such as0.5sets no limit. Use a whole number.memory_reservation(String) Reserved memory in bytes, as a whole number in a string:"268435456"is 256 MiB. Dokploy reads the value withparseInt, so a Docker-style suffix such as512mdeploys as 512 bytes and a fraction such as0.5sets no limit. Use a whole number.network_ids(Set of String) Ids of the Dokploy network records to attach this service to. The attachment applies on the next deploy. Omit it to keep only the defaultdokploy-network. An empty set is not valid. Omit the attribute instead.replicas(Number) Number of container replicas. Defaults to1. Ifswarm.modeis set, Dokploy uses the mode and ignores this attribute. Setreplicasorswarm.mode, not both: the provider rejects the pair at plan time.server_id(String) Id of the remote server that runs the service. Defaults to the Dokploy host.sqld_node(String) Topology role:primaryorreplica. A replica requiressqld_primary_url, and cannot have any external port. On Dokploy v0.30.5 the stored role alone does not make the container replicate; setcommandas the resource note describes.sqld_primary_url(String) URL of the primary sqld node, for examplehttp://<primary app_name>:5001. Required whensqld_nodeisreplica. The server rejects it whensqld_nodeis notreplica, which includes the defaultprimary. Dokploy passes it to the container asSQLD_PRIMARY_URL, whichsqlddoes not read; seecommand.swarm(Attributes) The Docker Swarm service specification. Each attribute maps to one Dokploy column and keeps the Docker field names in snake case. Omit the block to write null to every column. A change starts a redeploy whendeploy_on_changeis true. This service type has noulimitscolumn, so the provider rejects that attribute. (see nested schema for swarm)
Read-Only
app_name(String) Internal Dokploy app name,<app_name_prefix>-<suffix>. The server generates it at create. You cannot set it; setapp_name_prefixinstead.created_at(String) Creation timestamp from the server.id(String) LibSQL service id.status(String) Service status from Dokploy.
Nested Schema for swarm
Optional:
endpoint_spec(Attributes) The endpoint of the service. (see nested schema for swarm.endpoint_spec)health_check(Attributes) The container health check. (see nested schema for swarm.health_check)labels(Map of String) Docker labels of the service containers.mode(Attributes) The service mode. If this attribute is set, Dokploy uses it and ignores the top-levelreplicasattribute. Setswarm.modeorreplicas, not both: the provider rejects the pair at plan time. Swarm cannot change the mode of a service that exists. (see nested schema for swarm.mode)network(Attributes List) Swarm networks that the service joins. (see nested schema for swarm.network)placement(Attributes) Where Swarm can place the tasks. (see nested schema for swarm.placement)restart_policy(Attributes) The restart policy of the tasks. (see nested schema for swarm.restart_policy)rollback_config(Attributes) The policy for a rollback after a failed update. (see nested schema for swarm.rollback_config)stop_grace_period(Number) Time that Swarm waits after a stop signal before it kills a container, in nanoseconds.ulimits(Attributes List) Ulimits of the containers. (see nested schema for swarm.ulimits)update_config(Attributes) The rolling update policy. (see nested schema for swarm.update_config)
Nested Schema for swarm.endpoint_spec
Optional:
mode(String) Endpoint mode:vipordnsrr.ports(Attributes List) Published ports of the service. (see nested schema for swarm.endpoint_spec.ports)
Nested Schema for swarm.endpoint_spec.ports
Optional:
protocol(String) Protocol:tcp,udp, orsctp.publish_mode(String) Publish mode:ingressorhost.published_port(Number) Port on the host or on the routing mesh.target_port(Number) Port in the container.
Nested Schema for swarm.health_check
Optional:
interval(Number) Time between two checks, in nanoseconds.retries(Number) Number of failed checks after which the container is unhealthy.start_period(Number) Time after the start in which a failed check does not count, in nanoseconds.test(List of String) The check command, for example["CMD", "curl", "-f", "http://localhost"].timeout(Number) Time after which a check fails, in nanoseconds.
Nested Schema for swarm.mode
Optional:
global(Attributes) Run one task on each node. Set the attribute to{}. (see nested schema for swarm.mode.global)global_job(Attributes) Run a job once on each node. Set the attribute to{}. (see nested schema for swarm.mode.global_job)replicated(Attributes) Run a set number of tasks. (see nested schema for swarm.mode.replicated)replicated_job(Attributes) Run a job with a set number of completions. (see nested schema for swarm.mode.replicated_job)
Nested Schema for swarm.mode.global
Nested Schema for swarm.mode.global_job
Nested Schema for swarm.mode.replicated
Optional:
replicas(Number) Number of tasks.
Nested Schema for swarm.mode.replicated_job
Optional:
max_concurrent(Number) Maximum number of tasks that run at the same time.total_completions(Number) Number of tasks that must complete.
Nested Schema for swarm.network
Optional:
aliases(List of String) Network aliases of the service.driver_opts(Map of String) Driver options of the network attachment.target(String) Name or ID of the network.
Nested Schema for swarm.placement
Optional:
constraints(List of String) Placement constraints, for example["node.labels.tier == app"].max_replicas(Number) Maximum number of tasks on one node. The value0means no limit.platforms(Attributes List) Platforms that Swarm can use. (see nested schema for swarm.placement.platforms)preferences(Attributes List) Placement preferences. (see nested schema for swarm.placement.preferences)
Nested Schema for swarm.placement.platforms
Required:
architecture(String) The CPU architecture, for exampleamd64.os(String) The operating system, for examplelinux.
Nested Schema for swarm.placement.preferences
Required:
spread(Attributes) Spread the tasks over the values of a node label. (see nested schema for swarm.placement.preferences.spread)
Nested Schema for swarm.placement.preferences.spread
Required:
spread_descriptor(String) The node label to spread over, for examplenode.labels.zone.
Nested Schema for swarm.restart_policy
Optional:
condition(String) Condition to restart a task:none,on-failure, orany.delay(Number) Time between two restarts, in nanoseconds.max_attempts(Number) Number of restarts before Swarm stops the attempts.window(Number) Time to wait before Swarm decides that a restart worked, in nanoseconds.
Nested Schema for swarm.rollback_config
Required:
order(String) Order of the tasks:start-firstorstop-first.parallelism(Number) Number of tasks that roll back at the same time. The value0means all tasks at once.
Optional:
delay(Number) Time between two batches, in nanoseconds.failure_action(String) Action if a task fails:continue,pause, orrollback.max_failure_ratio(Number) Fraction of failed tasks that the service tolerates, from0to1.monitor(Number) Time to watch each task for a failure after it starts, in nanoseconds.
Nested Schema for swarm.ulimits
Required:
hard(Number) The hard limit.name(String) Name of the limit, for examplenofile.soft(Number) The soft limit.
Nested Schema for swarm.update_config
Required:
order(String) Order of the tasks:start-firstorstop-first.parallelism(Number) Number of tasks that update at the same time. The value0means all tasks at once.
Optional:
delay(Number) Time between two batches, in nanoseconds.failure_action(String) Action if a task fails:continue,pause, orrollback.max_failure_ratio(Number) Fraction of failed tasks that the service tolerates, from0to1.monitor(Number) Time to watch each task for a failure after it starts, in nanoseconds.
Import
Import is supported using the following syntax:
In Terraform v1.5.0 and later, the import block can be used with the id attribute, for example:
import {
to = dokploy_libsql.example
id = "V1StGXR8_Z5jdHi6B-myT"
}The terraform import command can be used, for example:
terraform import dokploy_libsql.example V1StGXR8_Z5jdHi6B-myT