rqlite 10.6.4
Overview
This guide covers launching and using rqlite 10.6.4 on Ubuntu 24.04 from SecureAnyCloud on Amazon EC2. It is one version of SecureAnyCloud's distributed and embedded SQL databases listing on AWS Marketplace. You choose it as the software version when you subscribe and launch. The other databases in the listing are described on the listing's guide hub.
rqlite is a lightweight, open source distributed relational database that uses SQLite as its storage engine and the Raft consensus protocol to replicate it. You talk to it over a simple HTTP API (SQL in, JSON out), through its built-in web console, or with the rqlite shell. It runs well as a single node, as this image ships it, and grows into a fault-tolerant cluster of several nodes when you need one.
What you get:
- No default login, no anonymous access. Started without an authentication file, rqlite has no authentication at all. This image always starts it with one. First boot creates the only rqlite user,
admin, with a 32-character password generated on your instance, and nothing is granted to anonymous requests. Every API path and the web console answer an unauthenticated or wrong-password request with401. The password is written to the root-only file/root/rqlite-credentials.txt, never to a command line, a log or the journal. - HTTPS only, on localhost. The HTTP API and the web console are served over TLS with a certificate generated on your instance at first boot. There is no plaintext listener. Both the API (
127.0.0.1:4001) and Raft (127.0.0.1:4002) listen on the loopback address only, so from the network only SSH is reachable. You reach rqlite through an SSH tunnel (Step 7). - Built from source, scanned. rqlite 10.6.4 (a security release) is compiled on the image from the unmodified upstream source at the
v10.6.4tag with Go 1.27.3, with every dependency exactly as upstream pins it. It is checked withgovulncheckat build time, which finds no known vulnerabilities in the code it links. The build provenance, the scan report and the licence of every linked component ship on the image. - Hardened service.
rqliteruns as the unprivileged rqlite user with no capabilities, a read-only view of the system and no access to/root. It cannot reach the instance metadata service, and the AMI requires IMDSv2. A start-up check refuses to start rqlite before first boot, without its data volume or TLS, or with an authentication file that would allow anonymous access. SSH accepts keys only, and fwupd's automatic firmware-metadata refresh is switched off (EC2 has no firmware it can update). - Your data on its own disk. The data directory (
/var/lib/rqlite: the SQLite database, the Raft log and snapshots) is on a separate 20 GiB EBS volume that you can grow or snapshot on its own. The image ships it empty, and each instance starts its own new cluster. - Fully patched. Ubuntu 24.04 LTS is patched at build time, with unattended security upgrades switched on.
What is on the image: rqlite 10.6.4 (rqlited, the server, runs as rqlited.service; rqlite, the shell), a helper rqlite-query that runs SQL and API calls with your credentials, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. The database is empty, ready for your tables.
Default user: ubuntu; Architecture: x86_64; Recommended instance type: m5.large
What this is not
This is a single-node rqlite. A single node is a complete database: reads and writes go through Raft and SQLite as usual. It is not fault-tolerant, but Step 11 outlines how to grow it into a cluster.
rqlite replicates every write to a majority of nodes, which suits read-heavy workloads and moderate write rates. It is not a drop-in replacement for a large OLTP server.
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH) from your admin network. rqlite listens on the loopback address only, so no database port needs to be open. You reach it through an SSH tunnel.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick rqlite 10.6.4 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2.
Select m5.large (or larger), your key pair and a security group as described above. The AMI brings two volumes: the root volume and a 20 GiB data volume (/dev/sdf) for /var/lib/rqlite. Size the data volume for your data at launch.
To launch with the AWS CLI instead, replace the values in angle brackets. This example grows the data volume to 50 GiB:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--block-device-mappings 'DeviceName=/dev/sdf,Ebs={VolumeSize=50,VolumeType=gp3}' \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=rqlite}]'If you make the data volume larger at launch, grow the file system once after first boot with sudo resize2fs "$(findmnt -no SOURCE /var/lib/rqlite)".
First boot takes a few seconds once the instance is running.
Connect to your instance
Connect over SSH with these values:
Version: rqlite 10.6.4 on Ubuntu 24.04; SSH user: ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
Confirm that the first-boot service and rqlite are both active:
systemctl is-active rqlite-firstboot.service rqlited.serviceactive activerqlite listens on the loopback address only, so from the network only SSH is reachable:
sudo ss -HtlnLISTEN 0 4096 0.0.0.0:22 0.0.0.0:* LISTEN 0 4096 127.0.0.54:53 0.0.0.0:* LISTEN 0 4096 127.0.0.1:4002 0.0.0.0:* LISTEN 0 4096 127.0.0.1:4001 0.0.0.0:* LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* LISTEN 0 4096 [::]:22 [::]:*Port 4001 is the HTTPS API and web console, and 4002 is Raft. The port 53 lines are Ubuntu's local DNS resolver, which is also loopback only.
Get your password
Read your connection details from /root/rqlite-credentials.txt:
sudo grep -E '^RQLITE_(USER|URL|CONSOLE_URL|TLS_CERT|TLS_SHA256)=' /root/rqlite-credentials.txtRQLITE_USER=admin RQLITE_URL=https://127.0.0.1:4001 RQLITE_CONSOLE_URL=https://127.0.0.1:4001/console/ RQLITE_TLS_CERT=/etc/rqlite/tls/server.crt RQLITE_TLS_SHA256=72:49:94:70:1B:21:81:69:E3:77:8C:20:9D:2F:22:ED:0E:6E:E2:DF:49:AE:B8:7E:88:47:0F:4D:1F:F6:78:34Show the password itself when you need it, for the web console or for a client on your own computer:
sudo grep '^RQLITE_PASSWORD=' /root/rqlite-credentials.txtRQLITE_TLS_SHA256 is the SHA-256 fingerprint of this instance's TLS certificate (RQLITE_TLS_CERT). Compare it with what your browser or client shows the first time it connects.
Run SQL
rqlite-query sends SQL to rqlite over HTTPS as admin, trusting this instance's certificate. It hands the password from the credentials file to curl in a configuration file rather than on a command line.
Each argument is one statement, and --tx runs them in one transaction. Create a table and add some rows:
sudo rqlite-query --tx "CREATE TABLE orders (id INTEGER PRIMARY KEY, customer TEXT NOT NULL, region TEXT NOT NULL, cents INTEGER NOT NULL)" "INSERT INTO orders (customer, region, cents) VALUES ('Ada', 'EMEA', 25025), ('Grace', 'AMER', 99999), ('Alan', 'EMEA', 44780), ('Hedy', 'APAC', 12000), ('Linus', 'APAC', 8050)"{ "results": [ { "rows": null }, { "last_insert_id": 5, "rows_affected": 5, "rows": null } ] }Query them:
sudo rqlite-query "SELECT region, COUNT(*) AS orders, SUM(cents) / 100.0 AS total FROM orders GROUP BY region ORDER BY total DESC"{ "results": [ { "types": { "orders": "integer", "region": "text", "total": "real" }, "rows": [ { "orders": 1, "region": "AMER", "total": 999.99 }, { "orders": 2, "region": "EMEA", "total": 698.05 }, { "orders": 2, "region": "APAC", "total": 200.5 } ] } ] }Every write is committed through Raft before rqlite answers.
For applications, prefer parameterised statements, which the HTTP API supports directly. For example, post [["INSERT INTO orders (customer, region, cents) VALUES (?, ?, ?)", "Ada", "EMEA", 25025]] to /db/execute. See the rqlite API documentation for details.
Check the node
rqlite-query --get calls any API path. The /readyz path reports whether the node, the Raft leader and the store are ready:
sudo rqlite-query --get /readyz[+]node ok [+]leader ok [+]store ok [+]db ok/status returns everything about the node as JSON, such as the version, the Raft state and the API's security settings:
sudo rqlite-query --get /status | python3 -c 'import json, sys; d = json.load(sys.stdin); print(d["build"]["version"], d["store"]["raft"]["state"], "auth", d["http"]["auth"], "tls", d["http"]["tls"]["enabled"], d["http"]["bind_addr"])'v10.6.4 Leader auth enabled tls true 127.0.0.1:4001Open the web console through an SSH tunnel
rqlite's built-in web console shows the cluster and your schema, runs queries and takes backups. rqlite serves it at /console/ on the same HTTPS port, so you reach it through an SSH tunnel from your computer:
ssh -i <your-key.pem> -N -L 4001:127.0.0.1:4001 ubuntu@<public-ip>Then open https://127.0.0.1:4001/console/ in your browser. You can also use https://localhost:4001/console/, because the certificate names both.
The certificate is self-signed and unique to your instance, so the browser warns about it the first time. Check that the SHA-256 fingerprint it shows matches RQLITE_TLS_SHA256 from Step 4, then continue. To avoid the warning, copy /etc/rqlite/tls/server.crt to your computer and trust it for localhost.
The browser asks for a user name and password. Sign in as admin with the password from Step 4.
The Home page shows the cluster. This node is the leader of a one-node cluster, its API address is HTTPS and Raft is on the loopback address:
Query runs SQL. This example runs the query from Step 5:
Schema shows every table and its columns:
Backup downloads a copy of the database as a SQLite file, and Restore loads one. Both act on the whole database, so use them with care.
Connect applications from your computer
With the tunnel from Step 7 open, applications on your computer connect to https://localhost:4001 with HTTP basic authentication as admin. First copy the instance's certificate so your client can verify it:
ssh -i <your-key.pem> ubuntu@<public-ip> cat /etc/rqlite/tls/server.crt > rqlite-instance.crt curl --cacert rqlite-instance.crt -u admin -G https://localhost:4001/db/query --data-urlencode 'q=SELECT COUNT(*) FROM orders'curl -u admin asks for the password, so it does not end up in your shell history. rqlite's client libraries take an HTTPS URL, a user and a password the same way. Examples are pyrqlite for Python, gorqlite for Go and rqlite-js for JavaScript.
The rqlite shell is also on the instance and on rqlite's release downloads. It accepts credentials only as -u admin:<password> on its command line. Other local users can see them there while it runs, and your shell may record them. On a shared machine, prefer rqlite-query, the console or a client library.
If you use the shell, connect like this: rqlite -s https -H localhost -p 4001 -c rqlite-instance.crt -u admin:<password>.
For applications inside your VPC, the same tunnel (or an SSH-based bastion) keeps the database ports closed to the network. To expose the API to your VPC instead, change the listen address as shown in Step 11. Then allow TCP 4001 in the security group from your application subnets only, never 0.0.0.0/0.
Security checks
Confirm that rqlite and its first-boot service cannot reach the instance metadata service:
systemctl show -p IPAddressDeny rqlited.service rqlite-firstboot.serviceIPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32 IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32Confirm that a request without credentials is refused and that plaintext HTTP is refused. The self-signed certificate is not trusted unless you name it, and curl exit code 60 is a certificate error:
curl -s -o /dev/null -w '%{http_code}\n' --cacert /etc/rqlite/tls/server.crt https://localhost:4001/status
curl -s http://127.0.0.1:4001/status; echo
curl -s -o /dev/null https://localhost:4001/status; echo "curl exit code $?"401 Client sent an HTTP request to an HTTPS server. curl exit code 60Confirm that rqlite runs unprivileged. The password, the authentication file and the TLS key are readable by root only, and the last two are also readable by the rqlite service group:
sudo stat -c '%a %U:%G %n' /etc/rqlite/auth.json /etc/rqlite/tls/server.key /root/rqlite-credentials.txt ps -o user:10=,comm= -u rqlite
sudo grep -E '^(CapEff|NoNewPrivs)' /proc/$(systemctl show -p MainPID --value rqlited.service)/status640 root:rqlite /etc/rqlite/auth.json 640 root:rqlite /etc/rqlite/tls/server.key 600 root:root /root/rqlite-credentials.txt rqlite rqlited CapEff: 0000000000000000 NoNewPrivs: 1Review how this rqlite was built and the build-time vulnerability scan:
rqlited -version sed -n '1,4p' /usr/share/doc/sac/rqlite-BUILD-PROVENANCE.txt grep -c 'No vulnerabilities found' /usr/share/doc/sac/rqlite-govulncheck.txtrqlited v10.6.4 linux amd64 go1.27.3 sqlite3.53.4 (commit 64145717224d620809174cb2235ac86ec604aac5, compiler gc) rqlite v10.6.4 on this image was compiled by sac from the unmodified upstream source: repository https://github.com/rqlite/rqlite (MIT) tag v10.6.4 (commit 64145717224d620809174cb2235ac86ec604aac5; go.mod sha256 d4187d82ca17de2cce2c2bdf64cf70211617dcfdecfe7279f5248337cc9c640a; go.sum sha256 b200367b9ee837f5e05a0b2fcc69a64b2fb89f9e5ab44c5689b43bf518477788) toolchain go1.27.3 linux/amd64, CGO_ENABLED=1 (SQLite 3.53.4, vendored by github.com/rqlite/go-sqlite3) 2Run the image's own round-trip check. It confirms that the per-instance password reads and writes through Raft, using a transactional, parameterised write and an aggregate read on a scratch table that it drops again. It confirms that anonymous, wrong, blank, common and unknown-user credentials are refused with 401. It also checks that plaintext is refused, that the certificate is needed and that both ports are loopback only:
sudo /usr/local/sbin/rqlite-roundtrip.sh | tail -1OK-rqlite-roundtripChange the password
rqlite reads users and passwords from /etc/rqlite/auth.json (rqlite 10.6.4 stores them in plain text, which is why only root and the rqlite group can read the file). Edit the password there and in the credentials file with an editor, then restart rqlite:
sudo nano /etc/rqlite/auth.json
# change the "password" value
sudo nano /root/rqlite-credentials.txt
# change RQLITE_PASSWORD to the same value
sudo systemctl restart rqlitedUse a long random password, for example one from openssl rand -base64 32. Do not pass it to sudo on a command line, because that records it in /var/log/auth.log.
You can add further users with narrower permissions, for example ["query", "execute"] for an application, or ["query"] for read-only reporting. See rqlite's security documentation for the permission names.
Never add a user named *. rqlite grants that user's permissions to anonymous requests, and the image's start-up check refuses to start rqlite with one. The check also expects exactly one user. If you add users, remove the check from rqlited.service with sudo systemctl edit rqlited (an empty ExecStartPre= line) and keep the file's permissions.
Growing into a cluster
A fault-tolerant rqlite cluster has three or more nodes, and a majority must be up to accept writes. The image is configured as a single node. To build a cluster from several instances of it, follow this outline:
- Put the nodes in one security group that allows TCP 4001 and 4002 from itself only (the group as the source), never from
0.0.0.0/0. - Create your own certificate authority and a certificate for each node that names its private IP address. This encrypts and mutually authenticates Raft traffic between nodes. Give each node the CA so the HTTPS API can verify its peers.
- On each node, change the
ExecStartline ofrqlited.service(sudo systemctl edit --full rqlited) to listen on the private address and join the first node. For example:
/usr/local/bin/rqlited -http-addr 0.0.0.0:4001 -http-adv-addr <private-ip>:4001 \
-raft-addr 0.0.0.0:4002 -raft-adv-addr <private-ip>:4002 \
-auth /etc/rqlite/auth.json -join-as admin -join <first-node-private-ip>:4002 \
-http-cert /etc/rqlite/tls/server.crt -http-key /etc/rqlite/tls/server.key -http-ca-cert /etc/rqlite/tls/ca.crt \
-node-cert /etc/rqlite/tls/node.crt -node-key /etc/rqlite/tls/node.key -node-ca-cert /etc/rqlite/tls/ca.crt -node-verify-client \
/var/lib/rqlite/data- Use the same
auth.jsonon every node. Join nodes that start with an empty data directory: stop rqlite and empty/var/lib/rqlite/dataon a fresh instance before its first join.
rqlite's clustering and security documentation describes each flag, automatic bootstrapping (-bootstrap-expect) and read-only nodes.
Backup, updates and maintenance
- Back up by snapshotting the data volume (stop rqlite first for a fully consistent copy:
sudo systemctl stop rqlited), or download a consistent SQLite copy of the database while it runs, from the console's Backup page or the API:
sudo sh -c 'printf "user = \"admin:%s\"\n" "$(sed -n "s/^RQLITE_PASSWORD=//p" /root/rqlite-credentials.txt)" | curl -sS -K - --cacert /etc/rqlite/tls/server.crt -o /root/rqlite-backup.sqlite https://localhost:4001/db/backup'rqlite can also back up automatically to Amazon S3 (-auto-backup). This image blocks rqlite from the instance metadata service, so that feature needs an access key in its configuration file rather than the instance role. EBS snapshots of the data volume need no credentials on the instance.
Logs: run sudo journalctl -u rqlited.service -n 50.
Updates: Ubuntu security updates install automatically. rqlite is not an apt package, so you update it by hand. Read the release notes first. SecureAnyCloud also publishes new images as rqlite releases.
To move to a newer rqlite, follow these steps:
- Take a snapshot of the data volume.
- Download the binaries from the new release on rqlite's GitHub releases page, and check the release's SHA-256 digest first.
- Run sudo systemctl stop rqlited.
- Replace /usr/local/bin/rqlited and /usr/local/bin/rqlite with the new binaries, installing the two files with mode 0755.
- Run sudo systemctl start rqlited.
The build provenance of the shipped binaries is in /usr/share/doc/sac/rqlite-BUILD-PROVENANCE.txt.
Support and licensing
rqlite is open source software under the MIT licence, and SQLite is in the public domain. The licence of rqlite and of every Go module linked into it (MIT, Apache-2.0, BSD and MPL-2.0 licences) is in /usr/share/doc/sac/rqlite-third-party-licences/, with a notice saying where to obtain the source of each module. The rqlite on this image is built from the unmodified upstream source.
SecureAnyCloud provides 24/7 technical support for this image by email and live chat: sales@secureanycloud.com.
rqlite and SQLite are trademarks of their respective owners. SecureAnyCloud is not affiliated with or endorsed by the rqlite project or the SQLite developers.
Deploy on AWS
Launch rqlite 10.6.4 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com