diff --git a/tools/include/images/GHOST1.png b/tools/include/images/GHOST1.png new file mode 100644 index 00000000..eff3e0d9 Binary files /dev/null and b/tools/include/images/GHOST1.png differ diff --git a/tools/include/images/MYSQL1.png b/tools/include/images/MYSQL1.png new file mode 100644 index 00000000..f9ee7052 Binary files /dev/null and b/tools/include/images/MYSQL1.png differ diff --git a/tools/include/markdown/GHOST1-footer.md b/tools/include/markdown/GHOST1-footer.md new file mode 100644 index 00000000..fb051810 --- /dev/null +++ b/tools/include/markdown/GHOST1-footer.md @@ -0,0 +1,19 @@ +=== "Configuration" + + Initial setup includes: + - automatic database schema setup on first run + - admin account created via web interface + - Default port: `9190` + - Admin URL: `http://:9190/ghost` (or behind reverse proxy like SWAG) + - Site: `http://:9190` + +=== "Directories" + + - Install directory: `/armbian/ghost` + - Content volume mounted to: `/armbian/ghost/content` + +=== "View logs" + + ```sh + docker logs -f ghost + ``` diff --git a/tools/include/markdown/GHOST1-header.md b/tools/include/markdown/GHOST1-header.md new file mode 100644 index 00000000..ca8b849e --- /dev/null +++ b/tools/include/markdown/GHOST1-header.md @@ -0,0 +1 @@ +Ghost is a powerful open-source publishing platform designed for professional publishing, newsletters, and modern blogs. It’s built on Node.js and provides a clean, fast, and customizable CMS experience. diff --git a/tools/include/markdown/MYSQL1-footer.md b/tools/include/markdown/MYSQL1-footer.md new file mode 100644 index 00000000..d82e1db5 --- /dev/null +++ b/tools/include/markdown/MYSQL1-footer.md @@ -0,0 +1,20 @@ +=== "Configuration" + + Database access configuration is done at first install: + - create root password + - create database + - create normal user + - create password for normal user + + - Database host: `` + +=== "Directories" + + - Install directory: `/armbian/mysql` + - Data volume mounted to: `/armbian/mysql/data` + +=== "View logs" + + ```sh + docker logs -f mysql + ``` diff --git a/tools/include/markdown/MYSQL1-header.md b/tools/include/markdown/MYSQL1-header.md new file mode 100644 index 00000000..da996b10 --- /dev/null +++ b/tools/include/markdown/MYSQL1-header.md @@ -0,0 +1 @@ +MySQL is one of the world’s most widely used open-source database servers. Trusted for decades in web, cloud, and enterprise applications. diff --git a/tools/json/config.software.json b/tools/json/config.software.json index 89f63ee9..d37be014 100644 --- a/tools/json/config.software.json +++ b/tools/json/config.software.json @@ -330,6 +330,38 @@ "id": "Database", "description": "SQL database servers and web interface managers", "sub": [ + { + "id": "MYSQL1", + "description": "MySQL SQL database server", + "short": "MySQL", + "module": "module_mysql", + "command": [ + "module_mysql install" + ], + "status": "Stable", + "author": "@armbian", + "condition": "! module_mysql status" + }, + { + "id": "MYSQL2", + "description": "MySQL remove", + "command": [ + "module_mysql remove" + ], + "status": "Stable", + "author": "@armbian", + "condition": "module_mysql status" + }, + { + "id": "MYSQL3", + "description": "MySQL purge with data folder", + "command": [ + "module_mysql purge" + ], + "status": "Stable", + "author": "@armbian", + "condition": "module_mysql status" + }, { "id": "DAT001", "description": "Mariadb SQL database server", @@ -2293,6 +2325,38 @@ "status": "Stable", "author": "@igorpecovnik", "condition": "module_swag status" + }, + { + "id": "GHOST1", + "description": "Ghost CMS install", + "short": "Ghost", + "module": "module_ghost", + "command": [ + "module_ghost install" + ], + "status": "Stable", + "author": "@armbian", + "condition": "! module_ghost status" + }, + { + "id": "GHOST2", + "description": "Ghost CMS remove", + "command": [ + "module_ghost remove" + ], + "status": "Stable", + "author": "@armbian", + "condition": "module_ghost status" + }, + { + "id": "GHOST3", + "description": "Ghost CMS purge with data folder", + "command": [ + "module_ghost purge" + ], + "status": "Stable", + "author": "@igorpecovnik", + "condition": "module_ghost status" } ] } diff --git a/tools/modules/runtime/config.runtime.sh b/tools/modules/runtime/config.runtime.sh index 934e36fc..3d09f40f 100644 --- a/tools/modules/runtime/config.runtime.sh +++ b/tools/modules/runtime/config.runtime.sh @@ -168,3 +168,5 @@ update_sub_submenu_data "Software" "Downloaders" "RDR002" "http://$LOCALIPADD:${ update_sub_submenu_data "Software" "Downloaders" "DOW026" "http://$LOCALIPADD:${module_options["module_prowlarr,port"]}" update_sub_submenu_data "Software" "Downloaders" "JEL002" "http://$LOCALIPADD:${module_options["module_jellyseerr,port"]}" +# web +update_sub_submenu_data "Software" "WebHosting" "GHOST2" "http://$LOCALIPADD:${module_options["module_ghost,port"]}/ghost" diff --git a/tools/modules/software/module_ghost.sh b/tools/modules/software/module_ghost.sh new file mode 100644 index 00000000..58ddb013 --- /dev/null +++ b/tools/modules/software/module_ghost.sh @@ -0,0 +1,108 @@ +module_options+=( + ["module_ghost,author"]="@igorpecovnik" + ["module_ghost,maintainer"]="@igorpecovnik" + ["module_ghost,feature"]="module_ghost" + ["module_ghost,example"]="install remove purge status help" + ["module_ghost,desc"]="Install Ghost CMS container" + ["module_ghost,status"]="Active" + ["module_ghost,doc_link"]="https://ghost.org/docs/" + ["module_ghost,group"]="WebHosting" + ["module_ghost,port"]="9190" + ["module_ghost,arch"]="x86-64 arm64" +) + +# +# Module ghost +# +function module_ghost () { + local title="ghost" + local condition=$(which "$title" 2>/dev/null) + + if pkg_installed docker-ce; then + local container=$(docker container ls -a | mawk '/(^|[[:space:]])ghost([[:space:]]|$)/{print $1}') + local image=$(docker image ls -a | mawk '/(^|[[:space:]])ghost([[:space:]]|$)/{print $1":"$2}') + fi + + GHOST_BASE="${SOFTWARE_FOLDER}/ghost" + + local commands + IFS=' ' read -r -a commands <<< "${module_options["module_ghost,example"]}" + + case $1 in + "${commands[0]}") + + # instatall mysql if not installed + if ! module_mysql status; then + module_mysql install + fi + + # exit if ghost is already running + if module_ghost status; then + exit 0 + fi + + MYSQL_USER="${2:-armbian}" + MYSQL_PASSWORD="${3:-armbian}" + + [[ -d "$GHOST_BASE" ]] || mkdir -p "$GHOST_BASE" || { echo "Couldn't create storage directory: $GHOST_BASE"; exit 1; } + docker pull ghost:5-alpine + docker run -d \ + --name ghost \ + --net=lsio \ + --restart unless-stopped \ + -e database__client=mysql \ + -e database__connection__host="mysql" \ + -e database__connection__user="${MYSQL_USER}" \ + -e database__connection__password="${MYSQL_PASSWORD}" \ + -e database__connection__database="ghost" \ + -p ${module_options["module_ghost,port"]}:2368 \ + -e url=http://$LOCALIPADD:${module_options["module_ghost,port"]} \ + -v "$GHOST_BASE:/var/lib/ghost/content" \ + ghost:5-alpine + ;; + "${commands[1]}") + if pkg_installed docker-ce; then + local container=$(docker container ls -a | mawk '/(^|[[:space:]])ghost([[:space:]]|$)/{print $1}') + local image=$(docker image ls -a | mawk '/(^|[[:space:]])ghost([[:space:]]|$)/{print $1":"$2}') + fi + if [[ "${container}" ]]; then + docker container rm -f "$container" >/dev/null + fi + if [[ "${image}" ]]; then + docker image rm "$image" >/dev/null + fi + ;; + "${commands[2]}") + ${module_options["module_ghost,feature"]} ${commands[1]} + if [[ -n "${GHOST_BASE}" && "${GHOST_BASE}" != "/" ]]; then + rm -rf "${GHOST_BASE}" + fi + ;; + "${commands[3]}") + if pkg_installed docker-ce; then + local container=$(docker container ls -a | mawk '/(^|[[:space:]])ghost([[:space:]]|$)/{print $1}') + local image=$(docker image ls -a | mawk '/(^|[[:space:]])ghost([[:space:]]|$)/{print $1":"$2}') + fi + if [[ "${container}" && "${image}" ]]; then + return 0 + else + return 1 + fi + ;; + "${commands[4]}") + echo -e "\nUsage: ${module_options["module_ghost,feature"]} " + echo -e "Commands: ${module_options["module_ghost,example"]}" + echo "Available commands:" + echo -e "\tinstall\t- Install $title." + echo -e "\t Optionally accepts arguments:" + echo -e "\t db_host db_user db_pass db_name url" + echo -e "\tremove\t- Remove $title." + echo -e "\tpurge\t- Purge $title image and data." + echo -e "\tstatus\t- Show container status." + echo + ;; + *) + module_ghost "${commands[4]}" + ;; + esac +} diff --git a/tools/modules/software/module_mysql.sh b/tools/modules/software/module_mysql.sh new file mode 100644 index 00000000..53a04ba2 --- /dev/null +++ b/tools/modules/software/module_mysql.sh @@ -0,0 +1,121 @@ +module_options+=( + ["module_mysql,author"]="@igorpecovnik" + ["module_mysql,maintainer"]="@igorpecovnik" + ["module_mysql,feature"]="module_mysql" + ["module_mysql,example"]="install remove purge status help" + ["module_mysql,desc"]="Install mysql container" + ["module_mysql,status"]="Active" + ["module_mysql,doc_link"]="https://hub.docker.com/_/mysql" + ["module_mysql,group"]="Database" + ["module_mysql,port"]="3306" + ["module_mysql,arch"]="x86-64 arm64" +) +# +# Module mysql +# +function module_mysql () { + local title="mysql" + local condition=$(which "$title" 2>/dev/null) + + if pkg_installed docker-ce; then + local container=$(docker container ls -a | mawk '/mysql?( |$)/{print $1}') + local image=$(docker image ls -a | mawk '/mysql?( |$)/{print $1":"$2}') + fi + + local commands + IFS=' ' read -r -a commands <<< "${module_options["module_mysql,example"]}" + + MYSQL_BASE="${SOFTWARE_FOLDER}/mysql" + + case $1 in + "${commands[0]}") + + if module_mysql status; then + echo "deb" + exit 0 + fi + + pkg_installed docker-ce || module_docker install + # get parameters or fallback to dialog + MYSQL_ROOT_PASSWORD="${2:-armbian}" + MYSQL_DATABASE="${3:-armbian}" + MYSQL_USER="${4:-armbian}" + MYSQL_PASSWORD="${5:-armbian}" + + [[ -d "$MYSQL_BASE" ]] || mkdir -p "$MYSQL_BASE" || { echo "Couldn't create storage directory: $MYSQL_BASE"; exit 1; } + + docker pull mysql:lts + docker run -d \ + --name mysql \ + --net=lsio \ + -e MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-armbian}" \ + -e MYSQL_DATABASE="${MYSQL_DATABASE:-armbian}" \ + -e MYSQL_USER="${MYSQL_USER:-armbian}" \ + -e MYSQL_PASSWORD="${MYSQL_PASSWORD:-armbian}" \ + -v "${MYSQL_BASE}:/var/lib/mysql" \ + -p 3306:3306 \ + --restart unless-stopped \ + mysql:lts + + until docker exec mysql \ + env MYSQL_PWD="$MYSQL_ROOT_PASSWORD" \ + mysql -uroot -e "SELECT 1;" &>/dev/null; do + echo "⏳ Waiting for MySQL to accept connections..." + sleep 2 + done + + MYSQL_DATABASES=("ghost") # Add any additional databases you want to create here + for MYSQL_DATABASE in "${MYSQL_DATABASES[@]}"; do + echo "⏳ Creating database: $MYSQL_DATABASE and granting privileges..." + + docker exec -i mysql \ + env MYSQL_PWD="$MYSQL_ROOT_PASSWORD" \ + mysql -uroot <<-EOF + CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\`; + GRANT ALL PRIVILEGES ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%'; + FLUSH PRIVILEGES; + EOF + done + ;; + "${commands[1]}") + if [[ "${container}" ]]; then + docker container rm -f "$container" >/dev/null + fi + if [[ "${image}" ]]; then + docker image rm "$image" >/dev/null + fi + ;; + "${commands[2]}") + ${module_options["module_mysql,feature"]} ${commands[1]} + if [[ -n "${MYSQL_BASE}" && "${MYSQL_BASE}" != "/" ]]; then + rm -rf "${MYSQL_BASE}" + fi + ;; + "${commands[3]}") + if pkg_installed docker-ce; then + local container=$(docker container ls -a | mawk '/mysql?( |$)/{print $1}') + local image=$(docker image ls -a | mawk '/mysql?( |$)/{print $1":"$2}') + fi + if [[ "${container}" && "${image}" ]]; then + return 0 + else + return 1 + fi + ;; + "${commands[4]}") + echo -e "\nUsage: ${module_options["module_mysql,feature"]} " + echo -e "Commands: ${module_options["module_mysql,example"]}" + echo "Available commands:" + echo -e "\tinstall\t- Install $title." + echo -e "\t Optionally accepts arguments:" + echo -e "\t root_password database user user_password" + echo -e "\tremove\t- Remove $title." + echo -e "\tpurge\t- Purge $title data folder." + echo -e "\tstatus\t- Installation status $title." + echo + ;; + *) + ${module_options["module_mysql,feature"]} ${commands[4]} + ;; + esac +}