Přeskočit na obsah
Přihlásit

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, zip a opcache. zip a curl používá Composer, opcache drží 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 s mod_rewrite a mod_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).