Hi,
since firezone will change to containerized type (docker), however which is not the prefer tool in my common Linux support (Redhat / Fedora).
here I have make test on podman, but no luck in podman-compose tool, seems it is not fully compatible.
so I try to modify it, I am not a programmer so the script may not perfect as expect, but should able to execute in a fresh installation.
here I would share the script for those who want to use podman for testing. thanks
I also share in google drive for easy download
https://drive.google.com/file/d/18jnK50crP337Dr5Rgq9ngumdwRfwQl0q/view
Regard,
Lawes
#!/bin/bash
set -e
#####################################
# This script is for podman only
# support in firezone 0.67 fresh deployment
# version 2.5
# - support podman 4.x
# - support firezone 0.67
# - support fresh installation only, not for data migration
# - support Linux, test on Fedora 35, 36
# - create pod
# - create firezone-network
# - create host container caddy
# - create bridge container firezone, postgres
# - assign static ip to firezone
# - fix caddy syntax error now
# Remark:
# - caddy process not running in PID 1, therefore podman stop command will not take effect
# ##################################
podmanCheck () {
if ! type podman > /dev/null; then
echo "podman not found. Please install podman and try again."
exit 1
fi
set +e
podman version | grep -q "Version: 4"
if [ $? -ne 0 ]; then
echo "Error: Automatic installation is only supported with Podman version 4 or higher."
echo "Please upgrade Podman Version"
exit 1
fi
set -e
}
curlCheck () {
if ! type curl > /dev/null; then
echo "curl not found. Please install curl to use this script."
exit 1
fi
}
capture () {
if type curl > /dev/null; then
if [ ! -z "$telemetry_id" ]; then
curl -s -XPOST \
-m 5 \
-H "Content-Type: application/json" \
-d "{
\"api_key\": \"phc_ubuPhiqqjMdedpmbWpG2Ak3axqv5eMVhFDNBaXl9UZK\",
\"event\": \"$1\",
\"properties\": {
\"distinct_id\": \"$telemetry_id\",
\"email\": \"$2\"
}
}" \
https://telemetry.firez.one/capture/ > /dev/null \
|| true
fi
fi
}
promptInstallDir() {
read -p "$1" installDir
if [ -z "$installDir" ]; then
installDir=$defaultInstallDir
fi
if ! test -d $installDir; then
mkdir $installDir
fi
}
promptExternalUrl() {
read -p "$1" externalUrl
# Remove trailing slash if present
externalUrl=$(echo $externalUrl | sed "s:/*$::")
if [ -z "$externalUrl" ]; then
externalUrl=$defaultExternalUrl
fi
}
promptEmail() {
read -p "$1" adminEmail
case $adminEmail in
*@*)
adminUser=$adminEmail
;;
*)
promptEmail "Please provide a valid email: "
;;
esac
}
promptContact() {
read -p "Could we email you to ask for product feedback? Firezone depends heavily on input from users like you to steer development. (Y/n): " contact
case $contact in
n|N)
;;
*)
capture "contactOk" $adminUser
;;
esac
}
promptACME() {
read -p "Would you like to enable automatic SSL cert provisioning? Requires a valid DNS record and port 80 to be reachable. (Y/n): " acme
case $acme in
n|N)
tlsOpts=" tls internal {
on_demand
}"
;;
*)
tlsOpts=" tls {
on_demand
}"
;;
esac
}
promptTelemetry() {
read -p "Firezone collects crash and performance logs to help us improve the product. Would you like to disable this? (N/y): " telem
case $telem in
y|Y)
telemEnabled="false"
;;
*)
telemEnabled="true"
;;
esac
}
firezoneSetup() {
export FZ_INSTALL_DIR=$installDir
db_pass=$(od -vN "8" -An -tx1 /dev/urandom | tr -d " \n" ; echo)
# podman, if use shortname for image search may return error, here use full image_path
podman run --rm docker.io/firezone/firezone:latest bin/gen-env > "$installDir/.env"
# search and update .env variable
sed -i.bak "s/ADMIN_EMAIL=.*/ADMIN_EMAIL=$1/" "$installDir/.env"
sed -i.bak "s~EXTERNAL_URL=.*~EXTERNAL_URL=$2~" "$installDir/.env"
sed -i.bak "s/DATABASE_PASSWORD=.*/DATABASE_PASSWORD=$db_pass/" "$installDir/.env"
echo "TLS_OPTS=$3" >> "$installDir/.env"
echo "TELEMETRY_ENABLED=$telemEnabled" >> "$installDir/.env"
# XXX: This causes perms issues on macOS with postgres
# echo "UID=$(id -u)" >> $installDir/.env
# echo "GID=$(id -g)" >> $installDir/.env
# Set DATABASE_PASSWORD explicitly here in case the user has this var set in their shell
#
# - f compse.yml file
# - d backend execute
DATABASE_PASSWORD=$db_pass
echo "Show DATABASE_PASSWORD..."
echo $DATABASE_PASSWORD
#DATABASE_PASSWORD=$db_pass $dc -f $installDir/podman-compose.yml up -d postgres
#
# check does pod_firezone and firezone_network exist
podExist=$(podman pod exists pod-firezone; echo $?)
networkExist=$(podman network exists firezone-network; echo $?)
caddyExist=$(podman container exists caddy; echo $?)
#
if [ $podExist -eq 0 ]; then
echo " "
echo "stopping and remove pod pod-firezone..."
podman pod stop pod-firezone
podman pod rm -i pod-firezone
sleep 5
REpodExist=$(podman pod exists pod-firezone; echo $?)
if [ $REpodExist -gt 1 ]; then
echo "something wrong during remove pod pod-firezone or container..."
#echo "please manually correct It (podman system reset)"
exit 1
fi
fi
if [ $networkExist -eq 0 ]; then
echo " "
echo "remove pod firezone-network..."
podman network rm firezone-network
sleep 5
REnetworkExist=$(podman network exists firezone-network; echo $?)
if [ $REnetworkExist -gt 1 ]; then
echo "something wrong during remove network firezone-network..."
#echo "please manually correct It (podman system reset)"
exit 1
fi
fi
if [ $caddyExist -eq 0 ]; then
echo " "
echo "stop and remove container caddy..."
podman container stop caddy
sleep 5
podman container rm -i caddy
sleep 5
REcaddyExist=$(podman container exists caddy; echo $?)
if [ $REcaddyExist -gt 1 ]; then
echo "something wrong during remove container caddy..."
#echo "please manually correct It (podman system reset)"
exit 1
fi
fi
REpodExist=$(podman pod exists pod-firezone; echo $?)
REnetworkExist=$(podman network exists firezone-network; echo $?)
REcaddyExist=$(podman container exists caddy; echo $?)
#
if [[ $REpodExist -eq 1 && $REnetworkExist -eq 1 && $REcaddyExist -eq 1 ]]; then
echo " "
echo "creating pod pod-firezone..."
podman pod create --name pod-firezone -p 51820:51820/udp
sleep 3
echo " "
echo "creating network firezone-network..."
podman network create firezone-network --subnet 172.25.0.0/16 --gateway 172.25.0.1 --label firezone-network
sleep 5
fi
mkdir -p ${FZ_INSTALL_DIR}/postgres-data
echo " "
echo "creating container postgres..."
# the following script run once only, if ${FZ_INSTALL_DIR:-.}/postgres-data is empty
podman run --pod=pod-firezone --name postgres -dt --net=firezone-network -e POSTGRES_DB=${DATABASE_NAME:-firezone} -e POSTGRES_USER=${DATABASE_USER:-postgres} -e POSTGRES_PASSWORD=${DATABASE_PASSWORD:?err} -v ${FZ_INSTALL_DIR}/postgres-data/:/var/lib/postgresql/data/:Z docker.io/library/postgres:15
echo " "
echo "waiting for DB to boot..."
sleep 5
podman logs postgres
echo " "
echo "Resetting DB password..."
sleep 5
#
# The following is the method to reset ROLE postgres passowrd ...
# first, create a file in postgres home_directory /var/lib/postgresql/, named password_reset
podman container exec postgres /bin/su - postgres -c 'touch password_reset'
#
# create content
podman container exec postgres /bin/bash -c "echo -e ALTER ROLE postgres WITH PASSWORD \'${DATABASE_PASSWORD}\' > /var/lib/postgresql/password_reset"
# then execute the reset process
podman container exec postgres /bin/su - postgres -c 'psql -p 5432 -U postgres -d firezone -h localhost --file=password_reset'
#
# execute container_firezone
# change to static ip, although podman support container alias, change it for compatible in future
mkdir -p ${FZ_INSTALL_DIR:-.}/firezone
podman run --pod=pod-firezone --name firezone -dt --net=firezone-network --ip=172.25.0.100 --requires postgres --cap-add NET_ADMIN,SYS_MODULE --sysctl net.ipv6.conf.all.disable_ipv6=0 --sysctl net.ipv4.ip_forward=1 --sysctl net.ipv6.conf.all.forwarding=1 --env-file=${FZ_INSTALL_DIR:-.}/.env -v ${FZ_INSTALL_DIR:-.}/firezone:/var/firezone:Z docker.io/firezone/firezone:latest
#
# execute container caddy
mkdir -p ${FZ_INSTALL_DIR:-.}/caddy
#
externalFQDN=$externalUrl
#remove http:// or https://
externalFQDN=${externalFQDN#*//}
#remove /*
externalFQDN=${externalFQDN%/*}
#
# -execute run - caddy cli during container init
#podman run --name caddy -dt --network=host --privileged -v ${FZ_INSTALL_DIR:-.}/caddy:/data/caddy:Z docker.io/library/caddy:2 caddy reverse-proxy --from ${externalFQDN} --to 172.25.0.100:13000
#
# -execute exec - bin/sh -c method
#podman container exec caddy /bin/sh -c "cat <<@EOF > /etc/caddy/Caddyfile && cd /etc/caddy && caddy fmt --overwrite && caddy run --config /etc/caddy/Caddyfile
#
# -execute run - entrypoint method, interactive mode
#podman run --name caddy -it --network=host --privileged --entrypoint=/bin/sh -v ${FZ_INSTALL_DIR:-.}/caddy:/data/caddy:Z docker.io/library/caddy:2 -i
#
# - execute run - entrypoint method, detach mode
podman run --name caddy -dt --network=host --privileged --entrypoint "/bin/sh" -v ${FZ_INSTALL_DIR:-.}/caddy:/data/caddy:Z docker.io/library/caddy:2 -c "cat <<@EOF > /etc/caddy/Caddyfile && ( cd /etc/caddy; caddy fmt --overwrite; caddy run --config /etc/caddy/Caddyfile --adapter caddyfile )
${externalFQDN} {
log
reverse_proxy 172.25.0.100:13000
${tlsOpts:-}
}
"@EOF
echo " "
echo "Waiting for app to boot before creating admin..."
sleep 15
podman exec firezone bin/create-or-reset-admin
displayLogo
cat << EOF
Installation complete!
You should now be able to log into the Web UI at $externalUrl with the
following credentials:
`grep ADMIN_EMAIL $installDir/.env`
`grep DEFAULT_ADMIN_PASSWORD $installDir/.env`
EOF
}
displayLogo() {
cat << EOF
::
!!:
.??^
~J?^
:???.
.??J^
.??J!
.??J!
^J?J~
!???:
.???? ::
^J?J! :~:
7???: :~~
.???7 ~~~.
:??J^ :~~^
:???..~~~:
............. .?J7 ^~~~ ....
.. ......::.... ~J!.~~~^ ::..
...:::.... !7^~~~^ .^: .
...:::.... ~~~~~~:. .:~^ .
....:::.... .~~~~~~~~~:..
...::::.... .::^^^^:...
.....:::.............
.......:::.....
EOF
}
main() {
defaultExternalUrl="https://$(hostname)"
adminUser=""
externalUrl=""
defaultInstallDir="$HOME/.firezone"
tlsOpts=""
promptEmail "Enter the administrator email you'd like to use for logging into this Firezone instance: "
promptInstallDir "Enter the desired installation directory ($defaultInstallDir): "
promptExternalUrl "Enter the external URL that will be used to access this instance. ($defaultExternalUrl): "
promptACME
promptContact
promptTelemetry
read -p "Press <ENTER> to install or Ctrl-C to abort."
if [ $telemEnabled = "true" ]; then
capture "install" "email-not-collected@dummy.domain"
fi
firezoneSetup $adminUser $externalUrl "$tlsOpts"
}
podmanCheck
curlCheck
telemetry_id=$(od -vN "8" -An -tx1 /dev/urandom | tr -d " \n" ; echo)
main