Bitwarden's self-hosted release repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

334 lines
9.0 KiB

#!/usr/bin/env bash
set -e
cat << "EOF"
_ _ _ _
| |__ (_) |___ ____ _ _ __ __| | ___ _ __
| '_ \| | __\ \ /\ / / _` | '__/ _` |/ _ \ '_ \
| |_) | | |_ \ V V / (_| | | | (_| | __/ | | |
|_.__/|_|\__| \_/\_/ \__,_|_| \__,_|\___|_| |_|
EOF
cat << EOF
Open source password management solutions
Copyright 2015-$(date +'%Y'), Bitwarden, Inc.
https://bitwarden.com, https://github.com/bitwarden
===================================================
EOF
RED='\033[0;31m'
NC='\033[0m' # No Color
if [ "$EUID" -eq 0 ]; then
echo -e "${RED}WARNING: This script is running as the root user!"
echo -e "If you are running a standard deployment this script should be running as a dedicated Bitwarden User as per the documentation.${NC}"
read -p "Do you still want to continue? (y/n): " choice
# Check the user's choice
case "$choice" in
[Yy]|[Yy][Ee][Ss])
echo -e "Continuing...."
;;
*)
exit 1
;;
esac
fi
# Setup
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SCRIPT_NAME=$(basename "$0")
SCRIPT_PATH="$DIR/$SCRIPT_NAME"
OUTPUT="$DIR/bwdata"
if [ $# -eq 2 ]
then
OUTPUT=$2
fi
if docker compose &> /dev/null; then
dccmd='docker compose'
elif command -v docker-compose &> /dev/null; then
dccmd='docker-compose'
echo "docker compose not found, falling back to docker-compose."
else
echo "Error: Neither 'docker compose' nor 'docker-compose' commands were found. Please install Docker Compose." >&2
exit 1
fi
SCRIPTS_DIR="$OUTPUT/scripts"
BITWARDEN_SCRIPT_URL="https://func.bitwarden.com/api/dl/?app=self-host&platform=linux"
RUN_SCRIPT_URL="https://func.bitwarden.com/api/dl/?app=self-host&platform=linux&variant=run"
# Please do not create pull requests modifying the version numbers.
COREVERSION="2025.8.1"
WEBVERSION="2025.8.3"
KEYCONNECTORVERSION="2024.8.0"
echo "bitwarden.sh version $COREVERSION"
docker --version
if [[ "$dccmd" == "docker compose" ]]; then
$dccmd version
else
$dccmd --version
fi
echo ""
# Functions
function downloadSelf() {
if curl -L -s -S -w "http_code %{http_code}" -o $SCRIPT_PATH.1 $BITWARDEN_SCRIPT_URL | grep -q "^http_code 20[0-9]"
then
mv -f $SCRIPT_PATH.1 $SCRIPT_PATH
chmod u+x $SCRIPT_PATH
else
exit_code=$?
rm -f $SCRIPT_PATH.1
exit $exit_code
fi
}
function downloadRunFile() {
if [ ! -d "$SCRIPTS_DIR" ]
then
mkdir $SCRIPTS_DIR
fi
local tmp_script=$(mktemp)
run_file_status_code=$(curl -s -S -L -w "%{http_code}" -o $tmp_script $RUN_SCRIPT_URL)
if echo "$run_file_status_code" | grep -q "^20[0-9]"
then
mv $tmp_script $SCRIPTS_DIR/run.sh
chmod u+x $SCRIPTS_DIR/run.sh
rm -f $SCRIPTS_DIR/install.sh
else
echo "Unable to download run script from $RUN_SCRIPT_URL. Received status code: $run_file_status_code"
echo "http response:"
cat $tmp_script
rm -f $tmp_script
exit 1
fi
}
function checkOutputDirExists() {
if [ ! -d "$OUTPUT" ]
then
echo "Cannot find a Bitwarden installation at $OUTPUT."
exit 1
fi
}
function checkOutputDirNotExists() {
if [ -d "$OUTPUT/docker" ]
then
echo "Looks like Bitwarden is already installed at $OUTPUT."
exit 1
fi
}
function compressLogs() {
LOG_DIR=${1#$(pwd)/}/logs
START_DATE=$2
END_DATE=$3
tempfile=$(mktemp)
function validateDateFormat() {
if ! [[ $1 =~ ^[0-9]{8}$ ]]; then
echo "Error: $2 date format is invalid. Please use YYYYMMDD."
exit 1
fi
}
function validateDateOrder() {
if [[ $(date -d "$1" +%s) > $(date -d "$2" +%s) ]]; then
echo "Error: start date ($1) must be earlier than end date ($2)."
exit 1
fi
}
# Validate start date format
if [ -n "$START_DATE" ]; then
validateDateFormat "$START_DATE" "start"
if [ -z "$END_DATE" ]; then
echo "Error: an end date is required when an start date is provided."
exit 1
fi
fi
# Validate end date format and order
if [ -n "$END_DATE" ]; then
validateDateFormat "$END_DATE" "end"
validateDateOrder "$START_DATE" "$END_DATE"
fi
if [ -n "$START_DATE" ] && [ -n "$END_DATE" ]; then
OUTPUT_FILE="bitwarden-logs-${START_DATE}-to-${END_DATE}.tar.gz"
if [[ "$START_DATE" == "$END_DATE" ]]; then
OUTPUT_FILE="bitwarden-logs-${START_DATE}.tar.gz"
fi
for d in $(seq $(date -d "$START_DATE" "+%Y%m%d") $(date -d "$END_DATE" "+%Y%m%d")); do
# Find and list files matching the date in the filename and modification time, append to tempfile
find $LOG_DIR \( -type f -name "*$d*.txt" -o -name "*.log" -newermt "$START_DATE" ! -newermt "$END_DATE" \) -exec bash -c 'echo "${1#./}" >> "$2"' _ {} "$tempfile" \;
done
echo "Compressing logs from $START_DATE to $END_DATE ..."
else
OUTPUT_FILE="bitwarden-logs-all.tar.gz"
find $LOG_DIR -type f -exec bash -c 'echo "${1#./}" >> "$2"' bash {} "$tempfile" \;
echo "Compressing all logs..."
fi
tar -czvf "$OUTPUT_FILE" -T "$tempfile"
echo "Logs compressed into $(pwd $OUTPUT_FILE)/$OUTPUT_FILE"
rm $tempfile
}
function checkSmtp() {
CONFIG_FILE="$1/env/global.override.env"
if [ ! -f "$CONFIG_FILE" ]; then
echo "Configuration file not found at $CONFIG_FILE"
exit 1
fi
if ! command -v openssl &> /dev/null; then
echo "OpenSSL is not available but is required for this check."
exit 1
fi
host=$(grep 'globalSettings__mail__smtp__host=' "$CONFIG_FILE" | cut -d '=' -f2)
port=$(grep 'globalSettings__mail__smtp__port=' "$CONFIG_FILE" | cut -d '=' -f2)
ssl=$(grep 'globalSettings__mail__smtp__ssl=' "$CONFIG_FILE" | cut -d '=' -f2)
username=$(grep 'globalSettings__mail__smtp__username=' "$CONFIG_FILE" | cut -d '=' -f2)
password=$(grep 'globalSettings__mail__smtp__password=' "$CONFIG_FILE" | cut -d '=' -f2)
if [ "$ssl" == "true" ]; then
ssl_command="-ssl"
else
ssl_command="-starttls smtp"
fi
set +e
SMTP_RESPONSE=$(
{
echo "EHLO localhost"
if [ "$ssl_command" != "-ssl" ]; then
echo "STARTTLS"
sleep 2
echo "EHLO localhost"
fi
# Check if username and password are set before proceeding
if [[ -n "$username" && -n "$password" ]]; then
echo "AUTH LOGIN"
echo "$(echo -ne "$username" | base64)"
echo "$(echo -ne "$password" | base64)"
fi
echo "QUIT"
} | openssl s_client -connect $host:$port $ssl_command -ign_eof 2>/dev/null
)
if echo "$SMTP_RESPONSE" | grep -q "^2[0-9][0-9] "; then
echo -e "SMTP settings are correct."
else
echo "SMTP authentication failed or connection error occurred."
fi
}
function listCommands() {
cat << EOT
Available commands:
install
start
restart
stop
update
updatedb
updaterun
updateself
updateconf
uninstall
renewcert
rebuild
compresslogs
help
See more at https://bitwarden.com/help/article/install-on-premise/#script-commands-reference
EOT
}
# Commands
case $1 in
"install")
checkOutputDirNotExists
mkdir -p $OUTPUT
downloadRunFile
$SCRIPTS_DIR/run.sh install $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"start" | "restart")
checkOutputDirExists
$SCRIPTS_DIR/run.sh restart $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"update")
checkOutputDirExists
downloadRunFile
$SCRIPTS_DIR/run.sh update $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"rebuild")
checkOutputDirExists
$SCRIPTS_DIR/run.sh rebuild $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"updateconf")
checkOutputDirExists
$SCRIPTS_DIR/run.sh updateconf $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"updatedb")
checkOutputDirExists
$SCRIPTS_DIR/run.sh updatedb $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"stop")
checkOutputDirExists
$SCRIPTS_DIR/run.sh stop $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"renewcert")
checkOutputDirExists
$SCRIPTS_DIR/run.sh renewcert $OUTPUT $COREVERSION $WEBVERSION $KEYCONNECTORVERSION
;;
"updaterun")
checkOutputDirExists
downloadRunFile
;;
"updateself")
downloadSelf && echo "Updated self." && exit
;;
"uninstall")
checkOutputDirExists
$SCRIPTS_DIR/run.sh uninstall $OUTPUT
;;
"compresslogs")
checkOutputDirExists
compressLogs $OUTPUT $2 $3
;;
"checksmtp")
checkOutputDirExists
checkSmtp $OUTPUT
;;
"help")
listCommands
;;
*)
echo "No command found."
echo
listCommands
esac