diff --git a/CLAUDE.md b/CLAUDE.md index 360465a..eb0827d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,9 +10,31 @@ Libra Law Firm is a bilingual (Arabic/English) web platform for managing client ## Production Environment -- **Server:** Rocky Linux 9.6 on 69.62.106.94 -- **PHP:** 8.4 (use `php84` command, not `php`) -- **Database:** MariaDB/MySQL +- **Server:** h1 (`h1.elenoslabs.com`, `163.172.67.77`) — Rocky Linux 9, ElenosLabs-owned. **Not** + `69.62.106.94` — that stale IP is left over from before the migration to h1 and does not serve + this app; a past `.env` even had `MAIL_HOST` pointed at it by mistake (see *Mail* below). Full + server details: `wiki/prod_servers/elenoslabs/h1server.md` (Jarvis workspace), § libra.adv.ps. +- **App user:** `libra` — app root `/home/libra/public_html/`, logs `/home/libra/logs/` +- **PHP:** 8.4 (use `php84` command — there is no bare `php` binary on this box; even Composer + needs `php84 /usr/local/bin/composer ...`) +- **Database:** MariaDB, Redis (sessions/cache/queue) +- **Queue worker:** `libra-queue.service` (`queue:work redis`) — a **long-running process**, see + the queue note below. +- **Git:** production was file-copied at initial migration and only properly linked to git for + the first time on 2026-09-28 (`git checkout -f -B main origin/main` after backing up the prior + state) — before that date, `git pull` on production did nothing (empty local branch, no + commits). It is now a normal git-tracked checkout; a plain `git pull` works going forward. + +### Mail + +`MAIL_HOST` must be `mx1.elenoslabs.com` (h1's own Postfix/Dovecot stack, MX for `adv.ps`) — **not** +`mail.adv.ps`, which resolves to the stale `69.62.106.94` host and times out. This caused a real +incident (2026-09-28): the workshop-registration form's emails silently never arrived because of +this wrong value, and a separate real bug in `App\Services\AdminNotificationService` (a Carbon +`TypeError` on a string `throttle_minutes` config value — fixed, see git history around +2026-09-28) masked the actual SMTP error in the logs the whole time it was broken. If mail seems +to silently fail again, check `MAIL_HOST` first, then `storage/logs/laravel.log` for a +`TransportException`. ### Production Commands All artisan commands on production require `php84` prefix: @@ -24,16 +46,25 @@ php84 artisan optimize:clear ### Deployment Checklist ```bash -# On production server -composer install --no-dev --optimize-autoloader -php84 artisan migrate --force +# On production server (as the libra user, in /home/libra/public_html) +git pull +php84 /usr/local/bin/composer install --no-dev --optimize-autoloader # only if composer.json/lock changed +npm install && npm run build # only if frontend/Tailwind classes changed php84 artisan optimize:clear php84 artisan config:cache php84 artisan route:cache php84 artisan view:cache -# IMPORTANT: Always restart PHP-FPM after deployment +# IMPORTANT: always restart PHP-FPM after ANY deploy, even a content/lang-only change. +# 2026-09-28 incident: opcache.validate_timestamps is On with revalidate_freq=2, which should +# have picked up a changed lang/*.php file within 2 seconds on its own — it didn't, and only a +# full php84-php-fpm restart made the change visible. Root cause not fully diagnosed; until it +# is, treat the restart as mandatory on every deploy, not just composer/config changes. sudo systemctl restart php84-php-fpm + +# IMPORTANT: always restart the queue worker too — it's a long-running process that holds old +# code and old .env/config values in memory until restarted, independent of the php-fpm restart. +php84 artisan queue:restart ``` **Note:** The server has both PHP 8.3 and 8.4. Always use `php84` for artisan commands. Failing to restart PHP-FPM can cause cached config issues.