diff --git a/deploy/1-click/README.md b/deploy/1-click/README.md
new file mode 100644
index 0000000000..88ea66c4c8
--- /dev/null
+++ b/deploy/1-click/README.md
@@ -0,0 +1,78 @@
+# 1-Click Self-Hosting
+
+In this guide, we will walk you through the process of setting up a 1-click self-hosted environment. Self-hosting allows you to have full control over your applications and data. It's a great way to ensure privacy, control, and customization.
+
+Let's get started!
+
+## Installing Plane
+
+Installing Plane is a very easy and minimal step process.
+
+### Prerequisite
+
+- Operating System (latest): Debian / Ubuntu / Centos
+- Supported CPU Architechture: AMD64 / ARM64 / x86_64 / aarch64
+
+### Downloading Latest Stable Release
+
+```
+curl -fsSL https://raw.githubusercontent.com/makeplane/plane/master/deploy/1-click/install.sh | sh -
+
+```
+
+
+ Downloading Preview Release
+
+```
+export BRANCH=preview
+
+curl -fsSL https://raw.githubusercontent.com/makeplane/plane/preview/deploy/1-click/install.sh | sh -
+
+```
+
+NOTE: `Preview` builds do not support ARM64/AARCH64 CPU architecture
+
+
+--
+
+
+Expect this after a successful install
+
+
+
+Access the application on a browser via http://server-ip-address
+
+---
+
+### Get Control of your Plane Server Setup
+
+Plane App is available via the command `plane-app`. Running the command `plane-app --help` helps you to manage Plane
+
+
+
+Basic Operations:
+1. Start Server using `plane-app start`
+1. Stop Server using `plane-app stop`
+1. Restart Server using `plane-app restart`
+
+Advanced Operations:
+1. Configure Plane using `plane-app --configure`. This will give you options to modify
+ - NGINX Port (default 80)
+ - Domain Name (default is the local server public IP address)
+ - File Upload Size (default 5MB)
+ - External Postgres DB Url (optional - default empty)
+ - External Redis URL (optional - default empty)
+ - AWS S3 Bucket (optional - to be configured only in case the user wants to use an S3 Bucket)
+
+1. Upgrade Plane using `plane-app --upgrade`. This will get the latest stable version of Plane files (docker-compose.yaml, .env, and docker images)
+
+1. Updating Plane App installer using `plane-app --update-installer` will update the `plane-app` utility.
+
+1. Uninstall Plane using `plane-app --uninstall`. This will uninstall the Plane application from the server and all docker containers but do not remove the data stored in Postgres, Redis, and Minio.
+
+1. Plane App can be reinstalled using `plane-app --install`.
+
+Application Data is stored in the mentioned folders:
+1. DB Data: /opt/plane/data/postgres
+1. Redis Data: /opt/plane/data/redis
+1. Minio Data: /opt/plane/data/minio
\ No newline at end of file
diff --git a/deploy/1-click/images/help.png b/deploy/1-click/images/help.png
new file mode 100644
index 0000000000..c14603a4b1
Binary files /dev/null and b/deploy/1-click/images/help.png differ
diff --git a/deploy/1-click/images/install.png b/deploy/1-click/images/install.png
new file mode 100644
index 0000000000..c8ba1e5f82
Binary files /dev/null and b/deploy/1-click/images/install.png differ
diff --git a/deploy/selfhost/install.sh b/deploy/selfhost/install.sh
index 30f2d15d72..16b6ea7c39 100755
--- a/deploy/selfhost/install.sh
+++ b/deploy/selfhost/install.sh
@@ -13,6 +13,23 @@ YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
+function print_header() {
+clear
+
+cat <<"EOF"
+---------------------------------------
+ ____ _
+| _ \| | __ _ _ __ ___
+| |_) | |/ _` | '_ \ / _ \
+| __/| | (_| | | | | __/
+|_| |_|\__,_|_| |_|\___|
+
+---------------------------------------
+Project management tool from the future
+---------------------------------------
+EOF
+}
+
function buildLocalImage() {
if [ "$1" == "--force-build" ]; then
DO_BUILD="1"
@@ -110,7 +127,7 @@ function download() {
exit 0
fi
else
- docker compose -f $PLANE_INSTALL_DIR/docker-compose.yaml pull
+ docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH pull
fi
echo ""
@@ -121,19 +138,48 @@ function download() {
}
function startServices() {
- cd $PLANE_INSTALL_DIR
- docker compose up -d --quiet-pull
- cd $SCRIPT_DIR
+ docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH up -d --quiet-pull
+
+ local migrator_container_id=$(docker container ls -aq -f "name=plane-app-migrator")
+ if [ -n "$migrator_container_id" ]; then
+ local idx=0
+ while docker inspect --format='{{.State.Status}}' $migrator_container_id | grep -q "running"; do
+ local message=">>> Waiting for Data Migration to finish"
+ local dots=$(printf '%*s' $idx | tr ' ' '.')
+ echo -ne "\r$message$dots"
+ ((idx++))
+ sleep 1
+ done
+ fi
+ printf "\r\033[K"
+
+ # if migrator exit status is not 0, show error message and exit
+ if [ -n "$migrator_container_id" ]; then
+ local migrator_exit_code=$(docker inspect --format='{{.State.ExitCode}}' $migrator_container_id)
+ if [ $migrator_exit_code -ne 0 ]; then
+ echo "Plane Server failed to start ❌"
+ stopServices
+ exit 1
+ fi
+ fi
+
+ local api_container_id=$(docker container ls -q -f "name=plane-app-api")
+ local idx2=0
+ while ! docker logs $api_container_id 2>&1 | grep -m 1 -i "Application startup complete" | grep -q ".";
+ do
+ local message=">>> Waiting for API Service to Start"
+ local dots=$(printf '%*s' $idx2 | tr ' ' '.')
+ echo -ne "\r$message$dots"
+ ((idx2++))
+ sleep 1
+ done
+ printf "\r\033[K"
}
function stopServices() {
- cd $PLANE_INSTALL_DIR
- docker compose down
- cd $SCRIPT_DIR
+ docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH down
}
function restartServices() {
- cd $PLANE_INSTALL_DIR
- docker compose restart
- cd $SCRIPT_DIR
+ docker compose -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH restart
}
function upgrade() {
echo "***** STOPPING SERVICES ****"
@@ -144,47 +190,137 @@ function upgrade() {
download
echo "***** PLEASE VALIDATE AND START SERVICES ****"
+}
+function viewSpecificLogs(){
+ local SERVICE_NAME=$1
+ if docker-compose -f $DOCKER_FILE_PATH ps | grep -q "$SERVICE_NAME"; then
+ echo "Service '$SERVICE_NAME' is running."
+ else
+ echo "Service '$SERVICE_NAME' is not running."
+ fi
+
+ docker compose -f $DOCKER_FILE_PATH logs -f $SERVICE_NAME
+}
+function viewLogs(){
+
+ ARG_SERVICE_NAME=$2
+
+ if [ -z "$ARG_SERVICE_NAME" ];
+ then
+ echo
+ echo "Select a Service you want to view the logs for:"
+ echo " 1) Web"
+ echo " 2) Space"
+ echo " 3) API"
+ echo " 4) Worker"
+ echo " 5) Beat-Worker"
+ echo " 6) Migrator"
+ echo " 7) Proxy"
+ echo " 8) Redis"
+ echo " 9) Postgres"
+ echo " 10) Minio"
+ echo " 0) Back to Main Menu"
+ echo
+ read -p "Service: " DOCKER_SERVICE_NAME
+
+ until (( DOCKER_SERVICE_NAME >= 0 && DOCKER_SERVICE_NAME <= 10 )); do
+ echo "Invalid selection. Please enter a number between 1 and 11."
+ read -p "Service: " DOCKER_SERVICE_NAME
+ done
+
+ if [ -z "$DOCKER_SERVICE_NAME" ];
+ then
+ echo "INVALID SERVICE NAME SUPPLIED"
+ else
+ case $DOCKER_SERVICE_NAME in
+ 1) viewSpecificLogs "web";;
+ 2) viewSpecificLogs "space";;
+ 3) viewSpecificLogs "api";;
+ 4) viewSpecificLogs "worker";;
+ 5) viewSpecificLogs "beat-worker";;
+ 6) viewSpecificLogs "migrator";;
+ 7) viewSpecificLogs "proxy";;
+ 8) viewSpecificLogs "plane-redis";;
+ 9) viewSpecificLogs "plane-db";;
+ 10) viewSpecificLogs "plane-minio";;
+ 0) askForAction;;
+ *) echo "INVALID SERVICE NAME SUPPLIED";;
+ esac
+ fi
+ elif [ -n "$ARG_SERVICE_NAME" ];
+ then
+ ARG_SERVICE_NAME=$(echo "$ARG_SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
+ case $ARG_SERVICE_NAME in
+ web) viewSpecificLogs "web";;
+ space) viewSpecificLogs "space";;
+ api) viewSpecificLogs "api";;
+ worker) viewSpecificLogs "worker";;
+ beat-worker) viewSpecificLogs "beat-worker";;
+ migrator) viewSpecificLogs "migrator";;
+ proxy) viewSpecificLogs "proxy";;
+ redis) viewSpecificLogs "plane-redis";;
+ postgres) viewSpecificLogs "plane-db";;
+ minio) viewSpecificLogs "plane-minio";;
+ *) echo "INVALID SERVICE NAME SUPPLIED";;
+ esac
+ else
+ echo "INVALID SERVICE NAME SUPPLIED"
+ fi
}
function askForAction() {
- echo
- echo "Select a Action you want to perform:"
- echo " 1) Install (${CPU_ARCH})"
- echo " 2) Start"
- echo " 3) Stop"
- echo " 4) Restart"
- echo " 5) Upgrade"
- echo " 6) Exit"
- echo
- read -p "Action [2]: " ACTION
- until [[ -z "$ACTION" || "$ACTION" =~ ^[1-6]$ ]]; do
- echo "$ACTION: invalid selection."
+ local DEFAULT_ACTION=$1
+
+ if [ -z "$DEFAULT_ACTION" ];
+ then
+ echo
+ echo "Select a Action you want to perform:"
+ echo " 1) Install (${CPU_ARCH})"
+ echo " 2) Start"
+ echo " 3) Stop"
+ echo " 4) Restart"
+ echo " 5) Upgrade"
+ echo " 6) View Logs"
+ echo " 7) Exit"
+ echo
read -p "Action [2]: " ACTION
- done
- echo
+ until [[ -z "$ACTION" || "$ACTION" =~ ^[1-7]$ ]]; do
+ echo "$ACTION: invalid selection."
+ read -p "Action [2]: " ACTION
+ done
+ if [ -z "$ACTION" ];
+ then
+ ACTION=2
+ fi
+ echo
+ fi
- if [ "$ACTION" == "1" ]
+ if [ "$ACTION" == "1" ] || [ "$DEFAULT_ACTION" == "install" ]
then
install
askForAction
- elif [ "$ACTION" == "2" ] || [ "$ACTION" == "" ]
+ elif [ "$ACTION" == "2" ] || [ "$DEFAULT_ACTION" == "start" ]
then
startServices
askForAction
- elif [ "$ACTION" == "3" ]
+ elif [ "$ACTION" == "3" ] || [ "$DEFAULT_ACTION" == "stop" ]
then
stopServices
askForAction
- elif [ "$ACTION" == "4" ]
+ elif [ "$ACTION" == "4" ] || [ "$DEFAULT_ACTION" == "restart" ]
then
restartServices
askForAction
- elif [ "$ACTION" == "5" ]
+ elif [ "$ACTION" == "5" ] || [ "$DEFAULT_ACTION" == "upgrade" ]
then
upgrade
askForAction
- elif [ "$ACTION" == "6" ]
+ elif [ "$ACTION" == "6" ] || [ "$DEFAULT_ACTION" == "logs" ]
+ then
+ viewLogs $@
+ askForAction
+ elif [ "$ACTION" == "7" ]
then
exit 0
else
@@ -217,4 +353,8 @@ then
fi
mkdir -p $PLANE_INSTALL_DIR/archive
-askForAction
+DOCKER_FILE_PATH=$PLANE_INSTALL_DIR/docker-compose.yaml
+DOCKER_ENV_PATH=$PLANE_INSTALL_DIR/.env
+
+print_header
+askForAction $@