jcergolj / metator-for-laravel
Laravel package that installs Deployer deployment scaffolding into an application.
Package info
github.com/jcergolj/metator-for-laravel
Language:Shell
pkg:composer/jcergolj/metator-for-laravel
Requires
- php: ^8.2
- deployer/deployer: ^8.0
- illuminate/console: ^12.0 || ^13.0
- illuminate/filesystem: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
- laravel/prompts: ^0.3
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- v5
- v4
- v3
- v2
- v1
- dev-issue-106-deployer-capability-checks
- dev-issue-105-scaffolding-upgrade-guide
- dev-issue-104-deployer-interface-docs
- dev-issue-99-redis-site-isolation
- dev-issue-99-sqlite-extension-check
- dev-issue-83-sqlite-noop
- dev-issue-84-caddy-readiness
- dev-issue-85-permissions-noop
- dev-issue-86-ssh-order
- dev-issue-87-mariadb-rerun
- dev-issue-88-environment-noop
- dev-issue-90-preparation-noop
- dev-issue-90-base
- dev-fix/worker-sudoers-reruns
- dev-feat/optional-node-capability
- dev-fix/provisioning-confirmation
- dev-fix/provisioning-review
- dev-fix/activate-caddy-preparation
- dev-fix/verify-composer-preparation
- dev-fix/prepare-server-php-fpm
- dev-issue-60-release-gate-os-matrix
- dev-issue-51-refactor
- dev-issue-59-ubuntu-2604-support
- dev-issue-37-release-gate
- dev-issue-34-reconcile-disabled
- dev-issue-33-site-workers
- dev-issue-32-deployer-integration
- dev-issue-36-custom-steps-dns
- dev-issue-12-caddy-routing
- dev-agent/issue-35-environment
- dev-agent/issue-31-scheduler
- dev-agent/issue-30-redis
- dev-feat/29-local-mariadb
- dev-feat/28-github-deploy-key
- dev-feat/27-owned-sqlite-site
- dev-feat/26-ubuntu-php-baseline
- dev-feat/25-remote-provisioning
- dev-feat/minimal-deployer-recipe
- dev-feat/provisioning-behavioral-ci
- dev-feat/local-site-configuration
- dev-fix/9-production-environment-generation
- dev-fix/remaining-installation-bugs
- dev-fix/queue-worker-timeout
- dev-fix/preserve-dotenv-secrets
- dev-fix/restart-workers-in-scaffolding
This package is auto-updated.
Last update: 2026-09-26 09:07:51 UTC
README
Metator installs deployment scaffolding for Laravel applications. It combines Deployer with a metadata-driven server bootstrap pipeline.
Metator can prepare:
- PHP-FPM and CLI
- Caddy and optional Cloudflare DNS
- SQLite or site-owned local MariaDB
- Redis cache and runtime databases
- Scheduler and optional queue or Horizon workers
- GitHub deploy-key access
Metator prepares infrastructure. You run Deployer separately to release the application.
Requirements
Before installation, provide:
- A Laravel application with
.env.example - PHP 8.2 or newer locally
- Composer
- An already secured Ubuntu server
- Noninteractive SSH access with administrative
sudo - Git, Composer, PHP-FPM, systemd, and
sudoon the server
The supported server baseline is Ubuntu 24.04 with PHP 8.4 or 8.5. Basic OS hardening and operator SSH access are outside Metator's scope.
Quick Start
Install the package in your Laravel application:
composer require --dev jcergolj/metator-for-laravel php artisan metator:install
The installer creates:
metator.<name>.php: non-secret site configurationdeploy.php: editable Deployer recipescripts/: selected server bootstrap pipeline- A copy of the application's
.env.example
Then prepare, provision, and deploy:
php artisan metator:prepare-server --config=metator.production.php php artisan metator:provision --config=metator.production.php vendor/bin/dep deploy production
Provisioning does not deploy application code. Register the generated read-only GitHub deploy key when provisioning requests it.
Installation Choices
metator:install asks for the settings needed by one site:
- Site ID
- Repository and deployment branch
- SSH host and deployment user
- Domain
- PHP version
- SQLite or local MariaDB
- Redis, scheduler, and worker capabilities
- Deployment steps
The site ID is immutable and identifies the remote resources. It is not the repository name, domain, filename, or local checkout name.
The generated site configuration contains no secrets. Cloudflare credentials, when needed, are stored separately in an untracked local companion file.
Use --force only when deliberately regenerating an existing installation:
php artisan metator:install --force
Within scripts/steps/, forced regeneration replaces or removes only files
tracked in scripts/.metator-manifest.json. Untracked custom step files are
preserved.
Updating an existing installation
metator:install exits with an error if the selected site configuration already
exists, unless --force is supplied. In other cases, existing generated output
files are skipped without --force. Forced regeneration replaces the selected
site configuration, the generated deploy.php, bootstrap libraries and
instructions, and scripts/.env.example. Back up and compare customized
deploy.php content before restoring or merging application-specific tasks.
The selected-step manifest controls replacement of generated
scripts/steps/*.sh files. The package manifest controls updates to package-owned
files in metator/steps/; custom files in that local catalogue are preserved and
can be selected again. A forced install with Cloudflare deselected removes the
local metator.<name>.local.php companion file, so save any credentials you
still need before changing that selection.
For a deliberate scaffold upgrade:
- Back up the site configuration, local secret companion file, customized
deploy.php, custommetator/steps/files, and.env.production.local. - Update the package and run
php artisan metator:install --force, keeping the same configuration name and site ID for the existing site. - Compare the regenerated
deploy.phpwith the backup and merge required release-specific tasks. Confirm custom steps and local environment values are present before continuing. - Run
metator:prepare-serveronly if the shared baseline needs a capability or repair; then runmetator:provision --config=...for the selected site. - Review the readiness summary and run
vendor/bin/dep deploy productionseparately. Scaffolding installation itself makes no remote changes.
Forced regeneration changes local scaffolding only. Shared preparation, provisioning, and application deployment remain separate operator-run actions.
Server Workflow
Run the commands in this order:
- Install the local scaffolding.
- Prepare the shared server baseline when needed.
- Provision the selected site.
- Register the GitHub deploy key.
- Deploy the application with Deployer.
- Verify the URL, database, scheduler, and workers selected for the site.
prepare-server installs shared packages and capabilities. provision creates
only the selected site's resources and reuses the prepared baseline.
Who owns each operation
| Operation | Responsibility |
|---|---|
metator:prepare-server |
Prepare shared server capabilities such as PHP, Redis, Caddy, and Supervisor when the server needs them. |
metator:provision |
Configure the selected site's ownership, database and Redis allocations, GitHub access, web route, scheduler, worker program, permissions, custom steps, and readiness. It does not deploy application code. |
vendor/bin/dep deploy production |
Run the Laravel release lifecycle: fetch code, install Composer dependencies, migrate, optimize/cache, activate the release, clean old releases, and activate or restart only the selected site's workers. It does not prepare or provision the server. |
The generated deploy.php reads the selected site configuration for the site
identity, repository, SSH target, deployment user and path, PHP runtime, database
mode, and worker mode. The operator keeps the recipe editable for branch choice,
application builds, and other release-specific tasks. Metator's bootstrap
scripts remain responsible for infrastructure and site-owned resources.
The remote commands:
- Upload the exact local
scripts/directory - Use a fresh, site-owned staging directory
- Stream remote output locally
- Return the remote exit status
- Do not read from remote stdin
If SSH disconnects, inspect the server before retrying. The remote operation may have completed.
Deploying
Review deploy.php before the first deployment. It reads the selected site
configuration for the repository, SSH target, deployment path, PHP binary,
database mode, and worker lifecycle.
Deploy with:
vendor/bin/dep deploy production
The generated recipe verifies the provisioned PHP runtime before making release changes. It supports no workers, queue workers, or Horizon.
Custom deployment scripts
Add application-specific release work to the editable deploy.php. Define a
task, then attach it to a Deployer lifecycle task:
task('deploy:build-assets', function (): void { run('cd {{release_path}} && npm ci'); run('cd {{release_path}} && npm run build'); }); after('deploy:vendors', 'deploy:build-assets');
Use:
{{release_path}}for files in the new release{{bin/php}}for the configured PHP binary- A hook before
deploy:symlinkfor required release files
For Tailwind:
task('deploy:build-tailwind', function (): void { run('cd {{release_path}} && {{bin/php}} artisan tailwindcss:download --force'); run('cd {{release_path}} && {{bin/php}} artisan tailwindcss:build --prod --no-tty'); }); after('deploy:vendors', 'deploy:build-tailwind');
If the Tailwind binary is already installed on the server, omit the download command. A failed task stops deployment before the new release is symlinked.
Verify generated files in the release directory:
test -f /var/www/<site-id>/releases/<release>/public/.tailwindcss-manifest.json find /var/www/<site-id>/releases/<release>/public/dist/css -name 'app-*.css' -type f
Keep deployment tasks in deploy.php. Do not add release commands to the
Metator server bootstrap scripts.
Custom Server Steps
Custom server steps are shell files in metator/steps/. Publish the catalogue
first if you want to inspect or edit the built-in steps:
php artisan vendor:publish --tag=metator-steps
Each custom step needs metadata and a matching function:
# @id: install-imagemagick # @title: Install ImageMagick # @group: none # @required: false # @default: false # @order: 65 step_install_imagemagick() { sudo apt-get install -y imagemagick }
Metadata rules:
@id: lowercase letters, numbers, and single hyphens@title: label shown by the installer@group: exclusive group, ornone@required:trueorfalse@default:trueorfalse@order: non-negative execution order
Available variables and helpers include APP_FOLDER, DOMAIN, PHP_VERSION,
PHP_PACKAGE_PREFIX, sudo, ok, warn, and die.
Custom steps must return a nonzero status on failure. The pipeline stops and reports the failed operation. Correct the step and rerun provisioning.
After adding a step:
php artisan metator:install
Select the custom step during installation. The generated scripts/steps/
directory is copied to the server and should not be edited there.
Optional Services
Web server
Caddy is the default web server and manages public HTTPS. Before provisioning:
- Point DNS to the server
- Allow inbound HTTP and HTTPS
- Ensure the configured domain resolves correctly
To use Nginx instead, add an Nginx step to metator/steps/ with the
web-server group, then select it and deselect Configure Caddy. Only one
web-server step may be selected.
Cloudflare DNS
Cloudflare DNS is optional. Leave Configure Cloudflare DNS unchecked when you do not want API credentials or DNS API calls.
Cloudflare does not replace Caddy. The web server and DNS choices are separate.
Workers and scheduler
Select only the capabilities used by the application:
- No workers
- Standard queue workers
- Horizon
- Scheduler
Worker and scheduler configuration is scoped to the site. Unrelated sites are not restarted when one site changes.
Multiple Sites
Multiple sites may use the same repository. Give each site a unique site ID.
For every site:
- Create a separate
metator.<name>.php - Use a unique site ID
- Register its generated GitHub deploy key
- Select its PHP, database, Redis, worker, and scheduler settings
- Provision and deploy separately
Prepare the server again only when a new shared capability is needed. Existing sites keep their configuration, credentials, data, deploy keys, and running work.
Updating Environment Values
Before the first deployment, review the generated scripts/.env.example for
application-specific production values. Provisioning initializes the remote
environment noninteractively and reports that review guidance locally; it does
not open an editor or wait for input on the server.
Put application-specific production values in a Git-ignored local dotenv file:
php artisan metator:update-env \ --config=metator.production.php \ --input=.env.production.local
Metator preserves its managed identity, runtime, database, Redis, and key values. It does not refresh Laravel's cached configuration or restart workers; use the normal Deployer and application lifecycle for those actions.
Retries and Changes
An unchanged provisioning rerun verifies existing resources without:
- Rotating credentials or keys
- Rewriting configuration
- Reloading shared services
- Restarting unrelated workers
- Duplicating cron entries
If provisioning fails, it returns a nonzero status and does not report the site as ready. Existing site-owned resources are preserved for recovery.
Metator rejects unmanaged ownership conflicts and ordinary PHP or database engine changes. Resolve those explicitly instead of deleting site data.
Troubleshooting
Missing shared capability
Run metator:prepare-server for a configuration that selects the capability,
then rerun metator:provision.
Provisioning failed
Use the step summary and remote error as the source of truth. Inspect the server before retrying.
Ownership conflict
Keep the existing resource unchanged. Resolve the site ID or conflicting managed resource manually; Metator will not adopt unmarked resources.
HTTPS unavailable
Check DNS and inbound HTTP/HTTPS access. Caddy obtains the certificate only when the configured domain resolves correctly.
Deployment failed
Review:
deploy.php- GitHub deploy-key registration
- The selected PHP binary
- The application's
.env - Custom deployment tasks
Provisioning and deployment are separate operations, so rerun Deployer after fixing the deployment issue.
Resource Ownership
Metator manages site-owned resources including:
- Site directory and metadata
- Shared environment
- Database and MariaDB credentials
- Redis allocations
- GitHub deploy key and SSH block
- Caddy route
- Scheduler entry
- Worker configuration
Metator does not provide a full uninstall command or delete site data. Stop the site lifecycle, archive required data, confirm no other site uses the resources, and remove them manually. Shared PHP, MariaDB, Redis, cron, Supervisor, and Caddy services remain in place.