Skip to content
Shortspan

Search documentation

Find a page by title, section, or summary.

Installation

From a clean host to a serving deployment, including the two keys you must generate before anyone signs up.

1. Get the code

bash
git clone https://github.com/shortspan/shortspan.git
cd shortspan
composer install --no-dev --optimize-autoloader
npm ci && npm run build

Node is needed for the build only. The built assets go into public/build; no Node process runs in production.

2. Generate the two keys

Do this before anyone signs up. Both keys are permanent decisions.

bash
cp .env.example .env

php artisan key:generate                 # APP_KEY - sessions and cookies
php artisan encryption:generate-key      # SHORTSPAN_MASTER_KEY - the secret store

While you are here, set PASSKEYS_USER_HANDLE_SECRET explicitly. It defaults to APP_KEY, which couples passkey identity to a key you should be able to rotate.

3. Configure

.env
APP_NAME=Shortspan
APP_ENV=production
APP_DEBUG=false
APP_URL=https://shortspan.example.com

DB_CONNECTION=pgsql
DB_HOST=…
DB_DATABASE=shortspan
DB_USERNAME=…
DB_PASSWORD=…

QUEUE_CONNECTION=database
CACHE_STORE=database
SESSION_DRIVER=database

MAIL_MAILER=resend
RESEND_API_KEY=…
MAIL_FROM_ADDRESS=noreply@shortspan.example.com

TRUSTED_PROXIES=…

DOCS_DOMAIN=docs.shortspan.example.com
DOCS_URL=https://docs.shortspan.example.com

Every variable is documented in Configuration reference. APP_DEBUG=true in production will leak configuration in stack traces, so check it.

4. Migrate

bash
php artisan migrate --force

Creates the schema and backfills state for anything that needs it. On a fresh install there is nothing to backfill; on an upgrade there may be - see Upgrading.

5. Serve it

Point your web server at public/. A minimal nginx server block:

nginx
server {
    listen 443 ssl http2;
    server_name shortspan.example.com;
    root /srv/shortspan/public;

    index index.php;

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

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

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

Serving the documentation on its own hostname means a second server block with the same root and a server_name matching DOCS_DOMAIN. The application routes by hostname; nothing else differs.

6. Start the worker and the scheduler

Neither is optional, and both fail silently. Run the worker under a supervisor:

/etc/supervisor/conf.d/shortspan-worker.conf
[program:shortspan-worker]
command=php /srv/shortspan/artisan queue:work --tries=3 --timeout=90
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/log/shortspan-worker.log
stopwaitsecs=3600
crontab -u www-data -e
* * * * * cd /srv/shortspan && php artisan schedule:run >> /dev/null 2>&1

7. Cache the configuration

bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

8. Create a platform administrator

bash
php artisan shortspan:grant-platform-admin you@example.com --role=super

The control plane is at /admin, with its own login separate from the customer one. Being a workspace owner grants nothing there.

9. Verify

  1. 01

    Load the application over HTTPS and sign up. Onboarding should complete cleanly.

  2. 02

    Check that the verification email arrived. If not, the queue worker or the mail transport is the problem.

  3. 03

    Store a secret and read it back. That exercises the whole encryption path.

  4. 04

    Point the CLI at your host with shortspan config set api_host and run shortspan login.

  5. 05

    Open the control plane and check the operations page - every health probe should be green, and the scheduler heartbeats should be recent.

  6. 06

    Confirm audit entries record real client addresses, not your proxy's. If they do not, TRUSTED_PROXIES is wrong.

Something here wrong or missing? Tell us.