Streaming live at 10am (PST)

Partial Webflow migration using reverse proxy

Currently, we have lots of SEO-relevant aggregation pages and public pages in our old, self-hosted website we’re not immediately ready to move to the new application. These pages are automatically generated from complex database queries, receive serious traffic (~40k views per day), and cannot be replicated in Webflow easily.
Unfortunately, those pages are all placed on the root domain ( domain.com/offending-pages ), and by “lots”, I meant several hundreds of them. Thus, we can’t simply add redirects in Webflow, but have to keep pointing the DNS for domain.com to our own web servers. There, we take it the other way around and redirect the traffic for all non-SEO pages to Webflow.

In case this helps anyone: I’ve achieved this with a very flexible nginx setup, without any changes to the existing site, the SSL certificates, or Webflow settings. Any performance hit by the doubled requests is levelled out by Cloudflare caching in front of nginx.

# Start by defining an upstream to send requests to. This helps organization.
upstream webflow {

    # Make sure to add the port after the server name, because nginx won't do this
    # automatically, even if proxying to a https target.
    server proxy-ssl.webflow.com:443;
}

# Make sure nginx can resolve the webflow domain correctly
resolver 8.8.8.8 8.8.4.4;

server {

    # The server name of our primary domain. Note that this configuration will be used for
    # both the old _and_ the new website.
    server_name www.domain.com;

    # This named location is only routed internally, and will proxy any requests to the 
    # webflow upstream with the proper configuration set.
    location @webflow {

        # Note the "https" here, making sure the request is re-encrypted
        proxy_pass                          https://webflow;

        # Set the host header of our current request (probably www.domain.com). We want to
        # forward that to the upstream, so they can properly route the request.
        proxy_set_header Host               $host;

        # Setting these is good faith
        proxy_set_header X-Forwarded-For    $remote_addr;
        proxy_set_header X_FORWARDED_PROTO  https;

        # Disable SSL verification: As we don't own the Webflow upstream, we can't keep 
        # track of their certificate. We trust their upstream anyway, so if they went rogue,
        # we couldn't do anything about it otherwise, either.
        proxy_ssl_verify        off;

        # Reuse SSL sessions: This prevents having to perform a separate SSL handshake for
        # every single request, but pool connections instead.
        proxy_ssl_session_reuse on;

        # SSL server name: This is the crucial bit. During SNI (server name identification),
        # nginx uses the name of the upstream by default, which would be Webflow's
        # proxy-ssl.webflow.com in our case. Here, we enable manual ambiguation.
        proxy_ssl_server_name   on;

        # Set the actual SNI name to send: Here, we use our Host header value instead, so 
        # the request can be identified on the Webflow origin server.
        proxy_ssl_name          $host;
    }

    # This block matches any URLs that start with a language code, and forwards them to the
    # webflow named location.
    location ~^ /([a-z]{2})/.*$ {
        try_files /dev/null @webflow;
    }

    # This block matches all requests for the homepage (eg. a single "/"), and forwards them
    # to the webflow named location.
    location = / {
        try_files /dev/null @webflow;
    }

    # This is the default location for all other requests, routed to our legacy application.
    location / {
        try_files $uri $uri/ @app;
    }

    # ...
}

If you’re interested in how this works in detail, I’ve written a post on my blog about it (not linking because I hate blogspam).