Skip to content
This is documentation for version 1.X.X, which may no longer be maintained. Go to the latest version (2.2).

CPalius CMF 1.1.0 'Liman'

Released: 2026-09-14 · Channel: stable · Critical: no

This release is about where files live and how they travel: copying uploads to a remote target, getting backups off the server, serving images through a CDN, and updating a single file without downloading a full package. Hence the name — liman is Turkish for harbour, the place where cargo is held and shipped out.

New

  • Storage targets (AACP → Maintenance → Storage & CDN). Amazon S3, Cloudflare R2 and FTP/FTPS. Every S3-compatible service works through the same driver: MinIO, DigitalOcean Spaces, Backblaze B2. No AWS SDK is installed — requests are signed with SigV4 directly, because ~90 MB of service definitions for three HTTP verbs would be felt on every install of a package that operators upload to shared hosting over FTP.

  • One button: save and test. A target is not used until it has passed a live write probe against exactly the configuration now stored: the probe writes a real file, reads it back and deletes it. A bucket policy that allows listing but denies writes, and a read-only FTP account, both pass every check lighter than this one.

  • Media offload. Uploads are always written to public/uploads and then copied to the selected target. The original stays on this server — thumbnails are generated from disk by GD, the public/uploads/.htaccess hardening does not travel to a bucket with the bytes, and the files backup keeps containing the site's media. If the remote is unreachable the site still serves images from its own disk.

  • Nightly sweep. Collects files whose upload-time push failed, and thumbnails. It works from a cursor: each run continues where the last stopped and wraps to the beginning on completion. This is the setting to turn on when moving an existing site across for the first time. Off by default.

  • Off-site backups. The archive is uploaded after it is written and then read back from the destination to confirm it arrived. With keep the local copy off, the local archive is removed only after that confirmation. Remote retention is configurable; deleting the local and the remote copy are two separate buttons.

  • CDN for images. One setting covers both common setups: the base URL replaces the /uploads part. For a pull zone in front of this origin use https://cdn.example.com/uploads; for a public bucket use https://pub-xxxx.r2.dev. The CDN is independent of offload — a pull zone needs no upload at all.

  • File-level updates (patches). When one file changes, installations in the field can take just that file instead of a forty-megabyte archive. The panel lists every file a patch would replace, and its SHA-256, before it is applied.

  • cp:patch command. Prints the pending patch and its file list; writes nothing. Applying requires --apply, and asks for confirmation on top of that in an interactive session.

Security

  • Patch bodies are fetched only from CPalius-owned addresses, and every file is SHA-256 verified before it is written. If one does not match, not a single byte reaches the project tree — a half-applied patch is a mixture of versions nobody has ever tested.

  • A patch cannot write to cp-includes/vendor, public/uploads, cp-core/var or .env. The rule lives in one place shared with the full updater; a rule kept in two copies eventually diverges, and the diverging side becomes a hole.

  • A patch must ship CpVersion.php, and the downloaded file's constant must state the manifest's version. Without this, a manifest announcing 1.1.1 while shipping 1.1.0 code would apply, leave the running version where it was, and be offered again on every check forever.

  • No patch is ever applied on its own. There is no code path from the cron check to the installer; a CSRF-protected form or a deliberate command is required. Auto-applying would mean whoever controls the CPalius GitHub organisation controls every installation in the field without an operator in the loop.

  • Storage credentials are stored encrypted in cp_settings (SettingSecretCodec). The screen never renders a secret back; an empty password field means "leave the stored value alone".

Fixes

  • Upload URLs are now produced in one place. They were written out at six separate call sites as '/uploads/'.$key; a CDN is the first situation in which that answer stops being the same everywhere.

  • cp:backup:create now returns a non-zero exit code when the off-site copy fails. A command run from crontab that reports success while the backup never left the server sells its operator a year of not looking.

Breaking changes

None. No default changes behaviour: storage targets, the nightly sweep and the CDN all ship switched off. Install this release and touch nothing, and the site behaves exactly as it did on 1.0.0.

Upgrade notes

  • Upgrading from 1.0.0 needs no extra step. There is no schema change; the new settings are created the first time they are written.
  • On a live server, cp-core/var/cache/prod/ must be emptied. Symfony does not rebuild the compiled container on its own in prod, so new services and the new cron job stay invisible until the cache is cleared.
  • Updating from the panel does this for you.

Known limitations

  • The FTP target requires ext-ftp. Where the extension is missing, the card says so up front.
  • A patch cannot write into cp-includes/vendor. A change that needs a new dependency requires a full release.
  • Patches apply as a chain: the panel only offers the patch that upgrades from the running version. Intermediate versions cannot be skipped.
  • Remote-primary storage — the original living only in the bucket — is not in this release. The remote target is always a copy.
Last updated: 16.10.2026