Running Nginx in an active-active cluster keeps HTTP service available during node outages and supports maintenance without taking the site offline. Multiple nodes serving at the same time also enables traffic distribution across instances for better aggregate capacity and reduced impact from single-node failures.

In a Pacemaker cluster managed with pcs, Nginx can be controlled as a systemd resource. Cloning the resource starts one nginx.service instance per node, while Pacemaker monitors resource health and attempts recovery when failures occur. Traffic distribution remains outside the cluster and is typically handled by a load balancer or DNS strategy.

Active-active clustering does not replicate /etc/nginx configuration or web content, so every node must serve consistent configuration and files to avoid inconsistent responses. Cloned resources can start Nginx on multiple nodes simultaneously, so port bindings, firewall rules, and load balancer health checks must be ready before client traffic is pointed at the nodes. Stateful backends behind Nginx require additional coordination beyond cloning to avoid data inconsistency.

Steps to set up Nginx active-active with PCS:

  1. Confirm the cluster is online with quorum.
    $ sudo pcs status
    Cluster name: clustername
    Cluster Summary:
      * Stack: corosync (Pacemaker is running)
      * Current DC: node-01 (version 2.1.6-6fdc9deea29) - partition with quorum
      * Last updated: Thu Jan  1 00:49:10 2026 on node-01
      * Last change:  Thu Jan  1 00:49:09 2026 by root via cibadmin on node-01
      * 3 nodes configured
      * 5 resource instances configured
    ##### snipped #####
  2. Confirm the nginx.service unit exists on every cluster node.
    $ systemctl list-unit-files --type=service --no-pager | grep -E '^nginx\.service'
    nginx.service                                disabled        enabled
  3. Validate the Nginx configuration on every node before handing control to Pacemaker.
    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

    A failed configuration test can leave the pcs resource stuck in restart loops and prevent the clone set from reaching a stable Started state.

  4. Create a pcs resource for Nginx using the systemd agent.
    $ sudo pcs resource create nginx_service systemd:nginx op monitor interval=30s

    systemd:nginx maps to nginx.service and is managed through systemd start/stop operations.

    Resource creation can start Nginx immediately and bind to ports like 80/443, which can affect live traffic if client routing is already pointed at the nodes.

  5. Clone the resource so an instance runs on every eligible node.
    $ sudo pcs resource clone nginx_service
  6. Verify the clone set is started on all nodes.
    $ sudo pcs status resources
      * Clone Set: dummy-check-clone [dummy-check]:
        * Started: [ node-01 node-02 node-03 ]
    ##### snipped #####
      * Clone Set: nginx_service-clone [nginx_service]:
        * Started: [ node-01 node-02 node-03 ]
  7. Request an HTTP response from each node to confirm Nginx is serving content.
    $ curl -sI http://node-01/
    HTTP/1.1 200 OK
    Server: nginx/1.24.0 (Ubuntu)
    Date: Thu, 01 Jan 2026 00:49:17 GMT
    Content-Type: text/html
    Content-Length: 10671
    Last-Modified: Sun, 28 Dec 2025 06:15:52 GMT
    Connection: keep-alive
    ETag: "6950cb18-29af"
    Accept-Ranges: bytes
    
    $ curl -sI http://node-02/
    HTTP/1.1 200 OK
    Server: nginx/1.24.0 (Ubuntu)
    Date: Thu, 01 Jan 2026 00:49:17 GMT
    Content-Type: text/html
    Content-Length: 10671
    Last-Modified: Sun, 28 Dec 2025 06:15:52 GMT
    Connection: keep-alive
    ETag: "6950cb18-29af"
    Accept-Ranges: bytes
  8. Update client routing to distribute traffic across all active nodes.

    Health checks should target a stable URI that returns 200 and quickly removes an unhealthy node from rotation.

  9. Run a failover test on the clone set.

    Failover testing can interrupt active connections if the load balancer does not drain sessions or clients do not retry failed requests.