Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend host "appserver": resolves to too many addresses when running multiple sites with Lando #5

Open
kaszarobert opened this issue Mar 21, 2022 · 2 comments
Labels
bug Something isn't working

Comments

@kaszarobert
Copy link

I'm experiencing an issue I don't have any idea how to solve it when working with the Drupal 9 recipe.

After lando poweroff if I start a site with Varnish, the Varnish can connect to the "appserver" as expected.
But if I start another website that doesn't have Varnish, and only after that I try to start a site together with Varnish, visiting the site via Varnish, the page only shows this text: Bad Gateway

Running lando logs -s varnish shows this error:

varnish_1      | Error:
varnish_1      | Message from VCC-compiler:
varnish_1      | Backend host "appserver": resolves to too many addresses.
varnish_1      | Only one IPv4 and one IPv6 are allowed.
varnish_1      | Please specify which exact address you want to use, we found all of these:
varnish_1      |        172.28.0.5:80
varnish_1      |        172.28.0.4:80
varnish_1      | ('/etc/varnish/includes/backend.vcl' Line 4 Pos 13)
varnish_1      |     .host = "appserver";
varnish_1      | ------------###########-
varnish_1      |
varnish_1      |
varnish_1      | In backend specification starting at:
varnish_1      | ('/etc/varnish/includes/backend.vcl' Line 3 Pos 1)
varnish_1      | backend backend1 {
varnish_1      | #######-----------
varnish_1      |
varnish_1      | Running VCC-compiler failed, exited with 2
varnish_1      | VCL compilation failed

Why does Lando want to connect to a whole different project that happens to have an "appserver" service, too? I thought they are completely separated, no matter how many sites I'm starting with lando start.

This is how I include the varnish in the Landofile currently:

  varnish:
    type: varnish:6
    backends:
      - appserver
    ssl: true
    config:
      vcl: .lando/default.vcl
    overrides:
      environment:
        VARNISH_BACKEND_HOST: appserver
        VARNISH_BACKEND_PORT: 80
        VARNISH_BACKEND_FIRST_BYTE_TIMEOUT: 300s
        VARNISH_ALLOW_UNRESTRICTED_PURGE: 1
        VARNISHD_PARAM_HTTP_RESP_HDR_LEN: 65536
        VARNISHD_PARAM_HTTP_RESP_SIZE: 98304
        VARNISHD_PARAM_WORKSPACE_BACKEND: 131072

And this is the "default.vcl" I'm trying to use:

vcl 4.0;
import std;
import directors;

# Default backend definition. Set this to point to your content server.
backend default {
    .host = "{{ getenv "VARNISH_BACKEND_HOST" }}";
    .port = "{{ getenv "VARNISH_BACKEND_PORT" "80" }}";
    .first_byte_timeout = 300s;
}

# Respond to incoming requests.
sub vcl_recv {
    # Pass through files, as they are static, and can be returned quickly.
    if (req.url ~ "^/sites/default/files/" ||
        req.url ~ "^/sites/[^/]+/files/" ||
        req.url ~ "^/system/files/") {
            if (!req.url ~ "^/sites/default/files/styles/") {
                return (pass);
            }
    }

    # Add an X-Forwarded-For header with the client IP address.
    if (req.restarts == 0) {
        if (req.http.X-Forwarded-For) {
            set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
        }
        else {
            set req.http.X-Forwarded-For = client.ip;
        }
    }

    # Only allow PURGE requests from IP addresses in the 'purge' ACL.
    if (req.method == "PURGE") {
        return (hash);
    }

    # Only allow BAN requests from IP addresses in the 'purge' ACL.
    if (req.method == "BAN") {
        # Logic for the ban, using the Cache-Tags header. For more info
        # see https://github.com/geerlingguy/drupal-vm/issues/397.
        if (req.http.Cache-Tags) {
            ban("obj.http.Cache-Tags ~ " + req.http.Cache-Tags);
        }
        else {
            return (synth(403, "Cache-Tags header missing."));
        }

        # Throw a synthetic page so the request won't go to the backend.
        return (synth(200, "Ban added."));
    }

    if (req.method == "URIBAN") {
      ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
      # Throw a synthetic page so the request won't go to the backend.
      return (synth(200, "Ban added."));
    }

    # Only cache GET and HEAD requests (pass through POST requests).
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    # Pass through any administrative or AJAX-related paths.
    if (req.url ~ "^/status\.php$" ||
        req.url ~ "^/install\.php" ||
        req.url ~ "^/user" ||
        req.url ~ "^/user/.*$" ||
        req.url ~ "^/users/.*$" ||
        req.url ~ "^/info/.*$" ||
        req.url ~ "^/update\.php$" ||
        req.url ~ "^/admin$" ||
        req.url ~ "^/admin/.*$" ||
        req.url ~ "^/flag/.*$" ||
        req.url ~ "^.*/ajax/.*$" ||
        req.url ~ "^.*/ahah/.*$") {
           return (pass);
    }

    # Removing cookies for static content so Varnish caches these files.
    if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
        unset req.http.Cookie;
    }

    # Remove all cookies that Drupal doesn't need to know about. We explicitly
    # list the ones that Drupal does need, the SESS and NO_CACHE. If, after
    # running this code we find that either of these two cookies remains, we
    # will pass as the page cannot be cached.
    if (req.http.Cookie) {
        # 1. Append a semi-colon to the front of the cookie string.
        # 2. Remove all spaces that appear after semi-colons.
        # 3. Match the cookies we want to keep, adding the space we removed
        #    previously back. (\1) is first matching group in the regsuball.
        # 4. Remove all other cookies, identifying them by the fact that they have
        #    no space after the preceding semi-colon.
        # 5. Remove all spaces and semi-colons from the beginning and end of the
        #    cookie string.
        set req.http.Cookie = ";" + req.http.Cookie;
        set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
        set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
        set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
        set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

        if (req.http.Cookie == "") {
            # If there are no remaining cookies, remove the cookie header. If there
            # aren't any cookie headers, Varnish's default behavior will be to cache
            # the page.
            unset req.http.Cookie;
        }
        else {
            # If there is any cookies left (a session or NO_CACHE cookie), do not
            # cache the page. Pass it on to Apache directly.
            return (pass);
        }
    }
}

# Set a header to track a cache HITs and MISSes.
sub vcl_deliver {
    # Remove ban-lurker friendly custom headers when delivering to client.
    unset resp.http.X-Url;
    unset resp.http.X-Host;
    # Comment these for easier Drupal cache tag debugging in development.
    unset resp.http.Cache-Tags;
    unset resp.http.X-Drupal-Cache-Contexts;

    if (obj.hits > 0) {
        set resp.http.Cache-Tags = "HIT";
    }
    else {
        set resp.http.Cache-Tags = "MISS";
    }
}

# Instruct Varnish what to do in the case of certain backend responses (beresp).
sub vcl_backend_response {
    # Set ban-lurker friendly custom headers.
    set beresp.http.X-Url = bereq.url;
    set beresp.http.X-Host = bereq.http.host;

    # Cache 404s, 301s, at 500s with a short lifetime to protect the backend.
    if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
        set beresp.ttl = 10m;
    }

    # Don't allow static files to set cookies.
    # (?i) denotes case insensitive in PCRE (perl compatible regular expressions).
    # This list of extensions appears twice, once here and again in vcl_recv so
    # make sure you edit both and keep them equal.
    if (bereq.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
        unset beresp.http.set-cookie;
    }

    # Allow items to remain in cache up to 6 hours past their cache expiration.
    set beresp.grace = 6h;
}
@kaszarobert kaszarobert added the bug Something isn't working label Mar 21, 2022
@SanderWind
Copy link

I solved this by using an environment override and defining the Docker container name as VARNISH_BACKEND_HOST:

services:
  varnish:
    type: varnish:6
    overrides:
      environment:
        VARNISH_BACKEND_HOST: <docker_container_name> # Like project_appserver_1

@kaszarobert
Copy link
Author

You're right. Specifying the container name does fix it. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants