Note: Any instance of angled brackets (e.g., <app-name>
) denotes something to be replaced with an actual value or name, minus the angled brackets.
This repo contains:
fly.toml
, which Fly uses to configure app deploymentDockerfile
, which Fly uses to build the appstatic/
, which is a copy of listmonk's static directory for purposes of customization
Note: Fly uses Dockerfiles to deploy apps, but it does not deploy Docker containers. Instead, it create a Firecracker VM based on the Dockerfile.
Follow these instructions to install the CLI flyctl
.
If you don't already have a Fly account, run flyctl auth signup
and sign up.
Log in with flyctl auth login
.
cd
to the directory where you cloned this repo. This will be the working directory that flyctl
associates with this particular app.
Open fly.toml
and look at [build]
section, which provides keys and values for the application build:
[build]
dockerfile = "./Dockerfile"
ADMIN_USERNAME=""
ADMIN_PASSWORD=""
POSTGRES_HOST=""
POSTGRES_PORT=5432
POSTGRES_USER="listmonk"
POSTGRES_PASSWORD=""
POSTGRES_DATABASE=""
Copy this section and save it somewhere, since Fly's launch
command might remove it, and you'll need to add it back and edit it.
Enter flyctl launch
to go create a new app and an attached Postgres database app.
When flyctl launch
asks you if you'd like to copy the configuration of the existing fly.toml
file, type y
.
You can have it automatically generate an app name, or choose one yourself.
Choose the default organization (personal)—you can always change this later.
Select a region to deploy the app in. Fly will pre-select a region near your IP address. Take note of the three-character code representing your region. You'll need it later.
When it asks you if you want to set up a Postgres database, type y
.
Choose the "Development" level configuration (lowest, free tier).
Once your postgres cluster is created, copy the information flyctl
displays: Username
, Password
, Hostname
, Proxy Port
, and PG Port
. These are all default values or based on your app name, but Password
is unique, so be sure you save it. And you'll need Hostname
a bit later on.
Also take note of the name of your Postgres app in the line:
Postgres cluster <app-name-db> is now attached to <app-name>
When flyctl launch
asks you if you want to deploy now, type n
, in order to do some preliminary setup.
It's best not to give an app superuser database credentials like the postgres
user and its password that you copied. So create a new user in your postgres app:
flyctl postgres connect -a <app-name-db>
In the postgres command line, type \l
to list databases in the cluster. You'll see a database entry that closely matches your app's name. This is the database the listmonk app will use. Take note of the database name, since it may be slightly different from your app name.
Create and save a secure and unique password for the new listmonk
user.
Type CREATE USER listmonk WITH ENCRYPTED PASSWORD '<new password>';
, placing your new password between the single quotes '
. Be sure to include the ;
at the end, which terminates the command.
Type GRANT ALL PRIVILEGES ON DATABASE <database_name> TO listmonk;
, substituting <database_name>
with the name of your database.
Type \q
to exit the postgres command line.
You'll need the three-character <region code>
from when you used fly launch
Use flyctl vol create listmonk_data --region <region code> --size 1
to create a persistent storage volume called listmonk_data
in the same region as your app.
Edit fly.toml
and check if the [build]
section you copied is still there. It likely isn't. Re-add it from your copy (or copy this repo). I don't think placement matters, but I put it just above [env]
.
Between the double quotes "
for each key, enter the following info that you'll be passing in to your listmonk app build:
ADMIN_USERNAME
: create a user name for accessing listmonk's admin page withADMIN_PASSWORD
: create a unique password for that user namePOSTGRES_HOST
: theHostname
that the Postgres cluster setup process offly launch
gave you (it's probably<app-name-db>.internal
)POSTGRES_PASSWORD
: the password you created when you made thelistmonk
user in the Postgres command line—not the masterpostgres
password that you saved earlier.POSTGRES_DATABASE
: the name of the database you granted access to for userlistmonk
.
Check that the following section still exists in fly.toml
, and if not, add it.
[mounts]
destination = "/data"
source = "listmonk_data"
Use flyctl deploy
to deploy the app.
Once the deployment is finished, you can find your app at <app-name>.fly.dev
, and log in with the user name and password you chose.
If you want to use a custom domain for your listmonk install, follow these instructions.
At build time, Fly will pull the build values and plug them into the Dockerfile's ENV
variables, which will be used to configure listmonk.
The Dockerfile's COPY static/ /tmp/static/
line copies the static/
folder into temporary storage on the app.
Then the commands in CMD
, which run once the persistent storage volume is mounted, copy the static/
folder to persistent storage, and install/upgrade/run listmonk.
For reference: listmonk's docs about its system templates.
To edit the system templates, simply make your edits in the static/
directory on your computer.
To deploy the changes, use fly deploy
(making sure you're in the root directory of the for the Fly app).
listmonk has an option ssl_mode
that can be enabled, in order to encrypt traffic between the listmonk app and its database, in case of snooping by unauthorized processes or users on the server.
On Fly, this is unnecessary because:
- Fly creates a private and encrypted network using Wireguard between the the app and its database (via
<app-name-db>.internal
) - Accessing the Postgres database from the command line uses this same encrypted connection.
(See this comment for reference).
In case of database failure, it's good to have a backup. Adding a replica is simple:
flyctl volumes list <app-name-db>
and get the size of the volume.
flyctl volumes create pg_data -a <app-name-db> --size <same size as original volume> --region <region code>
and choose a different region for a volume.
Create other volumes if desired with the same command.
Then scale out your app to include these volumes as replicas. flyctl scale count <# of volumes including replicas> -a <app-name-db>
Use flyctl status -a <app-name-db>
to check that the new volume is running with no errors. May take a minute or two.