I’ve got a Layer 7 Load Balancer setup using HAProxy for WordPress Multisite.

I’m looking to have anything related to the WordPress backend to be served from a specific group of servers (A/K/A anything in /wp-admin/) while serving the frontend of the WordPress websites from another group of servers.

Do I need to adjust something in wp-config.php to change cookie names so that they include the server ID? or check for the server ID in the WordPress cookie? I feel like problems #1 and #2 are cookie related. I have no idea why #3 is happening. My servers aren’t lagging at all, and should be responding plenty fast.

With my current configuration I’m facing a few problems here:

  1. It does indeed appear to be connecting me to the appropriate admin server. However, after a while in the dashboard. The WordPress
    login form pops up asking me to re-login again.

  2. Most admin pages work just fine however once in a while, again, same
    as #1, the WordPress login for pops up and asks me to login again.

  3. Every now in then I get a “504 Gateway Time-out – The server didn’t
    respond in time.”

Here’s what my configuration looks like:

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http
        retries 3
        option redispatch
        maxconn 2000
        timeout connect 5000
        timeout check 5000
        timeout client 30000
        timeout server 30000

frontend http-in
    bind *:80
    option  httplog
    option http-server-close

    acl has_domain hdr(host) -m found
    acl has_www hdr_beg(host) -i www.

    use_backend live_servers if has_domain has_www

    acl has_admin path_beg /wp-admin
    acl has_login path_beg /wp-login.php
    acl has_custom_login path_beg /manage

    use_backend admin_servers if has_admin or has_login or has_custom_login

    default_backend live_servers

backend live_servers
    mode http
    stats enable
    stats uri /haproxy?stats
    balance roundrobin
    option httpclose
    option forwardfor
    cookie SERVERID insert indirect nocache
    server s1 1.1.1.1:80 check cookie s1
    server s2 2.2.2.2:80 check cookie s2

backend admin_servers
    mode http
    stats enable
    stats uri /haproxy?stats
    balance roundrobin
    option httpclose
    option forwardfor
    cookie SERVERID insert indirect nocache
    server s1 1.1.1.1:80 check cookie s1

I’m willing to provide a pretty hefty bounty for this. If there’s any settings which I’m missing or you think you could improve upon my configuration, please provide a full configuration including all appropriate settings in your answer.

Edit: I am currently using HAProxy 1.6.x and willing to upgrade to latest version if that’s what it takes to get a valid solution.

2 s
2

The problem #1 & #2:

Don’t know why you need to add and validate extra cookies, but for me, it’s simple and quite straight forward:

This is what I have tried on vagrant boxes and with default WordPress structure:

1. Prepare 6 separate servers

  • 111.111.1.10 – MySQL server
  • 111.111.1.11 – HAProxy server
  • 111.111.1.12 & 111.111.1.13 – for admin URLs
  • 111.111.1.14 & 111.111.1.15 – for non-admin URLs

HAProxy (v1.6) configurations:

defaults
    log     global
    mode    http
    option  httplog
    option  forwardfor    
    option  dontlognull
    option  http-server-close
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

frontend http-revolver
    bind 111.111.1.11:80
    acl url_is_wp_admin path_beg /wp-admin /wp-login.php /manage
    use_backend admin-servers if url_is_wp_admin
    default_backend public-servers

backend public-servers
    server s1 111.111.1.12:80 check
    server s2 111.111.1.13:80 check

backend admin-servers
    server s3 111.111.1.14:80 check
    server s4 111.111.1.15:80 check

listen stats
    bind  111.111.1.11:1984
    stats enable
    stats scope http-revolver
    stats scope public-servers
    stats scope admin-servers
    stats uri /
    stats realm Haproxy\ Statistics
    stats auth user:password

2. Use wpms.dev as a demo domain and point it to 111.111.1.11 in /etc/hosts of host machine.

3. Install a base box with ubuntu/trusty64 (LAMP stack + WP multisite) on server 111.111.1.12.

The most important step to avoid the problem #1 & #2 is, because some WordPress cookies depend on paths, we must make sure these constants are consistent in all servers:

define('WP_HOME', 'http://wpms.dev');
define('WP_SITEURL', 'http://wpms.dev');
define('DOMAIN_CURRENT_SITE', 'wpms.dev');
define('PATH_CURRENT_SITE', "https://wordpress.stackexchange.com/");
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);

To do it, we just need to add it to wp-config.php in this base box.

4. Package the base box and duplicate it on other servers: 111.111.1.13, 111.111.1.14 and 111.111.1.15. Now vagrant up for all servers and check it out.

If you have ssh authentication failure, you must point config.ssh.private_key_path to the private_key of the base box in Vagrantfiles of the duplicated boxes.

The problem #3 is too abroad and may be off-topic here. It can be storage error, server config error… You should ask it on a appropriate network site. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *