Suggested filters
keyword:keyword:setup
results for a specific keyword
question:question:how do I get started?
AI will suggest the best answer
Dashboard
Edit Article Logout

Setup Reverse Proxy


HelpGuides support configuration of reverse proxy for advanced scenarios.

What is Reverse Proxy?

For the sake of example, let's say you own a domain example.com. You have an existing website using that domain running WordPress where you host a blog: example.com/blog/example-name.

You then created a project on HelpGuides myproject.helpguides.io. And, you want to move your blog content from WordPress to HelpGuides while still using WordPress for your main website. This setup is known as a reverse proxy.

How it works

Requests sent to example.com/blog/example-name are proxied to myproject.helpguides.io/example-name. The blog content is hosted at myproject.helpguides.io, but the browser URL and canonical URL remains example.com/blog/example-name.

Why use a reverse proxy?

The use case for a reverse proxy is:

  • Migrate content to a more robust platform, e.g. HelpGuides (search, APIs, AI tools, etc.)
  • Do not break existing, published URLs
  • Ensure that content remains associated with the root domain vs. a subdomain - good for SEO.

Setting up a Reverse Proxy

Setting up a Reverse Proxy is a complex topic. But platforms such as Cloudflare make these types of advanced configurations relatively simple.

Recommended

If you want to support a reverse proxy for your HelpGuides content, please contact support. Reverse proxy configuration is only available in our enterprise plans.

Reverse Proxy with Cloudflare

Important

Setting up a reverse proxy with Cloudflare requires mapping your DNS record to Cloudflare. If you cannot do this, you cannot use Cloudflare for reverse DNS.

Step 1 - Get your application domain

You Application Domain is found in your HelpGuides project settings:

When no reverse proxy is used, this is the path used for your documentation hosted on HelpGuides. Note, HelpGuides does support custom subdomains too.

Step 2 - Get your canonical path

Your canonical path is configured by the HelpGuides team. Once configured you can find it on the Advanced Tab in settings:

In the above example, we're showing how we map requests to httsp://helpguides.io/blog to our main domain https://vszh13.helpguides.io. This could just as easily be https://yourdomain.com/blog mapping to https://[your subdomain].helpguides.io.

Step 3 - Create a Cloudflare worker

Create a Cloudflare worker to manage reverse proxy requests from your domain into your helpguides.io project. You will need your Application Domain. The script below is used to rewrite requests that have a /blog/.

For example, a request to:

https://helpguides.io/blog/helpguidesio-now-supports-model-context-protocol-mcp

is reverse proxied to:

https://vszh13.helpguides.io/helpguidesio-now-supports-model-context-protocol-mcp

If you are going to use different paths, your configuration may be different.

export default { const app_domain "https://vszh13.helpguides.io/"; async fetch(request, env, ctx) { const incomingUrl = new URL(request.url); // Check if path starts with /blog or is exactly /blog if (incomingUrl.pathname === "/blog" || incomingUrl.pathname === "/blog/") { // Handle root blog page return fetchAndProcess(app_domain, request, incomingUrl); } // Handle all other blog paths like /blog/hello-world, /blog/site.json if (incomingUrl.pathname.startsWith("/blog/")) { const targetPath = incomingUrl.pathname.replace("/blog", ""); const targetUrl = `${app_domain}${targetPath}${incomingUrl.search}`; return fetchAndProcess(targetUrl, request, incomingUrl); } return new Response("Not Found", { status: 404 }); } } // Extracted handler function for reuse async function fetchAndProcess(targetUrl, originalRequest, incomingUrl) { const proxyRequest = new Request(targetUrl, { method: originalRequest.method, headers: new Headers({ ...Object.fromEntries(originalRequest.headers), 'X-Forwarded-Host': incomingUrl.hostname, // passes "root domain" }), body: originalRequest.body, redirect: "manual" }); const originResponse = await fetch(proxyRequest); const contentType = originResponse.headers.get("Content-Type") || ""; // HTML: rewrite relative paths if (contentType.includes("text/html")) { let html = await originResponse.text(); html = html.replace(/(href|src)=["']\/(?!\/)/g, `$1="${app_domain}`); return new Response(html, { status: originResponse.status, headers: { "Content-Type": "text/html", "Cache-Control": "public, max-age=60" } }); } // Other file types (CSS, JSON, etc.) return new Response(originResponse.body, { status: originResponse.status, headers: originResponse.headers }); }

How helpful was this article?

πŸ‘ or πŸ‘Ž

Related Articles

Markdown Version