Cogeze
Guide

Deployment

Production build, caching, the route cache trap, queue workers, and web server setup.

Build#

bash
composer install --no-dev --optimize-autoloader
yarn install --frozen-lockfile
yarn build

php artisan migrate --force
php artisan storage:link
php artisan config:cache
php artisan view:cache
php artisan event:cache

The route cache#

bash
php artisan route:cache

This is safe — public routes use an invokable controller, not closures, so they cache correctly. The risk is staleness, not failure.

Once routes are cached, the routes the Hub generates at boot are frozen. If an administrator then changes a URL in route_map:

  • the old URL keeps returning 200
  • the new URL returns 404
  • nothing is logged

Cogeze handles this: every operation that changes routing structure bumps the route map's version counter and deletes Laravel's route cache file. The next request re-registers routes — slightly slower, but correct. Run route:cache again on your next deploy.

If you script deploys, do not restore a route cache file from a build artifact after an administrator has edited URLs.

Optimisation summary#

Command Safe to cache Notes
config:cache Yes Re-run after any .env change.
view:cache Yes
event:cache Yes
route:cache Yes, with the caveat above Cleared automatically when URLs change.
optimize Yes Runs the above together.

Queue worker#

bash
php artisan queue:work --tries=3 --max-time=3600

Run it under a supervisor (systemd, supervisord, or your platform's process manager). --max-time lets the process exit periodically so a deploy picks up new code.

Scheduler#

* * * * * cd /path/to/app && php artisan schedule:run >> /dev/null 2>&1

Required for token pruning and any plugin that schedules work.

Web server#

Point the document root at public/. Standard Laravel configuration applies.

nginx
server {
    listen 80;
    server_name example.com;
    root /var/www/cogeze/public;

    index index.php;
    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Note the catch-all: the Hub serves pages at arbitrary paths, including single-segment URLs such as /about. try_files … /index.php is what lets that work.

Production checklist#

Setting Value Why
APP_DEBUG false With debug on, a failing optional need returns 500 instead of degrading.
APP_ENV production
CACHE_STORE redis The route map and page needs are read on every request.
SESSION_DRIVER redis or database
SANCTUM_STATEFUL_DOMAINS the production host Otherwise admin login returns 419.
storage/ and bootstrap/cache/ writable
Queue worker running Otherwise queued mail and media jobs never run.

Verifying a deploy#

bash
php artisan route:list --path=api/admin | head        # admin API is up
curl -o /dev/null -w '%{http_code}\n' https://example.com/          # storefront
curl -o /dev/null -w '%{http_code}\n' https://example.com/nope      # themed 404
curl -o /dev/null -w '%{http_code}\n' https://example.com/api/admin/plugins   # 401, not 500

The last one is worth checking explicitly. A guest request to an admin API endpoint must return 401 regardless of the Accept header — a 500 there means the authentication layer is misconfigured and is masking an auth failure as a server error.

No storefront installed#

If no plugin claims /, the core serves a minimal page with HTTP 503. That is deliberate: missing configuration is not content, and a 200 would tell search engines the empty page is the site.