Repository navigation
Version 4.0.0
php and php-cron move to PHP 8.5, with sessions kept in memcached through PHP's native handler. Disaster recovery can restore from another hostname and S3 endpoint, rebuild nested Git checkouts and run site-specific steps, backups can go to a second S3 destination, and the deploy account is configurable. Read the upgrade notes before pulling.
Why a major version
docker-compose.yml now runs php and php-cron on the bitrix-php:8.5 image with their config binds under /etc/php/8.5. That image does not ship the memcache extension, so a Bitrix site whose bitrix/.settings.php uses the memcache session type fails every request after the switch. Bitrix has no memcached session type; the save_handler.php.ini type hands sessions to PHP's native handler, which config/php/90-php.ini now points at memcached-sessions:11211. Change the session setting before pulling (upgrade note 1).
PHP and sessions
- Sessions use the php-memcached native handler. A request waits up to about 30 seconds for a session lock held by another request of the same visitor, and a lock expires after 60 seconds.
- nginx resolves the php upstream once, so after php is recreated it keeps the old container address and answers 502 until it reloads; the PHP switching steps in the Readme say so.
MySQL and memcached
sort_buffer_sizeincreases from 256K to 2M to reduce disk-based sorts. MySQL grows sort memory as needed, so this is a per-connection cap, not a reservation.- The MySQL container sets
oom_score_adj: -500to make it less likely to be selected during an out-of-memory event. - The component cache memcached gets 3 GB instead of 2 GB.
- Sizing: the 4 GB InnoDB buffer pool (unchanged since v3.0.0) needs a host with at least 8 GB of RAM; on a 4 GB host the kernel kills mysqld while it initialises the data directory. The Readme says how to shrink it locally.
nginx
- The open file cache is off. It kept a replaced file's descriptor and size for up to 30 seconds, so a new versioned URL could receive the old bytes, or the new content cut to the old size, and browsers could keep that response for the configured cache lifetime.
- In vhosts using
bitrix.conf, the root icon paths (/favicon.ico,/favicon.svg,/apple-touch-icon.png) are cached for a day instead of as immutable, and feed.xmland.txtfiles under/upload/are revalidated within the hour. - The static-host CORS origin is an overlay map in
conf.d/overlay-maps.conf, so includingstatic-cdn.confwithout a private overlay no longer fails the configuration test.
Disaster recovery
RESTORE_FROM_HOSTselects the hostname whose backups are restored, andRESTORE_S3_ENDPOINTandRESTORE_AWS_PROFILEselect the S3 endpoint and the credentials profile. The bucket, domain and database name remain site-specific values at the top of the script. Without the variables the script restores from the default hostname and endpoint as before; the credentials now come from the deploy account's~/.aws.- After the restore merge, the repository's tracked files are put back to the clone, since the backup's copies can be older.
DR_NESTED_REPOSlists restored checkouts, such as the private overlay, as<dir>=<git url>pairs; the script turns each into a Git repository trackingorigin/masterthat keeps the restored working files, using the restoredprivate/updater_ssh_keyand a pinned GitHub host key, because the backups leave out.git. - An executable
private/scripts/dr-hook.shis called withpre-startbefore the containers start and withpost-dbafter the database import, for site-specific steps. - The script installs the host tools the backup jobs need, sets up the deploy account (uid 1000, passwordless sudo, Docker group, the updater's SSH key) and works without a terminal; the Readme section "Disaster recovery" has the details.
- The database import waits until the final mysqld is running and accepts the root login. On a fresh host the image's temporary initialisation server already answered
mysqladmin ping, so the import started too early and failed withERROR 1045. - The MTU settings for Yandex Cloud DDoS protection apply only on Yandex Cloud; on other hosts the network is left alone.
Backups
- When
BACKUP2_S3_BUCKETis set inbackup.env,file-backup.shalso runs its own duplicity chain against that bucket andmysql-dump.shsyncs the dumps there. A failure at one destination does not stop the other; the run still exits non-zero and leaves the monitoring status file unwritten.
Deploy account
scripts/deploy-user.shresolves the account that owns the checkouts, runs the deploy pulls and keeps the backup credentials in~/.aws, fromDEPLOY_USERin the environment or in.env, withadminas the default. The recovery, permission, pull and backup scripts use it, and the DNS token cron job runs as it throughrunuser.- When that account has uid 1000, the nightly
fix-rights.shalso gives the tracked files, every directory recorded inHEADand.gitof the public and private checkouts to it, setsprivate/environmentsecrets to mode 0600 and the Zabbix agent's MySQL credentials to uid 1997 with mode 0400. Cron and logrotate files stay root-owned and MySQL configuration stays uid 1001. The repair is skipped when the account does not have uid 1000.
Dev renewal
renew-dev.shreads its site-specific values from the environment, with the previous values as defaults, and refuses destinations that overlap production. It now needs GNUrealpath -m, refuses a productiondbconn.phpwhose$DBLoginor$DBNameis not a single quoted literal assignment, and no longer rewrites theskypark.cdnmodule'scdn_domains1; provide that throughPOST_RENEW_HOOKif you need it.
Other changes
update-dns-token.shleavesAUTH_KEYalone when the DNS provider is not Yandex Cloud.- Upload deduplication skips hidden
.*-backupsrollback directories. - The PHPStan triggers carry a
notifytag from the template macro{$PHPSTAN.NOTIFY}, empty by default, so alert actions can route them. Re-import the template and set the macro to the value your actions match.
Upgrade notes
- Before pulling, change the general session handler in the
sessionblock ofbitrix/.settings.phpto'general' => array ('type' => 'save_handler.php.ini')(the Readme has the full example). Move any local override that binds files under/etc/php/8.4/to/etc/php/8.5/. After the pull, with your overlay'sCOMPOSE_PROFILESset:docker compose pull php php-cron && docker compose up -d php php-cron, then test nginx and reload it (docker compose exec nginx nginx -t && docker compose exec nginx nginx -s reload). docker compose up -d --timeout 120 mysqlrecreates mysqld with the newmy.cnfandoom_score_adj; it interrupts the database.- Recreate memcached with
docker compose up -d memcachedfor the 3 GB limit, and check the host has the memory. - nginx reads
nginx.confthrough a file-level bind mount: test the new file in a fresh container as the Readme describes, then restart nginx. - If the host has an account named
adminwith uid 1000, the nextfix-rights.shrun changes the ownership of both checkouts and ofprivate/environmentas described above. If your deploy account has another name, setDEPLOY_USERin.envbefore that run, and make sure that account holds the backup credentials in its~/.awsand, for Yandex Cloud DNS renewal, theycCLI in its home.