• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Installing and Configuring Laravel Octane with Swoole on Ubuntu 24.04 LTS for High-Throughput B2B APIs

Installing and Configuring Laravel Octane with Swoole on Ubuntu 24.04 LTS for High-Throughput B2B APIs

Prerequisites and System Preparation

Before embarking on the installation of Laravel Octane with Swoole, ensure your Ubuntu 24.04 LTS server is up-to-date and properly configured for a production PHP environment. This includes having a robust PHP installation with essential extensions, a web server (Nginx is recommended for its performance characteristics with Octane), and Composer. We’ll assume a fresh Ubuntu 24.04 LTS installation.

Begin by updating your package lists and upgrading existing packages:

sudo apt update && sudo apt upgrade -y

Install PHP 8.3 and common extensions required by Laravel and Swoole. We’ll also install Nginx and Git.

sudo apt install -y php8.3 php8.3-cli php8.3-common php8.3-mysql php8.3-zip php8.3-gd php8.3-mbstring php8.3-curl php8.3-xml php8.3-bcmath php8.3-fpm php8.3-opcache nginx git unzip

Verify your PHP version:

php -v

Next, install Composer globally. This is crucial for managing Laravel dependencies.

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"

Confirm Composer installation:

composer --version

For Swoole, we’ll compile it from source to ensure compatibility and access to the latest features. This process requires development tools.

sudo apt install -y pkg-config build-essential autoconf libtool

Download the Swoole source code. It’s advisable to use a recent stable version. Check the official Swoole GitHub repository for the latest releases.

cd /tmp
wget https://github.com/swoole/swoole-src/archive/refs/tags/v5.1.0.tar.gz -O swoole-src-5.1.0.tar.gz
tar -xzf swoole-src-5.1.0.tar.gz
cd swoole-src-5.1.0

Compile and install Swoole. The --enable-openssl and --enable-sockets flags are important for many B2B API functionalities.

phpize
./configure --enable-openssl --enable-sockets
make && sudo make install

After installation, you need to tell PHP to load the Swoole extension. Create a new `.ini` file for Swoole.

echo "extension=swoole.so" | sudo tee /etc/php/8.3/mods-available/swoole.ini

Enable the Swoole extension for the CLI and FPM SAPI. This ensures it’s loaded regardless of how your application is run.

sudo phpenmod -v 8.3 swoole

Verify that Swoole is installed and enabled by checking your PHP configuration or running a command that lists loaded extensions.

php -m | grep swoole

You should see swoole in the output. If not, double-check the compilation and installation steps, and ensure the `.ini` file is correctly placed and enabled.

Installing Laravel and Octane

Now, let’s set up a new Laravel project or integrate Octane into an existing one. For this example, we’ll create a new project. Navigate to your desired project directory.

cd /var/www
composer create-project laravel/laravel b2b-api-service

Change into the project directory:

cd b2b-api-service

Install Laravel Octane via Composer:

composer require laravel/octane

After installing Octane, you need to publish its configuration file. This will create config/octane.php.

php artisan octane:install

The octane:install command will prompt you to choose an application server. Select Swoole. If you don’t see the prompt, you can manually set the server in .env or config/octane.php.

OCTANE_SERVER=swoole

Alternatively, edit config/octane.php and set the server key:

<?php

return [
    // ...
    'server' => env('OCTANE_SERVER', 'swoole'),
    // ...
];

Configuring Octane with Swoole for Production

The config/octane.php file is where you’ll fine-tune Swoole’s behavior for your B2B API. Key parameters include:

  • server: Set to swoole.
  • workers: The number of Swoole worker processes. A common starting point is (CPU cores * 2) + 1. For high-throughput APIs, this might need careful tuning based on load testing.
  • max_requests: The number of requests a worker will process before being respawned. This helps mitigate memory leaks. A value between 1000 and 10000 is typical.
  • listen: The IP address and port Swoole will listen on. For production, it’s often recommended to listen on a specific IP (e.g., 127.0.0.1) and let Nginx proxy requests to it.
  • reload_on_path_changes: Set to false in production to prevent unexpected reloads.
  • swoole: This nested array allows direct configuration of Swoole’s underlying settings. Important options include:
    • daemonize: Set to true for production to run Swoole as a background daemon.
    • log_file: Specify a path for Swoole’s logs.
    • pid_file: Specify a path for the PID file.
    • dispatch_mode: Controls how tasks are dispatched to workers. Mode 2 (SWOOLE_DISPATCH_ROUND) is often a good default.
    • task_worker_num: If you use Swoole’s task workers for background processing, configure this.

Here’s an example of a production-ready config/octane.php snippet:

<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Application Server
    |--------------------------------------------------------------------------
    |
    | This is the application server that will be used to serve your Octane
    | application. The supported servers are:
    |
    | - swoole
    | - roadrunner
    | - FrankenPHP
    |
    */

    'server' => env('OCTANE_SERVER', 'swoole'),

    /*
    |--------------------------------------------------------------------------
    | Application Server Listen Address
    |--------------------------------------------------------------------------
    |
    | This is the IP address and port that the Octane server will listen on.
    | For production, it's recommended to listen on localhost and use Nginx
    | as a reverse proxy.
    |
    */

    'listen' => env('OCTANE_LISTEN', '127.0.0.1:8000'),

    /*
    |--------------------------------------------------------------------------
    | Maximum number of requests to process before respawning the server.
    |--------------------------------------------------------------------------
    |
    | This is useful for preventing memory leaks, but it will also cause
    | requests to be processed by a new server process.
    |
    */

    'max_requests' => env('OCTANE_MAX_REQUESTS', 3000),

    /*
    |--------------------------------------------------------------------------
    | Number of workers to start.
    |--------------------------------------------------------------------------
    |
    | This is the number of worker processes that will be started. For
    | high-throughput APIs, this should be tuned based on your server's
    | CPU cores and expected load.
    |
    */

    'workers' => env('OCTANE_WORKERS', (int) shell_exec('nproc') * 2 + 1),

    /*
    |--------------------------------------------------------------------------
    | Enable file watching and automatic reloading.
    |--------------------------------------------------------------------------
    |
    | For production, this should be disabled.
    |
    */

    'reload_on_path_changes' => env('OCTANE_RELOAD_PATH_CHANGES', false),

    /*
    |--------------------------------------------------------------------------
    | Swoole Configuration
    |--------------------------------------------------------------------------
    |
    | You may configure Swoole's underlying settings here.
    |
    */

    'swoole' => [
        'daemonize' => env('SWOOLE_DAEMONIZE', true),
        'log_file' => env('SWOOLE_LOG_FILE', storage_path('logs/swoole.log')),
        'pid_file' => env('SWOOLE_PID_FILE', storage_path('run/swoole.pid')),
        'dispatch_mode' => env('SWOOLE_DISPATCH_MODE', 2), // SWOOLE_DISPATCH_ROUND
        'task_worker_num' => env('SWOOLE_TASK_WORKER_NUM', 0), // Adjust if using task workers
        // Add other Swoole configurations as needed, e.g.:
        // 'open_tcp_keepalive' => true,
        // 'tcp_keepalive_time' => 60,
        // 'tcp_keepalive_intvl' => 10,
        // 'tcp_keepalive_probes' => 5,
    ],

    // ... other Octane configurations
];

Ensure the directories for logs and PID files exist and are writable by the web server user (e.g., www-data if using Nginx with PHP-FPM, though Octane runs as a separate user when daemonized). You might need to create these directories and set permissions:

sudo mkdir -p storage/logs storage/run
sudo chown -R www-data:www-data storage/logs storage/run
sudo chmod -R 755 storage/logs storage/run

Important Note on Permissions: When Swoole runs as a daemon (daemonize=true), it typically runs as the user that started the process. If you start it via php artisan octane:start as a regular user, it will run as that user. If you intend to run it as a specific service user (e.g., www-data), you’ll need to adjust how you start and manage the process (e.g., via systemd). For simplicity in this guide, we’ll assume it runs as the user executing the command, and that user has write permissions to storage/logs and storage/run.

Configuring Nginx as a Reverse Proxy

Since Swoole will be listening on a specific port (e.g., 127.0.0.1:8000), Nginx needs to be configured as a reverse proxy to forward incoming HTTP requests to the Octane application. This also allows Nginx to handle SSL termination, static file serving, and load balancing if you scale horizontally.

Create a new Nginx server block configuration file for your API:

sudo nano /etc/nginx/sites-available/b2b-api-service

Paste the following configuration, adjusting server_name and paths as necessary. This configuration assumes your API is accessible via api.yourdomain.com and Swoole is listening on 127.0.0.1:8000.

server {
    listen 80;
    server_name api.yourdomain.com; # Replace with your domain

    root /var/www/b2b-api-service/public; # Adjust to your project's public directory
    index index.php index.html index.htm;

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

    # Proxy requests to Laravel Octane (Swoole)
    location / {
        proxy_pass http://127.0.0.1:8000; # Matches OCTANE_LISTEN in .env or config/octane.php
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Connection ""; # Important for HTTP/1.1 keep-alive
    }

    # Serve static files directly from Nginx for performance
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public";
        access_log off;
        try_files $uri =404;
    }

    # Deny access to .env files, vendor directories, etc.
    location ~ /\.env { deny all; }
    location ~ ^/vendor/ { deny all; }
    location ~ ^/storage/app/public/ { deny all; } # If not serving via symlink

    error_log /var/log/nginx/b2b-api-service.error.log;
    access_log /var/log/nginx/b2b-api-service.access.log;
}

Enable the new Nginx configuration and test it:

sudo ln -s /etc/nginx/sites-available/b2b-api-service /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

If you are using SSL, you will need to configure Nginx to handle SSL termination and proxy to Swoole. This typically involves obtaining SSL certificates (e.g., via Let’s Encrypt) and updating the listen directive in your Nginx config to listen 443 ssl; and specifying the certificate paths.

Running and Managing Laravel Octane with Swoole

To start your Octane application with Swoole:

php artisan octane:start

This command will start Swoole. If daemonize is set to true in your configuration, it will run in the background. You can check its status using:

php artisan octane:status

To stop the Octane application:

php artisan octane:stop

To restart (useful after code changes or configuration updates):

php artisan octane:restart

For production environments, it’s highly recommended to manage the Octane process using a process manager like systemd. This ensures that Octane starts automatically on server boot and is automatically restarted if it crashes.

Create a systemd service file:

sudo nano /etc/systemd/system/octane-b2b-api.service

Add the following content, adjusting paths and user/group as necessary. Ensure the User and Group are appropriate for your deployment. If Swoole is configured to daemonize, the ExecStart command should be php artisan octane:start. If you want systemd to manage the daemonization, you might need to set daemonize=false in config/octane.php and rely solely on systemd.

[Unit]
Description=Laravel Octane B2B API Service
After=network.target

[Service]
Type=simple
User=www-data # Or the user your application should run as
Group=www-data # Or the group your application should run as
WorkingDirectory=/var/www/b2b-api-service # Path to your Laravel project
ExecStart=/usr/bin/php /var/www/b2b-api-service/artisan octane:start --host=127.0.0.1 --port=8000 --workers={{OCTANE_WORKERS}} --max-requests={{OCTANE_MAX_REQUESTS}} # Adjust host/port if needed, and pass Octane config values
ExecStop=/usr/bin/php /var/www/b2b-api-service/artisan octane:stop
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Note on systemd and daemonize: If you set daemonize=true in config/octane.php, systemd will try to manage a process that immediately detaches. This can lead to systemd thinking the service has stopped. It’s often cleaner to set daemonize=false in your Octane config and let systemd handle the process lifecycle. If you do this, you’ll need to adjust the ExecStart command to explicitly set the host and port if they differ from the defaults or your .env file.

For example, if daemonize=false:

[Service]
# ... other settings
ExecStart=/usr/bin/php /var/www/b2b-api-service/artisan octane:start --host=127.0.0.1 --port=8000 --workers={{OCTANE_WORKERS}} --max-requests={{OCTANE_MAX_REQUESTS}}
# ...

Replace {{OCTANE_WORKERS}} and {{OCTANE_MAX_REQUESTS}} with actual values or use environment variables if your systemd setup supports it. A simpler approach is to ensure these are set in the project’s .env file and systemd inherits them.

Reload systemd, enable, and start the service:

sudo systemctl daemon-reload
sudo systemctl enable octane-b2b-api.service
sudo systemctl start octane-b2b-api.service
sudo systemctl status octane-b2b-api.service

Monitor the logs for any errors. Swoole’s logs can be found at storage/logs/swoole.log (if configured), and your application logs are in storage/logs/laravel.log. Nginx logs are typically in /var/log/nginx/.

Performance Tuning and Considerations

Achieving high throughput for B2B APIs with Octane and Swoole requires careful tuning:

  • Worker Count: Start with (CPU cores * 2) + 1 and adjust based on load testing. Monitor CPU and memory usage. Too many workers can lead to context switching overhead and memory contention.
  • Max Requests: Regularly respawning workers (e.g., every 1000-5000 requests) is crucial for preventing memory leaks in long-running processes.
  • Swoole Configuration: Explore Swoole’s advanced settings like dispatch_mode, task_worker_num, and network-related options (e.g., keepalives) if your API involves significant I/O or concurrent operations.
  • Database Connections: Octane keeps database connections open. Ensure your database server can handle the increased number of persistent connections. Consider using connection pooling if your database driver supports it or if you implement a custom solution.
  • Caching: Leverage Octane’s caching capabilities. Octane caches application bootstrapped components, but you can also implement application-level caching for frequently accessed data.
  • Background Jobs: For long-running tasks (e.g., report generation, complex data processing), offload them to Swoole’s task workers or a dedicated queue system (like Redis queues) to avoid blocking the main request-response cycle.
  • Memory Management: Monitor memory usage closely. Identify and fix any memory leaks in your application code or dependencies.
  • Load Testing: Use tools like ApacheBench (ab), k6, or JMeter to simulate realistic API traffic and identify bottlenecks.

By following these steps, you can establish a high-performance Laravel Octane application powered by Swoole on Ubuntu 24.04 LTS, suitable for demanding B2B API workloads.

Reader Interactions

Leave a Reply Cancel reply

You must be logged in to post a comment.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
  • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
  • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store
  • How to refactor legacy event ticket registers queries using modern WP_Query and custom Transient caching
  • Step-by-Step Guide: Offloading high-frequency member profile directories metadata writes to a Redis KV store

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (662)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • PHP (5)
  • PHP Development (49)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (647)
  • SEO & Growth (492)
  • Server (118)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (726)
  • WordPress Theme Development (357)

Recent Posts

  • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
  • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
  • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (726)
  • Debugging & Troubleshooting (662)
  • Security & Compliance (647)
  • SEO & Growth (492)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala