diff --git a/Dockerfile b/Dockerfile index 4e215eb..d97c5b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ ARG BUILD_DATE ARG VERSION ARG BOOKSTACK_RELEASE LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="homerr" +LABEL maintainer="thespad" ENV S6_STAGE2_HOOK="/init-hook" diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index f783299..5436878 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -7,7 +7,7 @@ ARG BUILD_DATE ARG VERSION ARG BOOKSTACK_RELEASE LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="homerr" +LABEL maintainer="thespad" ENV S6_STAGE2_HOOK="/init-hook" diff --git a/Jenkinsfile b/Jenkinsfile index 33edd61..712bba9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -31,12 +31,12 @@ pipeline { PR_DOCKERHUB_IMAGE = 'lspipepr/bookstack' DIST_IMAGE = 'alpine' MULTIARCH = 'true' - CI = 'true' + CI = 'false' CI_WEB = 'false' CI_PORT = '80' CI_SSL = 'false' CI_DELAY = '60' - CI_DOCKERENV='TEST_RUN=1' + CI_DOCKERENV='' CI_AUTH = '' CI_WEBPATH = '' } diff --git a/README.md b/README.md index 4a82432..8330609 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,6 @@ Find us at: [![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/bookstack.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=pulls&logo=docker)](https://hub.docker.com/r/linuxserver/bookstack) [![Docker Stars](https://img.shields.io/docker/stars/linuxserver/bookstack.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=stars&logo=docker)](https://hub.docker.com/r/linuxserver/bookstack) [![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-bookstack%2Fjob%2Fmaster%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-bookstack/job/master/) -[![LSIO CI](https://img.shields.io/badge/dynamic/yaml?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=CI&query=CI&url=https%3A%2F%2Fci-tests.linuxserver.io%2Flinuxserver%2Fbookstack%2Flatest%2Fci-status.yml)](https://ci-tests.linuxserver.io/linuxserver/bookstack/latest/index.html) [Bookstack](https://github.com/BookStackApp/BookStack) is a free and open source Wiki designed for creating beautiful documentation. Featuring a simple, but powerful WYSIWYG editor it allows for teams to create detailed and useful documentation with ease. @@ -63,30 +62,39 @@ The architectures supported by this image are: ## Application Setup -The default username is admin@admin.com with the password of **password**, access the container at http://dockerhost:6875. +The default username is admin@admin.com with the password of **password**, access the container at http://:6875. This application is dependent on a MySQL database be it one you already have or a new one. If you do not already have one, set up our MariaDB container here https://hub.docker.com/r/linuxserver/mariadb/. - If you intend to use this application behind a subfolder reverse proxy, such as our SWAG container or Traefik you will need to make sure that the `APP_URL` environment variable is set to your external domain, or it will not work. Documentation for BookStack can be found at https://www.bookstackapp.com/docs/. ### BookStack File & Directory Paths + This container ensures certain BookStack application files & folders, such as user file upload folders, are retained within the `/config` folder so that they are persistent & accessible when the `/config` container path is bound as a volume. There may be cases, when following the BookStack documentation, that you'll need to know how these files and folders are used relative to a non-container BookStack installation. Below is a mapping of container `/config` paths to those relative within a BookStack install directory: - **/config container path** => **BookStack relative path** - `/config/www/.env` => `.env` -- `/config/www/laravel.log` => `storage/logs/laravel.log` -- `/config/www/backups/` => `storage/backups/` +- `/config/log/bookstack/laravel.log` => `storage/logs/laravel.log` +- `/config/backups/` => `storage/backups/` - `/config/www/files/` => `storage/uploads/files/` - `/config/www/images/` => `storage/uploads/images/` - `/config/www/themes/` => `themes/` - `/config/www/uploads/` => `public/uploads/` +### Changing APP_URL + +If you change the APP_URL after initial install, you should run the following line from your host terminal to update the database URL entries: + +```shell +docker exec -it bookstack php /app/www/artisan bookstack:update-url ${OLD_URL} ${NEW_URL} +``` + ### Advanced Users (full control over the .env file) + If you wish to use the extra functionality of BookStack such as email, Memcache, LDAP and so on you will need to make your own .env file with guidance from the BookStack documentation. When you create the container, do not set any arguments for any SQL settings. The container will copy an exemplary .env file to /config/www/.env on your host system for you to edit. @@ -101,40 +109,24 @@ To help you get started creating a container from this image you can either use --- services: bookstack: - image: lscr.io/linuxserver/bookstack + image: lscr.io/linuxserver/bookstack:latest container_name: bookstack environment: - PUID=1000 - PGID=1000 - - TZ=Europe/London - - APP_URL=https://bookstack.example.com - - DB_HOST=bookstack_db + - TZ=Etc/UTC + - APP_URL= + - DB_HOST= - DB_PORT=3306 - - DB_USER=bookstack - - DB_PASS= - - DB_DATABASE=bookstackapp + - DB_USERNAME= + - DB_PASSWORD= + - DB_DATABASE= + - QUEUE_CONNECTION= #optional volumes: - - /path/to/bookstack_app_data:/config + - /path/to/bookstack/config:/config ports: - 6875:80 restart: unless-stopped - depends_on: - - bookstack_db - - bookstack_db: - image: lscr.io/linuxserver/mariadb - container_name: bookstack_db - environment: - - PUID=1000 - - PGID=1000 - - TZ=Europe/London - - MYSQL_ROOT_PASSWORD= - - MYSQL_DATABASE=bookstackapp - - MYSQL_USER=bookstack - - MYSQL_PASSWORD= - volumes: - - /path/to/bookstack_db_data:/config - restart: unless-stopped ``` ### docker cli ([click here for more info](https://docs.docker.com/engine/reference/commandline/cli/)) @@ -145,12 +137,12 @@ docker run -d \ -e PUID=1000 \ -e PGID=1000 \ -e TZ=Etc/UTC \ - -e APP_URL=yourbaseurl \ - -e DB_HOST=yourdbhost \ - -e DB_PORT=yourdbport \ - -e DB_USER=yourdbuser \ - -e DB_PASS=yourdbpass \ - -e DB_DATABASE=bookstackapp \ + -e APP_URL= \ + -e DB_HOST= \ + -e DB_PORT=3306 \ + -e DB_USERNAME= \ + -e DB_PASSWORD= \ + -e DB_DATABASE= \ -e QUEUE_CONNECTION= `#optional` \ -p 6875:80 \ -v /path/to/bookstack/config:/config \ @@ -168,12 +160,12 @@ Containers are configured using parameters passed at runtime (such as those abov | `-e PUID=1000` | for UserID - see below for explanation | | `-e PGID=1000` | for GroupID - see below for explanation | | `-e TZ=Etc/UTC` | specify a timezone to use, see this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). | -| `-e APP_URL=yourbaseurl` | for specifying the IP:port or URL your application will be accessed on (ie. `http://192.168.1.1:6875` or `https://bookstack.mydomain.com` | -| `-e DB_HOST=yourdbhost` | for specifying the database host | -| `-e DB_PORT=yourdbport` | for specifying the database port if not default 3306 | -| `-e DB_USER=yourdbuser` | for specifying the database user | -| `-e DB_PASS=yourdbpass` | for specifying the database password (minimum 4 characters & non-alphanumeric passwords must be properly escaped.) | -| `-e DB_DATABASE=bookstackapp` | for specifying the database to be used | +| `-e APP_URL=` | The IP:port or URL your application will be accessed on (ie. `http://192.168.1.1:6875` or `https://bookstack.mydomain.com` | +| `-e DB_HOST=` | The database instance hostname | +| `-e DB_PORT=3306` | Database port (default `3306`) | +| `-e DB_USERNAME=` | Database user | +| `-e DB_PASSWORD=` | Database password (minimum 4 characters & non-alphanumeric passwords must be properly escaped.) | +| `-e DB_DATABASE=` | Database name | | `-e QUEUE_CONNECTION=` | Set to `database` to enable async actions like sending email or triggering webhooks. See [documentation](https://www.bookstackapp.com/docs/admin/email-webhooks/#async-action-handling). | | `-v /config` | Persistent config files | @@ -339,6 +331,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **11.10.24:** - Default to environment config over .env file config. * **06.09.24:** - Add php-exif for reading image EXIF data. * **27.05.24:** - Rebase to Alpine 3.20. Existing users should update their nginx confs to avoid http2 deprecation warnings. * **25.01.24:** - Existing users should update: site-confs/default.conf - Cleanup default site conf. diff --git a/jenkins-vars.yml b/jenkins-vars.yml index d8285e6..11a6cda 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -19,11 +19,11 @@ repo_vars: - PR_DOCKERHUB_IMAGE = 'lspipepr/bookstack' - DIST_IMAGE = 'alpine' - MULTIARCH = 'true' - - CI = 'true' + - CI = 'false' - CI_WEB = 'false' - CI_PORT = '80' - CI_SSL = 'false' - CI_DELAY = '60' - - CI_DOCKERENV='TEST_RUN=1' + - CI_DOCKERENV='' - CI_AUTH = '' - CI_WEBPATH = '' diff --git a/readme-vars.yml b/readme-vars.yml index 9bfcb09..3cc7bce 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -24,12 +24,12 @@ param_volumes: - { vol_path: "/config", vol_host_path: "/path/to/{{ project_name }}/config", desc: "Persistent config files" } param_usage_include_env: true param_env_vars: - - { env_var: "APP_URL", env_value: "yourbaseurl", desc: "for specifying the IP:port or URL your application will be accessed on (ie. `http://192.168.1.1:6875` or `https://bookstack.mydomain.com`"} - - { env_var: "DB_HOST", env_value: "yourdbhost", desc: "for specifying the database host" } - - { env_var: "DB_PORT", env_value: "yourdbport", desc: "for specifying the database port if not default 3306" } - - { env_var: "DB_USER", env_value: "yourdbuser", desc: "for specifying the database user" } - - { env_var: "DB_PASS", env_value: "yourdbpass", desc: "for specifying the database password (minimum 4 characters & non-alphanumeric passwords must be properly escaped.)" } - - { env_var: "DB_DATABASE", env_value: "bookstackapp", desc: "for specifying the database to be used" } + - { env_var: "APP_URL", env_value: "", desc: "The IP:port or URL your application will be accessed on (ie. `http://192.168.1.1:6875` or `https://bookstack.mydomain.com`"} + - { env_var: "DB_HOST", env_value: "", desc: "The database instance hostname" } + - { env_var: "DB_PORT", env_value: "3306", desc: "Database port (default `3306`)" } + - { env_var: "DB_USERNAME", env_value: "", desc: "Database user" } + - { env_var: "DB_PASSWORD", env_value: "", desc: "Database password (minimum 4 characters & non-alphanumeric passwords must be properly escaped.)" } + - { env_var: "DB_DATABASE", env_value: "", desc: "Database name" } param_usage_include_ports: true param_ports: @@ -39,80 +39,50 @@ opt_param_usage_include_env: true opt_param_env_vars: - { env_var: "QUEUE_CONNECTION", env_value: "", desc: "Set to `database` to enable async actions like sending email or triggering webhooks. See [documentation](https://www.bookstackapp.com/docs/admin/email-webhooks/#async-action-handling)." } -custom_compose: | - --- - services: - bookstack: - image: lscr.io/linuxserver/bookstack - container_name: bookstack - environment: - - PUID=1000 - - PGID=1000 - - TZ=Europe/London - - APP_URL=https://bookstack.example.com - - DB_HOST=bookstack_db - - DB_PORT=3306 - - DB_USER=bookstack - - DB_PASS= - - DB_DATABASE=bookstackapp - volumes: - - /path/to/bookstack_app_data:/config - ports: - - 6875:80 - restart: unless-stopped - depends_on: - - bookstack_db - - bookstack_db: - image: lscr.io/linuxserver/mariadb - container_name: bookstack_db - environment: - - PUID=1000 - - PGID=1000 - - TZ=Europe/London - - MYSQL_ROOT_PASSWORD= - - MYSQL_DATABASE=bookstackapp - - MYSQL_USER=bookstack - - MYSQL_PASSWORD= - volumes: - - /path/to/bookstack_db_data:/config - restart: unless-stopped - # application setup block app_setup_block_enabled: true app_setup_block: | - The default username is admin@admin.com with the password of **password**, access the container at http://dockerhost:6875. + The default username is admin@admin.com with the password of **password**, access the container at http://:6875. This application is dependent on a MySQL database be it one you already have or a new one. If you do not already have one, set up our MariaDB container here https://hub.docker.com/r/linuxserver/mariadb/. - If you intend to use this application behind a subfolder reverse proxy, such as our SWAG container or Traefik you will need to make sure that the `APP_URL` environment variable is set to your external domain, or it will not work. Documentation for BookStack can be found at https://www.bookstackapp.com/docs/. ### BookStack File & Directory Paths + This container ensures certain BookStack application files & folders, such as user file upload folders, are retained within the `/config` folder so that they are persistent & accessible when the `/config` container path is bound as a volume. There may be cases, when following the BookStack documentation, that you'll need to know how these files and folders are used relative to a non-container BookStack installation. Below is a mapping of container `/config` paths to those relative within a BookStack install directory: - **/config container path** => **BookStack relative path** - `/config/www/.env` => `.env` - - `/config/www/laravel.log` => `storage/logs/laravel.log` - - `/config/www/backups/` => `storage/backups/` + - `/config/log/bookstack/laravel.log` => `storage/logs/laravel.log` + - `/config/backups/` => `storage/backups/` - `/config/www/files/` => `storage/uploads/files/` - `/config/www/images/` => `storage/uploads/images/` - `/config/www/themes/` => `themes/` - `/config/www/uploads/` => `public/uploads/` + ### Changing APP_URL + + If you change the APP_URL after initial install, you should run the following line from your host terminal to update the database URL entries: + + ```shell + docker exec -it bookstack php /app/www/artisan bookstack:update-url ${OLD_URL} ${NEW_URL} + ``` + ### Advanced Users (full control over the .env file) + If you wish to use the extra functionality of BookStack such as email, Memcache, LDAP and so on you will need to make your own .env file with guidance from the BookStack documentation. When you create the container, do not set any arguments for any SQL settings. The container will copy an exemplary .env file to /config/www/.env on your host system for you to edit. - # changelog changelogs: + - { date: "11.10.24:", desc: "Default to environment config over .env file config."} - { date: "06.09.24:", desc: "Add php-exif for reading image EXIF data."} - { date: "27.05.24:", desc: "Rebase to Alpine 3.20. Existing users should update their nginx confs to avoid http2 deprecation warnings."} - { date: "25.01.24:", desc: "Existing users should update: site-confs/default.conf - Cleanup default site conf." } diff --git a/root/etc/s6-overlay/s6-rc.d/init-bookstack-config/run b/root/etc/s6-overlay/s6-rc.d/init-bookstack-config/run index 39aa3bf..ffabb69 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-bookstack-config/run +++ b/root/etc/s6-overlay/s6-rc.d/init-bookstack-config/run @@ -44,86 +44,13 @@ if [[ ! -L "/app/www/storage/logs" ]]; then ln -s "/config/log/bookstack" "/app/www/storage/logs" fi -# Echo init finish for test runs -if [ -n "${TEST_RUN}" ]; then - echo '[ls.io-init] done.' -fi - -# Create API key if needed -if [ ! -f "/config/BOOKSTACK_APP_KEY.txt" ]; then - echo "Generating BookStack app key for first run" - key=$(php /app/www/artisan key:generate --show) - echo "${key}" >/config/BOOKSTACK_APP_KEY.txt - echo "App Key set to ${key} you can modify the file to update /config/BOOKSTACK_APP_KEY.txt" -elif [ -f "/config/BOOKSTACK_APP_KEY.txt" ]; then - echo "App Key found - setting variable for seds" - key=$(cat /config/BOOKSTACK_APP_KEY.txt) -fi - -# .env file setup -# check for the default app key or if it has been updated -if ! grep -Fxq "APP_KEY=${key}" /config/www/.env; then - sed -i "s#^APP_KEY=.*#APP_KEY=${key}#" /config/www/.env -fi - -# if DB_HOST contains a port and DB_HOST is not a IPv6 without brackets [..] -# support ipv4:port, [ipv6]:port, and domain:port -if [[ ${DB_HOST} =~ :[0-9]+$ ]] && ! [[ ${DB_HOST} =~ ^(:{0,2}[a-fA-F0-9]{1,4})+$ ]]; then - DB_HOST_PORT="${DB_HOST}" -fi - -# if DB_HOST_PORT is set -if [[ -n "${DB_HOST_PORT}" ]]; then - # if DB_PORT is set - if [[ -n "${DB_PORT}" ]]; then - echo "DB_PORT is not supported when using DB_HOST with port" +# Check for app key +if [[ -z ${APP_KEY} ]]; then + if ! grep -qE "APP_KEY=[0-9A-Za-z:+\/=]{1,}" /app/www/.env 2> /dev/null; then + echo "An application key is missing, halting init!" + echo "You can generate a key with: docker exec -it bookstack php /app/www/artisan key:generate --show" sleep infinity fi - DB_HOST="${DB_HOST_PORT%:*}" - DB_PORT="${DB_HOST_PORT##*:}" -fi - -# if DB_PORT is not set -if [[ -z "${DB_PORT}" ]]; then - DB_PORT="3306" -fi - -# check to see if DB_HOST is set, if it is then run seds and if not then leave them -if [[ -n "${DB_HOST}" ]]; then - echo "Running config - DB_HOST set" - - if ! grep -xqE "^[#]?DB_PORT=.*" /config/www/.env; then - # add DB_PORT line to /config/www/.env because current /app/www/.env.example doesn't have it - sed -i -E "/^[#]?DB_HOST=.*/a DB_PORT='${DB_PORT}'" /config/www/.env - echo "**** Insert DB_PORT='${DB_PORT}' into /config/www/.env ****" - fi - - sed -i -E "s/^[#]?DB_HOST=.*/DB_HOST='${DB_HOST}'/g" /config/www/.env - sed -i -E "s/^[#]?DB_PORT=.*/DB_PORT='${DB_PORT}'/g" /config/www/.env - SED_DB_DATABASE=$(sed -e 's|[&\\/]|\\&|g; s|$|\\|; $s|\\$||' <<<"${DB_DATABASE}") - sed -i -E "s/^[#]?DB_DATABASE=.*/DB_DATABASE='${SED_DB_DATABASE}'/g" /config/www/.env - SED_DB_USER=$(sed -e 's|[&\\/]|\\&|g; s|$|\\|; $s|\\$||' <<<"${DB_USER}") - sed -i -E "s/^[#]?DB_USERNAME=.*/DB_USERNAME='${SED_DB_USER}'/g" /config/www/.env - SED_DB_PASS=$(sed -e 's|[&\\/]|\\&|g; s|$|\\|; $s|\\$||' <<<"${DB_PASS}") - sed -i -E "s/^[#]?DB_PASSWORD=.*/DB_PASSWORD='${SED_DB_PASS}'/g" /config/www/.env -fi - -# set appurl -if [ -z "${APP_URL}" ]; then - EXT_IP=$(curl -s https://icanhazip.com) - APP_URL="http://${EXT_IP}:6875" - echo "**** Docker env var APP_URL is not set, setting it to ${APP_URL} ****" -fi -OLD_URL=$(grep APP_URL /config/www/.env | sed 's|.*APP_URL=||g') -if [ "${APP_URL}" != "${OLD_URL}" ]; then - sed -r "s,([#\s]*)?APP_URL=.*,APP_URL=${APP_URL},g" -i /config/www/.env - echo "**** APP_URL in /config/www/.env is being updated from ${OLD_URL} to ${APP_URL} ****" - if [ "${OLD_URL}" != "http://example.com" ]; then - echo "**** If this is an existing install, you should run the following line from your host terminal to update the database URL entries: ****" - echo "************************************************************************" - echo "docker exec -it bookstack php /app/www/artisan bookstack:update-url ${OLD_URL} ${APP_URL}" - echo "************************************************************************" - fi fi ## Bump php upload max filesize and post max size to 100MB by default @@ -134,33 +61,30 @@ if ! grep -qx '^post_max_size.*$' /config/php/php-local.ini; then echo 'post_max_size = 100M' >>/config/php/php-local.ini fi +# if DB_PORT is not set +if [[ -z "${DB_PORT}" ]]; then + DB_PORT="3306" +fi + # check for the mysql endpoint echo "Waiting for DB to be available" END=$((SECONDS + 30)) while [[ ${SECONDS} -lt ${END} ]] && [[ -n "${DB_HOST+x}" ]]; do if [[ $(/usr/bin/nc -w1 "${DB_HOST}" "${DB_PORT}" | tr -d '\0') ]]; then - if [[ -n "${RUN}" ]]; then - break - fi - RUN="RAN" - # we sleep here again due to first run init on DB containers if [[ ! -f /dbwait.lock ]]; then sleep 5 fi + touch /dbwait.lock + break else sleep 1 fi done # update database - will set up database if fresh, or, migrate existing -if [ -z "${CI_RUN+x}" ]; then - php /app/www/artisan migrate --force -fi +php /app/www/artisan migrate --force # permissions lsiown -R abc:abc \ /app/www/storage \ /config - -# set lockfile to avoid DB waits for this specific container -touch /dbwait.lock