Deep-dive on the Next Gen Platform. Join the Webinar!

Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Visit the Heroku Blog

    Find news and updates from Heroku in the blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Language Support
  • PHP
  • Working with PHP
  • Customizing Web Server and Runtime Settings for PHP

Customizing Web Server and Runtime Settings for PHP

English — 日本語に切り替える

Last updated April 15, 2025

Table of Contents

  • How applications are launched during dyno boot
  • Specifying which runtime to use
  • Specifying which web server to use
  • Setting the document root
  • Default behavior
  • Web server settings
  • PHP runtime settings

PHP has a built-in web server that can be used to run on Heroku web dynos, however this is not recommended. Instead you should be using a boot script which is referenced in your Procfile to launch a web server together with PHP.

This article explains the different ways in which you can pass arguments to this boot script to customize settings for the PHP runtime as well as the web server software.

How applications are launched during dyno boot

The Nginx web server is not currently not supported on the Fir generation of the Heroku platform.

During a deploy, Heroku will install the heroku/heroku-buildpack-php Composer package as an internal dependency. This package contains boot scripts for launching PHP together with either the Apache or the Nginx web servers.

The names of the boot scripts available for your use are:

  • heroku-php-apache2 (for PHP & Apache2)
  • heroku-php-nginx (for PHP & Nginx)

These boot scripts installed by the heroku/heroku-buildpack-php package are placed on $PATH, and will use bundled configuration files to launch PHP-FPM together with the web server of your choice.

Heroku recommends you maintain dev/prod parity by running the same packages locally. You can use the package you are running in production as a development dependency by adding it to the require-dev section of your composer.json file. Then you can launch a local development environment that will work seamlessly on your development machine, provided that you have Apache or Nginx installed.

Once you’ve installed the heroku/heroku-buildpack-php package locally you can view any of the boot scripts’ help screen. The boot scripts accept various options and arguments that you can use to control settings related to PHP and the web server software. To get the detailed help you can execute any of the installed binaries from the list above with the --help flag. For example, to get help with options for launching PHP & Apache, you would run:

$ heroku-php-apache2 --help

Specifying which runtime to use

For full details on supported features and versions, check the PHP reference article.

Refer to the following sections to learn what your Procfile should look like and what arguments are available to customize the configuration of your application.

Specifying which web server to use

In your Procfile, you must specify which of the boot scripts in the list at the beginning of this document to use. Heroku will then launch the corresponding web server together with PHP when your dyno starts.

For example, to use Nginx together with PHP, your Procfile should contain:

web: heroku-php-nginx

Setting the document root

The most common configuration customization applications require is the so-called document root.

The document root is the directory where the application will begin looking for your .php files. To change the document root, you may supply the path to the directory (relative to your application root directory) as an argument to the boot script. It is not necessary to change configuration files or rewrite rules to define the document root.

For example, if you’re using Apache with PHP, and you’d like your document root to be set to the public sub-directory of your application (because that’s where your index.php and all images, CSS and JavaScript reside), your Procfile would look like this:

web: heroku-php-apache2 public/

If you specify additional options to the script (as described in the sections that follow), you must ensure that the document root argument is at the end of the command, after all options; for example:

web: heroku-php-nginx -C rewrite.conf www/

In order to not define a document root (and thus have the root directory of your application act as the document root), simply omit the argument altogether:

web: heroku-php-apache2

Default behavior

Heroku will launch a FastCGI Process Manager (PHP-FPM) application server. This application server will accept requests to execute PHP files from a web server, either Apache or Nginx.

The web server will bind to the port in the $PORT environment variable and respond to incoming HTTP requests; if the request is for an existing file with a name ending in .php, the web server will pass the request to execute this PHP file to the application server using the FastCGI protocol.

The configuration for these web servers can be customized.

Depending on the web server you chose (Apache or Nginx) each will come with different defaults. You can find them directly below.

Apache defaults

Apache uses a Virtual Host that responds to all hostnames. The document root is set up as a <Directory> reachable without access limitations and AllowOverride All set to enable the use of .htaccess files. Any request to a URL ending on .php will be rewritten to PHP-FPM using a proxy endpoint named fcgi://heroku-fcgi via mod_proxy_fcgi. The DirectoryIndex directive is set to “index.php index.html index.html”.

Nginx defaults

Nginx uses a server that responds to all hostnames. The document root has no access limitations. Any request to a URL containing .php will be be rendered by fastcgi_pass with PHP-FPM using an upstream called “heroku-fcgi” after a try_files call on the entire URL. The index directive is set to “index.php index.html index.html”

Web server settings

You can configure Apache or Nginx by providing your own site-specific settings.

Apache

Using .htaccess

You may use regular .htaccess files to customize the behavior of the Apache HTTP server. The AllowOverride option for the document root is set to all, which means you can use any configuration directive allowed in .htaccess contexts.

This is the recommended approach for customizing Apache settings, as it does not require the use of a custom (and potentially error-prone) config include.

Most modern web frameworks require very little configuration which can be placed into a .htaccess file in the document root directory.

For example, to configure Apache for a Laravel or Symfony app, create a .htaccess file in the public/ directory with the following line:

FallbackResource /index.php

Then, your Procfile command only needs to specify a document root directory:

web: heroku-php-apache2 public/

Using a custom application level Apache configuration

Inside the default server level configuration file Heroku uses during the startup of Apache, it includes a very simple default application level config file. You can replace this file with your custom configuration. For example, to configure Apache to use some rewrite rules for your application, you’d create an apache_app.conf inside your application’s root directory with contents like the following:

RewriteEngine On

RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

RewriteRule .? %{ENV:BASE}/app.php [L]

Then, in your Procfile, you can use the -C argument of the boot script to tell Heroku to include this file for you:

web: heroku-php-apache2 -C apache_app.conf

To understand in which context this configuration file will be included, we recommend you take a look at the server-level configuration for Apache that Heroku loads right after the system-wide configuration file during startup.

Nginx

Using a custom application level Nginx configuration

Inside the default server level configuration file Heroku uses during the startup of Nginx, it includes a very simple default application level config file. You can replace this file with your custom configuration. For example, to configure Nginx to use some rewrite rules for your Symfony application, you’d create an nginx_app.conf inside your application’s root directory with the following contents:

location / {
    # try to serve file directly, fallback to rewrite
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    # rewrite all to index.php
    rewrite ^(.*)$ /index.php/$1 last;
}

location ~ ^/index\.php(/|$) {
    try_files @heroku-fcgi @heroku-fcgi;
    # ensure that /index.php isn't accessible directly, but only through a rewrite
    internal;
}

The internal; directive in the config above ensures that calls to /index.php etc are not allowed if they aren’t coming from rewrites.

You can always use try_files @heroku-fcgi @heroku-fcgi; to delegate handling to the default rule for .php files using the “@heroku-fcgi” named location. This is the easiest and most portable way of invoking PHP. When using fastcgi_pass instead, use “heroku-fcgi” as the destination. It’s an upstream group and configured so that your FastCGI requests will always be handed to the correct backend process.

After you have created a new default configuration you can tell your application to start with this configuration by using the -C argument of the boot script.

For example if you’ve written your own nginx_app.conf you can modify your Procfile to use this configuration file:

web: heroku-php-nginx -C nginx_app.conf

To understand in which context this configuration file will be included, we recommend you take a look at the server-level configuration for Nginx that Heroku loads right after the system-wide configuration file during startup.

PHP runtime settings

INI settings

Heroku supports several of the methods that PHP offers for changing its php.ini settings.

In addition to using ini_set in your PHP code at runtime, you may also configure Heroku to use an additional configuration file for PHP-FPM that may contain INI directives and will be loaded after the default configuration during startup.

The recommended approach for most cases is a per-directory .user.ini file that PHP-FPM will pick up automatically.

The methods below only apply to web dynos, as worker processes do not use PHP-FPM, but typically invoke the php executable directly, which allow passing of INI directives using the -d command line option.

.user.ini files (recommended)

PHP-FPM will read settings from any .user.ini file in the same directory as the .php file that is being served via a web server; if none is found, it will also read settings from a .user.ini file in any parent directory up to your application’s configured document root.

Heroku recommends using .user.ini files to customize PHP settings for web traffic. Please refer to the section on .user.ini files in the PHP manual to learn more about this feature and which settings you can control through it.

For example, to change the maximum size for a single file uploaded through an HTML form to 5 MB, and the total POST size to 20 MB, you would place a .user.ini into your document root with the following contents:

post_max_size = 20M
upload_max_filesize = 5M

PHP-FPM configuration include

A small set of PHP.ini configuration directives cannot be modified using .user.ini; for example, always_populate_raw_post_data cannot be changed this way despite its official PHP_INI_PERDIR changeability mode. The same is true for any directive with PHP_INI_SYSTEM changeability mode.

In this case, you can pass additional configuration settings for PHP at startup time using a custom configuration file include for PHP’s FastCGI Process Manager by using the php_value and php_flag directives as documented here in the PHP manual.

For example, to set always_poplate_raw_post_data to -1 to prevent deprecation notices in PHP 5.6 when accessing php://input, you would add an fpm_custom.conf file to your application with the following contents:

php_value[always_populate_raw_post_data]=-1

After you have created such a new custom FPM configuration include you can tell your application to start with this configuration by using the -F option of the boot script. For the example above, you’d modify your Procfile as follows to use that configuration file (assuming your document root is the sub-directory public/):

web: heroku-php-nginx -F fpm_custom.conf public/
PHP-FPM settings

In addition to php_value and php_flag for php.ini specific settings, any pool specific PHP-FPM configuration directives are valid in that configuration file, so you can use it to fine tune PHP-FPM’s behavior.

Incorrect PHP-FPM configuration directives may easily cause your application to stop working or behave unexpectedly, so use with caution.

For example, PHP-FPM can be instructed to log longer running requests that exceed a certain number of seconds using the request_slowlog_timeout directive, in which case it will print information about the request, including a backtrace, to heroku logs:

request_slowlog_timeout = 1s

The default value for request_slowlog_timeout is 3s.

Keep reading

  • Working with PHP

Feedback

Log in to submit feedback.

Uploading Files to S3 in PHP Deploying PHP Apps on Heroku

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices