Skip to content

Instantly share code, notes, and snippets.

@StrangeRanger
Last active November 2, 2024 20:03
Show Gist options
  • Save StrangeRanger/84925fd3e6d8aa84a0b3ece5a01f4484 to your computer and use it in GitHub Desktop.
Save StrangeRanger/84925fd3e6d8aa84a0b3ece5a01f4484 to your computer and use it in GitHub Desktop.
An easy way to install PrivateBin in a secure method, seperating files that can be publicly accessible and one's that can't.
#!/bin/bash
#
# An easy way to install PrivateBin in a secure method, seperating files that can be
# publicly accessible and one's that can't.
#
# NOTE:
# This script requires root privileges to modify ownership of the files.
#
# Version: v1.0.0-rc1
# License: MIT License
# Copyright (c) 2024 Hunter T. (StrangeRanger)
#
########################################################################################
####[ Global Variables ]################################################################
###
### [ Configurable Variables ]
###
# Directory for files that should be accessible from the web.
readonly C_PUBLIC_FILE_PATH="public"
# Directory for files that should not be accessible from the web.
readonly C_PRIVATE_FILE_PATH="private"
# Defines the path to the private files, to be specified in the 'index.php' file.
readonly C_DEFINED_PATH="../private/"
# Owner of files.
readonly C_FILE_OWNER="www-data"
###
### [ Non-Configurable Variables ]
###
readonly C_PRIVATE=("bin" "cfg" "data" "lib" "tpl" "tst" "vendor")
C_LATEST_RELEASE_URL=$(curl -s "https://api.github.com/repos/PrivateBin/PrivateBin/releases/latest" \
| grep "tarball_url" | cut -d '"' -f 4)
readonly C_LATEST_RELEASE_URL
## Used to colorize output.
C_YELLOW="$(printf '\033[1;33m')"
C_RED="$(printf '\033[1;31m')"
C_NC="$(printf '\033[0m')"
readonly C_YELLOW C_RED C_NC
## Short-hand colorized messages.
readonly C_WARNING="${C_YELLOW}WARNING:${C_NC} "
readonly C_ERROR="${C_RED}ERROR:${C_NC} "
####[ Functions ]#######################################################################
####
# Copy an item from the source to the destination.
#
# PARAMETERS:
# - $1: src (Required)
# - The source file or directory to copy.
# - $2: dst (Required)
# - The destination file or directory to copy to.
# - $3: name (Required)
# - The name of the file or directory being copied, used for error messages.
copy_item() {
local src="$1"
local dst="$2"
local name="$3"
if [[ -e "$src" ]]; then
cp -r "$src" "$dst" || {
echo "${C_ERROR}Failed to migrate '$name'"
exit 1
}
fi
}
####
# Remove files that are no longer needed.
remove_files() {
local files_to_remove=(
"latest-release.tar.gz"
"$C_PUBLIC_FILE_PATH.old"
"$C_PRIVATE_FILE_PATH.old"
)
echo "Cleaning up..."
for file in "${files_to_remove[@]}"; do
[[ -e $file ]] && rm -rf "$file"
done
}
####
# Revert changes made by the script. This ensures that the script resets all changes in
# the event of an error or user interrupt.
revert_changes() {
echo "Reverting changes..."
if [[ -d "$C_PUBLIC_FILE_PATH.old" && -d "$C_PRIVATE_FILE_PATH.old" ]]; then
rm -rf "$C_PUBLIC_FILE_PATH"
rm -rf "$C_PRIVATE_FILE_PATH"
mv "$C_PUBLIC_FILE_PATH.old" "$C_PUBLIC_FILE_PATH"
mv "$C_PRIVATE_FILE_PATH.old" "$C_PRIVATE_FILE_PATH"
else
[[ ! -d $C_PUBLIC_FILE_PATH ]] \
&& echo "${C_WARNING}'${C_PUBLIC_FILE_PATH}.old' directory not found"
[[ ! -d $C_PRIVATE_FILE_PATH ]] \
&& echo "${C_WARNING}'${C_PRIVATE_FILE_PATH}.old' directory not found"
echo "${C_WARNING}Not all directories were found, manual intervention required"
exit 2
fi
}
####
# Cleanly exit the script.
#
# PARAMETERS:
# - $1: exit_code (Required)
# - The exit code to exit the script with.
clean_exit() {
local exit_code="$1"
# Unset the EXIT trap to prevent re-entry.
trap - EXIT
case "$exit_code" in
0)
remove_files
;;
1)
echo ""
revert_changes
;;
2)
echo -e "\nExiting without clean up..."
;;
130)
echo -e "\n${C_WARNING}User interrupt detected (SIGINT)"
revert_changes
;;
143)
echo -e "\n${C_WARNING}Termination signal detected (SIGTERM)"
revert_changes
;;
129)
echo -e "\n${C_WARNING}Hangup signal detected (SIGHUP)"
revert_changes
;;
131)
echo -e "\n${C_WARNING}Quit signal detected (SIGQUIT)"
revert_changes
;;
*)
echo -e "\n${C_WARNING}Exiting with code: $exit_code"
revert_changes
;;
esac
echo "Exiting..."
exit "$exit_code"
}
####[ Trapping Logic ]##################################################################
trap 'clean_exit 130' SIGINT
trap 'clean_exit 143' SIGTERM
trap 'clean_exit 129' SIGHUP
trap 'clean_exit 131' SIGQUIT
trap 'clean_exit $?' EXIT
####[ Main ]############################################################################
(
set -e
echo "Backing up existing files..."
[[ -d $C_PUBLIC_FILE_PATH ]] && mv "$C_PUBLIC_FILE_PATH" "$C_PUBLIC_FILE_PATH.old"
[[ -d $C_PRIVATE_FILE_PATH ]] && mv "$C_PRIVATE_FILE_PATH" "$C_PRIVATE_FILE_PATH.old"
mkdir "$C_PUBLIC_FILE_PATH"
mkdir "$C_PRIVATE_FILE_PATH"
) || {
echo "${C_ERROR}Failed to backup existing files"
clean_exit 1
}
(
set -e
echo "Fetching latest release..."
curl -L -o latest-release.tar.gz "$C_LATEST_RELEASE_URL"
tar -xzf latest-release.tar.gz --strip-components=1 -C "$C_PUBLIC_FILE_PATH"
) || {
echo "${C_ERROR}Failed to fetch latest release"
clean_exit 1
}
echo "Moving files to private directory..."
for file in "${C_PRIVATE[@]}"; do
if [[ -d "$C_PUBLIC_FILE_PATH/$file" || -f "$C_PUBLIC_FILE_PATH/$file" ]]; then
mv "$C_PUBLIC_FILE_PATH/$file" "$C_PRIVATE_FILE_PATH" || {
echo "${C_ERROR}Failed to move '$file' to private directory"
clean_exit 1
}
fi
done
echo "Migrating files..."
copy_item "$C_PUBLIC_FILE_PATH.old/.htaccess" "$C_PUBLIC_FILE_PATH/" ".htaccess file"
copy_item "$C_PRIVATE_FILE_PATH.old/cfg/conf.php" "$C_PRIVATE_FILE_PATH/cfg/" "conf.php file"
copy_item "$C_PRIVATE_FILE_PATH.old/data" "$C_PRIVATE_FILE_PATH/" "data directory"
echo "Correcting file permissions..."
sudo chown -R "$C_FILE_OWNER:$C_FILE_OWNER" "$C_PUBLIC_FILE_PATH" "$C_PRIVATE_FILE_PATH" \
|| echo "${C_WARNING}Failed to change file ownership, please do so manually"
echo "Setting path to private files..."
sed -i "s/define('PATH', *'[^']*')/define('PATH', '${C_DEFINED_PATH//\//\\/}')/" \
"$C_PUBLIC_FILE_PATH/index.php" || {
echo "${C_ERROR}Failed to set path to private files, please do so manually"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment