HELP — Setup, Run & Ops
All project docs render at /docs on the site. This file is the ops manual.
1. Requirements
- PHP 8.3+ (extensions: pdo_mysql, gd, curl, intl, opcache)
- MariaDB 10.11+ (this host has it)
- Nginx (+ certbot) on the production host
- Composer (optional — a built-in autoloader fallback exists)
2. First-time setup (host)
# 1) code at /home/fla — docroot is /home/fla/public
# 2) environment
cp .env.example .env # then edit values (never commit .env)
# 3) database (one-time, as root)
mariadb -u root <<'SQL'
CREATE DATABASE IF NOT EXISTS fla_event CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'fla'@'%' IDENTIFIED BY '<strong-password>';
GRANT ALL PRIVILEGES ON fla_event.* TO 'fla'@'%';
FLUSH PRIVILEGES;
SQL
# 4) tables + seeds
./database/migrate.sh # uses DB_* env overrides if needed
# 5) autoloader (optional optimization)
composer dump-autoload -o
# 6) writable runtime dirs
mkdir -p storage/{cards,uploads,cache,logs} && chmod -R 775 storage
3. Web server — subdomain on plain 443
Nginx server block (template also kept in the repo under deploy/nginx.conf):
server {
listen 80;
server_name event.production1.jugaar.ai;
root /home/fla/public;
index index.php;
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\. { deny all; }
}
Then HTTPS (plain 443, no ports):
certbot --nginx -d event.production1.jugaar.ai # creates :443 vhost + auto-redirect
APP_URL in .env must stay https://event.production1.jugaar.ai — share links use absolute_url() so they're always canonical.
4. Daily ops
| Task | Command / location |
|---|---|
| Health check | curl https://event.production1.jugaar.ai/health |
| Docs in browser | https://event.production1.jugaar.ai/docs |
| QA suite (29 checks) | ./bin/qa.sh |
| Re-run migrations | ./database/migrate.sh (idempotent; reads creds from .env) |
| Demo share cards | php bin/card-demo.php → PNGs in storage/cards/ |
| Logs (app) | PHP error log (fpm) + storage/logs/whatsapp.log |
| Back up DB | mysqldump fla_event > db-dump-$(date +%F).sql (nightly cron recommended — git-ignored) |
5. Feature toggles & branding
feature_togglestable:branding.panel,registration.*,ai.qa,voting,
cards.gd, judges.panel, tickets, comms.mass, winners.announce, audit.ui, docs.public.
settingstable:brand.name,brand.tagline,brand.primary_color,
brand.logo_path, campaign.{applied|visiting|winner}_text (placeholders {event} {name} {category}), voting.weight_{public|admin}, voting.mode, vote.reason_enabled.
- From v0.2.0 these are edited in
/admin/branding— until then SQL is fine.
6. External keys (when they arrive)
| Key | Put in .env | Effect |
|---|---|---|
| MiniMax | AI_API_KEY, AI_BASE_URL, AI_MODEL, AI_MOCK=false | live AI interviews |
LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET | real OAuth | |
WHATSAPP_PROVIDER, WHATSAPP_API_KEY | real messaging | |
| SMTP/mail | (added alongside comms milestone) | real emails |
7. Troubleshooting
- 500 on every page → check
.envexists, PHP fpm socket path in nginx, then error log. - "View not found" → route references a missing
views/…file; check module. - DB down →
/healthshowsdb:down; verifyflagrants +DB_*values. - Cards blank text → DejaVu font missing at
/usr/share/fonts/truetype/dejavu/
(GD falls back to a small built-in font).
- Migrations fail → run
mariadb fla_eventmanually and execute the failing file to see the error.