CMS Development

robertainslie
HubSpot Employee
HubSpot Employee

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

Note: The purpose of this post is to share lessons learned about setting up a reverse proxy with HubSpot CMS Enterprise. If you have experience, we invite you to share on this thread!

 

HubSpot CMS Enterprise allows for content to be served through a reverse proxy. This implementation requires significant technical know-how and while possible, is not a recommended standard implementation.

 

The core documentation for the HubSpot side implementation is available here

 

While not a recommended setup due to the trade-offs and technical expertise required, there are some use cases where setting up a reverse proxy makes sense and is technically supported by HubSpot CMS Enterprise. The primary use case for implementing a reverse proxy with the HubSpot CMS acting as a content source is when a website serves a web application from the same domain as the marketing website. For example, if you offer a web application at www.domain.com/login and also host a marketing content site at www.domain.com, a reverse proxy can route traffic to your web application servers on certain subdirectory paths, and to HubSpot CMS on other subdirectory paths.

 

HubSpot’s Professional Service’s Technical Consultants have aided customers in this implementation and hope to pass along a few lessons, including a sample nginx server configuration sample. (Note: HubSpot Services teams cannot provide recommendations on the ‘external to HubSpot’ aspects of this setup and we are sharing this information to document this publicly for others to learn from. Usage and implementation is your responsibility). If you do need guidance on the HubSpot setup, we can work on a project with you -  just reach out to your Customer Success Manager or Sales representative.

 

Lesson One: The domain in your HubSpot Domain Manager should match the domain being requested/served through your reverse proxy.

However, you do not need to directly connect / update your DNS settings to connect this domain to HubSpot’s servers. Instead, when a domain is securely served on an existing content host, HubSpot provides a TXT and CNAME record to add to your DNS that 
verifies domain ownership and pre-provisions an SSL certificate in the background. When implementing your reverse proxy, remember that the origin connection is a HubSpot CNAME and the Host and X-HS-Public-Host headers match the "added to HubSpot but not directly connected" HubSpot domain where content will be served from. The Host domain is added to HubSpot Domains so that the HubSpot systems are ‘aware’ of the domain, but that domain is never directly pointed to HubSpot in your DNS zone file.

 

Lesson Two: There are multiple ways to setup a reverse proxy server. Regardless of the approach, the implementation should always be in a load balanced environment so that traffic from your proxy rotates requests to the HubSpot CNAME origin from multiple IP addresses.

The two primary ways seen in our experience are using a managed CDN (like Amazon Web Services Cloudfront) or with a custom nginx webserver deployed on load balanced cloud infrastructure (such as Amazon Web Services EC2/ELB or Microsoft Azure). (Note: Due to HubSpot utilizing Cloudflare as it’s CDN, Cloudflare cannot be used in this setup). 

 

Lesson Three: When working with nginx, there are several headers and settings required to route traffic in an expected fashion. Below is a sample nginx location configuration file. Note: this is not guaranteed to work, and is a sample starting point. This is also a snippet of the entire configuration, highlighting location routing settings.

Due to the SNI (Server Name Indication) connection process that establishes a secure connection between your proxy and HubSpot’s servers, the proxy connection and content host domain are different (one is a HubSpot provided CNAME and one is the domain the content should be served from and is added to the HubSpot Domain Manager). To enable this in your nginx proxy, ensure that you include two important settings. These instruct nginx to send the server domain name with the SNI SSL connection handshake since the origin domain is different from the Host.

 

proxy_ssl_name www.example.com;
proxy_ssl_server_name on;

 

Here are two location paths that set each of the required and recommended settings in an nginx configuration file. Inspect each included value and what needs to be customized for your implementation. We encourage you to review the nginx documentation for settings such as securing upstream traffic, proxy_ssl and $proxy_protocol_addr

location ~ ^(/|/some-other-path) {
    proxy_set_header Host $http_host;
    proxy_set_header X-HS-Public-Host www.example.com
    proxy_pass_request_headers on;
    proxy_set_header X-HubSpot-Trust-Forwarded-For true;
    proxy_pass https://2XX93.sites-proxy.hscoscdnXX.net;
    proxy_ssl_name www.example.com;
    proxy_ssl_server_name on;
    proxy_set_header   X-Real-IP $proxy_protocol_addr;
    proxy_set_header   X-Forwarded-Proto  $scheme;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-HubSpot-Client-IP $proxy_protocol_addr;
  }

location ~ ^(/hs|/_hcms|/hubfs|/hs-fs) {
    proxy_set_header Host $http_host;
    proxy_set_header X-HS-Public-Host www.example.com
    proxy_pass_request_headers on;
    proxy_set_header X-HubSpot-Trust-Forwarded-For true;
    proxy_pass https://2XX93.sites-proxy.hscoscdnXX.net;
    proxy_ssl_name www.example.com;
    proxy_ssl_server_name on;
    proxy_set_header   X-Real-IP  $proxy_protocol_addr;
    proxy_set_header   X-Forwarded-Proto  $scheme;
    proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header   X-HubSpot-Client-IP $proxy_protocol_addr;
  }

We hope this is helpful for any HubSpot customers who are interested in setting up a reverse proxy with HubSpot CMS. HubSpot Technical Consulting services can help provide guidance on the HubSpot components of this setup. If interested, please reach out to your main HubSpot point of contact or reach out via the form on this page.

 

If you have other advice or lessons learned with a reverse proxy setup with HubSpot, please share them for the community to benefit from!

8 Replies 8
robertainslie
HubSpot Employee
HubSpot Employee

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

One additional item that might help - if you were attempting to perform the same type of lookup using curl as the proxy (using the HubSpot CNAME), it would look like this:

curl https://tc.robertpainslie.com/proxy-page --connect-to ::XX.sites-proxy.hscoscdnXX.net

Compare to this (to replicate what won't work):

curl https://XX.sites-proxy.hscoscdnXX.net/ -H 'Host: tc.robertpainslie.com/proxy-page'  

 

0 Upvotes
robertainslie
HubSpot Employee
HubSpot Employee

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

Relating to Lesson 1 - I wanted to show some images around what this actually looks like in HubSpot and a CDN acting as a proxy. The most important aspect of this - your active and live domain that users will see is also the domain you add to HubSpot but never ACTUALLY connect in your DNS. Instead, your proxy performs a request to the provided CNAME.


I've set up a proxy for a domain - tc.robertpainslie.com that points to an AWS Cloudfront CDN distribution. Depending on the URL path, it either proxies to an AWS S3 bucket or it proxies to HubSpot CMS.
So,tc.robertpainslie.com/  shows a very simple web page originating from an S3 bucket and tc.robertpainslie.com/proxy-page shows a page served from HubSpot CMS

 

The pathway is:
Internet > tc.roberpainslie.com/proxy-page > AWS Cloudfront > HubSpot CMS
OR
Internet > tc.roberpainslie.com/ > AWS Cloudfront > AWS S3

1. In Cloudfront, I have an Origin that points to the proper HubSpot CNAME as directed by the HubSpot reverse proxy documentation Screen Shot 2021-10-25 at 5.50.03 PM.png
Then, there are Cloudfront behaviors that dictate which Origin is used for which paths:

robertainslie_2-1635199582435.png

 

2. In HubSpot, I have the domain tc.robertpainslie.com added to my Domain Manager - this is the exact domain I want to proxy! DO NOT create a new subdomain that is added to HubSpot - you want the initiating domain to be the exact same that you add to HubSpot. When connecting, the domain should already be live and hosting content over a secure connection. When this happens, HubSpot will detect the existing secure connection and ask you to pre-provision SSL - take the CNAME and TXT record and verify in your DNS. HubSpot provisions an SSL cert for the 'tc.robertpainslie.com' domain in the background even though this domain will never ACTUALLY be connected to HubSpot (because it will remain connected to your proxy).

robertainslie_0-1635198910273.png

You'll see in the above screenshot that it says 'Connected via reverse proxy' - this will eventually show up (after successful requests are proxied and may take a few weeks to appear). But, it will initially show 'Not connected'. To proceed with the process, for the specific domain:
- Edit > under, 'Edit publishing status' > Mark as 'Ready for publishing' 
- Under Domain Security Settings > 'Require HTTPS'

robertainslie_0-1635254512483.png

and 

robertainslie_1-1635254533884.png

 

 

3. Now, go to the HubSpot CMS page publisher and create and publish a page on the domain - (in my case, tc.robertpainslie.com/proxy-page). 

Screen Shot 2021-10-25 at 6.03.25 PM.png
To get traffic to this page, a request routes to your proxy, and then you forward the request to the appropriate HubSpot CNAME. HubSpot CMS then looks up the appropriate page based on the domain and path in the HOST header, and boom - it routes back through your proxy and to the originating requester

 

Hope this helps anyone who is struggling with this setup

 

 

PTrojanowski
Member

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

hi, I have a question becouse you type: "you want the initiating domain to be the exact same that you add to HubSpot". Then it is not possible to create a proxy if I have a subdomain at HubSpot (blog.mydomain.com) already and my main domain is "mydomain.com" ?

0 Upvotes
robertainslie
HubSpot Employee
HubSpot Employee

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

@PTrojanowski In this situation, I'll assume the following:

  1. You have an externally (non-HubSpot) hosted website at 'mydomain.com'
  2. You have an existing blog hosted with HubSpot at blog.mydomain.com
  3. You want to have traffic go to mydomain.com/blog/{article} and that content to be your HubSpot hosted blog origin

Assuming that's the desired behavior, you would need to (at a high level):

  1. Have the HubSpot CMS Enterprise product tier
  2. Follow the instructions to 'add' mydomain.com to HubSpot, but not ACTUALLY update your DNS to point the domain at HubSpot (it should point to your proxy server)
  3. Once SSL is pre-provisioned in HubSpot, make mydomain.com/blog the new primary domain & sub-directory of your HubSpot hosted blog in HubSpot
  4. Have your proxy point traffic at HubSpot for the specific routes
  5. Set up redirects for all traffic from blog.mydomain.com/{article} to mydomain.com/blog/{article} so that old traffic routes to the proxied domain

 

0 Upvotes
PTrojanowski
Member

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

Hi @robertainslie, thanks for the answer!

 

I understand that  "HubSpot CMS Enterprise product tier" is necessary to have this?

0 Upvotes
robertainslie
HubSpot Employee
HubSpot Employee

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

@PTrojanowski - correct - reverse proxy setup is only available as part of a HubSpot CMS Enterprise tier.

There are obviously some other great features part of that product tier as well (one of the most powerful is access to CMS serverless functions, allowing for dynamic/data driven pages/light weight web apps).

 

If you're wanting to move forward with this project but not sure on your product tiers, shoot me a DM with your HubSpot Hub ID and I can connect with you, and loop in your Customer Success Manager or account executive and we can chat more about if this is the right fit to move forward with.

0 Upvotes
Maicon
Participant

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

You're amazing! Thank you so much for the extra details, I couldn't finish the setup just looking in the official page. It worked perfectly using AWS Cloudfront.

robertainslie
HubSpot Employee
HubSpot Employee

Lessons Learned from Setting up a Reverse Proxy With HubSpot CMS (includes sample nginx config!)

You're welcome! 
If you have any additional insights or want to comment on the specifics of your implementation it would help make this post stronger!
Also, let me know what was unclear in the official documentation - I've been working with HubSpot's Tech Writing team to improve the reverse proxy documentation.