How to Configure Custom NGINX in xCloud

Updated October 29, 2026 · 10 min read

Summarize with:
Share:

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 curl if 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 Create Custom Nginx Configuration modal with the config type dropdown open, showing Inside Main Location Block among the insertion points

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:

Run & Debug showing a green success message for a valid configuration

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

Run & Debug showing a red error message for an invalid configuration

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.

The Custom Nginx Config table listing saved rules with their type, an Active toggle per rule, and edit, preview and delete actions

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:// or https:// URL whose host is a literal public IPv4 or IPv6 address, written without variables or credentials, for example proxy_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_pass and grpc_pass accept 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 Site Admin’s Run & Debug check refused, with the message ‘Use a public IP address for proxy_pass, or ask a server administrator to configure a hostname.’ shown below Config Content

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:

  1. Run & Debug reports successful NGINX validation.
  2. The rule appears in the config table with the intended type.
  3. The Active column shows the intended state.
  4. The site loads normally over HTTPS.
  5. The rule affects only the intended request. Check the exact URL, response header, redirect, or application behavior the rule targets.
  6. 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_location is 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 within location /.
  • 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

If a rule validates but the site misbehaves and you cannot narrow it down, feel free to reach out to our support team.