Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Capsule Laravel Package

dgtlss/capsule

Capsule is a Laravel package for organizing your application into self-contained modules. It provides a clean structure for routes, migrations, views, and classes, making large codebases easier to navigate, reuse, and maintain.

View on GitHub
Deep Wiki
Context7

Getting Started

Capsule 3.0.0 is a Laravel backup package built around artisan commands and a published config file. The upgrade is significant: it drops Laravel 10/11 and PHP 8.1, so confirm your matrix before installing.

1. Check the platform first — this is the most common reason an install fails on v3:

php -v                      # 8.2+ for Laravel 12, 8.3+ for Laravel 13
php -m | grep -E 'zip|sodium|zlib|pdo_sqlite|sqlite3'

zip, sodium and zlib are required. pdo_sqlite is needed to back up and validate SQLite databases; sqlite3 is additionally needed to restore them. AES-encrypted ZIP support depends on the underlying libzip build — verify with a throwaway encrypted ZIP if you rely on that format.

2. Install and publish:

composer require dgtlss/capsule
php artisan vendor:publish --tag=capsule-config

3. Configure a destination and a password. Put the password in your secret manager or environment, not in config/capsule.php:

// config/capsule.php (shape will vary — read the published file)
'destination' => [
    'disk' => 's3-backups',
    'path' => 'capsule',
],
'encryption' => [
    'enabled'  => true,
    'password' => env('CAPSULE_PASSWORD'),
],

4. Run your first backup and, more importantly, your first restore. The single habit that matters with this package is proving recovery works before you need it:

php artisan backup:run --no-local --encrypt
php artisan backup:list
php artisan backup:restore --list
php artisan backup:restore --dry-run

Where to look first: the published config for destination/retention/encryption keys, php artisan backup:run --help for the option set on your exact version, and the README section on encrypted streaming recovery. Treat the release notes' "encrypted streaming recovery" block as required reading — .capsule.enc files are not ZIPs and cannot be opened by ordinary archive tools.

First real use case: a nightly encrypted streaming backup to object storage, paired with a weekly scheduled restore into a scratch database.

Implementation Patterns

Scheduled encrypted streaming backup. Register the schedule and keep the local footprint small:

// routes/console.php (Laravel 11+) or app/Console/Kernel.php
Schedule::command('backup:run --no-local --encrypt')
    ->dailyAt('02:30')
    ->withoutOverlapping()
    ->onFailure(function () {
        // alert
    });

Schedule::command('backup:clean')
    ->dailyAt('04:00');

--no-local avoids writing a complete backup archive on the application server, which is the main operational win for large datasets. --encrypt encrypts contents, filenames, manifests and temporary remote chunks.

Keep full and incremental archives together. Incrementals are now checksum-bound to a base archive and record deletions. If you split fulls and incrementals across different disks, prefixes or retention buckets, you break the chain. Use one prefix per backup set and let cleanup run against that prefix.

Restore workflow, in order. Never restore blind:

  1. backup:restore --list — see what is actually in the archive, including the preserved root directory layout.
  2. backup:restore --dry-run — exercise path resolution and validation without touching the destination.
  3. Restore to a staging path or scratch database first.
  4. Only then restore in place.

New-format restores preserve named or numbered file-root directories. If your archive was taken of /var/www/app, expect the restored tree to carry that root rather than flattening — inspect with --list and plan your rsync/move step accordingly.

Disaster recovery with standalone decryption. vendor/bin/capsule-decrypt recovers an encrypted streaming archive without the original Laravel application or backup catalog, which makes it viable for a break-glass runbook:

vendor/bin/capsule-decrypt backup.capsule.enc --output backup.zip
unzip -l backup.zip   # inspect before extracting

Store the password and a compatible Capsule installation (or a container image containing it) separately from the application it backs up. If your app host, its secrets and its backup tooling all live in the same account, you have no recovery path for the failure mode that matters most.

Handle the decrypted ZIP as sensitive. Decryption produces plaintext. Decrypt into a temp directory with restrictive permissions, extract, then shred the ZIP. Do not leave decrypted archives on shared build agents or in CI artifacts.

Monitor by exit code and inventory, not vibes. Alert on non-zero exit from backup:run, and separately on "no archive newer than N hours" from backup:list. A silent scheduler and a successful scheduler look identical until you check inventory.

Exercise the pipeline in CI. A cheap job that runs backup:run --no-local --encrypt against a seeded SQLite database, then capsule-decrypt and backup:restore --dry-run, catches missing extensions, libzip AES gaps and manifest regressions before they reach production.

Gotchas and Tips

  • Breaking platform change. Laravel 10/11 and PHP 8.1 are no longer supported. Plan the framework/PHP bump as part of the upgrade, not after it.
  • Extension drift. A dev machine that has sodium and a production container that doesn't will only reveal itself at backup time. Assert required extensions in your deploy healthcheck.
  • .capsule.enc is not a ZIP. Zip tools, archive managers and naive integrity checks will fail on it. Any runbook or monitoring script that assumes ZIP must branch on the extension.
  • --no-local is not zero-disk. It avoids a complete local backup archive, but SQLite snapshots and filesystem adapters still use temporary storage. Size /tmp and any configured temp path accordingly, or large databases will fail mid-run.
  • Changing the password or encryption settings resets incrementals. Older snapshot metadata or modified encryption settings cause the next incremental to start a fresh full base. That's safe but surprising: your storage usage and backup window will jump after a rotation. Rotate deliberately, and don't delete the previous base until the new chain has a verified restore.
  • Restore layout changed in v3. Named/numbered file-root directories are now preserved. Scripts that assumed a flattened restore will silently write to a different path. Always --list and --dry-run first.
  • Older ZIP formats are second-class. Standard AES-encrypted ZIP backups and historical ZIP recovery remain available, but they carry their documented checksum and deletion limitations. Don't assume v3-grade restore validation applies to pre-v3 archives — keep them and verify them with the tooling of their era.
  • Validation happens before mutation — lean on it. v3's stronger checks (paths, manifests, checksums, encrypted entries, incremental bases) run before destination data changes. A failed restore therefore tells you something useful; read the error rather than retrying blindly.
  • Debugging a failed restore: confirm the archive and its base are both present, confirm the password matches the one used at backup time, run backup:list to check the manifest is readable, and try capsule-decrypt in isolation to separate decryption failures from restore-placement failures.
  • Extension points: custom filesystem adapters and destination disks are the usual integration surface; notification/alerting is the other. Wrap them so a backup failure raises a signal outside the Laravel app — a dead app cannot report its own backup failure.
  • Recovery dependencies are part of the backup. Password managers, container images and Capsule versions used for restore must be escrowed independently of the application being backed up. Test the full break-glass path at least once per quarter.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo