---
title: "Optimizing the Web Server for DreamFactory | DreamFactory Docs"
source: "https://docs.dreamfactory.com/getting-started/optimizing-dreamfactory/web-server"
canonical_url: "https://docs.dreamfactory.com/getting-started/optimizing-dreamfactory/web-server"
converted_at: "2026-08-14T22:18:44.366Z"
format: "markdown"
converted_by: "html-to-md-ai"
---
DreamFactory is usually served by NGINX in front of PHP-FPM, and that is the configuration this page covers. The installer writes a working virtual host for you. What follows is what each part does and when you should change it.

## The Shipped Virtual Host[​](#the-shipped-virtual-host)

The essentials of the configuration DreamFactory installs:

```
upstream php_handler {    server unix:/var/run/php/php8.5-fpm.sock;}server {    listen 80;    server_name your.host.name;    root "/opt/dreamfactory/public";    index index.html index.htm index.php;    charset utf-8;    client_max_body_size 100m;    location / {        try_files $uri $uri/ /index.php?$query_string;    }    location ~ \.php$ {        try_files $uri /index.php?$query_string;        fastcgi_split_path_info ^(.+\.php)(/.+)$;        fastcgi_pass php_handler;        fastcgi_index index.php;        include fastcgi_params;        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;        fastcgi_connect_timeout 60;        fastcgi_send_timeout 180;        fastcgi_read_timeout 180;    }    location ~ /\.ht {        deny all;    }}
```

Two things are load-bearing. The document root is `public`, never the application directory itself, which keeps `.env` and the source tree outside the web root. And the `try_files` fallback routes every unmatched path into `index.php`, which is how Laravel's router sees the request at all.

## Upload Limits[​](#upload-limits)

`client_max_body_size 100m` caps the request body NGINX will accept. Exceed it and the client gets a `413`, from NGINX, before PHP is ever involved.

This value must be kept in step with PHP. Raising uploads means changing all three:

- NGINX `client_max_body_size`

- PHP `upload_max_filesize`

- PHP `post_max_size`

The effective limit is the smallest of the three, which is why raising one and forgetting the others produces a limit nobody can find in the config they just edited. See [PHP and Laravel](/getting-started/optimizing-dreamfactory/php-and-laravel).

## FastCGI Timeouts[​](#fastcgi-timeouts)

```
fastcgi_connect_timeout 60;fastcgi_send_timeout 180;fastcgi_read_timeout 180;
```

`fastcgi_read_timeout` is the one you will meet. It is how long NGINX waits for PHP to respond, and when it expires the client gets a `504 Gateway Timeout` even though PHP is still working on the request.

Raise it when you have legitimately slow operations: a scripted service calling a slow third-party API, a large export, a bulk import. Raise PHP's `max_execution_time` to match, or you have simply moved the failure from NGINX to PHP.

Before raising either, check whether the request is slow for a fixable reason. A `504` on a database endpoint is usually a missing index, not a timeout that needs to be longer. See [Optimizing Database APIs](/getting-started/optimizing-dreamfactory/database-apis).

## Never Cache the Admin UI Entry Point[​](#never-cache-the-admin-ui-entry-point)

```
location = /dreamfactory/dist/index.html {    add_header Cache-Control "no-store" always;}
```

Keep this rule. The admin interface is an Angular application with content-hashed chunk filenames. Those hashed assets are safe to cache aggressively and should be. `index.html` is the file that points at them, so a cached copy pins users to an old build indefinitely, and the symptom is bizarre: a browser that keeps loading a version of the UI that no longer exists on the server, fixed only by a hard refresh that most users will never think to try.

If you put a CDN or reverse proxy in front of DreamFactory, carry the same rule forward there.

## Compression[​](#compression)

JSON API responses compress extremely well, often to a fraction of their original size, and enabling compression is one of the cheapest wins available on a slow or metered network.

```
gzip on;gzip_types application/json application/javascript text/css text/plain;gzip_min_length 1024;
```

Do not compress everything indiscriminately. Very small responses get larger, not smaller, once framing overhead is counted, which is what `gzip_min_length` guards against. Already-compressed payloads such as images or archives gain nothing and cost CPU.

## Logging[​](#logging)

The shipped configuration sets `access_log off` and logs only errors. That is a deliberate trade: on a busy API gateway, access logging every request is a meaningful amount of disk I/O for data most operators never read.

Turn it on when you are diagnosing something:

```
access_log /var/log/nginx/dreamfactory-access.log;
```

Then turn it back off, or rotate it aggressively. An API that never sleeps fills a disk faster than most people expect, and a full disk takes the instance down.

## TLS[​](#tls)

Terminate TLS at NGINX or at a load balancer in front of it. When something else terminates TLS and forwards over plain HTTP, DreamFactory needs to be told, or it will build URLs with the wrong scheme in redirects and in generated API documentation. The shipped virtual host passes an `HTTPS` FastCGI parameter for exactly this reason.

Certificate setup is covered in [CORS and SSL](/system-settings/config/cors-and-ssl).

## Related Reading[​](#related-reading)

- [PHP and Laravel](/getting-started/optimizing-dreamfactory/php-and-laravel)

- [Optimizing Database APIs](/getting-started/optimizing-dreamfactory/database-apis)

- [CORS and SSL](/system-settings/config/cors-and-ssl)