#!/usr/bin/env bash set -euo pipefail ## CONSTANTS ## readonly CODEBASE_DIR="/opt/etebase" readonly DATA_DIR="/opt/etebase-data" ## HANDLE EXIT SIGNALS ## trap trap_exit EXIT SIGINT SIGTERM trap_exit(){ if [[ "${pid:+x}" ]]; then kill -- $pid 2> /dev/null || true q=0 while proc_running $pid; do q=$(( q + 1 )) snore 1 if [[ "$q" -ge 15 ]]; then echo "Sending kill to Etebase" 1>&2 kill -s KILL -- $pid 2> /dev/null || true break fi done fi exit 0 } # # LIB: Efficient sleep (does not create a new process). # snore(){ local IFS [[ -n "${_snore_fd:-}" ]] || exec {_snore_fd}<> <(:) read ${1:+-t "$1"} -u $_snore_fd || true } # # HELPER: Check whether given pid is running. # # @param $1 Process ID. # # @exit 0: Process is running # 1: Process is not running. # proc_running(){ # try reading state local state_path="/proc/$1/stat" [[ ! -f "$state_path" ]] && return 1 local state state=$(cat "$state_path" 2> /dev/null | cut -d ' ' -f3) || return 1 # parse state case "$state" in R|S|D|Z|W|W|P|I) return 0;; *) return 1;; esac } # # HELPER: Initialize etebase config files. # etebase_config_init(){ ## MAYBE CREATE SYMLINK ## if [[ ! -h "${CODEBASE_DIR}/etebase-server.ini" ]]; then ln -s "${DATA_DIR}/server.ini" "${CODEBASE_DIR}/etebase-server.ini" fi ## MAYBE WRITE DEFAULT FILE ## if [[ ! -f "${DATA_DIR}/server.ini" ]]; then echo "[global] debug = false secret_file = ${DATA_DIR}/secret.txt static_root = ${CODEBASE_DIR}/static media_root = ${DATA_DIR}/media ;language_code = en-us ;time_zone = UTC [allowed_hosts] allowed_host1 = * [database] engine = django.db.backends.sqlite3 name = ${DATA_DIR}/db.sqlite3" > "${DATA_DIR}/server.ini" fi } # # HELPER: Initialize django app. # etebase_app_init(){ ## RUN MIGRATIONS ## .venv/bin/python3 ./manage.py migrate ## MAYBE COPY STATIC FILES ## if [[ ! -d "${CODEBASE_DIR}/static" ]]; then .venv/bin/python3 ./manage.py collectstatic fi ## OVERWRITE INDEX PAGE ## cat /index.html > "${CODEBASE_DIR}/etebase_server/templates/success.html" } ## SET UP DATA DIRECTORIES ## mkdir -p "$DATA_DIR" mkdir -p "${DATA_DIR}/media" ## INITIALIZE CONFIG ## etebase_config_init ## INITIALIZE DJANGO APP ## etebase_app_init ## RUN SERVER ## .venv/bin/uvicorn etebase_server.asgi:application --host 0.0.0.0 --port 80 & pid=$! wait $pid