rqlite encrypts the connections between database nodes
rqlite 4.0.0 adds TLS to its inter-node transport and renames startup options. The implementation separates client HTTPS, node encryption and HTTP authorization, which remain distinct configuration choices.
Encrypting a database's HTTP API does not encrypt its replication traffic. rqlite nodes have a separate connection for communication inside the cluster, and that connection carries state needed to keep the database replicated. rqlite 4.0.0, released on 18 June, adds node-to-node encryption alongside the existing client-facing HTTPS support.
The release also renames command-line options. Its tagged changelog says that earlier startup commands will stop working, though existing options map one-to-one to renamed options. The project describes the other upgrade work as unnecessary. The immediate migration task is therefore to update the launch configuration and decide separately whether to enable the new transport encryption.
I value rqlite's restrained deployment model, but a small executable still has more than one network boundary. Adding encryption to the internal transport addresses a real distinction in that model. It also makes clear why securing the public API alone cannot describe the security properties of the whole cluster.
The inter-node transport is multiplexed
The 4.0.0 TCP implementation provides a multiplexer over a network listener. Connections carry a marker byte identifying which registered handler should receive them. Raft and cluster metadata can use separate logical layers over that transport.
The new TLS constructor wraps the listener with tls.NewListener and marks remote connections as encrypted. When a layer dials another node, it uses tls.DialWithDialer if that flag is set. Otherwise it uses the ordinary network dialer. After establishing the connection, the layer writes its marker byte as before.
Placing TLS below this dispatch means encryption applies before the connection is handed to a logical handler. The release's security guide describes the result as encryption of all inter-node traffic. The mechanism supports that description without requiring separate encryption implementations for each message type.
The multiplexer still has its own connection-handling behavior. It sets a deadline while waiting for the first marker byte, reads that byte and clears the deadline before passing the connection to its handler. TLS changes the transport that carries those operations, while the message dispatch continues to use the same basic arrangement.
Encryption is an explicit cluster setting
The release's security documentation enables node encryption with -node-encrypt. Each node also needs an X.509 certificate and the corresponding private key. The guide says that either every node in the cluster must enable encryption or none must enable it.
That requirement follows from the transport choice. A TLS connection starts differently from the plaintext connection expected by an unencrypted peer. Enabling the option on one node is not a transparent way to encrypt only its own traffic while leaving the other members unchanged.
The server entry point selects either NewTLSMux or NewMux when building the internal transport. It then creates the Raft layer from that multiplexer. The selection happens before the store uses the transport, so the mode belongs to node startup configuration.
rqlited -node-encrypt -node-cert node.crt -node-key node-key.pem ~/node.1
This example assumes usable certificate and key files and a deployment whose peers use the same transport mode. It does not enable HTTPS on the client API. That interface has separate certificate options. Keeping the example to the internal connection makes the scope of the new option clear.
Certificate verification has a separate control
The outgoing TLS configuration sets InsecureSkipVerify from the node verification option. That option is -node-no-verify in the actual argument definitions, and defaults to false. The normal setting therefore retains verification of the remote node certificate.
The security guide contains an example spelling -no-node-verify, but the released argument parser defines -node-no-verify. The parser is authoritative for a working invocation. This is a documentation inconsistency in the example, not an additional supported alias.
It is also important to describe the authentication provided by the implementation accurately. The inspected listener configuration loads its certificate and private key. It does not configure a client-certificate requirement, and the outgoing configuration shown in the layer does not supply a client certificate. The feature should therefore not be described as mutual TLS authentication of every node.
I prefer an explicit account of those limits to treating encryption as a complete identity policy. The implementation protects the inter-node transport and normally verifies the remote endpoint when dialing. Membership admission and authorization still involve other controls. The existence of node certificates alone does not establish that incoming peers must prove possession of their own certificate.
HTTP authorization still controls API operations
The security guide continues to describe Basic Auth and per-user permissions on the HTTP API. Its permissions include joining and removing nodes, as well as querying, execution and backups. The configuration file applies locally to each node, so operators must configure it correctly on every member.
The guide's secured-cluster example uses credentials in the join URL. That concerns the HTTP request asking an existing member to admit the new node. The node certificate settings concern the subsequent inter-node transport. These settings participate in one deployment, but they address different connections and checks.
Client HTTPS is configured with -http-cert and -http-key. The -http-no-verify setting concerns verification of a remote HTTPS certificate during joining. The node verification option instead concerns a remote internal transport endpoint. Similar names do not make them interchangeable.
The guide also retains network restrictions as part of deployment. Only the API port needs to be reachable by ordinary clients, while the internal port needs communication between members. Encryption does not change which endpoints the client uses, and it does not require exposing the Raft listener to every application that issues SQL.
Startup option names change with the release
The new argument names make the interface distinction easier to see. -http becomes -http-addr, and the advertised address uses -http-adv-addr. The Raft counterparts are -raft-addr and -raft-adv-addr. Certificate options identify whether they belong to HTTP or node traffic.
Other controls receive similar separation in their names. The Apply timeout becomes -raft-apply-timeout, while the initial-log wait becomes -raft-open-timeout. Heartbeat configuration uses -raft-timeout. The on-disk database flag is now -on-disk, while discovery uses -disco-id and -disco-url.
These are concrete reasons an unchanged service command can fail after replacing the binary. The changelog calls the existing-option changes cosmetic, but the command parser still requires the new spelling. A service definition, container command or startup script is part of the upgrade because it supplies those arguments.
The option rename is separate from turning encryption on. A deployment can update its existing command to the new spellings without selecting TLS for inter-node traffic. Conversely, adopting the encryption feature requires the additional certificate configuration and a consistent transport mode across the cluster.
Failures remain visible to the transport caller
The TLS listener constructor loads the certificate and key pair before returning the multiplexer. An error reading or parsing that pair propagates to startup, which stops if it cannot create the requested transport. A process does not silently fall back to plaintext because its encryption files are unusable.
The dialing side also returns connection errors to its caller. Only after a connection succeeds does it write the handler marker. If writing that byte fails, the layer closes the connection and returns the error. These paths preserve the distinction between obtaining a transport connection and having a usable connection dispatched to the intended internal handler. Encryption adds a stage to connection establishment without making failure in that stage a successful plaintext connection.
Transport status becomes inspectable
The release adds registration of status providers to the HTTP service, with the multiplexer as its first client. The mux statistics include its address, timeout and encrypted state. When encryption is enabled, they also identify the configured certificate and key paths and the verification setting.
Those fields report configuration information, not private-key contents. They make it possible to distinguish a running encrypted transport from an intended startup argument. They also expose whether the deployment selected the option to skip verification, which is materially different from merely observing that TLS is in use.
The CLI receives status and help commands in the same release. That makes the operational information easier to reach from an interactive session. For the encryption feature, the useful result is a connection between explicit startup choices and inspectable runtime state, while client authorization and database consensus retain their separate roles.