Getting started
Backend installation
This guide installs on a plain server. With Docker, follow Docker Deployment instead; the installer step is the same.
Requirements
- PHP 8.4 with the extensions
ctype,iconv,intl,mbstring,pdo_mysql,gd(built with WebP) andzip;exifandapcuare recommended. - MySQL 8.
- Composer 2 and Node 22 (only to build; not needed at runtime).
- A web server pointing at
public/: Caddy or FrankenPHP, nginx with PHP-FPM, or Apache. - A process manager (systemd or Supervisor) for the worker.
Steps
git clone <repository> classifieds && cd classifieds
composer install --no-dev --optimize-autoloader
npm ci && npm run build
Set the environment as real variables of the web server and the worker (not in a file under the project):
| Variable | Value |
|---|---|
APP_ENV | prod |
APP_DEBUG | 0 |
APP_SECRET | a long random string (openssl rand -hex 32); also signs the app's sign-in tokens |
DATABASE_URL | mysql://user:password@host:3306/database?serverVersion=8.0.30&charset=utf8mb4 |
MESSENGER_TRANSPORT_DSN | doctrine://default?auto_setup=0 |
MAILER_DSN | your email provider, e.g. mailgun+api://KEY:DOMAIN@default?region=eu |
SEND_EMAIL | 1 |
SEARCH_FULLTEXT | optional, 1 by default: the search box uses the database's full-text index on titles (MySQL 8 or MariaDB 10.6+). Set 0 only on a database without full-text search; it then scans titles, which is slower on large sites. |
SENTRY_DSN | optional |
FB_ID, FB_SECRET | optional, Facebook sign-in |
EXPO_DSN | optional, push notifications |
Then run the installer:
php bin/console app:install
It checks the server, creates the tables, asks for the platform name, public address, country, language, currency, support email and the first admin, adds the terms and privacy pages and imports the country's regions and localities. Add --template=general (or another marketplace template, Platform Configuration) to start with a full catalogue, and --demo for sample content. For scripted installs pass the answers as options:
php bin/console app:install --no-interaction \
--name="Velo Market" --url=https://velo.example.com --country=RO --locale=ro --currency=RON \
--support-email=help@velo.example.com --admin-email=owner@velo.example.com --admin-password='...'
The worker
[program:classifieds-worker]
command=php /srv/app/bin/console messenger:consume async scheduler_default --time-limit=3600 --memory-limit=256M
directory=/srv/app
user=www-data
autostart=true
autorestart=true
stopwaitsecs=30
Without it no email or push leaves and the daily jobs never run (see scheduled-jobs.md).
Web server
Point the document root at public/, send every request that is not a file to public/index.php, compress responses, and cache /build/* and /uploads/* for a year (Cache-Control: public, max-age=31536000, immutable); their file names change whenever their content does. docker/production/Caddyfile is a complete example.
First sign-in
Open https://your-domain/admin and sign in with the admin from the installer, then continue with Platform Configuration.
Found a mistake? Tell us.