Setting up rails with litestream on fly.io

published on 10/22/2024

Assume we have a vanilla Rails setup that has Dockerfile available and is running without issues at the moment.

To change default Rails setup

Updating Dockerfile

+# Install Litestream
+  RUN apt-get update && apt-get install -y wget && \
+  wget https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-amd64.tar.gz && \  `
+  tar -C /usr/local/bin -xzf litestream-v0.3.13-linux-amd64.tar.gz && \  `
+  rm litestream-v0.3.13-linux-amd64.tar.gz && \  `
+  apt-get remove -y wget && apt-get autoremove -y && apt-get clean  `

....

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
COPY --from=build /rails /rails

+  COPY --from=build /usr/local/bin/litestream /usr/local/bin/litestream  `
+  Copy Litestream config  `
+  COPY litestream.yml /etc/litestream.yml  `

...

# Start the server by default, this can be overwritten at runtime
EXPOSE 3000

-  CMD ["./bin/rails", "server"]  `
+  CMD ["sh", "-c", "litestream replicate -exec '/rails/bin/rails server'"]  `

Update docker-entrypoint

# If running the rails server then create or migrate existing database
-  if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then
-    ./bin/rails db:prepare
-  fi

+  if [[ "$@" == *"litestream replicate -exec '/rails/bin/rails server'"* ]]; then
+    /rails/bin/rails db:prepare
+  fi

A litestream.yml config file at root

dbs:
  - path: /data/production.sqlite3
    replicas:
      - url: ${S3_BUCKET_URL}
        sync-interval: 10s

Here we assume that the database is stored at /data/production.sqlite3 This is coming from the fly.toml config.

[[mounts]]
source = 'data'
destination = '/data'

[env]
DATABASE_URL = 'sqlite3:///data/production.sqlite3'

We already have a volume defined for the app, so just mounting it to the path in config

Have ENV values setup

AWS_ACCESS_KEY_ID
AWS_DEFAULT_REGION
AWS_SECRET_ACCESS_KEY

That should do it.