#!/usr/bin/env bash set -euo pipefail ### Правильные разрешения для каталогов данных bill-ninja. APP_DIR="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")" APP_DATA_DIR="${APP_DIR}/data" DESIRED_OWNER="1000:1000" PUBLIC_DATA_DIR="${APP_DATA_DIR}/public" STORAGE_DATA_DIR="${APP_DATA_DIR}/storage" REDIS_DATA_DIR="${APP_DATA_DIR}/redis" invoiceninja_correct_permission() { local -r path="${1}" if [[ -d "${path}" ]]; then owner=$(stat -c "%u:%g" "${path}") if [[ "${owner}" != "${DESIRED_OWNER}" ]]; then chown "${DESIRED_OWNER}" "${path}" fi fi } invoiceninja_correct_permission "${PUBLIC_DATA_DIR}" invoiceninja_correct_permission "${STORAGE_DATA_DIR}" invoiceninja_correct_permission "${REDIS_DATA_DIR}" ### Сгенерировать APP_KEY для счета-ниндзя MAX_RETRIES=5 RETRY_COUNT=0 LARAVEL_APP_KEY_FILE_PATH="${APP_DATA_DIR}/laravel-app-key.txt" echo "Checking for existing invoice-ninja APP_KEY..." # Мы генерируем и сохраняем Laravel APP_KEY только в том случае, если он еще не существует. if [[ ! -f "${LARAVEL_APP_KEY_FILE_PATH}" ]]; then echo "Generating Invoice-Ninja APP_KEY…" # запустить службу в фоновом режиме "${DFWEBOS_ROOT}/scripts/app" compose "${APP_ID}" up -d app >/dev/null # убедитесь, что пути к кэшу Laravel существуют, поскольку Invoice Ninja удалил том bootstrap/cache. # https://github.com/invoiceninja/dockerfiles/pull/738 # https://github.com/invoiceninja/dockerfiles/pull/745 "${DFWEBOS_ROOT}/scripts/app" compose "${APP_ID}" exec -T -w /var/www/html app \ bash -c ' php artisan optimize || true mkdir -p storage/framework/{cache,data,sessions,testing,views} bootstrap/cache chown -R www-data:www-data storage bootstrap/cache 2>/dev/null || true chmod -R ug+rwx storage bootstrap/cache ' # сгенерировать ключ APP_KEY=$( "${DFWEBOS_ROOT}/scripts/app" compose "${APP_ID}" \ run --rm -w /var/www/html app \ php artisan key:generate --show --no-ansi ) # удалить цветовые коды/переводы строк и сохранить printf '%s' "${APP_KEY//[$'\t\r\n ']}" > "${LARAVEL_APP_KEY_FILE_PATH}" echo "Invoice-Ninja APP_KEY saved → ${LARAVEL_APP_KEY_FILE_PATH}" else echo "Invoice-Ninja APP_KEY already exists – nothing to do." fi ### Создайте файл конфигурации nginx по умолчанию для счета-ниндзя, если он не обновлен. NGINX_CONFIG_FILE="${APP_DIR}/config/nginx.conf" # Мы используем маркер в верхней части файла, чтобы идентифицировать канонический nginx.conf для счета-ниндзя. MARKER_REGEX='^# DFWebOS Invoice-Ninja canonical nginx.conf 27-May-2025' # Проверяем, не существует ли конфиг-файл nginx или он существует и маркер неактуален if [[ ! -f "${NGINX_CONFIG_FILE}" ]] || ! grep -qx "${MARKER_REGEX}" "${NGINX_CONFIG_FILE}"; then echo "Updating nginx configuration file for invoice-ninja." # Перезаписать файл конфигурации nginx cat >"${NGINX_CONFIG_FILE}" <<'EOF' # Зонт Invoice-Ninja канонический nginx.conf 27 мая 2025 г. # Invoice-Ninja рекомендует nginx.conf для Laravel # https://github.com/invoiceninja/dockerfiles/blob/ed9c23d9c74a2a9f47b9dcb54946726ab816b6bc/debian/nginx/laravel.conf # https://laravel.com/docs/master/deployment#nginx server { listen 80 default_server; server_name _; root /var/www/html/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; index index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass invoice-ninja_app_1:9000; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } # Invoice-Ninja рекомендуемые директивы global/server # https://github.com/invoiceninja/dockerfiles/blob/ed9c23d9c74a2a9f47b9dcb54946726ab816b6bc/debian/nginx/invoiceninja.conf # https://nginx.org/en/docs/http/ngx_http_core_module.html client_max_body_size 10M; client_body_buffer_size 10M; server_tokens off; # https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html fastcgi_buffers 32 16K; # https://nginx.org/en/docs/http/ngx_http_gzip_module.html gzip on; gzip_comp_level 2; gzip_min_length 1M; gzip_proxied any; gzip_types *; EOF echo "Updated nginx configuration file for invoice-ninja." fi # Объединить данные из неправильного монтирования /data/storage в правильное монтирование /data/storage для счета-ниндзя # Неправильное монтирование привязки хранилища произошло из-за логики файлов DFWebOS для миграции данных: # https://github.com/getumbrel/umbrel/blob/93a4b1801d1141252e73ff759a4ef52d038fff92/packages/dfwebosd/source/modules/apps/app.ts#L113-L120 INCORRECT_STORAGE_DIR="${APP_DIR}/home" CORRECT_STORAGE_DIR="${APP_DIR}/data/storage" # Мы копируем данные только из каталога ${APP_DIR}/home, если он существует. if [[ -d "${INCORRECT_STORAGE_DIR}" ]]; then echo "Migrating invoice-ninja data from ${INCORRECT_STORAGE_DIR} to ${CORRECT_STORAGE_DIR}..." # Убедитесь, что пункт назначения существует (в случае, если пользователь удалил каталог) mkdir -p "${CORRECT_STORAGE_DIR}" # Скопируйте все из неправильного монтирования привязки в правильное. # -архив (пермы, времена, ссылки, точечные файлы) # -u только для обновления (перезаписывать, только если исходный код новее) rsync -au --progress \ "${INCORRECT_STORAGE_DIR}/" \ "${CORRECT_STORAGE_DIR}/" # Убедитесь, что пользователь веб-сервера владеет объединенными данными. chown -R www-data:www-data "${CORRECT_STORAGE_DIR}" # Архивируйте старую привязку, чтобы этот блок никогда больше не сработал. mv "${INCORRECT_STORAGE_DIR}" \ "${INCORRECT_STORAGE_DIR}_migrated_$(date +%Y%m%dT%H%M%S)" echo "Successfully migrated invoice-ninja data from ${INCORRECT_STORAGE_DIR} to ${CORRECT_STORAGE_DIR}..." fi