Share how to switch custom container images to Bitnami container images and how to configure them with reverse proxy software such as Traefik.

Writing in the front

Last year, I shared an article about Phabricator, “Using Docker and Traefik V2 to Build Phabricator”. At that time, I introduced how to build a custom container image and how to use the application with Chinese patches.

A year later, along with software and hardware upgrades, the service migration of Phabricator is also on the agenda.

To keep things as easy as possible, I switched to Bitnami’s image so I could use a transparent and trusted image built by GitHub every hour and have less to worry about with security patches and upgrades.

Combing problem

Bitnami’s mirrors provide a wide range of environment variable configurations for various scenarios. However, the support for the following two scenarios is incomplete:

  • Run the software with an existing database rather than initialize it from zero to one.
  • Use the reverse proxy service instead of providing the service directly.

Collect clues

Browse through the Dockerfile in the repository code and you can see that the entry script and the pre-execution script have a file each before the project starts:

ENTRYPOINT [ "/opt/bitnami/scripts/phabricator/entrypoint.sh" ]
CMD [ "/opt/bitnami/scripts/phabricator/run.sh" ]
Copy the code

If you look at the entryPoint.sh script, you can see that this script invokes the Web server, database, and scripts related to application initialization.

#! /bin/bash

# shellcheck disable=SC1091

set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose

# Load Phabricator environment
. /opt/bitnami/scripts/phabricator-env.sh

# Load libraries
. /opt/bitnami/scripts/libbitnami.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libwebserver.sh

print_welcome_page

if [[ "The $1" = "/opt/bitnami/scripts/phabricator/run.sh" || "The $1" = "/opt/bitnami/scripts/$(web_server_type)/run.sh" || "The $1" = "/opt/bitnami/scripts/nginx-php-fpm/run.sh"]].then
    info "** Starting Phabricator setup **"
    /opt/bitnami/scripts/"$(web_server_type)"/setup.sh
    /opt/bitnami/scripts/php/setup.sh
    /opt/bitnami/scripts/mysql-client/setup.sh
    /opt/bitnami/scripts/phabricator/setup.sh
    /post-init.sh
    info "** Phabricator setup finished! * *"
fi

echo ""
exec "$@"

Copy the code

One of the script path/opt/bitnami/scripts/phabricator/setup. Sh is suspected, perform this script phabricator/setup. Sh through, could see except for some check environment ready or not ready to work, You can also find two base dependencies:

.# Load libraries
. /opt/bitnami/scripts/libphabricator.sh
. /opt/bitnami/scripts/libwebserver.sh

...
Copy the code

Continued reading/opt/bitnami/scripts/libphabricator sh this script, will see the script defines the real phabricator all application configuration, some environment variables and container is not (including documentation), also has carried on the binding and the script, So this is the perfect place to start.

Adjust script: Add time zone Settings

Phabricator_initialize = phabricator.timezone = phabricator.timezone = phabricator.timezone = phabricator.timezone

# # # # # # # # # # # # # # # # # # # # # # # #
# Ensure Phabricator is initialized
# Globals:
# PHABRICATOR_*
# Arguments:
# None
# Returns:
# None
# # # # # # # # # # # # # # # # # # # # # # # # #
phabricator_initialize() {
    # Check if Phabricator has already been initialized and persisted in a previous run
    local -r app_name="phabricator"
    local -r port="${WEB_SERVER_HTTP_PORT_NUMBER:-"$WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER"}"
    if ! is_app_initialized "$app_name"; then
        info "Creating Phabricator configuration file"
        # Modified by @soulteary
        phabricator_conf_set "phabricator.timezone" "Asia/Shanghai"
Copy the code

Tuning script: Update the database namespace

Find the phabricator_configure_database_credentials function and update the storage.default-Namespace configuration project. If you haven’t set it before, delete or comment it out. Avoid missing previous data after application startup:

# # # # # # # # # # # # # # # # # # # # # # # # #
# Configure Phabricator database
# Globals:
# PHABRICATOR_*
# Arguments:
# $1 - database user name
# $2 - database user password
# Returns:
# None
# # # # # # # # # # # # # # # # # # # # # # # # #
phabricator_configure_database_credentials() {
    local -r db_user="The ${1:? missing database user}"
    local -r db_pass="The ${2:? missing database password}"

    info "Configuring database"
    phabricator_conf_set "mysql.host"                     "$PHABRICATOR_DATABASE_HOST"
    phabricator_conf_set "mysql.port"                     "$PHABRICATOR_DATABASE_PORT_NUMBER"
    phabricator_conf_set "mysql.user"                     "$db_user"
    phabricator_conf_set "mysql.pass"                     "$db_pass"
    # Modified by @soulteary
    # phabricator_conf_set "storage.default-namespace" "bitnami_phabricator"
    phabricator_conf_set "storage.mysql-engine.max-size"  "0"
}

Copy the code

Adjust the choreographer file: Set up the database

Since we are working directly with the old database, we do not want the script to run the “database initialization” process. We need to set environment variables for the choreographer file to make the script think that the database structure is ready and does not need to be initialized, and use the existing database configuration to provide services:

.
    environment:
      .
      You need to use it with PHABRICATOR_SKIP_BOOTSTRAP, otherwise you need to set more redundant content
      - ALLOW_EMPTY_PASSWORD=yes
      - PHABRICATOR_SKIP_BOOTSTRAP=yes
      - PHABRICATOR_DATABASE_HOST=database
      - PHABRICATOR_DATABASE_PORT_NUMBER=3306
      - PHABRICATOR_EXISTING_DATABASE_USER=root
      - PHABRICATOR_EXISTING_DATABASE_PASSWORD=QV8}! P! [&QmR
      .
Copy the code

Tweak scripts: Tweak application links to support reverse proxies

To support the reverse proxy environment, especially the HTTPS access capability provided by the reverse proxy gateway, We need to modify the phabricator_configure_host and Phabricator_configure_alternate_file_domain functions so that the application can run in non-HTTPS mode, Render the page link as https:// protocol.

# # # # # # # # # # # # # # # # # # # # # # # # #
# Configure Phabricator host
# Globals:
# PHABRICATOR_*
# Arguments:
# None
# Returns:
# None
# # # # # # # # # # # # # # # # # # # # # # # # #
phabricator_configure_host() {
    local host
    local scheme

    get_hostname() {
        if [[ -n "${PHABRICATOR_HOST:-}"]].then
            echo "$PHABRICATOR_HOST"
        else
            dns_lookup "$(hostname)" "v4"
        fi
    }

    host="$(get_hostname)"
    if is_boolean_yes "$PHABRICATOR_ENABLE_HTTPS"; then
        scheme="https"
        [[ "$PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER"! ="443" ]] && host+=":${PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER}"
    else
        scheme="http"
        [[ "$PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER"! ="80" ]] && host+=":${PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER}"
    fi
    info "Configuring Phabricator URL to ${scheme}: / /${host}"
    # Modified by @soulteary
    scheme="https"
    phabricator_conf_set "phabricator.base-uri" "${scheme}: / /${host}"
}

# # # # # # # # # # # # # # # # # # # # # # # # #
# Configure Phabricator alternate file domain
# Globals:
# PHABRICATOR_*
# Arguments:
# None
# Returns:
# None
# # # # # # # # # # # # # # # # # # # # # # # # #
phabricator_configure_alternate_file_domain() {
    local afd="$PHABRICATOR_ALTERNATE_FILE_DOMAIN"
    local scheme
    if is_boolean_yes "$PHABRICATOR_ENABLE_HTTPS"; then
        scheme="https"
        [[ "$PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER"! ="443" ]] && afd+=":${PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER}"
    else
        scheme="http"
        [[ "$PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER"! ="80" ]] && afd+=":${PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER}"
    fi
    # Modified by @soulteary
    scheme="https"
    info "Configuring Phabricator Alternate File Domain to ${scheme}: / /${afd}"
    phabricator_conf_set "security.alternate-file-domain" "${scheme}: / /${afd}"
}
Copy the code

The configuration corresponding to the choreographer file also needs to be declared:

.
    environment:
      .
      - PHABRICATOR_ENABLE_HTTPS=false
      - PHABRICATOR_HOST=board.lab.com
      - PHABRICATOR_ALTERNATE_FILE_DOMAIN=board-file.lab.com
      .
Copy the code

Complete container choreography configuration

Update the above to libphabricator.sh and write the container Choreographer configuration file:

version: '3.7'

services:

  phabricator:
    image: Bitnami/phabricator: 2021.13.0
    expose:
      - 8080
    environment:
      - APACHE_HTTP_PORT_NUMBER=8080
      - PHABRICATOR_ENABLE_HTTPS=false
      - PHABRICATOR_HOST=board.lab.com
      - PHABRICATOR_ALTERNATE_FILE_DOMAIN=board-file.lab.com
      - ALLOW_EMPTY_PASSWORD=yes
      - PHABRICATOR_SKIP_BOOTSTRAP=yes
      - PHABRICATOR_DATABASE_HOST=board.data.lab.com
      - PHABRICATOR_DATABASE_PORT_NUMBER=3306
      - PHABRICATOR_EXISTING_DATABASE_USER=root
      - PHABRICATOR_EXISTING_DATABASE_PASSWORD=QV8}! P! [&QmR
      - PHABRICATOR_ENABLE_PYGMENTS=true
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik"
      - "traefik.http.routers.phab0.middlewares=https-redirect@file"
      - "traefik.http.routers.phab0.entrypoints=http"
      - "traefik.http.routers.phab0.rule=Host(`board.lab.com`, `board-file.lab.com`, `phabricator.lab.io`, `phabricator-file.lab.io`)"
      - "traefik.http.routers.phab1.middlewares=content-compress@file"
      - "traefik.http.routers.phab1.entrypoints=https"
      - "traefik.http.routers.phab1.tls=true"
      - "traefik.http.routers.phab1.rule=Host(`board.lab.com`, `board-file.lab.com`, `phabricator.lab.io`, `phabricator-file.lab.io`)"
      - "traefik.http.services.phabbackend.loadbalancer.server.scheme=http"
      - "traefik.http.services.phabbackend.loadbalancer.server.port=8080"
    volumes:
      - ./libphabricator.sh:/opt/bitnami/scripts/libphabricator.sh:ro

networks:
  traefik:
    external: true
Copy the code

Save the above content as docker-compose. Yml and use docker-compose up -d to launch the application.

Reset the user password

After switching database and application versions, we may encounter a situation where users are unable to log in.

Here you can reset the user password in the way of the official issue. Using user name soulteary as an example, you can quickly get the password reset link by executing the following script:

docker-compose exec phabricator /opt/bitnami/phabricator/bin/auth recover soulteary
Use this link to recover access to the "soulteary" account from the web interface:

    https://board.lab.com/login/once/recover/1/eedkghmtxrvkktaqof7di54n5lkabcd/

After logging in, you can use the "Auth" application to add or restore authentication providers and allow normal logins to succeed.
Copy the code

Access the link to reset your password and log in again.

The last

This article about Phabricator switch Bitnami mirror content, first left here.

–EOF


We have a little group of people who like to do things.

In the case of no advertisement, we will talk about software and hardware, HomeLab and programming problems together, and also share some information of technical salon irregularly in the group.

Like to toss small partners welcome to scan code to add friends. (Please indicate the source and purpose, and note the real name, otherwise it will not pass the audit)

All this stuff about getting into groups


This article is published under a SIGNATURE 4.0 International (CC BY 4.0) license. Signature 4.0 International (CC BY 4.0)

Author: Su Yang

Creation time: April 18, 2021 statistical word count: 7591 words reading time: 16 minutes to read this article links: soulteary.com/2021/04/18/…