svg

How to Deploy UseMemos on Fly.io and Automatically Backup the SQLite Database to Backblaze B2

fly.io usememos

usememos

Create a Working Directory

First, create a working directory for your project:

mkdir -p /home/sumar/Projects/fly.io-usememos
cd /home/sumar/Projects/fly.io-usememos
  • mkdir -p: This command creates a new directory for your project. The -p flag ensures that any necessary parent directories are also created.
  • cd: This command changes the current directory to the newly created project directory.

Create a Fly.io App

Next, create a Fly.io app:

fly launch --name micro-sumarsono-com 
  --vm-memory 256 \
  --region sin \
  --no-deploy \
  --org personal

This command initializes a new Fly.io app with the specified name, memory allocation, region, and organization. The --no-deploy flag prevents the app from being deployed immediately.

Create a Volume

Create a volume for your app:

fly volumes create memos_data \
  --size 1 \
  --region sin \
  --auto-confirm

This command creates a new volume named memos_data with a size of 1GB in the Singapore region. The --auto-confirm flag automatically confirms the creation of the volume.

Update fly.toml

Update the fly.toml file to add swap and mount the volume:

app = "micro-sumarsono-com"
primary_region = "sin"

# add swap
swap_size_mb = 512

[build]

[http_service]
  internal_port = 5230
  force_https = true
  auto_stop_machines = "stop"
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

# mount the volume
[[mounts]]
destination = "/var/opt/memos"
source = "memos_data"

[[vm]]
memory_mb = 256
size = "shared-cpu-1x"

This configuration file defines the settings for your Fly.io app, including the app name, region, memory allocation, and volume mounts.

Create a Dockerfile

Create a Dockerfile with the following content:

# This specifies the base image for the container, 
# which is the stable version of UseMemos.
FROM neosmemo/memos:stable

# copies the Litestream binary
# from the specified image to the container
COPY --from=docker.io/litestream/litestream:0.3 /usr/local/bin/litestream /usr/local/bin/litestream

# copies the Litestream configuration 
# file to the container
COPY litestream.yml /etc/litestream.yml

# sets Litestream as the entrypoint
# to ensure that Litestream starts first
# and manages the replication of the SQLite database
ENTRYPOINT ["/usr/local/bin/litestream"]

# exposes port 5230, which is used by UseMemos
EXPOSE 5230

# starts the UseMemos application
# with Litestream actively replicating the database
CMD ["replicate", "-exec", "./memos --mode prod --port 5230"]

Create a litestream.yml File

Create a litestream.yml file with the following content:

dbs:
  - path: /var/opt/memos/memos_prod.db
    replicas:
      - type: s3
        bucket: usememos-backup # Your bucket name
        path: db
        endpoint: s3.bla-bla.backblazeb2.com # Your bucket endpoint
        force-path-style: true

This configuration file defines the settings for Litestream, including the path to the SQLite database and the S3-compatible storage settings for Backblaze B2.

Create a Secret for the Backblaze Secret Key

Set the Backblaze secret key as a Fly.io secret:

fly secrets set LITESTREAM_SECRET_ACCESS_KEY=your-secret-key

This command sets the Backblaze secret key as an environment variable in Fly.io. Replace your-secret-key with your actual Backblaze secret key.

Deploy the App

Finally, deploy the app:

fly deploy --ha=false

This command deploys the Fly.io app. The --ha=false flag disables high availability, which is suitable for smaller applications.

If we check the logs with fly logs command, we will see that litestream and usememos us running:

2025-01-31T06:37:32Z proxy[e82de1df0742d8] sin [info]Starting machine
2025-01-31T06:37:32Z app[e82de1df0742d8] sin [info]2025-01-31T06:37:32.811204695 [01JJX8461ENCFZXFZMMSMWRXRD:main] Running Firecracker v1.7.0
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info] INFO Starting init (commit: 676c82a4)...
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info] INFO Checking filesystem on /var/opt/memos
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info]/dev/vdd: clean, 21/64512 files, 8853/258048 blocks
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info] INFO Mounting /dev/vdd at /var/opt/memos w/ uid: 0, gid: 0 and chmod 0755
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info] INFO Resized /var/opt/memos to 1056964608 bytes
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info] INFO Preparing to run: `/usr/local/bin/litestream replicate -exec ./memos --mode prod --port 5230` as root
2025-01-31T06:37:33Z app[e82de1df0742d8] sin [info] INFO [fly api proxy] listening at /.fly/api
2025-01-31T06:37:34Z runner[e82de1df0742d8] sin [info]Machine started in 1.396s
2025-01-31T06:37:34Z proxy[e82de1df0742d8] sin [info]machine started in 1.415646817s
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]time=2025-01-31T06:37:34.136Z level=INFO msg=litestream version=v0.3.13
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]time=2025-01-31T06:37:34.138Z level=INFO msg="initialized db" path=/var/opt/memos/memos_prod.db
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]time=2025-01-31T06:37:34.138Z level=INFO msg="replicating to" name=s3 type=s3 sync-interval=1s bucket=usememos-backup path=db region="" endpoint=s3.eu-central-003.backblazeb2.com
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]2025/01/31 06:37:34 INFO SSH listening listen_address=[fdaa:e:739f:a7b:18a:c307:fb75:2]:22 dns_server=[fdaa::3]:53
2025-01-31T06:37:34Z proxy[e82de1df0742d8] sin [info]machine became reachable in 417.49551ms
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]---
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]Server profile
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]version: 0.23.1
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]data: /var/opt/memos
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]dsn: /var/opt/memos/memos_prod.db
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]addr:
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]port: 5230
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]mode: prod
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]driver: sqlite
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]---
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]Version 0.23.1 has been started on port 5230
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]---
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]See more in:
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]πŸ‘‰Website: https://usememos.com
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]πŸ‘‰GitHub: https://github.com/usememos/memos
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]---
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘
2025-01-31T06:37:34Z app[e82de1df0742d8] sin [info]β•šβ•β•     β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•     β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•

Access the App

My usememos use custom domain https://micro.sumarsono.com