How To: Install CouchDB on Fly.io
Table of contents
Intro
As Fly.io let's you run Dockerfile
s, it's usually not a problem to deploy almost anything on their Edge-Network. When I tried CouchDB a couple of days ago, the Docker part was as straight forward as it can be, just had to figure out how to configure my fly app correctly so I could access it. So here I wanna share what was needed to get it running.
For now I'm just talking about running a single-node instance.
Initializing the App
If you don't need a custom Dockerfile
, fly lets you just deploy existing images from Docker Hub. As I understand it defaults to Docker Hub, but providing a FQDN (fully qualified domain name), you should be able to launch/deploy Docker images from anywhere.
So in this case, as I just wanted to try out CouchDB I just ran the following command, (with flyctl
installed).
fly launch --image apache/couchdb
which, after answering a few questions:
- App Name (leave blank to use an auto-generated name) - left it blank
- Select region - (gru)
- Would you like to setup a Postgresql database now? - (No)
- Would you like to deploy now? - (No, as I need to tweak the config first)
created a fly.toml
file for me.
# fly.toml file generated for autogenerated-appname-1234 on 2022-05-10T11:32:36-05:00
app = "autogenerated-appname-1234"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[build]
image = "apache/couchdb"
[env]
[experimental]
allowed_public_ports = []
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
This is the standard config, which listens internally on port 8080, so the app within the container should listen on that port, which CouchDB doesn't, and Fly normally only makes your app available on ports 80 for http and 443 for TLS/https, which isn't sufficient in this case.
Luckily Fly is pretty flexible so we can adjust to our needs.
CouchDB expects port 5984, so I changed internal_port
and also added an additional services.ports
. It might be possible to remove ports 80 and 443 though I didn't came to actually test that, I think without further configuration the deployment would fail as fly uses those ports for healthchecks. Just checked and it's possible to remove the blocks for ports 80 & 443 without problems.
We also want to create a volume, so CouchDB can store its data and survive app re-deploys. The following will create a volume in São Paulo, Brazil (gru is the airport identifier) with a size of 1 GB.
Make sure that the volume's region matches your app's region!
fly volumes create couchdbdata --region gru --size 1
couchdbdata
is the volume's name, you can change that to your hearts desire, it's not too relevant, we just need it to connect it with our app, via the fly.toml
s mounts
key.
Uh and also CouchDB complained, that it won't auto-generate an admin user anymore, so we have to define 2 environment variables, which is best done via Fly Secrets, especially for sensitive information like in this case:
flyctl secrets set COUCHDB_USER="ADMIN_USER_NAME" COUCHDB_PASSWORD="YOUR_STRONG_ADMIN_PASSWORD"
Final fly.toml configuration file
# fly.toml file generated for autogenerated-appname-1234 on 2022-05-10T11:32:36-05:00
app = "autogenerated-appname-1234"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[build]
image = "apache/couchdb"
[experimental]
allowed_public_ports = []
auto_rollback = true
[mounts]
source="couchdbdata"
destination="/opt/couchbase/var"
[[services]]
http_checks = []
internal_port = 5984
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
handlers = ["tls", "http"]
port = 5984
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
Note the highlighted lines in the code block above (lines 9-10, 16-18, 22, 41-43) to see what has changed.
You can make the changes, or just copy the whole block into your fly.toml
, ideally from line 5 to keep your app name.
CouchDB Cluster on Fly.io
So far the only solution I found is to create multiple apps on Fly, which all get their own IP address, which we then can use to set up a cluster.
Thanks to fly create
we can create a new app without a new fly.toml
, I discovered this via the Remix Stacks.
fly secrets set COUCHDB_USER="USER_NAME" COUCHDB_PASSWORD=$(cat pw) --app ct-couchdb-1
fly secrets set COUCHDB_USER="USER_NAME" COUCHDB_PASSWORD=$(cat pw) --app ct-couchdb-2
fly secrets set COUCHDB_USER="USER_NAME" COUCHDB_PASSWORD=$(cat pw) --app ct-couchdb-3
fly volumes create data --size 1 --app ct-couchdb-1
fly volumes create data --size 1 --app ct-couchdb-2
fly volumes create data --size 1 --app ct-couchdb-3
That's it for now, thanks for reading. And feel free to get in touch via Twitter.
Resources
https://docs.couchdb.org/en/stable/install/docker.html
https://docs.couchdb.org/en/stable/setup/single-node.html
https://docs.couchdb.org/en/stable/setup/cluster.html

Doing web-development since around 2000, building my digital garden with a mix of back-to-the-roots-use-the-platform and modern edge-rendered-client-side-magic tech 📻🚀
Living and working in Cusco, Perú 🦙