> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://docs.flyinghost.com/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Add Custom Nginx Rules

Use Custom Nginx config for redirects, security headers, access rules, CORS, bot blocking, and reverse proxies.

## Before adding a rule

FlyingHost uses Nginx, so Apache **.htaccess rules do not work**.

Your custom configuration is inserted inside the site's existing Nginx server block. Do not include **http {}** or **server {}** wrappers.

Only use directives valid in a server or location context. Global directives such as **map**, **upstream**, and **limit_req_zone** are not supported here.

## Add and deploy a rule

1. Open the site in Cockpit.
2. Go to **Settings → Custom Nginx config**.
3. Select **Configure Nginx**.
4. Enter the rule or use the built-in generator.
5. Review the configuration.
6. Select **Test and deploy**.
7. Test the affected URL in a private browser window.

FlyingHost runs an Nginx syntax test before reloading the service. If the test or reload fails, the previous working configuration is restored.

A successful test confirms valid syntax. You must still check that the rule behaves as expected.

## Common examples

Replace the example paths and domains before deploying.

### Redirect one page

```nginx
location = /old-page/ {
    return 301 /new-page/;
}
```

Use 302 while testing. Change it to 301 only when the redirect is permanent.

### Add security headers

```nginx
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
```

Check both static and dynamic pages after deployment because headers can behave differently inside more specific locations.

### Allow CORS for one file

```nginx
location = /data/public.json {
    add_header Access-Control-Allow-Origin "https://app.example.com" always;
    add_header Vary "Origin" always;
    try_files $uri =404;
}
```

Replace the allowed domain with your frontend domain. Avoid allowing every origin for private or credentialed content.

### Block a path

```nginx
location ^~ /private-area/ {
    return 403;
}
```

A broad path can also block assets, APIs, or plugin callbacks below it.

### Block a user agent

```nginx
if ($http_user_agent ~* "(BadBot|ExampleCrawler)") {
    return 403;
}
```

User-agent names can be spoofed. Use this for traffic control, not authentication.

### Block countries using Cloudflare

Cloudflare can send the visitor’s country in the **CF-IPCountry** header when IP Geolocation is enabled. Nginx reads this header as **$http_cf_ipcountry**.

```nginx
if ($http_cf_ipcountry ~* "^(CN|RU)$") {
    return 403;
}
```

Replace **CN** and **RU** with the two-letter ISO country codes you want to block. Cloudflare also uses **XX** for an unknown country and **T1** for Tor traffic.

Only rely on this header for requests proxied through Cloudflare. This rule blocks at the origin.

### Reverse proxy a path

```nginx
location /external-api/ {
    proxy_pass https://api.example.com/;
    proxy_set_header Host api.example.com;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
```

The trailing slash affects the forwarded path. Use a stable upstream hostname; an unavailable or unresolvable upstream can prevent Nginx from reloading.

## Avoid these changes

Do not:

- Redefine the managed PHP handler
- Replace the main WordPress routing
- Expose wp-config.php, hidden files, backups, or database exports
- Configure listening ports or origin TLS
- Paste a complete configuration from another host
- Use directives that require the http, main, or events context

## If deployment fails

Check the error and line number, then:

1. Check braces and semicolons.
2. Remove any http or server wrapper.
3. Confirm the directive is valid in a server or location context.
4. Check for duplicate locations.
5. Confirm reverse-proxy hostnames resolve.
6. Test one small rule at a time.

When contacting support, include the complete rule, the validation error, the affected URL, and the expected behavior.