{"id":5233,"date":"2026-08-30T11:30:39","date_gmt":"2026-08-30T02:30:39","guid":{"rendered":"https:\/\/donguri3.net\/server-tech\/enable-quic-cloud-on-selfhosted-wordpress-via-wireguard-2\/"},"modified":"2026-08-30T11:30:41","modified_gmt":"2026-08-30T02:30:41","slug":"enable-quic-cloud-on-selfhosted-wordpress-via-wireguard","status":"publish","type":"post","link":"https:\/\/donguri3.net\/en\/server-tech\/wordpress-blog-seo\/enable-quic-cloud-on-selfhosted-wordpress-via-wireguard\/","title":{"rendered":"A True Account of Enabling QUIC.cloud on a Home WordPress Server (OpenLiteSpeed + WireGuard Exposure)"},"content":{"rendered":"<p>I was stuck trying to enable the LiteSpeed Cache CDN (QUIC.cloud) on my home WordPress server (running OpenLiteSpeed, hereafter OLS). However, I managed to break through using a three-stage rocket approach:<\/p>\n<ol>\n<li>\u2460 Temporarily insert nginx as an L7 terminator to append X-Forwarded-For \u2192<\/li>\n<li>\u2461 Register with QUIC.cloud \u2192<\/li>\n<li>\u2462 Remove nginx and revert to the L4 architecture using WireGuard + iptables.<\/li>\n<\/ol>\n<p>Since then, HTTP\/3 is terminated on the CDN side, while the origin remains OLS for a lightweight setup.<\/p>\n<p>I have already summarized the foundation for exposing a home server using a remote server (Oracle Cloud Infrastructure Free Tier) \u00d7 WireGuard in another article. Please refer to that post for details on how to set up the exposure route:<br \/>\n<a href=\"https:\/\/donguri3.net\/server-tech\/deploy-webserver-using-wireguard-oci\/\">Exposing a Web Server in an Apartment Complex Network Using WireGuard and a VPS (OCI)<\/a><\/p>\n<p>In this article, I will focus specifically on the stumbling blocks and workarounds for enabling QUIC.cloud.<\/p>\n<h2>Architecture and Terminology<\/h2>\n<ul>\n<li>Remote (OCI): WireGuard (hereinafter WG-Remote)<\/li>\n<li>Local (Home): WireGuard (hereinafter WG-Local) \u2192 OpenLiteSpeed (OLS) \u2192 WordPress<\/li>\n<li>Route: Internet \u2192 (CDN: QUIC.cloud) \u2192 WG-Remote \u2192 (Tunnel) \u2192 WG-Local \u2192 OLS<\/li>\n<\/ul>\n<p><a href=\"https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1.jpg\"><img decoding=\"async\" class=\"aligncenter size-large wp-image-379\" src=\"https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-1024x576.jpg\" alt=\"Exposing a Web Server in an Apartment Complex Network Using WireGuard and a VPS (OCI)\" width=\"1024\" height=\"576\" srcset=\"https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-1024x576.jpg 1024w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-300x169.jpg 300w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-768x432.jpg 768w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-1536x864.jpg 1536w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-320x180.jpg 320w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-530x298.jpg 530w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-565x318.jpg 565w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-710x399.jpg 710w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-725x408.jpg 725w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1-160x90.jpg 160w, https:\/\/donguri3.net\/wp-content\/uploads\/2025\/02\/\u30de\u30f3\u30b7\u30e7\u30f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5185\u306e\u30a6\u30a7\u30d6\u30b5\u30fc\u30d0\u3092\u516c\u958b-1.jpg 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<table>\n<thead>\n<tr style=\"height: 45px;\">\n<th style=\"width: 185.969px; height: 45px;\">Term<\/th>\n<th style=\"width: 247.469px; height: 45px;\">Layer\/Category<\/th>\n<th style=\"width: 291.562px; height: 45px;\">Function<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr style=\"height: 132px;\">\n<td style=\"width: 185.969px; height: 132px;\"><strong>L4 (Layer 4)<\/strong><\/td>\n<td style=\"width: 247.469px; height: 132px;\">Network (Transport Layer)<\/td>\n<td style=\"width: 291.562px; height: 132px;\">Port-based forwarding\/load balancing, DNAT\/SNAT, etc.<\/td>\n<\/tr>\n<tr style=\"height: 74px;\">\n<td style=\"width: 185.969px; height: 74px;\"><strong>DNAT<\/strong><\/td>\n<td style=\"width: 247.469px; height: 74px;\">L4\/NAT<\/td>\n<td style=\"width: 291.562px; height: 74px;\">Securely relays external ports to the backend server<\/td>\n<\/tr>\n<tr style=\"height: 74px;\">\n<td style=\"width: 185.969px; height: 74px;\"><strong>nginx <code>stream<\/code><\/strong><\/td>\n<td style=\"width: 247.469px; height: 74px;\">L4<\/td>\n<td style=\"width: 291.562px; height: 74px;\">Relays 80\/443 (TCP) and 443\/UDP (QUIC)<\/td>\n<\/tr>\n<tr style=\"height: 103px;\">\n<td style=\"width: 185.969px; height: 103px;\"><strong>L7 (Layer 7)<\/strong><\/td>\n<td style=\"width: 247.469px; height: 103px;\">Application Layer<\/td>\n<td style=\"width: 291.562px; height: 103px;\">Appends <code>X-Forwarded-For<\/code>, hostname\/URL-based control, WAF<\/td>\n<\/tr>\n<tr style=\"height: 74px;\">\n<td style=\"width: 185.969px; height: 74px;\"><strong>OLS (OpenLiteSpeed)<\/strong><\/td>\n<td style=\"width: 247.469px; height: 74px;\">Web Server<\/td>\n<td style=\"width: 291.562px; height: 74px;\">High-speed delivery, LSCache integration, QUIC (depending on conditions)<\/td>\n<\/tr>\n<tr style=\"height: 103px;\">\n<td style=\"width: 185.969px; height: 103px;\"><strong>X-Forwarded-For (XFF)<\/strong><\/td>\n<td style=\"width: 247.469px; height: 103px;\">HTTP Header (L7)<\/td>\n<td style=\"width: 291.562px; height: 103px;\">Passes the real IP to the application\/logs<\/td>\n<\/tr>\n<tr style=\"height: 74px;\">\n<td style=\"width: 185.969px; height: 74px;\"><strong>CDN (QUIC.cloud)<\/strong><\/td>\n<td style=\"width: 247.469px; height: 74px;\">Delivery Network<\/td>\n<td style=\"width: 291.562px; height: 74px;\">Caching, TLS\/HTTP3, DDoS mitigation, PoP optimization<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Enabling WordPress LiteSpeed Cache CDN (QUIC.cloud)<\/h2>\n<ul>\n<li>Conditions for enabling LiteSpeed Cache CDN (QUIC.cloud)\n<ul>\n<li>\u2026\/?rest_route=\/lscwp\/ip-check must return remote_ip (route IP) + <span style=\"color: #ff0000;\">x_forwarded_for (client real IP)<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>Why I Got Stuck<\/h2>\n<ul>\n<li>X-Forwarded-For cannot be added at L4<br \/>\nnginx stream and simple DNAT cannot touch the &#8220;inside&#8221; of TCP\/UDP packets.<\/li>\n<li>OpenLiteSpeed does not support PROXY protocol<br \/>\nTricks to carry the original IP via L4 (PROXY proto) cannot be used with OLS either.<\/li>\n<li>Result: WordPress\/OLS cannot recognize the real client IP, causing LiteSpeed Cache&#8217;s ip-check \/ CDN activation to be rejected.<\/li>\n<\/ul>\n<h2>Solution<\/h2>\n<ol>\n<li data-start=\"1374\" data-end=\"1496\"><strong data-start=\"1374\" data-end=\"1405\">Temporarily insert nginx in front at L7 (HTTP)<\/strong><br data-start=\"1405\" data-end=\"1408\" \/>Set up an nginx container on the remote side, perform <strong data-start=\"1432\" data-end=\"1441\">TLS termination<\/strong>, and <strong data-start=\"1442\" data-end=\"1467\"><code data-start=\"1444\" data-end=\"1461\">X-Forwarded-For<\/code> attachment<\/strong>. The backend connects to OLS via WireGuard.\n<ol>\n<li data-start=\"1374\" data-end=\"1496\"><code data-start=\"1502\" data-end=\"1532\">\/?rest_route=\/lscwp\/ip-check<\/code> will now return <strong data-start=\"1535\" data-end=\"1568\"><code data-start=\"1537\" data-end=\"1548\">remote_ip<\/code> + <code data-start=\"1549\" data-end=\"1566\">x_forwarded_for<\/code><\/strong>.<\/li>\n<\/ol>\n<\/li>\n<li data-start=\"1374\" data-end=\"1496\"><strong style=\"font-size: 1.4rem;\" data-start=\"1582\" data-end=\"1629\">Enable LiteSpeed Cache CDN (QUIC.cloud) in this state<br \/>\n<\/strong><span style=\"font-size: 1.4rem;\">Ownership verification and registration will pass. Confirm that <\/span><strong style=\"font-size: 1.4rem;\" data-start=\"1654\" data-end=\"1668\"><code data-start=\"1656\" data-end=\"1666\">x-qc-pop<\/code><\/strong><span style=\"font-size: 1.4rem;\"> and <\/span><strong style=\"font-size: 1.4rem;\" data-start=\"1670\" data-end=\"1694\"><code data-start=\"1672\" data-end=\"1692\">alt-svc: h3=\":443\"<\/code><\/strong><span style=\"font-size: 1.4rem;\"> appear in the response.<\/span><\/li>\n<li data-start=\"1374\" data-end=\"1496\"><strong style=\"font-size: 1.4rem;\" data-start=\"1707\" data-end=\"1752\">Remove nginx and revert to L4 (WireGuard + iptables DNAT)<\/strong><span style=\"font-size: 1.4rem;\">Exposed ports :80\/:443 (and :443\/udp if needed) are set to <\/span><strong style=\"font-size: 1.4rem;\" data-start=\"1786\" data-end=\"1800\">DNAT \u2192 OLS<\/strong><span style=\"font-size: 1.4rem;\">.<\/span><span style=\"font-size: 1.4rem;\"> Configure OLS with &#8220;Use Client IP in Header = Trusted IP Only&#8221;, and <\/span><strong style=\"font-size: 1.4rem;\" data-start=\"1864\" data-end=\"1905\">register the tunnel peer&#8217;s source IP in the Allowed List with a <code data-start=\"1880\" data-end=\"1883\">T<\/code> flag<\/strong><span style=\"font-size: 1.4rem;\"> (= accept <code style=\"font-size: 1.4rem;\" data-start=\"1921\" data-end=\"1926\">XFF<\/code> only from trusted proxies).<\/span><span style=\"font-size: 1.4rem;\">From then on, <\/span><strong style=\"font-size: 1.4rem;\" data-start=\"1944\" data-end=\"1963\">HTTP\/3 is terminated at the CDN side<\/strong><span style=\"font-size: 1.4rem;\">, keeping the origin lightweight.<\/span><\/li>\n<\/ol>\n<blockquote data-start=\"1976\" data-end=\"2044\">\n<p data-start=\"1978\" data-end=\"2044\">Key takeaway: <strong data-start=\"1983\" data-end=\"2024\">&#8220;Insert L7 only during registration to guarantee XFF&#8221; \u2192 Revert to L4 after registration<\/strong>. CDN handles operations, origin remains minimal.<\/p>\n<\/blockquote>\n<h2 data-start=\"2046\" data-end=\"2061\">Implementation Notes (Example)<\/h2>\n<p>Example of temporary nginx (L7)<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">server {\n  listen 443 ssl http2;\n  server_name example.com;\n  ssl_certificate     \/etc\/ssl\/fullchain.pem;\n  ssl_certificate_key \/etc\/ssl\/privkey.pem;\n  location \/ {\n    proxy_pass https:\/\/&amp;amp;lt;OLS_IP&amp;amp;gt;;\n    proxy_http_version 1.1;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # \u2190This is it!\n    proxy_set_header X-Forwarded-Proto https;\n    proxy_set_header X-Real-IP $remote_addr;\n  }\n}\n<\/pre>\n<p>This allows ip-check to recognize the &#8220;real IP (XFF)&#8221; and completes the QUIC.cloud activation.<\/p>\n<h3>After Reverting to L4 (WireGuard + DNAT)<\/h3>\n<ul>\n<li>DNAT: Public :80\/:443 (and :443\/udp if needed) \u2192 OLS :80\/:443<\/li>\n<li>SNAT\/MASQUERADE: Restricted only to &#8220;traffic originating from wg0 destined for OLS&#8221; (fixed return route)<\/li>\n<li>FORWARD: Allow only WAN\u2192wg0 destined for OLS \/ Returns allowed via ESTABLISHED,RELATED<\/li>\n<li>OLS: Set Use Client IP in Header = Trusted IP Only, register the tunnel peer IP with a T flag in the Allowed List (= accept XFF only from trusted proxies)<\/li>\n<\/ul>\n<blockquote>\n<p>Only keep <strong data-start=\"2934\" data-end=\"2952\">UDP\/443 DNAT<\/strong> if you want to receive direct access via HTTP\/3. <strong data-start=\"2956\" data-end=\"2972\">Unnecessary if CDN termination is sufficient<\/strong> (also reduces attack surface).<\/p>\n<\/blockquote>\n<h2>Verification Methods<\/h2>\n<ul>\n<li>CDN-proxied headers<br \/>\ncurl -I https:\/\/example.com | tr -d &#8216;\\r&#8217; | grep -i &#8216;server\\|x-qc-pop\\|alt-svc&#8217;<\/li>\n<li>CDN bypass (fixed SNI)<br \/>\ncurl -vk &#8211;resolve example.com:443: https:\/\/example.com\/ | head -n1<\/li>\n<li>WordPress-side view (using a test script)<br \/>\nSuccess if REMOTE_ADDR shows the real IP and X-Forwarded-For contains the same initial IP.<\/li>\n<\/ul>\n<h2>Pitfalls to Watch Out For<\/h2>\n<ul>\n<li>XFF cannot be attached with L4 alone (HTTP headers are an L7 concept)<\/li>\n<li>OpenLiteSpeed does not support PROXY protocol (cannot carry the original IP via L4)<\/li>\n<li>Broad iptables MASQUERADE is dangerous: restricting by sending IF &amp; destination subnet is the ironclad rule<\/li>\n<li>Do not expose :80\/:443 across multiple containers (watch out for docker-proxy conflicts)<\/li>\n<\/ul>\n<h2>Summary<\/h2>\n<ul>\n<li>Unless XFF is visible, QUIC.cloud&#8217;s ip-check will not pass.<\/li>\n<li>Therefore, interject L7 (nginx) only during registration to guarantee XFF, and revert to L4 (WireGuard + DNAT) once registration is complete.<\/li>\n<li>Operationally, terminate HTTP\/3 at the CDN and keep the origin light with OLS.<\/li>\n<li>Limit OLS to trusted proxies using Trusted IP Only + Allowed List.<\/li>\n<\/ul>\n<p>Through this workflow, I was able to successfully leverage QUIC.cloud even with a Home Server \u00d7 WireGuard \u00d7 OCI setup.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was stuck trying to enable the LiteSpeed Cache CDN (QUIC.cloud) on my home WordPress server (running OpenLit [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":2274,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"en_US","_original_post":"https:\/\/donguri3.net\/?p=2270","footnotes":""},"categories":[1166],"tags":[119,18,27,15,117,20,13,14,92,61,10,310,381,131],"class_list":["post-5233","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-wordpress-blog-seo","tag-cdn","tag-docker","tag-iptables","tag-litespeed","tag-litespeed-cache","tag-oci","tag-ols","tag-openlitespeed","tag-wireguard","tag-wordpress","tag-server","tag-310","tag-381","tag-131","en-US"],"_links":{"self":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5233","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/comments?post=5233"}],"version-history":[{"count":1,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5233\/revisions"}],"predecessor-version":[{"id":5236,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5233\/revisions\/5236"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media\/2274"}],"wp:attachment":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media?parent=5233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/categories?post=5233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/tags?post=5233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}