diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2c080a1..79643b4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,6 +42,72 @@ jobs: - name: Run Prettier run: npx prettier --check app/src/app + apache_deployment: + runs-on: ubuntu-latest + steps: + + - name: Checkout + uses: actions/checkout@v4 + + - name: Define global variables + id: global_variables + run: | + echo "BRANCH_NAME=${{ github.head_ref || github.ref_name }}" >> "$GITHUB_OUTPUT" + sed -i 's/^BASIL_TESTING=.*/BASIL_TESTING=1/' deploy/apache/.env + sed -i 's/^BASIL_API_PORT=.*/BASIL_API_PORT=5005/' deploy/apache/.env + sed -i 's/^BASIL_APP_PORT=.*/BASIL_APP_PORT=9056/' deploy/apache/.env + sed -i 's/^BASIL_ADMIN_PASSWORD=.*/BASIL_ADMIN_PASSWORD=dummy_password/' deploy/apache/.env + sed -i 's/^BASIL_DB_PASSWORD=.*/BASIL_DB_PASSWORD=dbSecret123/' deploy/apache/.env + TEMPDIR=$(mktemp -d) + sed -i "s|^BASIL_DB_PASSWORD=.*|BASIL_DB_PASSWORD=${TEMPDIR}|" deploy/apache/.env + + - name: Make deploy/apache/run.sh executable + run: chmod +x deploy/apache/run.sh + + - name: Run the deployment + run: | + cd deploy/apache && sudo ./run.sh + + - name: Test backend and frontend are up + run: | + echo "Test Api is running" + curl -vf http://localhost:5005/apis + curl -vf http://localhost:5005/libraries + curl -vf http://localhost:5005/version + echo "Test App is running" + curl -vf http://localhost:9056 + + - name: Install cypress-fail-fast plugin + run: npm install --save-dev cypress-fail-fast + working-directory: ./app + + - name: Cypress E2E Testing Chrome + uses: cypress-io/github-action@v6 + with: + browser: chrome + working-directory: ./app + spec: 'cypress/**/*.cy.js' + command: npx cypress run --browser chrome --spec cypress/**/login.cy.js --env failFast=true + env: + LIBGL_ALWAYS_SOFTWARE: 1 + + - name: Upload Cypress screenshots + uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-screenshots + path: | + app/cypress/screenshots + api/user-files + retention-days: 7 + + - name: Upload apache error log + uses: actions/upload-artifact@v4 + if: failure() + with: + name: apache-error.log + path: /var/log/apache2/error.log + build_and_test: runs-on: ubuntu-latest steps: diff --git a/deploy/apache/.env b/deploy/apache/.env new file mode 100644 index 0000000..973e4b0 --- /dev/null +++ b/deploy/apache/.env @@ -0,0 +1,13 @@ +BASIL_SERVER_NAME=127.0.0.1 # Your.Host.IP.Num +BASIL_SERVER_ALIAS=127.0.0.1 # hostname.domain.local +BASIL_SERVER_ADMIN=admin.name@domaine.local +BASIL_ADMIN_PASSWORD=my_secure_admin_password +BASIL_RESET_POSTGRES_CLUSTERS=1 +BASIL_DB_PASSWORD=my_secure_db_password +BASIL_TESTING=0 +BASIL_API_PORT=5000 +BASIL_APP_PORT=9000 +BASIL_TEST_RUNS_BASE_DIR=/var/basil/test-runs +BASIL_COMMITBEFORE= +BASIL_GITCLONE=1 +BASIL_GITGOBACK=0 diff --git a/deploy/apache/README.md b/deploy/apache/README.md new file mode 100644 index 0000000..3c7582f --- /dev/null +++ b/deploy/apache/README.md @@ -0,0 +1,112 @@ +### BASIL Apache deployment + +This folder contains helper scripts to deploy BASIL (API + Frontend) behind Apache on a Debian/Ubuntu host. + +Scripts expect configuration via a local `.env` file, then you run `run.sh` to provision PostgreSQL, build and configure the API (mod_wsgi) and the frontend under Apache. + +--- + +### Prerequisites + +- Run on a Debian/Ubuntu system with `systemd` and `apt`. +- A user with sudo privileges and outbound Internet access. +- Open TCP ports for the API and APP (defaults: 5000 and 9000). + +The scripts will install required packages (Apache, PostgreSQL, Python, Node toolchain) if missing. + +--- + +### Configure .env + +It is sourced by bash, so stick to `KEY=VALUE` and use quotes if values contain spaces. + +Required/commonly used variables: + +- BASIL_SERVER_NAME: public hostname or IP used in Apache vhosts +- BASIL_SERVER_ALIAS: optional additional host alias +- BASIL_SERVER_ADMIN: admin email for Apache configs +- BASIL_API_PORT: API Apache vhost port (default 5000) +- BASIL_APP_PORT: Frontend Apache vhost port (default 9000) +- BASIL_ADMIN_PASSWORD: password of BASIL admin user created by default +- BASIL_DB_PASSWORD: PostgreSQL user password used during DB init +- BASIL_TESTING: 1 to use a `test` DB instead of `basil` (default 0) +- BASIL_TEST_RUNS_BASE_DIR: base dir for tmt test runs (default `/var/basil/test-runs`) +- BASIL_GITCLONE: 1 = force fresh clone to `/tmp/basil`, 0 = reuse if present (default 1) +- BASIL_GITGOBACK: number of commits to revert from HEAD (default 0) +- BASIL_COMMITBEFORE: ISO8601 date used only when `BASIL_GITGOBACK < 0` (e.g. `2025-01-01 00:00:00 +0000`) +- BASIL_RESET_POSTGRES_CLUSTERS: 1 to wipe/recreate all local Postgres clusters (DANGEROUS), -1 to skip (default) + +Example `.env` you can copy and adjust: + +```bash +# Apache vhost details +BASIL_SERVER_NAME="your.host.name" +BASIL_SERVER_ALIAS="your.host.alias" +BASIL_SERVER_ADMIN="admin@example.com" + +# Ports +BASIL_API_PORT=5000 +BASIL_APP_PORT=9000 + +# BASIL runtime +BASIL_ADMIN_PASSWORD="ChangeMe_Strong_Admin_Password" +BASIL_TEST_RUNS_BASE_DIR="/var/basil/test-runs" +BASIL_TESTING=0 + +# Database +BASIL_DB_PASSWORD="ChangeMe_Strong_DB_Password" +BASIL_RESET_POSTGRES_CLUSTERS=-1 + +# Git checkout behavior for building +BASIL_GITCLONE=1 +BASIL_GITGOBACK=0 +# Only used if BASIL_GITGOBACK < 0 +BASIL_COMMITBEFORE="2025-01-01 00:00:00 +0000" +``` + +Notes: +- Passwords are required: set both `BASIL_ADMIN_PASSWORD` and `BASIL_DB_PASSWORD`. +- Use quotes for values with special characters. + +--- + +### Run the deployment + +From this folder: + +```bash +sudo ./run.sh +``` + +Why sudo? The scripts write under `/var/www`, `/etc/apache2`, manage services, and change ownership to `www-data`. + +What `run.sh` does: +- Installs required packages via apt +- Initializes PostgreSQL (`init_postgresql.sh`) +- Builds and configures the API for Apache/mod_wsgi (`build_basil_api.sh`) +- Builds the frontend, configures Apache static vhost with React router rewrite (`build_basil_frontend.sh`) + +Artifacts and logs in this folder: +- `init_postgresql.log` +- `build_basil_api.log` +- `build_basil_frontend.log` + +--- + +### Verify + +- API version endpoint: `http://:/version` +- Frontend version: `http://:/version` + +Both checks are executed automatically at the end of the respective scripts and reported in the logs. + +--- + +### Troubleshooting + +- Ports already in use: adjust `BASIL_API_PORT` / `BASIL_APP_PORT` in `.env` and re-run. +- Wrong hostname: update `BASIL_SERVER_NAME` (and optional alias) and re-run. +- PostgreSQL reset: set `BASIL_RESET_POSTGRES_CLUSTERS=1` only if you understand it will drop existing clusters. +- Rebuild from a clean checkout: set `BASIL_GITCLONE=1`. + + diff --git a/deploy/apache/build_basil_api.sh b/deploy/apache/build_basil_api.sh index 547caa0..9f4b7aa 100644 --- a/deploy/apache/build_basil_api.sh +++ b/deploy/apache/build_basil_api.sh @@ -1,151 +1,50 @@ #! /bin/bash -e +## ################################################################################################# +## Initial Author: Stefan Pofahl +## ################################################################################################# + +source .env +source ./common.sh + ## --- variables ----------------------------------------------------------------------------------- -SERVER_NAME=Your.Host.IP.Num -SERVER_ALIAS=hostname.domain.local -SERVER_ADMIN=admin.name@domaine.local -## --- +SERVER_NAME="${BASIL_SERVER_NAME:-localhost}" +SERVER_ALIAS="${BASIL_SERVER_ALIAS:-localhost}" +SERVER_ADMIN="${BASIL_SERVER_ADMIN:-admin@localhost.com}" +API_PORT="${BASIL_API_PORT:-5000}" + +## --- constants ----------------------------------------------------------------------------------- BASIL_REPOSITORY=https://github.com/elisa-tech/BASIL.git BASIL_BUILD_DIR=/tmp/basil BASIL_API=/var/www/basil-api WSGI_SCRIPT=$BASIL_API/api/wsgi.py BASIL_API_CONF=/etc/apache2/sites-available/basil-api.conf VIRTUAL_ENV=/opt/virtenv -DEFAULT_TEST_RUNS_BASE_DIR=/var/test-runs - -# --- Dates according to ISO8601, "JJJJ-MM-DD ..." -COMMITBEFORE="2025-09-08 14:45:51 +0200" -## --- If $CLONEBASIL == 1, perform a fresh clone. -CLONEBASIL=-1 -## --- get current version (HEAD) $GITGOBACK == 0 or go back in time > 0 -## --- $GITGOBACK < 0: take specified time $COMMITBEFORE to determine the value of $GITGOBACK -GITGOBACK=11 -# --- Dates according to ISO8601, "JJJJ-MM-DD ..." -COMMITBEFORE="2025-08-31 14:45:51 +0200" - -### #################################### main ################################################ -## --- constants: +TEST_RUNS_BASE_DIR="${BASIL_TEST_RUNS_BASE_DIR:-/var/basil/test-runs}" REFERENCEDATE01="2025-08-31 14:45:51 +0200" # Still with sqlite-database -## --- local functions ----------------------------------------------------------------------------- -rcpdir() { - local source_dir="$1" - local dest_dir="$2" - ## --- remove trailing slashes - source_dir="${source_dir%/}" - dest_dir="${dest_dir%/}" - ## --- Rsync with error treatment - if ! rsync -avq --partial --timeout=30 \ - "$source_dir"/ "$dest_dir"/ 2>/tmp/rsync_error; then - echo "Error: rsync operation failed" - echo "Error details:" - cat /tmp/rsync_error - rm -f /tmp/rsync_error - return 1 - exit 1; - fi - echo "Rsync completed successfully"$'\n' - rm -f /tmp/rsync_error - return 0 -} + ### --- main ------------------------------------------------------------------- -clear + # --- check if rsync is available if ! command -v rsync &> /dev/null; then - echo "Error: rsync is not installed, Execution terminates!"$'\n'; exit 1; + echo "Error: rsync is not installed, Execution terminates!"$'\n'; exit 1; fi +echo echo =================================================================== -echo install BASIL-API: +echo BASIL Backend API echo ------------------------------------------------------------------- cd ~ echo $(pwd) -# --- check if BASIL repository should be cloned --------------------------------------------------- -if [ $CLONEBASIL -eq 0 ]; then - # rm -R $BASIL_BUILD_DIR - if ! [ -d $BASIL_BUILD_DIR ]; then - echo "--- BASIL repository not found! Repository will be cloned! ---" - git clone $BASIL_REPOSITORY $BASIL_BUILD_DIR - else - echo "--- Keep current version of BASIL. --------------------------------------------"$'\n' - fi -else - echo $'\n'"--- re-clone BASIL git repository. -----------------------------------" - if [ -d $BASIL_BUILD_DIR ]; then - echo --- re-establish folder $BASIL_BUILD_DIR ------------------- - rm -R $BASIL_BUILD_DIR - fi - mkdir -p $BASIL_BUILD_DIR - ## --- clone git repository -------------------------------------------- - git clone $BASIL_REPOSITORY $BASIL_BUILD_DIR - echo $'\n'"=== END git clone =============================================================="$'\n' -fi +clone_basil_repo_if_needed -# --- Decide which mode to find the correct commit of BASIL go back in time or in commits / HEADS -cd "$BASIL_BUILD_DIR" || { echo "Error: Folder $BASIL_BUILD_DIR not found!"; exit 1; } -if [ $GITGOBACK -lt 0 ]; then - # --- validate correct time format of $COMMITBEFORE - if [[ ! "$COMMITBEFORE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}\ [+-][0-9]{4}$ ]]; then - echo "Error: Invalid date format: $COMMITBEFORE"$'\n'; exit 1; - fi - # --- Check if latest commit date is after time: $COMMITBEFORE - latest_commit_date=$(git log -1 --format=%cd --date=format:%s) - commit_before_date=$(date -d "$COMMITBEFORE" +%s 2>/dev/null) - if [ "$commit_before_date" -gt "$latest_commit_date" ]; then - echo "Warning: Date $COMMITBEFORE is after the latest commit" - echo "This will return the latest commit (HEAD)" - # Optional: exit 1 falls gewünscht - fi - echo "--- Go back to commit that lies before: $COMMITBEFORE ---" - # --- get the latest commit that is strictly before the reference date - ref_commit=$(git rev-list -1 --before="$COMMITBEFORE" HEAD) - if [ -z "$ref_commit" ]; then - echo "No commit found before $COMMITBEFORE" - exit 1 - fi - # --- set $GITGOBACK correctly to catch last commit that lies before $COMMITBEFORE - GITGOBACK=$(git rev-list --count "$ref_commit"..HEAD) -fi -# --- -TOTALNUMBEROFCOMMITS=$(git rev-list --count HEAD) -if [ $GITGOBACK -gt $TOTALNUMBEROFCOMMITS ]; then - echo $'\n'" ---- GITGOBACK = $GITGOBACK too high, maximum is $TOTALNUMBEROFCOMMITS ----"$'\n' - echo $'\n'"=========================================================================="$'\n' - exit 1; -fi -# --- Check if it is a "merge commit" -------------------------------------------------------------- -if ! git revert --no-commit HEAD~$GITGOBACK..HEAD 2>/dev/null; then - echo $'\n'"=========================================================================="$'\n' - echo "--- Error: git revert failed likely due to merge commits or other issues." - echo "--- Specify another commit! --- Maybe Refresh local copy of repository. " - echo "--- Specified or determined GITGOBACK is $GITGOBACK. --- Execution terminates now! ---" - echo $'\n'"=========================================================================="$'\n' -fi -# --- open with specified or determined HEAD=$GITGOBACK -------------------------------------------- -# echo "TOTALNUMBEROFCOMMITS: $TOTALNUMBEROFCOMMITS"$'\n' -COMMITDATE=$(git show -s --format=%ci HEAD~$GITGOBACK) -## --- Get the original commit message (subject + body) -ORIGMSG=$(git show -s --format=%B HEAD~$GITGOBACK) -## --- Extract commit number if present, don’t exit if missing -COMMITNUMBER=$(grep -oP '#\K[0-9]+' <<<"$ORIGMSG" || true) -## --- Combine them into one commit message (quote properly!) -COMMITMESSAGE="Revert of commit HEAD~${GITGOBACK} from: ${COMMITDATE}" -echo "--- Commit message: -------------------------------------------------------------"$'\n' -echo ${ORIGMSG} -echo $'\n'"------------------------------------------------------------------------------"$'\n' - -# echo "DBG --- This is line $LINENO, next: git commit -m " -## --- revert and commit, if $GITGOBACK is greater then 0: ----------------------------------------- -if [ $GITGOBACK -gt 0 ]; then - echo " --- GITGOBACK = $GITGOBACK is greater then 0: --- " - # --- Following commands should not stop the script execution, true = Exit-Code 0 - git revert --no-commit HEAD~$GITGOBACK..HEAD 2>/dev/null || true - git commit -m "$COMMITMESSAGE" 2>/dev/null || true -fi ## --- COPY local copy of repository to $BASIL_API and change to that directory ------------ if ! [ -d $BASIL_API ]; then - mkdir -p $BASIL_API + mkdir -p $BASIL_API fi + rcpdir "$BASIL_BUILD_DIR" "$BASIL_API" cd $BASIL_API + ## --- Compare Commit and Reference Date, to compare convert date to seconds since Unix epoch epoch1=$(date -d "$COMMITDATE" +%s) epoch2=$(date -d "$REFERENCEDATE01" +%s) @@ -163,72 +62,75 @@ echo "-------------------------------------------------------------------------- ## --- set rights for TEST_RUN_DIRECTORY ------------------------------- if ! [ -d $TEST_RUNS_BASE_DIR ]; then - mkdir -p $TEST_RUNS_BASE_DIR -fi -if [[ -v $TEST_RUNS_BASE_DIR ]]; then - chown -R www-data:www-data $BASIL_API && chmod -R 755 $TEST_RUNS_BASE_DIR -else - chown -R www-data:www-data $BASIL_API && chmod -R 755 $DEFAULT_TEST_RUNS_BASE_DIR + mkdir -p $TEST_RUNS_BASE_DIR fi +chmod -R 755 $TEST_RUNS_BASE_DIR ## --- configure directory $BASIL_API and add folder ------------------- if ! [ -d $BASIL_API/api/ssh_keys ]; then - mkdir -p $BASIL_API/api/ssh_keys + mkdir -p $BASIL_API/api/ssh_keys fi chown -R www-data:www-data $BASIL_API && chmod -R 755 $BASIL_API + ## --- create content of "wsgi.py": cd $BASIL_API/api echo $(pwd) echo create wsgi-pythonscript $WSGI_SCRIPT + ## --- create wsgi-pythonscript $WSGI_SCRIPT ---------------------------- printf "import sys \n\ import os \n\ sys.path.insert(0, '$BASIL_API/api') \n\ -os.environ['BASIL_DB_PASSWORD'] = 'rm_Zero' \n\ import api \n\ application = api.app \n\ import logging\n\ logging.basicConfig(stream=sys.stderr)" > $WSGI_SCRIPT + ## --- create virtual python environment: if [ -d $VIRTUAL_ENV ]; then - echo --- re-establish $VIRTUAL_ENV exist --------------------------- - rm -R $VIRTUAL_ENV + echo --- re-establish $VIRTUAL_ENV exist --------------------------- + rm -R $VIRTUAL_ENV fi + ## --- Create virtual environment mkdir -p $VIRTUAL_ENV chown -R www-data:www-data $VIRTUAL_ENV python3 -m venv $VIRTUAL_ENV + ## --- add to path, if not yet done if [ -d "$VIRTUAL_ENV" ] && [[ ":$PATH:" != *":$VIRTUAL_ENV:"* ]]; then - PATH="${PATH:+"$PATH:"}$VIRTUAL_ENV" + PATH="${PATH:+"$PATH:"}$VIRTUAL_ENV" fi echo $PATH -## --- Install Flask inside the virtual environment + +## --- Install python requirements inside the virtual environment +sed -i 's/^psycopg2-binary==/psycopg2-binary>=/' $BASIL_API/requirements.txt $VIRTUAL_ENV/bin/pip install --no-cache-dir -r $BASIL_API/requirements.txt + ## --- configure folder structure: echo --- configure folder structure: chown -R www-data:www-data $BASIL_API/api/ssh_keys chmod -R 750 $BASIL_API/api/ssh_keys -mkdir -p /var/test-runs -chmod -R 750 /var/test-runs mkdir -p $BASIL_API/api/user-files chmod -R 750 $BASIL_API/api/user-files mkdir -p $BASIL_API/db/sqlite3 mkdir -p $BASIL_API/db/models chmod -R a+rw $BASIL_API/db + ## --- activate virtual python environment, important is the leading point "." echo --- activate virtual python environment, important is the leading point "." echo $(pwd) . $VIRTUAL_ENV/bin/activate + ## --- write BASIL-API apache2-config file: echo --- write BASIL-API apache2-config file: -printf " \n\ +printf " \n\ ServerName $SERVER_NAME \n\ ServerAlias $SERVER_ALIAS \n\ ServerAdmin $SERVER_ADMIN \n\ # --- WSGI - stuff: WSGIProcessGroup basil-api \n\ - WSGIDaemonProcess basil-api python-home=$VIRTUAL_ENV python-path=$BASIL_API user=www-data group=www-data threads=5 \n\ + WSGIDaemonProcess basil-api python-home=$VIRTUAL_ENV python-path=$BASIL_API user=www-data group=www-data \n\ WSGIScriptAlias / $WSGI_SCRIPT \n\ # --- \n\ @@ -241,19 +143,42 @@ printf " \n\ CustomLog \${APACHE_LOG_DIR}/access.log combined \n\ " > $BASIL_API_CONF echo + +## --- Add port to apache configuration +add_port_to_listen "${API_PORT}" + +## --- Add Environment variables in apache systemd service +APACHE_ENVVARS_FILE=/etc/apache2/envvars +# Restore previous backup +if [ -f "${APACHE_ENVVARS_FILE}.backup" ]; then + cp "${APACHE_ENVVARS_FILE}.backup" "${APACHE_ENVVARS_FILE}" +else + cp "${APACHE_ENVVARS_FILE}" "${APACHE_ENVVARS_FILE}.backup" +fi +echo "export BASIL_ADMIN_PASSWORD=${BASIL_ADMIN_PASSWORD}" >> "${APACHE_ENVVARS_FILE}" +echo "export BASIL_DB_PASSWORD=${BASIL_DB_PASSWORD}" >> "${APACHE_ENVVARS_FILE}" +echo "export BASIL_TESTING=${BASIL_TESTING}" >> "${APACHE_ENVVARS_FILE}" +echo "export TEST_RUNS_BASE_DIR=${TEST_RUNS_BASE_DIR}" >> "${APACHE_ENVVARS_FILE}" + +# Step 3: Reload systemd and restart Apache +echo "Reloading systemd daemon..." +sudo systemctl daemon-reexec +sudo systemctl daemon-reload +sudo systemctl start apache2 + ## --- activate BASIL-API apache2-config file and restart apache2 server -echo --- send Apache2 to FOREGROUND: apache2ctl -D FOREGROUND ---------- -apache2ctl -D FOREGROUND echo --- activate BASIL-API apache2-config file sudo a2ensite basil-api.conf -echo --- restart apache2 via command: sudo apachectl graceful ---------------------------------$'\n' -sudo apachectl graceful +echo --- Enable wsgi module +sudo a2enmod wsgi +echo --- restart apache2 ----------------------------------------------------------------------$'\n' +sudo systemctl restart apache2 echo --- end main --- rights of folder: $BASIL_API -------------------------------------------$'\n' ls -ld $BASIL_API/ echo --- $WSGI_SCRIPT -----------------------------------------------------------------------$'\n' cat $WSGI_SCRIPT -echo $'\n'--- run gunicorn: -------------------------------------------------------------------$'\n' -cd $BASIL_API/api -/opt/virtenv/bin/gunicorn --bind 0.0.0.0:5000 api:app -cd ~ +echo $'\n' +echo --- Testing API Version endpoint -------------------------------------------------------------$'\n' +curl -s -w "%{http_code}" -o response.json http://${SERVER_NAME}:${API_PORT}/version | grep -q "200" && jq -e 'has("version")' response.json > /dev/null && echo "Test API Version endpoint: OK" || echo "Test API Version endpoint: FAIL" echo --- END ----------------------------------------------------------------------------------$'\n' +cd ~ diff --git a/deploy/apache/build_basil_frontend.sh b/deploy/apache/build_basil_frontend.sh index 1147ce5..df216d3 100644 --- a/deploy/apache/build_basil_frontend.sh +++ b/deploy/apache/build_basil_frontend.sh @@ -1,83 +1,66 @@ #! /bin/bash -e -## ### this script has to be run under admin previleges!!! ######################################### -## --- open toot CLI, command (or similar): su - ## ################################################################################################# -## Version: 1.0 -## Initial Author: Stefan Pofahl (with the support of AI and Luigi pellecchialuigi) +## Initial Author: Stefan Pofahl ## ################################################################################################# -### --- individual configuration variables: --------------------------------------------------------- -SERVER_NAME=Your.Host.IP.Num -SERVER_ALIAS=hostname.domain.local -SERVER_ADMIN=admin.name@domaine.local -## --- +source .env +source ./common.sh + +## --- variables ----------------------------------------------------------------------------------- +SERVER_NAME="${BASIL_SERVER_NAME:-localhost}" +SERVER_ALIAS="${BASIL_SERVER_ALIAS:-localhost}" +SERVER_ADMIN="${BASIL_SERVER_ADMIN:-admin@localhost.com}" +API_PORT="${BASIL_API_PORT:-5000}" +APP_PORT="${BASIL_APP_PORT:-9000}" + +## --- constants ----------------------------------------------------------------------------------- BASIL_REPOSITORY=https://github.com/elisa-tech/BASIL.git BASIL_BUILD_DIR=/tmp/basil BASIL_BUILD_APP=$BASIL_BUILD_DIR/app BASIL_FRONT_END=/var/www/basil BASIL_FRONT_END_CONF=/etc/apache2/sites-available/basil.conf BASIL_API=/var/www/basil-api -API_ENDPOINT=http://$SERVER_NAME:5000 +API_ENDPOINT=http://${SERVER_NAME}:${API_PORT} APPCONSTANTS_FILE=$BASIL_BUILD_APP/src/app/Constants/constants.tsx ### --- general instructions (0 == FALSE, > 0 TRUE ):----------------------------------------------- ## --- install mandatory software / toolchain: SETUPTOOLCHAIN=1 UPDATENODEPACKAGES=1 -## --- If $CLONEBASIL == 1, perform a fresh clone. -CLONEBASIL=1 -## --- get current version (HEAD) $GITGOBACK == 0 or go back in time > 0 -## --- $GITGOBACK < 0: take specified time $COMMITBEFORE to determine the value of $GITGOBACK -GITGOBACK=0 -# --- Dates according to ISO8601, "JJJJ-MM-DD ..." -COMMITBEFORE="2025-08-31 14:45:51 +0200" ### #################################### main ################################################ -## --- constants: -REFERENCEDATE01="2025-08-31 14:45:51 +0200" # Still with sqlite-database -## --- -clear +echo echo =============================================================================================== -echo install BASIL-FRONT-END: +echo BASIL Frontend web application echo ===============================================================================================$'\n' if [ $SETUPTOOLCHAIN -gt 0 ]; then - echo =============================================================================================== - echo install necessary packages / tools: - echo ===============================================================================================$'\n' - apt update - apt install -y curl gnupg - apt install -y python3 python3-pip python3-venv libapache2-mod-wsgi-py3 - ## --- run auto remove (delete old packages that are not needed) --- - apt autoremove && apt clean - rm -rf /var/lib/apt/lists/* - ## --- enable packages and restart apache2: - a2enmod wsgi - systemctl restart apache2 - echo === END of install necessary packages / tools ===========================================$'\n' - ## --- delete previous / current node.js-installation, if it exist: - if [ -d $$HOME/.nvm ]; then - rm -R $HOME/.nvm - fi + ## --- delete previous / current node.js-installation, if it exist: + if [ -d $$HOME/.nvm ]; then + rm -R $HOME/.nvm + fi fi + # --- check if npm is installed: ------------------------------------------------------------------- if ! command -v npm >/dev/null 2>&1 ; then - echo $'\n'"************************************************************************************************" - echo "*** Install nvm v10.X.Y and node.js v22.X.Y *************************************" - echo "*** please refer to: https://nodejs.org/en/download *************************************" - echo "************************************************************************************************"$'\n' + echo $'\n'"************************************************************************************************" + echo "*** Install nvm v10.X.Y and node.js v22.X.Y *************************************" + echo "*** please refer to: https://nodejs.org/en/download *************************************" + echo "************************************************************************************************"$'\n' + # --- be shure old nvm is deleted, before download! - if [ -d $$HOME/.nvm ]; then - rm -R $HOME/.nvm - fi - echo ---- down load nvm: ---------------------------------------------------------------------$'\n' - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash - echo ---- install nvm inside the root HOME folder: -------------------------------------------$'\n' + if [ -d $$HOME/.nvm ]; then + rm -R $HOME/.nvm + fi + + echo ---- download nvm: ---------------------------------------------------------------------$'\n' + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash + echo ---- install nvm inside the root HOME folder: -------------------------------------------$'\n' export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" - nvm install --lts - UPDATENODEPACKAGES=1 + [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" + [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" + nvm install --lts fi + echo "*** Version of npm and node.js: *********************************************************" echo " - javascript package manager, npm: v"$(npm -v) echo " - node.js: "$(node -v) @@ -86,98 +69,18 @@ echo " Please check the the messages displayed during script execution. Things echo " if you see nvm related massages you may try the option UPDATENODEPACKAGES=1 (see above)" echo "-------------------------------------------------------------------------------------------" -if [ $UPDATENODEPACKAGES -gt 0 ]; then - ## --- some nmp stuff: - echo "*** Repair and update node.js packages: ********************************************" - npm i --package-lock-only - npm audit fix - npx update-browserslist-db@latest - npm update chokidar - npm update --save -fi -#echo "This is line $LINENO" -# --- check if BASIL repository should be cloned --------------------------------------------------- -if [ $CLONEBASIL -eq 0 ]; then - # rm -R $BASIL_BUILD_DIR - if ! [ -d $BASIL_BUILD_DIR ]; then - echo "--- BASIL repository not found! Repository will be cloned! ---" - git clone $BASIL_REPOSITORY $BASIL_BUILD_DIR - else - echo "--- Keep current version of BASIL. --------------------------------------------"$'\n' - fi -else - echo $'\n'"--- re-clone BASIL git repository. -----------------------------------" - if [ -d $BASIL_BUILD_DIR ]; then - echo --- re-establish folder $BASIL_BUILD_DIR ------------------- - rm -R $BASIL_BUILD_DIR - fi - mkdir -p $BASIL_BUILD_DIR - ## --- clone git repository -------------------------------------------- - git clone $BASIL_REPOSITORY $BASIL_BUILD_DIR - echo $'\n'"=== END git clone =============================================================="$'\n' -fi - -# --- Decide which mode to find the correct commit of BASIL go back in time or in commits / HEADS -cd "$BASIL_BUILD_DIR" || { echo "Error: Folder $BASIL_BUILD_DIR not found!"; exit 1; } -if [ $GITGOBACK -lt 0 ]; then - # --- validate correct time format of $COMMITBEFORE - if [[ ! "$COMMITBEFORE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}\ [+-][0-9]{4}$ ]]; then - echo "Error: Invalid date format: $COMMITBEFORE"$'\n'; exit 1; - fi - # --- Check if latest commit date is after time: $COMMITBEFORE - latest_commit_date=$(git log -1 --format=%cd --date=format:%s) - commit_before_date=$(date -d "$COMMITBEFORE" +%s 2>/dev/null) - if [ "$commit_before_date" -gt "$latest_commit_date" ]; then - echo "Warning: Date $COMMITBEFORE is after the latest commit" - echo "This will return the latest commit (HEAD)" - # Optional: exit 1 falls gewünscht - fi - echo "--- Go back to commit that lies before: $COMMITBEFORE ---" - # --- get the latest commit that is strictly before the reference date - ref_commit=$(git rev-list -1 --before="$COMMITBEFORE" HEAD) - if [ -z "$ref_commit" ]; then - echo "No commit found before $COMMITBEFORE" - exit 1 - fi - # --- set $GITGOBACK correctly to catch last commit that lies before $COMMITBEFORE - GITGOBACK=$(git rev-list --count "$ref_commit"..HEAD) -fi -# --- -TOTALNUMBEROFCOMMITS=$(git rev-list --count HEAD) -if [ $GITGOBACK -gt $TOTALNUMBEROFCOMMITS ]; then - echo $'\n'" ---- GITGOBACK = $GITGOBACK too high, maximum is $TOTALNUMBEROFCOMMITS ----"$'\n' - echo $'\n'"=========================================================================="$'\n' - exit 1; -fi -# --- Check if it is a "merge commit" -------------------------------------------------------------- -if ! git revert --no-commit HEAD~$GITGOBACK..HEAD 2>/dev/null; then - echo $'\n'"=========================================================================="$'\n' - echo "--- Error: git revert failed likely due to merge commits or other issues." - echo "--- Specify another commit! --- Maybe Refresh local copy of repository. " - echo "--- Specified or determined GITGOBACK is $GITGOBACK. --- Execution terminates now! ---" - echo $'\n'"=========================================================================="$'\n' - exit 1 -fi -# --- open with specified or determined HEAD=$GITGOBACK -------------------------------------------- -# echo "TOTALNUMBEROFCOMMITS: $TOTALNUMBEROFCOMMITS"$'\n' -COMMITDATE=$(git show -s --format=%ci HEAD~$GITGOBACK) -## --- Get the original commit message (subject + body) -ORIGMSG=$(git show -s --format=%B HEAD~$GITGOBACK) -## --- Extract commit number if present, don’t exit if missing -COMMITNUMBER=$(grep -oP '#\K[0-9]+' <<<"$ORIGMSG" || true) -## --- Combine them into one commit message (quote properly!) -COMMITMESSAGE="Revert of commit HEAD~${GITGOBACK} from: ${COMMITDATE}" -echo "--- Commit message: -------------------------------------------------------------"$'\n' -echo ${ORIGMSG} -echo $'\n'"------------------------------------------------------------------------------"$'\n' +## --- Clone BASIL repo if needed -------------------------------------------------- +clone_basil_repo_if_needed +cd $BASIL_BUILD_APP -## --- revert and commit, if $GITGOBACK is greater then 0: ----------------------------------------- -if [ $GITGOBACK -gt 0 ]; then - echo " --- GITGOBACK = $GITGOBACK is greater then 0: --- " - # --- Following commands should not stop the script execution, true = Exit-Code 0 - git revert --no-commit HEAD~$GITGOBACK..HEAD 2>/dev/null || true - git commit -m "$COMMITMESSAGE" 2>/dev/null || true - echo $'\n'"=== Content of local copy of BASIL repository reverted to: COMMITDATE ============="$'\n' +if [ $UPDATENODEPACKAGES -gt 0 ]; then + ## --- some nmp stuff: + echo "*** Repair and update node.js packages: ********************************************" + npm i --package-lock-only + npm audit fix + npx update-browserslist-db@latest + npm update chokidar + npm update --save fi ## --- Build front end -------------------------------------------------- @@ -192,25 +95,25 @@ echo --- fine tune constants ------------------------------------------ if [ -f "$APPCONSTANTS_FILE" ]; then echo --- "$APPCONSTANTS_FILE exists." ----------------------------- ## --- Check if the variable exists inside this configuration file: - if ! grep -q "^export const API_BASE_URL" "$APPCONSTANTS_FILE"; then - echo "❌ API_BASE_URL not found in $APPCONSTANTS_FILE ❌" - kill -9 $$ - fi - ## --- extract current value: - current_value=$(grep -E "^export const API_BASE_URL" "$APPCONSTANTS_FILE" \ - | sed -E "s/^export const API_BASE_URL = '(.*)'.*/\1/") - echo "*** Definition of API_BASE_URL: $current_value ***********" - line=$(grep "^export const API_BASE_URL" "$APPCONSTANTS_FILE") - echo "*** Whole line: ***********" - echo "$line" - echo "--------------------------------------------------------------" - ## --- Replace old value with new one: $API_ENDPOINT - sed -i "s#http://localhost:5000#${API_ENDPOINT}#g" $APPCONSTANTS_FILE + if ! grep -q "^export const API_BASE_URL" "$APPCONSTANTS_FILE"; then + echo "❌ API_BASE_URL not found in $APPCONSTANTS_FILE ❌" + kill -9 $$ + fi + ## --- extract current value: + current_value=$(grep -E "^export const API_BASE_URL" "$APPCONSTANTS_FILE" \ + | sed -E "s/^export const API_BASE_URL = '(.*)'.*/\1/") + echo "*** Definition of API_BASE_URL: $current_value ***********" + line=$(grep "^export const API_BASE_URL" "$APPCONSTANTS_FILE") + echo "*** Whole line: ***********" + echo "$line" + echo "--------------------------------------------------------------" + ## --- Replace old value with new one: $API_ENDPOINT + sed -i "s#http://localhost:5000#${API_ENDPOINT}#g" $APPCONSTANTS_FILE ## --- Display line after modification: - echo "*** New value of API_BASE_URL: $API_ENDPOINT " - line=$(grep "^export const API_BASE_URL" "$APPCONSTANTS_FILE") - echo "*** Whole line of new definition: ***********" - echo "$line"'\n' + echo "*** New value of API_BASE_URL: $API_ENDPOINT " + line=$(grep "^export const API_BASE_URL" "$APPCONSTANTS_FILE") + echo "*** Whole line of new definition: ***********" + echo "$line"'\n' echo "*** End of modification of $APPCONSTANTS_FILE *******"$'\n' else echo =============================================================== @@ -219,25 +122,32 @@ else echo *** Please investigate changes inside the source code of BASIL. echo *** ❌Script execution terminates echo ===============================================================$'\n' - ## --- Kill the process + ## --- Kill the process kill -9 $$ fi echo "--- npm run build ------------------------------------------------"'\n' npm run build echo === install and build done ======================================== + # --- (re-)establish BASIL front-end folder: --------------------------- if [ -d $BASIL_FRONT_END ]; then - echo re-establish folder $BASIL_FRONT_END - rm -R $BASIL_FRONT_END + echo re-establish folder $BASIL_FRONT_END + rm -R $BASIL_FRONT_END fi mkdir -p $BASIL_FRONT_END -## --- copy artefacts / compiled BASIL-application files to BASIL root + +## --- copy artifacts / compiled BASIL-application files to BASIL root cp -r $BASIL_BUILD_APP/dist/* $BASIL_FRONT_END + ## --- rights and ownership for Apache2 user: chown -R www-data:www-data $BASIL_FRONT_END chmod -R 755 $BASIL_FRONT_END + +## --- Add port to Listen +add_port_to_listen "${APP_PORT}" + ## --- create Apache2 VirtualHost Configuration file for BASIL FrontEnd: -printf " \n\ +printf " \n\ ServerName $SERVER_NAME \n\ ServerAlias $SERVER_ALIAS \n\ ServerAdmin $SERVER_ADMIN \n\ @@ -262,18 +172,23 @@ printf " \n\ CustomLog \${APACHE_LOG_DIR}/access.log combined \n\ " > $BASIL_FRONT_END_CONF echo --- Apache2 BASIL conf-file written to: $BASIL_FRONT_END_CONF --- + ## --- activate BASIL-API apache2-config file and restart apache2 server echo --- activate BASIL-API apache2-config file sudo a2ensite basil.conf + +echo --- enable mod rewrite +sudo a2enmod rewrite + echo --- restart apache2 via command: sudo apachectl graceful ---------- -sudo apachectl graceful +sudo systemctl restart apache2 + ## --- display some information at the end ----------------------------- echo --- show Apache2 ports configuration file: ------------------------$'\n' cat /etc/apache2/ports.conf -## --- -if [ $GITGOBACK -gt 0 ]; then - echo "--- repository reverted to previous HEAD, Commit date of current commit is: $COMMITDATE_CURRENT" $'\n' - echo "$COMMITMESSAGE" -fi + +# Testing APP +echo --- Testing APP -------------------------------------------------------------$'\n' +curl -s -w "%{http_code}" http://${SERVER_NAME}:${APP_PORT}/version | grep -q "200" && echo "Test APP: OK" || echo "Test APP: FAIL" echo $'\n'--- END -----------------------------------------------------------$'\n' diff --git a/deploy/apache/common.sh b/deploy/apache/common.sh new file mode 100644 index 0000000..b79d1b7 --- /dev/null +++ b/deploy/apache/common.sh @@ -0,0 +1,145 @@ +#! /bin/bash -e + +source .env + +## --- If $CLONEBASIL == 1, perform a fresh clone. +CLONEBASIL="${BASIL_GITCLONE:-1}" +## --- get current version (HEAD) $GITGOBACK == 0 or go back in time > 0 +## --- $GITGOBACK < 0: take specified time $COMMITBEFORE to determine the value of $GITGOBACK +GITGOBACK="${BASIL_GITGOBACK:-0}" +# --- Dates according to ISO8601, "JJJJ-MM-DD ..." +TOMORROWDATE=$(date -d 'tomorrow 08:00' '+%Y-%m-%d %H:%M:%S %z') +COMMITBEFORE="${BASIL_COMMITBEFORE:-$TOMORROWDATE}" + +clone_basil_repo_if_needed() { + # --- check if BASIL repository should be cloned --------------------------------------------------- + if [ $CLONEBASIL -eq 0 ]; then + # rm -R $BASIL_BUILD_DIR + if ! [ -d $BASIL_BUILD_DIR ]; then + echo "--- BASIL repository not found! Repository will be cloned! ---" + git clone $BASIL_REPOSITORY $BASIL_BUILD_DIR + else + echo "--- Keep current version of BASIL. --------------------------------------------"$'\n' + fi + else + echo $'\n'"--- re-clone BASIL git repository. -----------------------------------" + if [ -d $BASIL_BUILD_DIR ]; then + echo --- re-establish folder $BASIL_BUILD_DIR ------------------- + rm -R $BASIL_BUILD_DIR + fi + mkdir -p $BASIL_BUILD_DIR + ## --- clone git repository -------------------------------------------- + git clone $BASIL_REPOSITORY $BASIL_BUILD_DIR + echo $'\n'"=== END git clone =============================================================="$'\n' + fi + + # --- Decide which mode to find the correct commit of BASIL go back in time or in commits / HEADS + cd "$BASIL_BUILD_DIR" || { echo "Error: Folder $BASIL_BUILD_DIR not found!"; exit 1; } + if [ $GITGOBACK -lt 0 ]; then + # --- validate correct time format of $COMMITBEFORE + if [[ ! "$COMMITBEFORE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}\ [+-][0-9]{4}$ ]]; then + echo "Error: Invalid date format: $COMMITBEFORE"$'\n'; exit 1; + fi + # --- Check if latest commit date is after time: $COMMITBEFORE + latest_commit_date=$(git log -1 --format=%cd --date=format:%s) + commit_before_date=$(date -d "$COMMITBEFORE" +%s 2>/dev/null) + if [ "$commit_before_date" -gt "$latest_commit_date" ]; then + echo "Warning: Date $COMMITBEFORE is after the latest commit" + echo "This will return the latest commit (HEAD)" + # Optional: exit 1 falls gewünscht + fi + echo "--- Go back to commit that lies before: $COMMITBEFORE ---" + # --- get the latest commit that is strictly before the reference date + ref_commit=$(git rev-list -1 --before="$COMMITBEFORE" HEAD) + if [ -z "$ref_commit" ]; then + echo "No commit found before $COMMITBEFORE" + exit 1 + fi + # --- set $GITGOBACK correctly to catch last commit that lies before $COMMITBEFORE + GITGOBACK=$(git rev-list --count "$ref_commit"..HEAD) + fi + # --- + TOTALNUMBEROFCOMMITS=$(git rev-list --count HEAD) + if [ $GITGOBACK -gt $TOTALNUMBEROFCOMMITS ]; then + echo $'\n'" ---- GITGOBACK = $GITGOBACK too high, maximum is $TOTALNUMBEROFCOMMITS ----"$'\n' + echo $'\n'"=========================================================================="$'\n' + exit 1; + fi + + # --- Check if it is a "merge commit" -------------------------------------------------------------- + if ! git revert --no-commit HEAD~$GITGOBACK..HEAD 2>/dev/null; then + echo $'\n'"=========================================================================="$'\n' + echo "--- Error: git revert failed likely due to merge commits or other issues." + echo "--- Specify another commit! --- Maybe Refresh local copy of repository. " + echo "--- Specified or determined GITGOBACK is $GITGOBACK. --- Execution terminates now! ---" + echo $'\n'"=========================================================================="$'\n' + fi + + # --- open with specified or determined HEAD=$GITGOBACK -------------------------------------------- + # echo "TOTALNUMBEROFCOMMITS: $TOTALNUMBEROFCOMMITS"$'\n' + COMMITDATE=$(git show -s --format=%ci HEAD~$GITGOBACK) + ## --- Get the original commit message (subject + body) + ORIGMSG=$(git show -s --format=%B HEAD~$GITGOBACK) + ## --- Extract commit number if present, don’t exit if missing + COMMITNUMBER=$(grep -oP '#\K[0-9]+' <<<"$ORIGMSG" || true) + ## --- Combine them into one commit message (quote properly!) + COMMITMESSAGE="Revert of commit HEAD~${GITGOBACK} from: ${COMMITDATE}" + echo "--- Commit message: -------------------------------------------------------------"$'\n' + echo ${ORIGMSG} + echo $'\n'"------------------------------------------------------------------------------"$'\n' + # echo "DBG --- This is line $LINENO, next: git commit -m " + + ## --- revert and commit, if $GITGOBACK is greater then 0: ----------------------------------------- + if [ $GITGOBACK -gt 0 ]; then + echo " --- GITGOBACK = $GITGOBACK is greater then 0: --- " + # --- Following commands should not stop the script execution, true = Exit-Code 0 + git revert --no-commit HEAD~$GITGOBACK..HEAD 2>/dev/null || true + git commit -m "$COMMITMESSAGE" 2>/dev/null || true + fi +} + +install_package() { + PACKAGE=$1 + if ! dpkg -s "$PACKAGE" &> /dev/null; then + echo + echo "---> Installing $PACKAGE..." + sudo apt install -y "$PACKAGE" + else + echo + echo "---> $PACKAGE is already installed." + fi +} + +add_port_to_listen() { + ## --- Add port to apache configuration + NEW_PORT="$1" + if ! grep -q "^Listen ${NEW_PORT}\$" /etc/apache2/ports.conf; then + echo "Listen ${NEW_PORT}" | sudo tee -a /etc/apache2/ports.conf + echo "Added 'Listen ${NEW_PORT}' to /etc/apache2/ports.conf" + else + echo "'Listen ${NEW_PORT}' already present in /etc/apache2/ports.conf" + fi +} + +rcpdir() { + local source_dir="$1" + local dest_dir="$2" + ## --- remove trailing slashes + source_dir="${source_dir%/}" + dest_dir="${dest_dir%/}" + ## --- Rsync with error treatment + if ! rsync -avq --partial --timeout=30 \ + "$source_dir"/ "$dest_dir"/ 2>/tmp/rsync_error; then + echo "Error: rsync operation failed" + echo "Error details:" + cat /tmp/rsync_error + rm -f /tmp/rsync_error + return 1 + exit 1; + fi + echo "Rsync completed successfully"$'\n' + rm -f /tmp/rsync_error + return 0 +} + + diff --git a/deploy/apache/init_postgresql.sh b/deploy/apache/init_postgresql.sh new file mode 100755 index 0000000..b1d10de --- /dev/null +++ b/deploy/apache/init_postgresql.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +source .env +source ./common.sh + +# Settings +DB_USER="basil-admin" +DB_NAME="basil" +DB_PASSWORD="${BASIL_DB_PASSWORD=-your_secure_password}" +RESET_CLUSTERS="${BASIL_RESET_POSTGRES_CLUSTERS=-1}" +TESTING="${BASIL_TESTING:-0}" + +if [ "$TESTING" = "1" ]; then + DB_NAME="test" +fi + +set -e + +echo +echo =================================================================== +echo BASIL Database initialization: ${DB_NAME} +echo ------------------------------------------------------------------- + +# Choose a safe working directory, e.g., /tmp or your home directory +WORKDIR="/tmp" + +pushd "$WORKDIR" >/dev/null + +# Check if postgres is installed +install_package postgresql +install_package postgresql-contrib + +# Start and enable PostgreSQL service +echo "Starting and enabling postgresql service..." +systemctl start postgresql +systemctl enable postgresql + +if [ "$RESET_CLUSTERS" -eq 1 ]; then + + echo "🔍 Detecting installed PostgreSQL version..." + + # Step 1: Detect installed PostgreSQL version + PG_VERSION=$(ls /usr/lib/postgresql 2>/dev/null | grep -E '^[0-9]+$' | sort -V | tail -n1) + + if [ -z "$PG_VERSION" ]; then + echo "❌ No PostgreSQL version installed." + exit 1 + fi + + echo "✅ PostgreSQL version detected: $PG_VERSION" + + # Step 2: Drop all existing clusters (if any) + echo "🧹 Dropping all existing clusters..." + while read -r version cluster_name _; do + if [[ "$version" =~ ^[0-9]+$ && "$cluster_name" != "Cluster" ]]; then + echo "⚠️ Dropping cluster: $version/$cluster_name" + pg_dropcluster --stop "$version" "$cluster_name" + fi + done < <(pg_lsclusters) + + # Step 3: Create a new default cluster + echo "🛠 Creating new cluster: ${PG_VERSION}/main" + pg_createcluster "$PG_VERSION" main --start --port=5432 + + # Step 4: Verify + echo "📋 Cluster list after recreation:" + pg_lsclusters + + # Optional: enable the service + systemctl enable --now postgresql + + echo "✅ PostgreSQL is reset with a fresh cluster on port 5432." +fi + +# Find the postgresql.conf location +PG_CONF=$(sudo -u postgres psql -t -P format=unaligned -c "SHOW config_file;") +echo "postgresql.conf found at: $PG_CONF" + +# Backup postgresql.conf before editing +cp "$PG_CONF" "${PG_CONF}.bak_$(date +%Y%m%d_%H%M%S)" + +# Ensure listen_addresses is set to '*' +sed -i "s/^#*\s*listen_addresses\s*=.*/listen_addresses = '*'/" "$PG_CONF" + +# Ensure port is set to 5432 +if grep -q "^port\s*=" "$PG_CONF"; then + sed -i "s/^port\s*=.*/port = 5432/" "$PG_CONF" +else + echo "port = 5432" | tee -a "$PG_CONF" > /dev/null +fi + +echo "Configuration updated. Restarting PostgreSQL..." +systemctl restart postgresql + +echo "PostgreSQL installed, configured, and running on port 5432." + +# Create user if it doesn't exist +sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" | grep -q 1 || \ + sudo -u postgres psql -c "CREATE USER \"${DB_USER}\" WITH PASSWORD '${DB_PASSWORD}';" + +# Create database if it doesn't exist +sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" | grep -q 1 || \ + sudo -u postgres psql -c "CREATE DATABASE \"${DB_NAME}\" OWNER \"${DB_USER}\";" + +# Grant privileges +sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE \"${DB_NAME}\" TO \"${DB_USER}\";" + +popd >/dev/null + +echo "✅ PostgreSQL user '${DB_USER}' and database '${DB_NAME}' are set up." diff --git a/deploy/apache/run.sh b/deploy/apache/run.sh new file mode 100755 index 0000000..3f1e071 --- /dev/null +++ b/deploy/apache/run.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +source .env +source ./common.sh + +set -e + +echo =================================================================== +echo BASIL Apache Deployment +echo ------------------------------------------------------------------- + +sudo apt update +packages="curl gnupg postgresql postgresql-contrib libapache2-mod-wsgi-py3 rsync git jq python3 python3-pip python3-venv" +for package in $packages; do + install_package $package +done +sudo apt autoremove -y && sudo apt clean + +bash ./init_postgresql.sh | tee init_postgresql.log +bash ./build_basil_api.sh | tee build_basil_api.log +bash ./build_basil_frontend.sh | tee build_basil_frontend.log