Nasazení
Instalace a provoz kostry na vlastním serveru: požadavky, PHP-FPM s Nginxem nebo Apache, zapisovatelné cesty, databáze a aktualizace, cron, HTTPS a proxy, zálohy, kontroly stavu, hybridní uspořádání a publikované image kontejnerů.
Tento návod instaluje web na server, kde si PHP, webový server a databázi spravujete sami: VPS, vyhrazený stroj nebo spravovaný hosting. Postup s Dockerem má vlastní návod: Nasazení na čisté VPS s Ubuntu pomocí Dockeru. Každý klíč Settings.json vysvětluje přehled nastavení.
Požadavky
- PHP 8.3 nebo novější (vývojový cíl je 8.4) s rozšířeními
mysqli,json,mbstring,fileinfo,curl,zipaopcache.zipacurlpoužívá Composer,opcachedrží zkompilované šablony v paměti. - Composer 2 na stroji, který instaluje závislosti (může to být váš počítač).
- MySQL 8 nebo MariaDB 10.6 a novější (výběr boxů používá
JSON_SEARCH). - Webový server, který každý požadavek, jenž není soubor, pošle do
public/index.php: Nginx s PHP-FPM, nebo Apache smod_rewriteamod_phpči PHP-FPM. - HTTPS před webem. Prosté HTTP stačí jen pro místní zkoušku.
1. Kód a závislosti
git clone https://github.com/rrsoftcz/wbengine-skeleton-app.git /var/www/wbengine-skeleton-app
cd /var/www/wbengine-skeleton-app
git checkout <značka vydání>
php bin/wbe install --no-dev
bin/wbe install vytvoří src/Config/Settings.json ze settings.json.default pokud soubor chybí (existující soubor jen zkontroluje, nikdy nepřepíše), vytvoří src/View/Compiled a spustí composer install --no-dev podle zamčeného souboru. Pro produkční build můžete místo toho spustit composer install --no-dev --optimize-autoloader.
Kořenem webového serveru je adresář public/. Nikdy ho nesměrujte na kořen projektu: src/, vendor/, schemas/ a bin/ nesmí být dostupné z webu.
2. Databáze
Vytvořte prázdnou databázi se znakovou sadou utf8mb4 a uživatele s právy jen na ni:
CREATE DATABASE wbengine_skeleton_app CHARACTER SET utf8mb4;
CREATE USER 'wbengine'@'127.0.0.1' IDENTIFIED BY 'dlouhé náhodné heslo';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP ON wbengine_skeleton_app.* TO 'wbengine'@'127.0.0.1';
Schéma a obsah se importují v tomto pořadí, poté se z přibalených souborů nainstalovaného frameworku vytvoří jeho tabulky (API, analytika a záznam změn), takže vždy sedí na jeho verzi:
mysql wbengine_skeleton_app < schemas/wbengine_skeletone_app_mysql_template.sql
mysql wbengine_skeleton_app < schemas/wbengine_skeletone_app_mysql_template_content.sql
sh bin/update-database.sh wbengine_skeleton_app
Skript použije stejné aktualizace frameworku jako instalátor pro Docker a lze ho bezpečně spustit znovu. Sloupce záznamu změn jsou nutné pro weby s API v2: bez nich doctor selže. Soubor s obsahem je počáteční naplnění nové instalace: není idempotentní, proto ho nikdy neimportujte do databáze, která už obsah má.
Existující instalace po záloze použije databázové aktualizace novější verze: nové soubory ze schemas/migrations/ jednou a v pořadí a aktualizace frameworku příkazem sh bin/update-database.sh DATABASE. Příkaz vendor/bin/wbengine.php migration:status ukáže, zda jsou tabulky frameworku úplné.
Poté upravte dbAdapterDefinition v Settings.json (hostitel, databáze, uživatel, heslo, charset). Vytvořte vlastního správce a odstraňte demo účet (admin@example.com / changeme, nikdy ho nenechávejte zapnutý):
php bin/wbe user:create --email=you@example.com --role=admin
php bin/wbe user:delete --example
3. Settings.json a tajné hodnoty
Settings.json nedávejte do správy verzí a nechte ho čitelný jen pro uživatele nasazení a uživatele PHP (chmod 640, skupina uživatele PHP). Tajné hodnoty dejte do prostředí procesu PHP místo souboru: WBENGINE_RECAPTCHA_SECRET a volitelně WBENGINE_DEBUG a WBENGINE_IMAGE_DIR. U PHP-FPM je nastavte v souboru poolu:
; /etc/php/8.4/fpm/pool.d/wbengine.conf
env[WBENGINE_RECAPTCHA_SECRET] = "..."
Kompletní produkční soubor je v přehledu nastavení. Minimum pro produkci: debug vypnuté, cache zapnutá, renderer.compileCheck na false, i18n.baseUrl na veřejnou adresu, http.trustedProxies při proxy před webem a výslovné absolutní adresáře pro běhové soubory (další část). Po prvním nasazení spusťte php vendor/bin/wbengine.php config:check --config=src/Config/Settings.json --root=src.
4. Zapisovatelné cesty a oprávnění
PHP běží pod jedním uživatelem (například www-data). Zápis mu dovolte jen tam, kam aplikace zapisuje, pomocí vlastnictví nebo omezené skupiny, nikdy chmod 777:
| Cesta | Účel | Nastavení |
|---|---|---|
src/View/Compiled/ |
zkompilované šablony | renderer.compiledDir |
/var/lib/wbengine/counters |
dávkovaná počítadla zobrazení článků | counters.views.dir |
/var/lib/wbengine/ratelimit |
počítadla limitu přihlášení | rateLimit.login.dir |
/var/cache/wbengine |
souborová cache a cache stránek | cache.dir |
/var/lib/wbengine/images |
obrázky nahrané přes API v2 | apiV2.imageDirectory nebo WBENGINE_IMAGE_DIR |
install -d -o www-data -g www-data -m 2770 /var/lib/wbengine/counters /var/lib/wbengine/ratelimit /var/lib/wbengine/images /var/cache/wbengine
chown -R www-data:www-data src/View/Compiled && chmod 2775 src/View/Compiled
Necháte-li adresáře nenastavené, framework použije podadresáře systémového dočasného adresáře. Při systemd s PrivateTmp=true (výchozí u PHP-FPM na mnoha distribucích) takový adresář po restartu zmizí a nesdílí se s příkazovou řádkou, proto nastavte výslovné cesty. Adresář obrázků musí být mimo public/; obrázky servíruje aplikace jako bajty.
Při renderer.compileCheck na false se šablony nekontrolují: po každém nasazení vyprázdněte adresář zkompilovaných šablon (rm -f src/View/Compiled/*) a vyprázdněte cache (část 9).
5. PHP-FPM s Nginxem
Nainstalujte nginx, php8.4-fpm a rozšíření a použijte hotový blok etc/nginx/wbengine-fpm.conf, odvozený od dockerového, ale komunikující přes unixový socket:
cp etc/nginx/wbengine-fpm.conf /etc/nginx/sites-available/wbengine.conf
# upravte server_name, root a socket ve fastcgi_pass
ln -s /etc/nginx/sites-available/wbengine.conf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Spouští se jen /index.php (označeno internal), přímé požadavky na *.php dostanou 404 a src, vendor, schemas, bin a etc jsou zakázané i při chybně zadaném kořeni. V produkci používejte opcache (opcache.enable=1, opcache.validate_timestamps=0 spolu s reloadem PHP-FPM při nasazení dává nejlepší výsledek; funguje i výchozí kontrola časových razítek). V php.ini ponechte display_errors = Off a log_errors = On.
6. Apache
S mod_php i PHP-FPM směruje požadavky public/.htaccess, takže virtuální host potřebuje AllowOverride All na public/. Zdokumentovaná šablona je etc/apache2/sites-available/wbengine-production.conf:
a2enmod rewrite headers ssl
cp etc/apache2/sites-available/wbengine-production.conf /etc/apache2/sites-available/wbengine.conf
# nahraďte každou hodnotu označenou CHANGE
a2ensite wbengine && apache2ctl configtest && systemctl reload apache2
Pro PHP-FPM přidejte blok SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost", který šablona ukazuje, a zapněte proxy_fcgi. U mod_php používejte SetEnv ve virtuálním hostu jen tehdy, když nelze použít prostředí jiné služby; záznamy env[] v poolu PHP-FPM jsou čistší.
7. HTTPS a hlavičky důvěryhodných proxy
Získejte certifikát (certbot --nginx nebo certbot --apache) a přesměrujte HTTP na HTTPS. Když je PHP samo za reverzní proxy, load balancerem nebo sítí kontejnerů, framework vidí proxy jako klienta a požadavek jako prosté HTTP, dokud výslovně nepovolíte předávaná metadata:
"http": {
"trustedProxies": ["127.0.0.1", "10.0.0.0/24"],
"forwardedHeaders": ["x-forwarded-for", "x-forwarded-proto"]
}
Uveďte jen adresy proxy, které provozujete, a každá proxy musí přepsat X-Forwarded-Proto vnějším schématem a sestavit X-Forwarded-For ze skutečného spojení. Bez toho jsou špatně zabezpečená cookies, /integrations/, absolutní odkazy jazyků i klíče limitu pokusů. Když TLS ukončuje přímo webový server (Nginx nebo Apache výše), nechte oba seznamy prázdné. Nastavte i18n.baseUrl, aby odkazy hreflang nezávisely na hlavičce Host.
8. Cron
Vlastní analytika drží denní souhrny po dobu analytics.retentionDays. Prošlé řádky mažte denně:
17 3 * * * www-data /usr/bin/php /var/www/wbengine-skeleton-app/vendor/bin/wbengine.php analytics:prune --config=/var/www/wbengine-skeleton-app/src/Config/Settings.json --root=/var/www/wbengine-skeleton-app/src >> /var/log/wbengine-cron.log 2>&1
Úloha čte stejné tajné hodnoty z prostředí, proto ji spouštějte pod webovým uživatelem se stejnými proměnnými (například načtením souboru vlastněného rootem v řádku crontabu). Tabulky záznamu změn a auditu je také třeba denně mazat (audit.retentionDays, viz Logování a audit):
27 3 * * * www-data /usr/bin/php /var/www/wbengine-skeleton-app/vendor/bin/wbengine.php audit:prune --config=/var/www/wbengine-skeleton-app/src/Config/Settings.json --root=/var/www/wbengine-skeleton-app/src >> /var/log/wbengine-cron.log 2>&1
9. Aktualizace, záloha a návrat
Před každým nasazením zálohujte databázi, Settings.json, adresář obrázků a soubor poolu či prostředí s tajnými hodnotami.
mysqldump --single-transaction --routines wbengine_skeleton_app | gzip > /var/backups/wbengine-$(date +%F).sql.gz
tar czf /var/backups/wbengine-files-$(date +%F).tgz src/Config/Settings.json /var/lib/wbengine/images
Aktualizace:
git fetch --tags && git checkout <nová značka>
composer install --no-dev --optimize-autoloader
# spusťte nové soubory ze schemas/migrations/ (v pořadí), potom aktualizace frameworku:
sh bin/update-database.sh wbengine_skeleton_app
rm -f src/View/Compiled/*
php vendor/bin/wbengine.php doctor --config=src/Config/Settings.json --root=src
systemctl reload php8.4-fpm
Cache vyprázdníte voláním POST /api/v2/cache/flush (integrační klíč s oprávněním cache:write, například z centrální administrace) nebo smazáním souborů v cache.dir. U cache APCu restartujte PHP-FPM.
Návrat: přepněte na předchozí značku, spusťte composer install --no-dev, vyprázdněte adresář zkompilovaných šablon a reloadujte PHP-FPM. Databázové aktualizace se automaticky nevracejí: pokud některá změnila schéma, obnovte zálohu databáze pořízenou před nasazením. Obsahové aktualizace mění jen text a lze je ponechat.
10. Logy
| Log | Obvyklé umístění |
|---|---|
| Nginx | /var/log/nginx/access.log, error.log |
| Apache | ${APACHE_LOG_DIR} (/var/log/apache2/), soubory uvedené ve virtuálním hostu |
| PHP-FPM | /var/log/php8.4-fpm.log, případně slow log poolu |
| Chyby PHP | hodnota ini error_log, jinak chybový log webového serveru |
| Aplikace | framework zapisuje přes error_log (například „cache disabled: ...“, když do adresáře cache nelze zapisovat) |
11. Kontroly stavu
php vendor/bin/wbengine.php doctor --config=src/Config/Settings.json --root=src
php vendor/bin/wbengine.php config:check --config=src/Config/Settings.json --root=src
php vendor/bin/wbengine.php migration:status --config=src/Config/Settings.json --root=src
curl -sI https://example.com/ | head -1
curl -sI https://example.com/cs/docs/ | head -1
curl -s https://example.com/api/v2/capabilities
doctor kontroluje tajné hodnoty, ladění, cache a stav adresářů bez změny schématu, config:check ověří soubor nastavení a migration:status ukáže, které migrace frameworku jsou použité. Končí kódem 0 při zdravém stavu a 1 při neúspěšné kontrole, takže se hodí do skriptu nasazení. Příkazová řádka má vlastní konfiguraci PHP: opcache webového SAPI, oprávnění webového uživatele a HTTPS ověřte zvlášť skutečnými požadavky.
Hybridní uspořádání
Hostitelský Nginx před kontejnery
PHP a MySQL běží v Dockeru a TLS zůstává na hostiteli. Přesně takové je uspořádání návodu Nasazení na čisté VPS s Ubuntu pomocí Dockeru: kontejner je publikovaný jen na 127.0.0.1:8080, hostitelský Nginx na něj proxyuje a instalátor zapíše odpovídající http.trustedProxies.
Externí spravovaná databáze
Nasměrujte dbAdapterDefinition.hostname na spravovanou službu MySQL nebo MariaDB a importujte schéma, obsah a aktualizace frameworku z části 2 klientem mysql ze stroje, který na ni dosáhne (import přes docker-entrypoint-initdb.d existuje jen pro přibalenou databázi). Použijte vyhrazeného uživatele a databázi, povolte připojení jen z hostitele aplikace a při přenosu po síti zapněte TLS na straně serveru. V souboru Compose odeberte službu db a položku depends_on. Ověřte, že verze databáze splňuje požadavky (JSON_SEARCH).
Sdílený hosting
Funguje, pokud hosting nabízí PHP 8.3 nebo novější s výše uvedenými rozšířeními, MySQL nebo MariaDB, mod_rewrite a .htaccess a dovolí nastavit kořen webu na public/ (jinak projekt nelze bezpečně nainstalovat). Čeho se držet: bez shellu a cronu, proto spusťte composer install --no-dev lokálně a nahrajte celý strom včetně vendor/; SQL soubory importujte nástrojem hostingu; bez proměnných prostředí, proto tajné hodnoty musí být v Settings.json (mimo správu verzí, s co nejpřísnějšími oprávněními, jaká hosting dovolí); bez analytics:prune, pokud panel nenabízí cron; zápis do src/View/Compiled a běhových adresářů je nutné zařídit přes panel. Pokud to hosting nezvládne, použijte VPS.
Sestavené image
Dockerfile.production sestaví produkční image: kód a produkční závislosti Composeru, žádná tajemství. Sestavte ho a spusťte s Settings.json připojeným jen pro čtení a svazkem pro zkompilované šablony:
docker build -f Dockerfile.production -t wbengine-skeleton-app:1.2.3 .
docker run -d --name wbengine --restart unless-stopped \
-p 127.0.0.1:8080:80 \
-v /etc/wbengine/Settings.json:/var/www/html/src/Config/Settings.json:ro \
-v wbengine_compiled:/var/www/html/src/View/Compiled \
-e WBENGINE_RECAPTCHA_SECRET="..." \
wbengine-skeleton-app:1.2.3
Každý build označte verzí a v produkci spouštějte tuto značku, ne latest. Kontejner obsluhuje prosté HTTP na portu 80: postavte před něj hostitelský Nginx (viz návod pro VPS) a nastavte http.trustedProxies na adresu, ze které kontejner proxy vidí. Databáze součástí image není; použijte přibalený soubor Compose nebo externí databázi popsanou výše. Při aktualizaci sestavte novou značku, použijte databázové aktualizace, pak docker rm -f wbengine a spusťte znovu; svazek se zkompilovanými šablonami se použije znovu (při compileCheck na false ho vyprázdněte).