How to Configure Custom NGINX in xCloud
Updated October 29, 2026 · 10 min read
Custom NGINX lets site administrators add NGINX directives from the xCloud dashboard without editing generated server files manually. This guide explains how to choose the correct insertion point, add and validate a rule, use Inside Main Location Block for a PHP application, and disable or re-enable a saved rule without deleting it.
Important: Custom NGINX rules can affect site availability, redirects, caching, and security. Test one change at a time, keep a copy of the previous rule, and use Run & Debug before saving.
Prerequisites
- A site hosted on a server that uses NGINX.
- Access to the site’s Tools → Nginx Customization page.
- Permission to manage Custom NGINX settings for the site. Members who cannot manage server settings have extra limits.
- A tested NGINX directive or rule and a rollback plan.
- A terminal with
curlif you want to verify response headers from outside xCloud.
Choose the correct insertion point
The available choices depend on the site’s application type and enabled features. PHP applications show the main and PHP location options, while non-PHP applications show the proxy location option.
| xCloud option | Internal type | Use it when the directive belongs… | Availability |
|---|---|---|---|
| Before Server Block | before |
Before the generated server {} block |
NGINX sites |
| Inside Server Block | server |
Directly inside the generated server {} block, but outside its location blocks |
NGINX sites |
| Inside Main Location Block | main_location |
Inside the main PHP application location / block |
PHP applications |
| Inside PHP Location Block | php |
Inside the dedicated PHP request-handler location | PHP applications |
| Inside Proxy Location Block | proxy |
Inside the location that proxies requests to a non-PHP application | Non-PHP applications |
| After Server Block | after |
After the generated server {} block |
NGINX sites |
| 7G Block or 8G Block | 7g or 8g |
Inside the corresponding firewall section | Only when that firewall is enabled |
Inside Main Location Block is not the same as Inside PHP Location Block. The main location handles normal application requests under location /; the PHP location handles .php requests passed to PHP. Put a directive in the narrowest valid context and check the directive’s official NGINX context before saving it.

The main_location type appears in the dashboard as Inside Main Location Block for PHP applications.
Step 1: Open Nginx Customization
Select the site in xCloud, then go to Tools → Nginx Customization.
Expected result: The Custom Nginx Config table opens and shows any saved rules, their type, active state, and available actions.
Step 2: Start a new configuration
Select Add a New Config.
Expected result: The Create Custom Nginx Configuration modal opens.
Step 3: Choose a template
Select a built-in template when it matches your use case. Otherwise, select Use My Own Config.
Expected result: When Use My Own Config is selected, the config type, file name, and content fields become available.
Step 4: Select the insertion point
Choose the option that matches the NGINX context required by your rule. For a directive that must run inside a PHP application’s main location / block, select Inside Main Location Block.
Expected result: The preview places your content at the selected insertion point. For main_location, xCloud stores the file under /etc/nginx/xcloud-conf/<site>/main_location/<file>.conf and includes it inside the generated main location block.
Step 5: Name the configuration
Enter a descriptive file name without the .conf extension, such as documentation-header or legacy-path-redirect.
Expected result: xCloud previews the generated .conf path below the field.
Step 6: Enter the NGINX directive
For a small, reversible test inside the server block, you can use a response header:
add_header X-Documentation-Rule "enabled" always;
For a PHP application’s main location block, this example redirects one test path:
rewrite ^/old-documentation-path$ /new-documentation-path permanent;
Replace the example paths with the real paths you intend to use. Do not copy a server {} or location {} wrapper into an insertion point that is already inside that context.
Expected result: The right-hand preview shows the directive in the generated NGINX configuration.
Step 7: Validate the rule
Select Run & Debug.
Expected result: xCloud writes a temporary configuration, runs NGINX validation, displays the result, and removes the temporary file after the check. A successful result confirms the syntax is valid in the selected insertion point. It does not confirm that the rule’s behavior matches your intent.
A successful check shows a green message:

If validation fails, xCloud removes the temporary file and does not reload NGINX. The error is shown in red:

Correct the reported directive, context, or syntax error before continuing.
Step 8: Save the rule
Select Save Config only after Run & Debug succeeds.
Expected result: xCloud validates the configuration and reloads NGINX only when validation passes. The saved rule appears in the table with an active state.

Each saved rule has its own Active toggle, so you can roll back one rule without deleting its content.
Built-in templates
The Select Template list ships ready-made rules for Rank Math sitemaps and Hide My WP. Pick one and xCloud fills the type, file name and content for you; choose Use My Own Config for anything else. The Rank Math template, for example, places these rewrites inside the server block:
# START NGINX Rewrites for Rank Math Sitemaps
rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last;
rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
rewrite ^/([a-z]+)?-sitemap\.xsl$ /index.php?xsl=$1 last;
# END NGINX Rewrites for Rank Math Sitemaps
Only a member who can manage server settings can apply the Hide My WP preset; a member with site-level access only, such as a Site Admin, is refused. If you use the Hide My WP template, match the plugin’s own settings to the rule; see set up the Hide My WP plugin on xCloud. To apply the same rule to many sites at once, use bulk NGINX customization.
Rules checked for members with site-level access
If your team role only lets you manage sites (for example Site Admin), xCloud checks each Custom NGINX rule before it applies it. Team owners, and Team Admins or Server Admins who can manage server settings, are not checked. In the team role editor, the server settings permission is the one described as “Allows members to manage settings and restart server and various services (nginx,mysql,php-fpm) running on the server”.
When a checked rule is refused, the reason appears in red below Config Content, and nothing is written to the server.
Insertion points and includes
A checked member can use the inside-site insertion points only. Before Server Block and After Server Block are refused with:
Before and after server blocks require server settings permission. Choose an inside-site block.
An include line is refused with:
Includes require server settings permission. Ask a server administrator to configure this template.
Directives a checked rule can use
A checked rule can use only these directives:
| Purpose | Directives |
|---|---|
| Blocks | location, if, limit_except |
| Rewrites and responses | rewrite, return, set, error_page, try_files, index, internal, default_type, charset, autoindex |
| Headers and caching | add_header, add_trailer, expires, etag, server_tokens |
| Request size and transfer | client_max_body_size, client_body_buffer_size, sendfile, tcp_nopush, tcp_nodelay, keepalive_timeout, limit_rate, limit_rate_after |
| Compression | gzip, gzip_types, gzip_vary, gzip_min_length |
| Access control | allow, deny, satisfy, auth_basic, auth_basic_user_file |
| Real client IP | set_real_ip_from, real_ip_header, real_ip_recursive |
| Proxy | proxy_pass, proxy_set_header, proxy_hide_header, proxy_redirect, proxy_read_timeout, proxy_send_timeout, proxy_connect_timeout, proxy_buffering, proxy_buffers, proxy_buffer_size, proxy_http_version, proxy_cache, proxy_cache_valid, proxy_cache_bypass, proxy_no_cache |
| PHP (FastCGI) and other upstreams | fastcgi_pass, fastcgi_param, fastcgi_index, fastcgi_split_path_info, fastcgi_read_timeout, fastcgi_buffers, uwsgi_pass, scgi_pass, grpc_pass |
| Files and paths | root, alias, ssl_certificate |
Any other directive is refused, including upstream, map, limit_req, access_log and Lua or Perl blocks. The message is:
This directive requires server settings permission. Ask a server administrator to review the configuration.
Other checks
| A checked rule is refused when… | Message below Config Content |
|---|---|
| Config Content is larger than 256 KB | Use a text configuration smaller than 256 KB. |
A fastcgi_param sets SCRIPT_FILENAME, DOCUMENT_ROOT, PATH_TRANSLATED, PATH_INFO, PHP_VALUE or PHP_ADMIN_VALUE |
Use non-reserved FastCGI parameters; PHP script paths and settings require server settings permission. |
A set overwrites a request or script path variable such as $uri, $request_uri, $request_filename, $document_root or $fastcgi_script_name |
Do not replace nginx request or PHP script path variables. |
alias is not inside a prefix location that ends in /, such as location /downloads/ { alias /var/www/SITE_NAME/files/; } |
Use alias inside a prefix location ending with a slash. |
root, alias, auth_basic_user_file or ssl_certificate points outside /var/www/SITE_NAME or /etc/nginx/xcloud-conf/SITE_NAME |
Use an absolute path inside this site’s web or nginx configuration directory. |
A rewrite, error_page, try_files or index target uses a variable or a .. segment (try_files may still use $uri and $uri/) |
Use static paths without parent segments; try_files may also use $uri. Keep the ShortPixel preset unchanged. |
| Quotes, braces or semicolons do not balance | Check the configuration quotes and syntax. or Check the configuration blocks and semicolons. |
Replace SITE_NAME with the site’s name as it appears in the generated .conf path preview.
proxy_pass accepts a literal public IP address only
In a checked rule, proxy_pass must point to one of these targets:
- an
http://orhttps://URL whose host is a literal public IPv4 or IPv6 address, written without variables or credentials, for exampleproxy_pass https://<public-ip>; - this site’s own PHP socket, for example
fastcgi_pass unix:/run/php/php8.3-fpm-SITE_USER.sock;(use your site’s PHP version and site user). This target is accepted on PHP sites only. The/var/run/php/path to the same socket also works.fastcgi_pass,uwsgi_pass,scgi_passandgrpc_passaccept only this socket.
A hostname such as https://api.example.com is refused with this message:
Use a public IP address for proxy_pass, or ask a server administrator to configure a hostname.

A literal address is also refused when it is private or reserved (such as 10.0.0.0/8, 192.168.0.0/16 or 127.0.0.1), in the shared 100.64.0.0/10 range, multicast, or the server’s own public or private IP. In those cases, or for a target that uses a variable, the message is:
Use this site’s PHP pool socket or a public HTTP(S) proxy IP address, without variables.
If the upstream needs a hostname, ask a team member who can manage server settings to add the rule. Their rules are not checked this way.
Existing rules are checked again when they are re-applied
xCloud does not change rules that are already saved. However, a saved rule is checked again, with all the checks above, whenever it is applied by a member with site-level access:
| Action | What happens to a rule that fails the check |
|---|---|
| Run & Debug or Save Config when you edit it | Refused with the message, and the server is not changed |
| Turning its Active toggle on | Refused, and the rule stays inactive |
| Bulk NGINX customization | The whole bulk apply is refused with the message, and no site is changed. Remove the failing sites or fix the rule, then try again. |
| Cloning the site | The rule is not applied to the clone. Ask a member who can manage server settings on the destination server to add it there. |
When you clone a site, each rule is checked against the destination server, using the permissions of the member who started the clone. If the clone already has a rule with the same type and file name as a refused rule, that rule is turned off.
Turning a rule off is never blocked by this check.
Disable or re-enable a rule safely
Step 1: Find the rule in the config table
Open Tools → Nginx Customization and locate the rule by its file name and type.
Expected result: The Active column shows whether the rule currently participates in the generated NGINX configuration.
Step 2: Turn off the Active toggle
Switch the rule from Active to Inactive.
Expected result: xCloud removes the rule’s generated configuration file, validates the complete NGINX configuration, and reloads NGINX. The saved rule and its content remain in xCloud so they can be re-enabled later.
If validation or reload fails, xCloud rolls the file change back and reports that the rule could not be deactivated.
Step 3: Verify the rollback
Repeat the request affected by the rule. For the response-header example, run:
curl -I https://example.com
Expected result: The X-Documentation-Rule header is no longer present after the rule is inactive. Replace example.com with your site’s public domain.
Step 4: Re-enable the rule when needed
Turn the same toggle back to Active.
Expected result: xCloud restores the saved configuration content, validates the full configuration, and reloads NGINX. If validation or reload fails, xCloud rolls back the activation and keeps the prior working state.
Verify the completed configuration
Confirm all of the following:
- Run & Debug reports successful NGINX validation.
- The rule appears in the config table with the intended type.
- The Active column shows the intended state.
- The site loads normally over HTTPS.
- The rule affects only the intended request. Check the exact URL, response header, redirect, or application behavior the rule targets.
- Disabling the rule removes its effect without deleting the saved configuration.
Limits and safety notes
- Custom NGINX is available only on servers that use NGINX.
- xCloud generates the surrounding server and location blocks. Do not redefine those blocks inside a narrower insertion point.
main_locationis shown for PHP applications; proxy-based applications use Inside Proxy Location Block instead.- Firewall insertion points appear only when the corresponding 7G or 8G firewall is enabled.
- A syntactically valid rule can still cause an unwanted redirect, caching policy, access restriction, or application behavior. Test the outcome separately from the syntax.
- Avoid duplicating xCloud-generated directives such as
try_files, PHP handling, proxy settings, or SSL configuration unless you understand how NGINX resolves duplicates and inheritance. - Prefer the per-rule toggle for temporary rollback. Delete a rule only when you no longer need its saved content.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Inside Main Location Block is not available | The site is not detected as a PHP application | Choose the insertion point that matches the application type. Non-PHP apps use Inside Proxy Location Block. |
| Run & Debug reports an invalid configuration | The directive has invalid syntax or is not allowed in the selected NGINX context | Read the reported line, confirm the directive’s allowed context, choose the correct insertion point, and run the check again. |
| Saving or toggling reports a validation or reload failure | The proposed state would make the full NGINX configuration invalid, or NGINX could not reload | Leave the previous state in place, review the displayed output, correct the rule, and retry. xCloud rolls back a failed toggle. |
| The rule validates but has no visible effect | The request does not pass through that block, or another directive takes precedence | Confirm the site type, insertion point, requested URL, and response with browser developer tools or curl. |
| The site behaves incorrectly after a successful save | The syntax is valid, but the rule’s logic is wrong or conflicts with generated configuration | Turn the rule off immediately, verify the site returns to normal, then narrow or correct the rule before re-enabling it. |
| An inactive rule still appears in the table | Inactive rules are retained by design | Leave it inactive for future use, or delete it only if you no longer need the stored configuration. |
| “Use a public IP address for proxy_pass, or ask a server administrator to configure a hostname.” | You cannot manage server settings, and the rule’s proxy_pass targets a hostname |
Point proxy_pass at the upstream’s literal public IP address, or ask a team member who can manage server settings to add the rule. |
| “Before and after server blocks require server settings permission. Choose an inside-site block.” | You cannot manage server settings, and the rule uses Before Server Block or After Server Block | Choose an inside-site insertion point such as Inside Server Block, or ask a team member who can manage server settings to add the rule. |
| “Includes require server settings permission. Ask a server administrator to configure this template.” | You cannot manage server settings, and the rule contains an include line |
Paste the directives you need instead of including a file, or ask a team member who can manage server settings to add the rule. |
| “This directive requires server settings permission. Ask a server administrator to review the configuration.” | The rule uses a directive outside the list for checked rules, or puts braces after a directive that is not location, if or limit_except |
Rewrite the rule with the listed directives, or ask a team member who can manage server settings to add it. |
Common mistakes
- Choosing Inside PHP Location Block when the directive belongs in the main application
location /block. - Adding a complete
location {}block inside Inside Main Location Block, which is already withinlocation /. - Saving before using Run & Debug.
- Treating successful syntax validation as proof that redirects, caching, or access rules behave correctly.
- Deleting a rule when the Active toggle would provide a faster, reversible rollback.
- Editing generated NGINX files over SSH instead of using xCloud’s managed insertion points; regenerated site configuration can replace manual edits.
Frequently asked questions
Does disabling a Custom NGINX rule delete it?
No. Disabling a rule removes its effect from NGINX while retaining the saved configuration in xCloud. You can re-enable it later.
What is the difference between main_location and php?
The main_location type inserts directives inside the PHP application’s main location / block. The php type inserts directives inside the dedicated location that passes .php requests to PHP.
Does Run & Debug apply the rule permanently?
No. It writes the proposed file temporarily, runs NGINX validation, reports the result, and removes the temporary file. Use Save Config to keep a validated rule.
What happens if a toggle would break NGINX?
xCloud validates the complete configuration before accepting the new state. If validation or reload fails, xCloud restores the previous file state and reports the failure.
Why is my proxy_pass to a hostname refused?
If your team role only lets you manage sites, xCloud checks each Custom NGINX rule you save, test or re-apply. In a checked rule, proxy_pass must point to a literal public IP address or to the site’s own PHP socket, such as unix:/run/php/php8.3-fpm-SITE_USER.sock. A hostname is refused. Use the upstream’s public IP address, or ask a member who can manage server settings (the team owner, or a Team Admin or Server Admin with that permission) to add the rule. Rules that are already saved are not changed.
Next steps
- Apply bulk NGINX customization to push one rule to many sites
- Add custom security headers, a common use of the server block
- Whitelist 7G and 8G WAF rules when the firewall insertion points are what you need
- Troubleshoot NGINX configuration regeneration failures if a regenerated site config conflicts with a rule
- Release notes: v2.7.0 added the main location insertion point, v2.7.3 added the per-rule enable and disable toggle, v2.9.7 added checks for rules saved by members with site-level access
If a rule validates but the site misbehaves and you cannot narrow it down, feel free to reach out to our support team.