{"id":4949,"date":"2026-10-02T12:01:56","date_gmt":"2026-10-02T06:31:56","guid":{"rendered":"https:\/\/cpanelfree.com\/blog\/how-to-host-a-static-website-with-caddy-server\/"},"modified":"2026-10-02T12:01:56","modified_gmt":"2026-10-02T06:31:56","slug":"how-to-host-a-static-website-with-caddy-server","status":"publish","type":"post","link":"https:\/\/cpanelfree.com\/blog\/how-to-host-a-static-website-with-caddy-server\/","title":{"rendered":"How to Host a Static Website with Caddy Server"},"content":{"rendered":"<p>Deploying high-performance static websites has historically mandated intricate reverse proxy configurations, fragile Certbot cron renewal jobs, and convoluted MIME-type mapping tables in legacy daemons like Apache or Nginx. Modern infrastructure engineers frequently validate static staging environments on <a href=\"https:\/\/cpanelfree.com\">CpanelFree<\/a> before deploying mission-critical architectures across distributed cloud edge nodes. By deploying Caddy Server\u2014a modern, memory-safe web server written in Go\u2014you gain instant zero-configuration TLS automation, native HTTP\/3 QUIC protocol support, and high-ratio Zstandard compression with an extraordinarily concise configuration file.<\/p>\n<p><!-- more --><\/p>\n<h2>Quick Answer: Hosting a Static Website with Caddy<\/h2>\n<div class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-left:4px solid #001b41;border-radius:4px;padding:18px 20px;margin:20px 0\">\n<p style=\"margin:0;font-size:15px;line-height:1.6;color:#333\"><strong>Direct Answer:<\/strong> To host a static website with Caddy, install the Caddy binary via your Linux package manager, place your static assets in <code>\/var\/www\/html<\/code>, and configure a four-line <code>\/etc\/caddy\/Caddyfile<\/code> specifying your domain, document root (<code>root * \/var\/www\/html<\/code>), static file server (<code>file_server<\/code>), and compression (<code>encode zstd gzip<\/code>). Caddy automatically provisions and renews Let&#8217;s Encrypt or ZeroSSL certificates over HTTP\/3 with zero manual cron jobs or external certificate managers.<\/p>\n<\/div>\n<h2>1. Architectural Overview: Why Caddy Outperforms Legacy Web Servers for Static Sites<\/h2>\n<p>Traditional static hosting architectures rely heavily on Nginx or Apache HTTPD. While battle-tested, both servers carry technical debt originating from decades-old operational models. Nginx requires manual OpenSSL linking, complex certificate renewal hooks, and separate modules for modern compression algorithms like Brotli or Zstandard. Apache relies on a process- or worker-threaded multi-processing module (MPM) model that introduces substantial kernel context-switching overhead under severe connection concurrency.<\/p>\n<p>Caddy approaches static delivery through a contemporary systems paradigm:<\/p>\n<ul>\n<li><strong>Memory Safety and Concurrency:<\/strong> Written entirely in Go, Caddy benefits from runtime memory safety, preventing buffer overflows and memory corruption vulnerabilities common in C-based networking daemons. Its network poller utilizes native kernel mechanisms (<code>epoll<\/code> on Linux, <code>kqueue<\/code> on BSD\/macOS) across lightweight goroutines.<\/li>\n<li><strong>Automatic HTTPS by Default:<\/strong> Caddy pioneered zero-touch TLS management. Its integrated ACME client handles domain validation (HTTP-01, TLS-ALPN-01, or DNS-01), certificate issuance via Let&#8217;s Encrypt and ZeroSSL, OCSP stapling, and non-disruptive key rotations without external daemons.<\/li>\n<li><strong>Native HTTP\/3 and QUIC Integration:<\/strong> While legacy web servers often treat QUIC as an experimental compile-time flag requiring custom OpenSSL forks (such as BoringSSL or quictls), Caddy provides first-class HTTP\/3 support out-of-the-box via UDP port 443, mitigating head-of-line blocking on lossy wireless networks.<\/li>\n<li><strong>Next-Generation Compression:<\/strong> In addition to standard Gzip, Caddy features native, streaming Zstandard (<code>zstd<\/code>) and Brotli encoders, providing 15-28% higher compression ratios and faster client decompression cycles for static HTML, CSS, and JavaScript bundles.<\/li>\n<\/ul>\n<blockquote class=\"wp-block-quote\" style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:16px 20px;margin:24px 0\">\n<p><strong style=\"color:#001b41\">Architecture Note:<\/strong> When hosting a <strong>caddy static site<\/strong>, Caddy utilizes Linux&#8217;s zero-copy <code>sendfile(2)<\/code> system call under the hood whenever static assets are transmitted without dynamic on-the-fly transformations. This shifts file block transfers directly from the kernel page cache to the network socket descriptor, completely bypassing user-space memory buffers.<\/p>\n<\/blockquote>\n<h2>2. Performance &amp; Feature Matrix: Caddy vs. Nginx vs. Apache<\/h2>\n<p>To quantify the engineering advantages of running a modern static web server, evaluate how Caddy compares against traditional industry workhorses across enterprise operational parameters:<\/p>\n<figure class=\"wp-block-table is-style-regular\">\n<table style=\"width:100%;border-collapse:collapse;margin:24px 0;font-size:15px;text-align:left\">\n<thead style=\"background:#001b41;color:#ffffff\">\n<tr>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Architectural Parameter<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Apache HTTPD (Event MPM)<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Nginx Open Source<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Caddy Server v2.8+<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;font-weight:600\">TLS \/ SSL Automation<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Manual \/ Certbot Cron<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Manual \/ Certbot Cron<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Fully Autonomous Native ACME<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;font-weight:600\">HTTP\/3 (QUIC) Delivery<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Experimental \/ Patch Required<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Manual Compilation \/ Third-Party<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Built-in Production Default<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;font-weight:600\">Configuration Lines (Base Static)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">~45 lines + vhost files<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">~30 lines<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">4 to 8 lines<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;font-weight:600\">Default Compression Formats<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">mod_deflate (Gzip only)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">gzip (Brotli requires module)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Zstandard (zstd) + Gzip<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;font-weight:600\">Zero-Downtime Reload API<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">graceful restart (SIGUSR1)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">HUP signal reload<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Native REST API \/ Atomic Socket Handoff<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;font-weight:600\">Memory Safety Risk Profile<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">C code pointer vulnerabilities<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">C code pointer vulnerabilities<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Go Garbage Collected \/ Memory Safe<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>3. Step-by-Step Installation on Enterprise Linux Distributions<\/h2>\n<p>Installing Caddy via official upstream package repositories guarantees you receive hardened systemd unit definitions, automated security patches, and correct binary capabilities. Avoid manual unpacks into <code>\/usr\/local\/bin<\/code> unless building custom Caddy plugins via <code>xcaddy<\/code>.<\/p>\n<h3>Deploying on Ubuntu 24.04 LTS and Debian 12<\/h3>\n<p>Execute the following commands to import the official Cloudsmith signing key and configure the APT source list:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Install required transmission and keyring utilities\nsudo apt-get update\nsudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl gnupg\n\n# Import the trusted GPG key for package validation\ncurl -1sLf 'https:\/\/dl.cloudsmith.io\/public\/caddy\/stable\/gpg.key' | sudo gpg --dearmor -o \/usr\/share\/keyrings\/caddy-stable-archive-keyring.gpg\n\n# Configure the official stable APT repository\ncurl -1sLf 'https:\/\/dl.cloudsmith.io\/public\/caddy\/stable\/debian.deb.txt' | sudo tee \/etc\/apt\/sources.list.d\/caddy-stable.list\n\n# Install the production Caddy binary\nsudo apt-get update\nsudo apt-get install -y caddy<\/code><\/pre>\n<h3>Deploying on RHEL 9, Rocky Linux, and AlmaLinux<\/h3>\n<p>On enterprise RPM-based platforms, install the package using DNF with EPEL and COPR repository integration:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Enable EPEL and COPR package managers\nsudo dnf install -y epel-release 'dnf-command(copr)'\nsudo dnf copr enable -y @caddy\/caddy\n\n# Install Caddy package\nsudo dnf install -y caddy\n\n# Enable and verify systemd service state\nsudo systemctl enable --now caddy\nsudo systemctl status caddy --no-pager<\/code><\/pre>\n<h2>4. Directory Hardening and POSIX Permissions<\/h2>\n<p>Security best practices dictate that static web files must never be owned by the web server runtime user if the process only needs read privileges. If an application flaw or unauthorized script executes within the web perimeter, strict ownership prevents malicious modifications to document roots.<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Create the static website document root\nsudo mkdir -p \/var\/www\/static-site\n\n# Assign administrative ownership to your deployment user, with group assigned to caddy\nsudo chown -R $USER:caddy \/var\/www\/static-site\n\n# Enforce least-privilege POSIX directory and file permissions\nsudo find \/var\/www\/static-site -type d -exec chmod 755 {} +\nsudo find \/var\/www\/static-site -type f -exec chmod 644 {} +\n\n# Verify SELinux context on RHEL\/Rocky distributions\nsudo restorecon -Rv \/var\/www\/static-site<\/code><\/pre>\n<blockquote class=\"wp-block-quote\" style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:16px 20px;margin:24px 0\">\n<p><strong style=\"color:#001b41\">Security Guardrail:<\/strong> Never execute Caddy as root in production. The official Linux packages automatically configure the <code>caddy<\/code> system user and grant low-port binding capabilities (<code>CAP_NET_BIND_SERVICE<\/code>) directly to the binary using <code>setcap<\/code>, allowing ports 80 and 443 to bind without administrative privilege.<\/p>\n<\/blockquote>\n<h2>5. Crafting the Enterprise Production Caddyfile<\/h2>\n<p>Caddy\u2019s configuration syntax, known as the <code>Caddyfile<\/code>, is declarative, human-readable, and free from the punctuation traps of Nginx. Below is a comprehensive, production-ready configuration for hosting high-traffic static websites, documentation sites (e.g., VitePress, Docusaurus), or Single Page Applications (SPAs) built with React, Vue, or Svelte.<\/p>\n<p>Save this configuration directly to <code>\/etc\/caddy\/Caddyfile<\/code>:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Global Options Block\n{\n    # Strict administrative and logging posture\n    admin 127.0.0.1:2019\n    email security-ops@example.com\n    \n    # Enforce modern TLS parameters\n    servers {\n        protocols h1 h2 h3\n        strict_sni_host insecure_off\n    }\n}\n\n# Primary Static Site Virtual Host Block\nexample.com, www.example.com {\n    # Canonicalize apex domain: redirect www to apex\n    @www host www.example.com\n    handle @www {\n        redir https:\/\/example.com{uri} permanent\n    }\n\n    # Define the document root path\n    root * \/var\/www\/static-site\n\n    # Enable high-ratio Zstandard and Gzip on-the-fly compression\n    encode zstd gzip\n\n    # Security and Performance HTTP Response Headers\n    header {\n        # Strict Transport Security (HSTS 2 Years with subdomains and preload)\n        Strict-Transport-Security \"max-age=63072000; includeSubDomains; preload\"\n        \n        # Clickjacking and MIME sniffing protections\n        X-Frame-Options \"SAMEORIGIN\"\n        X-Content-Type-Options \"nosniff\"\n        Referrer-Policy \"strict-origin-when-cross-origin\"\n        \n        # Permissions Policy: Disable unused device sensors\n        Permissions-Policy \"accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()\"\n        \n        # Strip default server identification token\n        -Server\n    }\n\n    # Immutable caching headers for fingerprinted static assets\n    @immutable path *.js *.css *.png *.jpg *.jpeg *.gif *.svg *.woff2 *.webp *.avif\n    header @immutable Cache-Control \"public, max-age=31536000, immutable\"\n\n    # HTML cache policy: require revalidation\n    @html path *.html \/\n    header @html Cache-Control \"public, max-age=0, must-revalidate\"\n\n    # SPA Routing Fallback: serve exact file or fallback to index.html\n    try_files {path} {path}\/ \/index.html\n\n    # Enable high-performance static file server with precompressed asset support\n    file_server {\n        precompressed zstd br gzip\n        hide .git .env *.conf\n    }\n\n    # Structured JSON access logging for observability and log parsers\n    log {\n        output file \/var\/log\/caddy\/static-site_access.log {\n            roll_size 50mb\n            roll_keep 10\n            roll_keep_for 720h\n        }\n        format json\n    }\n}<\/code><\/pre>\n<h3>Validating and Applying the Caddyfile<\/h3>\n<p>Before applying new configuration blocks to a live production cluster, always execute Caddy&#8217;s built-in syntax parser to guarantee zero syntactical errors:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Validate Caddyfile structure and directive grammar\ncaddy validate --config \/etc\/caddy\/Caddyfile\n\n# Reload configuration gracefully with zero dropped TCP\/UDP sockets\nsudo systemctl reload caddy<\/code><\/pre>\n<h2>6. Operating System &amp; Kernel Performance Tuning for Caddy Static Sites<\/h2>\n<p>While Caddy delivers remarkable throughput out of the box, unoptimized Linux kernel network defaults will throttle server capacity under massive traffic spikes. Bottlenecks often emerge at the socket backlog layer, local port allocations, and file descriptor limits.<\/p>\n<h3>Network and Memory Tuning via Sysctl<\/h3>\n<p>Create an enterprise kernel configuration file at <code>\/etc\/sysctl.d\/99-caddy-performance.conf<\/code> to optimize TCP\/UDP buffers, enable BBR congestion control, and enlarge connection queues:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Kernel File Descriptor Limits\nfs.file-max = 2097152\n\n# Socket Listen Backlog for high-concurrency connection queues\nnet.core.somaxconn = 65535\nnet.ipv4.tcp_max_syn_backlog = 65535\n\n# Enlarge UDP socket buffers for QUIC\/HTTP-3 throughput\nnet.core.rmem_max = 16777216\nnet.core.wmem_max = 16777216\nnet.core.rmem_default = 1048576\nnet.core.wmem_default = 1048576\n\n# TCP Window Scaling and Buffer Auto-tuning\nnet.ipv4.tcp_rmem = 4096 87380 16777216\nnet.ipv4.tcp_wmem = 4096 65536 16777216\n\n# Enable TCP BBR Congestion Control (requires Linux Kernel 4.9+)\nnet.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\n\n# Fast recycling of TIME_WAIT sockets\nnet.ipv4.tcp_tw_reuse = 1\nnet.ipv4.tcp_fin_timeout = 15<\/code><\/pre>\n<p>Apply the parameters immediately without restarting the host:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>sudo sysctl --system<\/code><\/pre>\n<h3>Systemd Service Resource Limits Override<\/h3>\n<p>By default, systemd caps process file descriptors. Under peak static asset delivery loads (tens of thousands of concurrent browser requests), Caddy will throw <code>too many open files<\/code> errors unless resource limits are expanded. Create a systemd drop-in override at <code>\/etc\/systemd\/system\/caddy.service.d\/override.conf<\/code>:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>[Service]\n# Raise file descriptor soft and hard limits for high concurrent connections\nLimitNOFILE=1048576\nLimitNPROC=512\n\n# Prevent OOM killer from prematurely killing the web server\nOOMScoreAdjust=-500\n\n# Security sandboxing enhancements\nProtectSystem=full\nProtectHome=true\nPrivateTmp=true<\/code><\/pre>\n<p>Reload systemd and restart the service:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>sudo systemctl daemon-reload\nsudo systemctl restart caddy<\/code><\/pre>\n<h2>7. Firewall Configuration for HTTP\/3 QUIC Operations<\/h2>\n<p>A frequent operational mistake when setting up a <strong>caddy static site<\/strong> is failing to open UDP port 443 in the host firewall. HTTP\/1.1 and HTTP\/2 operate exclusively over TCP. However, HTTP\/3 requires bidirectional UDP datagram communication. If UDP port 443 is blocked, modern client browsers will experience protocol fallback delays, degrading Core Web Vitals (INP and LCP).<\/p>\n<h3>UFW Configuration (Debian \/ Ubuntu)<\/h3>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># Allow standard HTTP (TCP 80) and HTTPS (TCP 443)\nsudo ufw allow 80\/tcp comment 'Caddy HTTP'\nsudo ufw allow 443\/tcp comment 'Caddy HTTPS TCP'\n\n# Allow HTTP\/3 QUIC (UDP 443)\nsudo ufw allow 443\/udp comment 'Caddy HTTP\/3 QUIC'\nsudo ufw reload<\/code><\/pre>\n<h3>Firewalld Configuration (RHEL \/ Rocky \/ AlmaLinux)<\/h3>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>sudo firewall-cmd --permanent --add-service=http\nsudo firewall-cmd --permanent --add-service=https\nsudo firewall-cmd --permanent --add-port=443\/udp\nsudo firewall-cmd --reload<\/code><\/pre>\n<h2>8. Enterprise Production Strategy: When to Transition to Managed Cloud<\/h2>\n<p>Deploying Caddy on self-managed VPS droplets or compute instances is ideal for lightweight static documentation, developer portfolios, and internal micro-sites. However, managing unmanaged Linux servers introduces significant enterprise overhead: applying continuous CVE kernel patches, provisioning DDoS mitigation scrubbing centers, managing persistent storage snapshots, and configuring multi-region Anycast DNS failover.<\/p>\n<p>For organizations running revenue-generating web properties, e-commerce storefronts, or high-traffic corporate blogs that demand continuous 99.99% uptime without sysadmin maintenance burdens, transitioning to <a href=\"https:\/\/merahost.org\" target=\"_blank\" rel=\"noopener\">MeraHost Enterprise Cloud<\/a> represents the optimal architectural path. MeraHost combines pure Enterprise NVMe storage arrays with enterprise-licensed LiteSpeed Web Server, automated multi-tier caching engines, and their signature <em>Same Renewal Price, Always<\/em> pledge (starting at \u20b999\/mo with zero renewal price inflation).<\/p>\n<h2>Frequently Asked Questions<\/h2>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Can Caddy serve precompressed Brotli and Zstandard assets?<\/summary>\n<p style=\"margin-top:10px;color:#444\">Yes. By adding the <code>precompressed zstd br gzip<\/code> directive inside your <code>file_server<\/code> block, Caddy will automatically search the filesystem for precompressed static siblings (e.g., <code>bundle.js.zst<\/code>, <code>styles.css.br<\/code>, or <code>index.html.gz<\/code>) before falling back to on-the-fly compression. This saves significant CPU cycles during continuous high-traffic asset serving.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">How does Caddy handle Let&#8217;s Encrypt rate limits during development?<\/summary>\n<p style=\"margin-top:10px;color:#444\">If you are repeatedly testing configurations on staging domains, you risk hitting Let&#8217;s Encrypt production rate limits (5 duplicate certificates per week). To avoid this, set <code>acme_ca https:\/\/acme-staging-v02.api.letsencrypt.org\/directory<\/code> inside your site block or global options block during staging tests before switching to the production CA.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Why is Caddy returning a 403 Forbidden error on my static files?<\/summary>\n<p style=\"margin-top:10px;color:#444\">A 403 Forbidden error almost always indicates either improper POSIX permissions or an active SELinux policy. Verify that the <code>caddy<\/code> user has read access (<code>chmod 644<\/code>) to files and execute\/traversal permissions (<code>chmod 755<\/code>) across all parent directories leading to your document root. On RHEL systems, run <code>chcon -Rt httpd_sys_content_t \/var\/www\/static-site<\/code>.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Can I route Single Page Applications (React, Vue, Vite) without broken 404s?<\/summary>\n<p style=\"margin-top:10px;color:#444\">Yes. Client-side routed applications require all non-file route requests to resolve to your root template. Including the directive <code>try_files {path} {path}\/ \/index.html<\/code> ensures that requests for virtual routes like <code>\/dashboard<\/code> or <code>\/settings<\/code> cleanly serve <code>index.html<\/code>, enabling client-side JavaScript routers to handle rendering seamlessly.<\/p>\n<\/details>\n<div class=\"wp-block-group has-background\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:8px;padding:32px;margin:40px 0;text-align:center\">\n<h3 style=\"color:#001b41;margin-top:0;font-size:24px;font-weight:700\">Deploy Enterprise-Grade Production Infrastructure<\/h3>\n<p style=\"color:#444;font-size:16px;line-height:1.6;max-width:680px;margin:12px auto 24px auto\">Need guaranteed performance with zero price hikes? Host mission-critical workloads on <strong style=\"color:#001b41\">MeraHost<\/strong> with pure Enterprise NVMe, LiteSpeed Web Server, and Same Renewal Price, Always (starting at \u20b999\/mo).<\/p>\n<div class=\"wp-block-buttons\" style=\"display:flex;gap:16px;justify-content:center;flex-wrap:wrap\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"https:\/\/merahost.org\" style=\"background:#001b41;color:#ffffff;font-weight:700;padding:12px 28px;border-radius:4px;text-decoration:none;display:inline-block;font-size:15px\" target=\"_blank\" rel=\"noopener\">Explore MeraHost NVMe Cloud &rarr;<\/a><\/div>\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link\" href=\"https:\/\/cpanelfree.com\" style=\"background:transparent;color:#001b41;font-weight:600;padding:12px 24px;border:2px solid #001b41;border-radius:4px;text-decoration:none;display:inline-block;font-size:15px\">Deploy Free Staging on CpanelFree<\/a><\/div>\n<\/p><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Master Caddy Server for hosting static sites with automated HTTPS, HTTP\/3, and Zstandard compression. Learn enterprise configurations and Linux kernel tuning.<\/p>\n","protected":false},"author":1,"featured_media":4948,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[211],"tags":[57,177,87,101,212],"class_list":["post-4949","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-servers","tag-almalinux","tag-databases-performance","tag-devops","tag-sysadmin","tag-web-servers"],"_links":{"self":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/4949","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/comments?post=4949"}],"version-history":[{"count":0,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/4949\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media\/4948"}],"wp:attachment":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media?parent=4949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/categories?post=4949"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/tags?post=4949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}