1
0
mirror of git://f0xx.org/ac/ac-deploy synced 2026-07-29 05:00:35 +03:00

cluster0: composed ac backend, /issues/ nginx, postgres semi-prod

Compose lab PHP from ac-workspace overlay; 301 /crashes/ → /issues/;
verify on issues path; optional native Postgres on cast01.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Anton Afanasyeu
2026-06-23 13:10:35 +02:00
parent 6c224d023f
commit 98f30786b7
7 changed files with 254 additions and 22 deletions

View File

@@ -37,8 +37,13 @@ URL_SHORTENER_ORIGIN=git://f0xx.org/ac/ac-ms-url-shortener
URL_SHORTENER_ROOT=/var/www/url-shortener URL_SHORTENER_ROOT=/var/www/url-shortener
APP_ROOT=/var/www/localhost/htdocs/apps/app/androidcast_project APP_ROOT=/var/www/localhost/htdocs/apps/app/androidcast_project
APP_BASE_PATH=/app/androidcast_project/crashes APP_BASE_PATH=/app/androidcast_project/issues
APP_LEGACY_BASE_PATH=/app/androidcast_project/crashes
APP_HUB_PATH=/app/androidcast_project APP_HUB_PATH=/app/androidcast_project
COMPOSE_BACKEND=/var/www/ac/composed/backend
AC_PLATFORM_ROOT=/var/www/ac/platform
COMPOSE_RUNTIME=1
POSTGRES_SEMI_ENABLE=1
# Set after DNS + FE redirect, then run verify_global_setup.sh # Set after DNS + FE redirect, then run verify_global_setup.sh
PUBLIC_ORIGIN=https://apps.f0xx.org PUBLIC_ORIGIN=https://apps.f0xx.org

View File

@@ -34,44 +34,62 @@ server {
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
} }
location = /app/androidcast_project/crashes {
return 301 /app/androidcast_project/crashes/;
}
location = /app/androidcast_project/graphs { location = /app/androidcast_project/graphs {
return 301 /app/androidcast_project/graphs/; return 301 /app/androidcast_project/graphs/;
} }
location ^~ /app/androidcast_project/crashes/assets/ { # --- Target paths (SPEC): /issues/ served from composed ac/* backend ---
alias /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/assets/; location = /app/androidcast_project/issues {
return 301 /app/androidcast_project/issues/;
} }
location ^~ /app/androidcast_project/graphs/assets/ { location ^~ /app/androidcast_project/issues/assets/ {
alias /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/assets/; alias /var/www/ac/composed/backend/public/assets/;
} }
location = /app/androidcast_project/crashes/api/upload.php { location = /app/androidcast_project/issues/api/upload.php {
include fastcgi_params; include fastcgi_params;
fastcgi_pass 127.0.0.1:9000; fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/api/upload.php; fastcgi_param SCRIPT_FILENAME /var/www/ac/composed/backend/public/api/upload.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/crashes/api/upload.php; fastcgi_param SCRIPT_NAME /app/androidcast_project/issues/api/upload.php;
fastcgi_param REQUEST_URI $request_uri; fastcgi_param REQUEST_URI $request_uri;
client_max_body_size 4m; client_max_body_size 4m;
} }
location ^~ /app/androidcast_project/issues/ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/ac/composed/backend/public/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/issues/index.php;
fastcgi_param REQUEST_URI $request_uri;
client_max_body_size 4m;
}
# Legacy /crashes/ → 301 to /issues/ (SPEC §7)
location = /app/androidcast_project/crashes {
return 301 /app/androidcast_project/issues/;
}
location ^~ /app/androidcast_project/crashes/ { location ^~ /app/androidcast_project/crashes/ {
include fastcgi_params; rewrite ^/app/androidcast_project/crashes/?(.*)$ /app/androidcast_project/issues/$1 permanent;
fastcgi_pass 127.0.0.1:9000; }
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/crashes/index.php; location ^~ /app/androidcast_project/crashes/assets/ {
fastcgi_param REQUEST_URI $request_uri; alias /var/www/ac/composed/backend/public/assets/;
client_max_body_size 4m; }
location = /app/androidcast_project/crashes/api/upload.php {
return 301 /app/androidcast_project/issues/api/upload.php;
}
location ^~ /app/androidcast_project/graphs/assets/ {
alias /var/www/ac/composed/backend/public/assets/;
} }
location = /app/androidcast_project/graphs/api/graphs.php { location = /app/androidcast_project/graphs/api/graphs.php {
include fastcgi_params; include fastcgi_params;
fastcgi_pass 127.0.0.1:9000; fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/api/graphs.php; fastcgi_param SCRIPT_FILENAME /var/www/ac/composed/backend/public/api/graphs.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/graphs/api/graphs.php; fastcgi_param SCRIPT_NAME /app/androidcast_project/graphs/api/graphs.php;
fastcgi_param REQUEST_URI $request_uri; fastcgi_param REQUEST_URI $request_uri;
} }
@@ -79,7 +97,7 @@ server {
location = /app/androidcast_project/graphs/api/graph_upload.php { location = /app/androidcast_project/graphs/api/graph_upload.php {
include fastcgi_params; include fastcgi_params;
fastcgi_pass 127.0.0.1:9000; fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/api/graph_upload.php; fastcgi_param SCRIPT_FILENAME /var/www/ac/composed/backend/public/api/graph_upload.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/graphs/api/graph_upload.php; fastcgi_param SCRIPT_NAME /app/androidcast_project/graphs/api/graph_upload.php;
fastcgi_param REQUEST_URI $request_uri; fastcgi_param REQUEST_URI $request_uri;
client_max_body_size 4m; client_max_body_size 4m;
@@ -88,7 +106,7 @@ server {
location ^~ /app/androidcast_project/graphs/ { location ^~ /app/androidcast_project/graphs/ {
include fastcgi_params; include fastcgi_params;
fastcgi_pass 127.0.0.1:9000; fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/index.php; fastcgi_param SCRIPT_FILENAME /var/www/ac/composed/backend/public/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/graphs/index.php; fastcgi_param SCRIPT_NAME /app/androidcast_project/graphs/index.php;
fastcgi_param REQUEST_URI $request_uri; fastcgi_param REQUEST_URI $request_uri;
client_max_body_size 4m; client_max_body_size 4m;

View File

@@ -71,6 +71,12 @@ run_phase_app() {
run_script "$ROOT/scripts/deploy-app.sh" run_script "$ROOT/scripts/deploy-app.sh"
run_script "$ROOT/scripts/deploy-ac-workspace.sh" run_script "$ROOT/scripts/deploy-ac-workspace.sh"
run_script "$ROOT/scripts/deploy-ac-url-shortener.sh" run_script "$ROOT/scripts/deploy-ac-url-shortener.sh"
if [ "${COMPOSE_RUNTIME:-0}" = "1" ]; then
run_script "$ROOT/scripts/compose-lab-backend.sh"
fi
if [ "${POSTGRES_SEMI_ENABLE:-0}" = "1" ] && is_primary_node; then
run_script "$ROOT/scripts/deploy-postgres-semi.sh" || journal_warn postgres_semi "install failed (non-fatal)"
fi
run_script "$ROOT/scripts/configure-nginx.sh" run_script "$ROOT/scripts/configure-nginx.sh"
rc-service php-fpm83 restart 2>/dev/null || true rc-service php-fpm83 restart 2>/dev/null || true
rc-service nginx reload 2>/dev/null || rc-service nginx restart 2>/dev/null || true rc-service nginx reload 2>/dev/null || rc-service nginx restart 2>/dev/null || true

View File

@@ -0,0 +1,163 @@
#!/bin/sh
# Assemble runnable PHP backend from ac-workspace submodules (overlay on legacy seed).
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
# shellcheck source=/dev/null
. "$ROOT/scripts/lib/common.sh"
load_cluster_env
WS="${AC_WORKSPACE_ROOT:-/var/www/ac/workspace}"
LEGACY="${APP_ROOT}/android_cast/examples/crash_reporter/backend"
COMPOSED="${COMPOSE_BACKEND:-/var/www/ac/composed/backend}"
PLATFORM_ROOT="${AC_PLATFORM_ROOT:-/var/www/ac/platform}"
APP_PASS="$(read_cred mariadb_app password)"
DB_HOST="$PRIMARY_DB_HOST"
if is_primary_node; then
DB_HOST=127.0.0.1
fi
[ -d "$WS/.git" ] || die "missing ac-workspace at $WS (run deploy-ac-workspace.sh first)"
overlay_src() {
_repo="$1"
_dir="${WS}/${_repo}/src"
[ -d "$_dir" ] || { log "skip src ${_repo} (no src/)"; return 0; }
log "overlay src ${_repo}"
cp -a "$_dir"/. "${COMPOSED}/src/"
}
overlay_api() {
_repo="$1"
_dir="${WS}/${_repo}/public/api"
[ -d "$_dir" ] || return 0
log "overlay api ${_repo}"
mkdir -p "${COMPOSED}/public/api"
cp -a "$_dir"/. "${COMPOSED}/public/api/"
}
overlay_views() {
_repo="$1"
_dir="${WS}/${_repo}/views"
[ -d "$_dir" ] || return 0
log "overlay views ${_repo}"
mkdir -p "${COMPOSED}/views"
cp -a "$_dir"/. "${COMPOSED}/views/"
}
if [ ! -f "${COMPOSED}/public/index.php" ] || [ "${FORCE_COMPOSE_SEED:-0}" = "1" ]; then
[ -d "$LEGACY/public" ] || die "legacy backend missing at $LEGACY — run deploy-app.sh first"
log "seed composed backend from legacy ${LEGACY}"
mkdir -p "$(dirname "$COMPOSED")"
rm -rf "$COMPOSED"
mkdir -p "$COMPOSED"
cp -a "${LEGACY}/." "$COMPOSED/"
fi
mkdir -p "$PLATFORM_ROOT"
if [ -d "${WS}/ac-platform-php/platform" ]; then
log "sync platform helpers → ${PLATFORM_ROOT}"
cp -a "${WS}/ac-platform-php/platform/." "$PLATFORM_ROOT/"
fi
if [ -d "${WS}/ac-platform-web/assets" ]; then
log "sync platform-web assets"
mkdir -p "${COMPOSED}/public/assets"
cp -a "${WS}/ac-platform-web/assets/." "${COMPOSED}/public/assets/"
if [ -f "${WS}/ac-platform-web/src/AnalyticsHead.php" ]; then
cp -a "${WS}/ac-platform-web/src/AnalyticsHead.php" "${COMPOSED}/src/"
fi
fi
overlay_src ac-platform-php
overlay_src ac-ms-identity
overlay_src ac-ms-rbac
overlay_src ac-ms-devices
overlay_src ac-ms-issues
overlay_src ac-ms-tickets
overlay_src ac-ms-graphs
overlay_src ac-ms-remote-access
overlay_api ac-ms-identity
overlay_api ac-ms-rbac
overlay_api ac-ms-devices
overlay_api ac-ms-issues
overlay_api ac-ms-tickets
overlay_api ac-ms-graphs
overlay_api ac-ms-remote-access
overlay_views ac-be-auth
overlay_views ac-be-issues
overlay_views ac-be-tickets
overlay_views ac-be-graphs
overlay_views ac-be-remote-access
overlay_views ac-be-access
ISSUES_BASE="${APP_BASE_PATH:-/app/androidcast_project/issues}"
mkdir -p "${COMPOSED}/config"
log "write composed config.php base_path=${ISSUES_BASE}"
cat > "${COMPOSED}/config/config.php" <<PHP
<?php
return [
'app_name' => 'Android Cast Issues',
'base_path' => '${ISSUES_BASE}',
'db' => [
'driver' => 'mariadb',
'sqlite_path' => __DIR__ . '/../data/crashes.sqlite',
'mysql' => [
'host' => '${DB_HOST}',
'port' => ${PRIMARY_DB_PORT},
'socket' => '',
'database' => 'androidcast_crashes',
'username' => 'androidcast',
'password' => '${APP_PASS}',
'charset' => 'utf8mb4',
],
],
'session_name' => 'ac_crash_sess',
'session_cookie_path' => '${APP_HUB_PATH}',
'debug' => true,
'rbac' => ['default_company_slug' => 'default', 'default_company_id' => 1],
'analytics' => ['enabled' => false, 'measurement_id' => '', 'debug' => false],
'remote_access' => [
'wg_endpoint' => '',
'wg_server_public_key' => '',
'provision_peers' => false,
'require_wg_tools' => false,
],
'auth' => [
'encryption_key' => 'lab-cluster-dev-32-char-min-secret!!',
'max_attempts' => 8,
'lockout_window_minutes' => 15,
],
'url_shortener' => [
'enabled' => true,
'public_base' => '${SHORT_LINKS_PUBLIC_BASE}',
'db' => [
'mysql' => [
'host' => '${DB_HOST}',
'port' => ${PRIMARY_DB_PORT},
'socket' => '',
'database' => 'url_shortener',
'username' => 'androidcast',
'password' => '${APP_PASS}',
'charset' => 'utf8mb4',
],
],
],
];
PHP
if command -v composer >/dev/null 2>&1; then
log "composer dump-autoload (optional)"
cat > "${COMPOSED}/composer.json" <<'JSON'
{
"name": "androidcast/lab-composed-backend",
"require": { "php": ">=8.1" },
"autoload": { "classmap": ["src/"] }
}
JSON
(cd "$COMPOSED" && composer dump-autoload -o 2>/dev/null) || true
fi
chown -R nginx:nginx "$(dirname "$COMPOSED")" "$PLATFORM_ROOT" 2>/dev/null || true
log "compose-lab-backend_ok $(host_short)${COMPOSED}"

View File

@@ -0,0 +1,32 @@
#!/bin/sh
# Optional semi-prod PostgreSQL on cast01 (native Alpine, no Docker).
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
# shellcheck source=/dev/null
. "$ROOT/scripts/lib/common.sh"
load_cluster_env
[ "$(host_short)" = "$CAST01_HOST" ] || { log "postgres semi-prod: cast01 only — skip on $(host_short)"; exit 0; }
PG_VER="${POSTGRES_SEMI_VERSION:-16}"
DB_NAME="${POSTGRES_SEMI_DB:-androidcast_semi_pg}"
if ! apk info -e "postgresql${PG_VER}" >/dev/null 2>&1; then
log "install postgresql${PG_VER}"
apk add --no-cache "postgresql${PG_VER}" "postgresql${PG_VER}-contrib" || apk add --no-cache postgresql postgresql-contrib
fi
if [ ! -d /var/lib/postgresql/data/PG_VERSION ]; then
log "initdb"
mkdir -p /var/lib/postgresql/data
chown postgres:postgres /var/lib/postgresql/data
su postgres -c "initdb -D /var/lib/postgresql/data"
fi
rc-service postgresql restart 2>/dev/null || rc-service postgresql start
sleep 2
su postgres -c "psql -tc \"SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'\" | grep -q 1" \
|| su postgres -c "createdb ${DB_NAME}"
log "postgres_semi_ok db=${DB_NAME} host=127.0.0.1"

View File

@@ -37,8 +37,10 @@ check_dir "ac-workspace" "$AC_ROOT"
check_dir "ac-platform-db" "${AC_ROOT}/ac-platform-db/sql/crash_reporter" check_dir "ac-platform-db" "${AC_ROOT}/ac-platform-db/sql/crash_reporter"
check_dir "ac-platform-php" "${AC_ROOT}/ac-platform-php/src" check_dir "ac-platform-php" "${AC_ROOT}/ac-platform-php/src"
check_dir "ac-platform-web" "${AC_ROOT}/ac-platform-web/assets/css" check_dir "ac-platform-web" "${AC_ROOT}/ac-platform-web/assets/css"
check_dir "legacy-monolith" "$LEGACY" check_dir "composed-backend" "${COMPOSE_BACKEND:-/var/www/ac/composed/backend}"
check_file "composed-index" "${COMPOSE_BACKEND:-/var/www/ac/composed/backend}/public/index.php"
check_file "legacy-backend" "${LEGACY}/examples/crash_reporter/backend/public/index.php" check_file "legacy-backend" "${LEGACY}/examples/crash_reporter/backend/public/index.php"
check_dir "legacy-monolith" "$LEGACY"
check_dir "url-shortener" "${URL_SHORTENER_ROOT:-/var/www/url-shortener}/public" check_dir "url-shortener" "${URL_SHORTENER_ROOT:-/var/www/url-shortener}/public"
if [ -d "${AC_ROOT}/.git" ]; then if [ -d "${AC_ROOT}/.git" ]; then

View File

@@ -46,6 +46,12 @@ check_local_node() {
DIAG="$(curl -sS "http://127.0.0.1${APP_BASE_PATH}/api/diag.php" 2>/dev/null || true)" DIAG="$(curl -sS "http://127.0.0.1${APP_BASE_PATH}/api/diag.php" 2>/dev/null || true)"
echo "$DIAG" | grep -q '"ok":true' || { log "FAIL diag.php"; FAIL=1; } echo "$DIAG" | grep -q '"ok":true' || { log "FAIL diag.php"; FAIL=1; }
LEGACY_REDIRECT="$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1${APP_LEGACY_BASE_PATH:-/app/androidcast_project/crashes}/" 2>/dev/null || echo 000)"
case "$LEGACY_REDIRECT" in
301|308) log "legacy_redirect=${LEGACY_REDIRECT}" ;;
*) log "WARN legacy_redirect=${LEGACY_REDIRECT} (want 301 from ${APP_LEGACY_BASE_PATH}/)" ;;
esac
if [ -x "$ROOT/scripts/validate-ac-repos.sh" ]; then if [ -x "$ROOT/scripts/validate-ac-repos.sh" ]; then
sh "$ROOT/scripts/validate-ac-repos.sh" || FAIL=1 sh "$ROOT/scripts/validate-ac-repos.sh" || FAIL=1
fi fi