--- name: oro-devops description: OroCommerce DevOps and infrastructure reference covering system requirements, installation, deployment, Docker, cron setup, Supervisor, monitoring, caching, environment configuration, CI/CD, and performance optimization. Use when setting up local dev environments, configuring CI/CD, debugging deployment issues, or planning infrastructure. For OroCloud-specific operations (production deployment, upgrades, backups), see the oro-cloud skill. --- # OroCommerce DevOps Infrastructure, deployment, and operations reference for OroCommerce. Docs: https://doc.oroinc.com/backend/setup/ **Note:** Production runs on OroCloud Enterprise. For cloud deployment, upgrades, backups, and maintenance commands, see the `oro-cloud` skill. This skill covers local dev, CI, and general infrastructure concepts. ## System Requirements ### Minimum Server - 2 CPU cores, 2GB RAM, SSD - Linux recommended (RHEL, Ubuntu, Debian, Oracle Linux) ### Software Stack | Component | Version | Notes | |---|---|---| | PHP | >= 8.4 | CLI + FPM | | PostgreSQL | >= 16.1 | with uuid-ossp extension | | Nginx or Apache | latest | Nginx recommended | | Node.js | >= 22 | asset build only | | NPM | > 10 | asset build only | | Redis | 7.2.x | cache + sessions (recommended) | | Elasticsearch | >= 8.4.1, < 9.0 | EE only | | RabbitMQ | 3.12.x | EE only | | Supervisor | latest | MQ consumer daemon | | Gotenberg | >= 8.5 | PDF generation (optional) | ### Required PHP Extensions ctype, curl, fileinfo, gd, intl (ICU >= 4.4), json, mbstring, sodium, openssl, pgsql, pcre, simplexml, tokenizer, xml, zip, imap, soap, bcmath, ldap, mongodb (for GridFS) ### PHP Settings ```ini date.timezone = UTC detect_unicode = Off memory_limit = 1G ; Increase for schema updates: max_execution_time = 300 ``` ## Environment Configuration Oro uses `.env-app` and `.env-app.local` for environment variables: ```bash ORO_ENV=prod ORO_SECRET= ORO_DB_URL=postgres://user:pass@localhost:5432/oro_db?sslmode=disable&charset=utf8&serverVersion=17 ORO_MQ_DSN=amqp://user:pass@localhost:5672/%2f # or dbal: for CE ORO_SEARCH_URL=elastic-search://localhost:9200 # EE only ORO_REDIS_URL=redis://localhost:6379 ORO_REDIS_CACHE_DSN=redis://localhost:6379/1 ORO_REDIS_DOCTRINE_DSN=redis://localhost:6379/2 ORO_REDIS_LAYOUT_DSN=redis://localhost:6379/3 ORO_SESSION_DSN=redis://localhost:6379/0 ORO_MAILER_DSN=smtp://localhost:1025 ORO_WEBSOCKET_SERVER_DSN=//0.0.0.0:8080 ORO_WEBSOCKET_FRONTEND_DSN=//*:8080/ws ORO_WEBSOCKET_BACKEND_DSN=tcp://127.0.0.1:8080 ``` ## Installation ```bash # Install dependencies composer install --prefer-dist --no-dev --optimize-autoloader # Install application (creates DB schema, loads fixtures, builds assets) php bin/console oro:install --env=prod \ --organization-name="My Org" \ --user-name=admin \ --user-email=admin@example.com \ --user-firstname=Admin \ --user-lastname=Admin \ --user-password= \ --application-url=https://app.example.com \ --timeout=3600 ``` Verify requirements: `php bin/console oro:check-requirements -vv` ## Deployment Steps ```bash # 1. Pull code git pull origin main # 2. Install dependencies composer install --prefer-dist --no-dev --optimize-autoloader # 3. Run migrations php bin/console oro:migration:load --env=prod # 4. Update extended entity schema php bin/console oro:entity-extend:update-schema --env=prod # 5. Clear and warmup cache php bin/console cache:clear --env=prod php bin/console oro:entity-extend:cache:warmup --env=prod # 6. Build assets php bin/console oro:assets:build --env=prod # 7. Update cron definitions php bin/console oro:cron:definitions:load --env=prod # 8. Restart consumers supervisorctl restart oro-consumer:* ``` ## Cron Setup Single system crontab entry runs Oro's dispatcher every minute: ```crontab */1 * * * * www-data /usr/bin/php /var/www/oro/bin/console oro:cron --env=prod > /dev/null ``` The `oro:cron` command dispatches scheduled commands to the MQ. ## Message Queue Consumers Use Supervisor to keep MQ consumers running: ```ini # /etc/supervisor/conf.d/oro-consumer.conf [program:oro-consumer] command=/usr/bin/php /var/www/oro/bin/console oro:message-queue:consume --env=prod --memory-limit=512 process_name=%(program_name)s_%(process_num)02d numprocs=2 autostart=true autorestart=true startsecs=5 user=www-data redirect_stderr=true stdout_logfile=/var/log/oro/consumer_%(process_num)02d.log ``` Scale `numprocs` based on MQ load. ## WebSocket Server For real-time notifications: ```ini [program:oro-websocket] command=/usr/bin/php /var/www/oro/bin/console gos:websocket:server --env=prod autostart=true autorestart=true user=www-data ``` ## Docker ### Two Docker Compose Patterns **Pattern 1: Backing services only (CI / DDEV / local PHP)** docker-compose.yml at project root provides only infrastructure services. App runs on host or via DDEV/Symfony CLI: ```yaml services: pgsql: image: oroinc/pgsql:17.4-alpine ports: ['5432'] environment: POSTGRES_USER: oro_db_user POSTGRES_DB: oro_db POSTGRES_PASSWORD: oro_db_pass volumes: - postgres:/var/lib/postgresql/data healthcheck: test: "pg_isready -U$${POSTGRES_USER} -d$${POSTGRES_DB}" interval: 5s timeout: 30s start_period: 40s redis: image: redis:7.4.2-alpine ports: ["6379"] elasticsearch: image: elasticsearch:8.17.4 command: bin/elasticsearch -Eingest.geoip.downloader.enabled=false environment: discovery.type: "single-node" xpack.security.enabled: "false" ES_JAVA_OPTS: -Xms2g -Xmx2g rabbitmq: image: oroinc/rabbitmq:3.13.7-alpine ports: ['5672'] mongodb: image: mongo:8.0.4 ports: ["27017"] mailcatcher: image: schickling/mailcatcher ports: ['1025', '1080'] ``` **Pattern 2: Full stack (PHP-FPM + Nginx) for team/staging-like dev** Separate docker-compose in `.docker/` with app container, nginx reverse proxy, Xdebug: ```yaml services: oro: build: context: ./php dockerfile: ./Dockerfile-6.1 environment: COMPOSER_AUTH: '{"github-oauth": {"github.com": "${GITHUB_TOKEN}"}}' XDEBUG_SESSION: PHPSTORM PHP_IDE_CONFIG: "serverName=localdev.example.com" volumes: - ../:/usr/share/nginx/html nginx: image: nginx:stable-alpine ports: ["8280:80", "2443:443"] depends_on: [oro] volumes: - ../public:/usr/share/nginx/html/public - ./nginx/default.conf.template:/etc/nginx/templates/default.conf.template:ro postgres: image: postgres:16-alpine ports: ['25432:5432'] volumes: - ./postgres/create_uuid-ossp_ext.sql:/docker-entrypoint-initdb.d/create_uuid-ossp_ext.sql rabbitmq: build: context: . dockerfile_inline: | FROM rabbitmq:3.12-management-alpine RUN wget -O $RABBITMQ_HOME/plugins/rabbitmq_delayed_message_exchange-3.12.0.ez \ https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.12.0/rabbitmq_delayed_message_exchange-3.12.0.ez && \ rabbitmq-plugins enable --offline rabbitmq_delayed_message_exchange ports: ['25672:15672'] ``` Notes: - PostgreSQL requires `uuid-ossp` extension. Init script: `CREATE EXTENSION IF NOT EXISTS "uuid-ossp";` - RabbitMQ delayed message exchange plugin is required for Oro delayed messages - Adminer (`adminer:latest` on port 28080) is useful for DB inspection during dev ### Service Container Reference | Service | Image | Health Check | |---|---|---| | PostgreSQL | oroinc/pgsql:17.4-alpine | `pg_isready` | | Redis | redis:7.4.2-alpine | `redis-cli ping` | | Elasticsearch | elasticsearch:8.17.4 | `curl localhost:9200/_cluster/health` | | RabbitMQ | oroinc/rabbitmq:3.13.7-alpine | port 5672 | ## Environment Files Oro uses `.env-app` (not `.env`) as the primary env file: | File | Purpose | |---|---| | `.env-app` | Default values, committed to repo | | `.env-app.local` | Local overrides (gitignored) | | `.env-app.test` | Test-specific overrides | Key variable prefix: `ORO_` (not `APP_`). ## CI/CD (Jenkins Pattern) Jenkins pipeline with parallel build stages: ```groovy stage('Build') { parallel { stage('Build:prod') { // composer install --no-dev, docker build, oro:install } stage('Build:test') { // composer install (with dev), phpcs, phpmd, unit tests, functional tests } } } ``` Static analysis tools in CI: - `bin/phpcs --standard=PSR2 src/` (PHP CodeSniffer) - `bin/phpmd src/ xml vendor/oro/platform/build/phpmd.xml` (PHP Mess Detector) - Unit: `phpunit --testsuite=unit src/` - Functional: `phpunit --testsuite=functional src/` Image push to OroCloud registry: `harborio.oro.cloud/{project}/orocommerce-enterprise-application:{tag}` ## Monitoring ### Application Health ```bash php bin/console oro:check-requirements -vv php bin/console debug:router --env=prod # verify routes php bin/console oro:message-queue:consume --help # MQ status ``` ### Key Metrics to Monitor - MQ queue depth (DBAL: `SELECT count(*) FROM oro_message_queue`) - Consumer process count (Supervisor) - PHP-FPM pool status - PostgreSQL connection count, slow queries - Redis memory usage - Elasticsearch cluster health - Disk usage (cache, logs, file storage) ### Logging Oro uses Monolog (Symfony standard). Config in `config/config_prod.yml`. Docs: https://doc.oroinc.com/backend/logging/ ## Performance Optimization - Enable OPcache for PHP - Use Redis for cache + sessions (not filesystem) - Use Elasticsearch for search (EE) - Use RabbitMQ instead of DBAL transport (EE) - Tune PostgreSQL (shared_buffers, work_mem, effective_cache_size) - Use `--no-debug` for all prod commands - Optimize Composer autoloader: `composer dump-autoload --optimize` - Docs: https://doc.oroinc.com/backend/setup/system-requirements/performance-optimization/