2024-02-21 15:41:38 +08:00
#!/usr/bin/env bash
2021-06-14 21:50:13 +08:00
set -eu
2023-08-28 22:43:03 +08:00
# Listmonk production setup using `docker compose`.
2021-06-14 21:50:13 +08:00
# See https://listmonk.app/docs/installation/ for detailed installation steps.
printf '\n'
RED = " $( tput setaf 1 2>/dev/null || printf '' ) "
BLUE = " $( tput setaf 4 2>/dev/null || printf '' ) "
GREEN = " $( tput setaf 2 2>/dev/null || printf '' ) "
NO_COLOR = " $( tput sgr0 2>/dev/null || printf '' ) "
info( ) {
2021-07-22 19:05:47 +08:00
printf '%s\n' " ${ BLUE } > ${ NO_COLOR } $* "
2021-06-14 21:50:13 +08:00
}
error( ) {
printf '%s\n' " ${ RED } x $* ${ NO_COLOR } " >& 2
}
completed( ) {
2021-07-22 19:05:47 +08:00
printf '%s\n' " ${ GREEN } ✓ ${ NO_COLOR } $* "
2021-06-14 21:50:13 +08:00
}
exists( ) {
2024-02-21 15:41:38 +08:00
command -v " $1 " >/dev/null 2>& 1
}
sed_inplace( ) {
local search_pattern = " $1 "
local replacement = " $2 "
local file = " $3 "
if [ [ " $( uname) " = = "Darwin" ] ] ; then
sed -i '' " s/ ${ search_pattern } / ${ replacement } /g " " $file "
else
sed -i " s/ ${ search_pattern } / ${ replacement } /g " " $file "
fi
2021-06-14 21:50:13 +08:00
}
check_dependencies( ) {
if ! exists curl; then
error "curl is not installed."
exit 1
2021-08-28 21:43:51 +08:00
fi
2021-06-14 21:50:13 +08:00
if ! exists docker; then
error "docker is not installed."
exit 1
2021-08-28 21:43:51 +08:00
fi
2021-06-14 21:50:13 +08:00
2023-08-28 22:43:03 +08:00
# Check for "docker compose" functionality.
2024-02-21 15:41:38 +08:00
if ! docker compose version >/dev/null 2>& 1; then
2023-08-28 22:43:03 +08:00
echo "'docker compose' functionality is not available. Please update to a newer version of Docker. See https://docs.docker.com/engine/install/ for more details."
2021-06-14 21:50:13 +08:00
exit 1
fi
2024-10-04 12:58:22 +08:00
if ! docker compose ls >/dev/null; then
echo "no docker access - you might need to run this script with sudo or see https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user"
exit 1
fi
2021-06-14 21:50:13 +08:00
}
2021-10-18 12:38:02 +08:00
check_existing_db_volume( ) {
info "checking for an existing docker db volume"
if docker volume inspect listmonk_listmonk-data >/dev/null 2>& 1; then
2023-08-28 22:43:03 +08:00
error "listmonk-data volume already exists. Please use docker compose down -v to remove old volumes for a fresh setup of PostgreSQL."
2021-10-18 12:38:02 +08:00
exit 1
fi
}
2021-06-14 21:50:13 +08:00
download( ) {
2021-08-28 21:43:51 +08:00
curl --fail --silent --location --output " $2 " " $1 "
2021-06-14 21:50:13 +08:00
}
is_healthy( ) {
2021-08-28 21:43:51 +08:00
info "waiting for db container to be up. retrying in 3s"
health_status = " $( docker inspect -f "{{.State.Health.Status}}" " $1 " ) "
if [ " $health_status " = "healthy" ] ; then
return 0
else
return 1
fi
2021-06-14 21:50:13 +08:00
}
is_running( ) {
2024-02-21 15:41:38 +08:00
info " checking if $1 is running "
2021-08-28 21:43:51 +08:00
status = " $( docker inspect -f "{{.State.Status}}" " $1 " ) "
if [ " $status " = "running" ] ; then
return 0
else
return 1
fi
2021-06-14 21:50:13 +08:00
}
generate_password( ) {
2024-02-21 15:41:38 +08:00
echo " $( LC_ALL = C tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo '' ) "
2021-06-14 21:50:13 +08:00
}
get_config( ) {
2021-08-28 21:43:51 +08:00
info "fetching config.toml from listmonk repo"
download https://raw.githubusercontent.com/knadh/listmonk/master/config.toml.sample config.toml
2021-06-14 21:50:13 +08:00
}
get_containers( ) {
2021-08-28 21:43:51 +08:00
info "fetching docker-compose.yml from listmonk repo"
download https://raw.githubusercontent.com/knadh/listmonk/master/docker-compose.yml docker-compose.yml
2021-06-14 21:50:13 +08:00
}
modify_config( ) {
2021-08-28 21:43:51 +08:00
info "generating a random password"
db_password = $( generate_password)
info "modifying config.toml"
2024-02-21 15:41:38 +08:00
sed_inplace 'host = "localhost"' 'host = "listmonk_db"' config.toml
sed_inplace 'password = "listmonk"' " password = \" ${ db_password } \" " config.toml
sed_inplace 'address = "localhost:9000"' 'address = "0.0.0.0:9000"' config.toml
2021-08-28 21:43:51 +08:00
info "modifying docker-compose.yml"
2024-02-21 15:41:38 +08:00
sed_inplace 'POSTGRES_PASSWORD=listmonk' " POSTGRES_PASSWORD= $db_password " docker-compose.yml
2021-06-14 21:50:13 +08:00
}
run_migrations( ) {
2021-08-28 21:43:51 +08:00
info "running migrations"
2023-08-28 22:43:03 +08:00
docker compose up -d db
2021-08-28 21:43:51 +08:00
while ! is_healthy listmonk_db; do sleep 3; done
2023-08-28 22:43:03 +08:00
docker compose run --rm app ./listmonk --install
2021-06-14 21:50:13 +08:00
}
start_services( ) {
2021-08-28 21:43:51 +08:00
info "starting app"
2023-08-28 22:43:03 +08:00
docker compose up -d app db
2021-06-14 21:50:13 +08:00
}
show_output( ) {
2021-08-28 21:43:51 +08:00
info "finishing setup"
sleep 3
if is_running listmonk_db && is_running listmonk_app
then completed "Listmonk is now up and running. Visit http://localhost:9000 in your browser."
else
error "error running containers. something went wrong."
fi
2021-06-14 21:50:13 +08:00
}
check_dependencies
2021-10-18 12:38:02 +08:00
check_existing_db_volume
2021-06-14 21:50:13 +08:00
get_config
get_containers
modify_config
run_migrations
start_services
show_output