Static Files, CGI Scripts, and PHP Pages

Static files, CGI scripts, and PHP pages can be served by two different, but related, types of applications, Static-only and Static/CGI/PHP applications.

Static-only applications serve files through each WebFaction server’s frontend nginx process, but never run CGI scripts or interpret PHP pages. While limited to serving ordinary files, like HTML, images, and CSS, Static-only applications serve media fast without additional memory consumption.

Static/CGI/PHP applications serve ordinary files like Static-only applications do, along with the ability to run CGI scripts, interpret PHP pages, and customize settings with .htaccess files.

See also

For more on how each server handles incoming requests and which processes are responsible for different activities, please see The Life Cycle of a Request and Response.

Static-only

Static-only apps serve static files with the server’s shared nginx process. A Static-only app is exclusively static; PHP files, for example, will not be interpreted in a Static-only app. We suggest Static-only apps when you need to serve static media (and only static media) fast with low memory consumption.

Serving Static Media

Even if most of your site is served dynamically by Django, Rails, TurboGears, or Zope (just to name a few), you will still have many static elements, such as style sheets, images, and videos. If these elements are served by your dynamic process, they will consume unnecessary additional memory and time to serve. You can save memory and time by serving static files with a Static-only application.

To serve static media with a Static-only application:

  1. With the control panel, create a Static-only application.
  2. With the control panel, modify or create a website entry which maps an unused path from your domain name (for example, www.example.com/media) to your new Static-only application.
  3. Wait up to two minutes for propagation of the new path and domain combination to complete.
  4. Copy static media files to $HOME/webapps/static-only.

Media served from the /media path of your website is now served by an nginx or Apache process, sparing your dynamic application from serving those requests.

Setting expires max

For new Static-only applications, you can enable long-lived HTTP caching headers. To enable these headers, enter expires max in the Extra info field while creating a new Static-only application.

Specifically, the expires max configuration value sets:

  • the Expires header to 31 December 2037 23:59:59 GMT, and
  • the Cache-Control header’s max-age directive to 10 years.

Static/CGI/PHP

Static/CGI/PHP apps, in addition to their role in serving static media, add the capacity to serve PHP pages, which are processed by the PHP interpreter on the server. Static/CGI/PHP apps should only be used when you need to make use of .htaccess files, PHP pages, or CGI scripts.

See also

For additional, PHP-specific configuration and troubleshooting information, please see PHP.

Adding a MIME Type

If you need to use a file extension that Apache does not recognize automatically, you can instruct Apache to use a specific MIME type with a .htaccess directive. To add a MIME type:

  1. Open an SSH session.

  2. Switch to the Static/CGI/PHP application’s directory. Enter cd $HOME/webapps/app, where app is the name of the application as it appears in the control panel, and press Enter.

  3. Open .htaccess (or create the file if it does notalready exist) in a text editor.

  4. For each new MIME type, add a new line containing AddType mime extension, where mime is the MIME type and extension is the file extension (including a dot).

    For example, to set .jnlp files to use the application/x-java-jnlp-file MIME type, enter AddType application/x-java-jnlp-file .jnlp into the .htaccess file.

  5. Save and close the file.

Blocking an IP Address or Host Name

To block an IP address or host name for accessing a Static/CGI/PHP application:

  1. Open an SSH session to your account.

  2. Switch to the Static/CGI/PHP application’s directory. Enter cd $HOME/webapps/app, where app is the name of the application as it appears in the control panel, and press Enter.

  3. Open .htaccess (or create the file if it does not already exist) in a text editor.

  4. Add these lines to the file:

    order allow,deny
    <deny directives>
    allow from all
    
    <Files .htaccess>
        order allow,deny
        deny from all
    </Files>
    

    where <deny directives> is any number of lines containing one directive each to deny access to IP addresses or host names. Such directives take the form of deny from IP and deny from hostname, where IP is an IP address to be blocked and {hostname} is a hostname to be blocked. For example:

    order allow,deny
    deny from example.com
    deny from 123.456.78.9
    allow from all
    
    <Files .htaccess>
        order allow,deny
        deny from all
    </Files>
    
  5. Save and close the file.

Future requests from the blocked IP addresses and host names will be rejected with a 403 Forbidden error.

Changing the Handler for Files

By default, a Static/CGI/PHP application’s instance of Apache will serve .cgi and .py files as CGI scripts. You can instruct Apache to use a different handler with a set of FilesMatch and SetHandler directives in your application’s .htaccess file.

To modify the handler:

  1. Open or create a new file $HOME/webapps/app/.htaccess, where app is the name of the application as it appears on the control panel.

  2. For each new handler you would like to add, insert these lines:

    <FilesMatch \.EXTENSION$>
      SetHandler HANDLER
    </FilesMatch>
    

    where EXTENSION is the file extension to apply the handler to and HANDLER is the handler to use.

    For example, to treat .py files as ordinary text files instead of as CGI scripts, add these lines to your .htaccess file:

    <FilesMatch \.py$>
      SetHandler default-handler
    </FilesMatch>
    

    For another example, to treat .xyz files as CGI scripts, add these lines to your .htaccess file:

    <FilesMatch \.xyz$>
      SetHandler cgi-script
    </FilesMatch>
    
  3. Save and close the file.

Enabling Server Side Includes

Server Side Includes (SSI) direct the Apache web server to substitute portions of HTML pages with content evaluated at the time the page is served.

To enable server side includes:

  1. Open an SSH session.

  2. Switch to the Static/CGI/PHP application’s directory. Enter cd $HOME/webapps/app, where app is the name of the application as it appears in the control panel, and press Enter.

  3. Open .htaccess (or create the file if it does not already exist) in a text editor.

  4. Add these lines:

    Options +Includes
    AddType text/html .shtml
    AddOutputFilter INCLUDES .html
    
  5. Save and close the file.

Now, you can use include directives in your pages, such as <!--#include file="includes/header.shtml"-->.

Granting Apache Write Access

To make a file or directory writeable by the apache user:

  1. Open an SSH session to your account.
  2. Enter setfacl -R -m u:apache:rwx path, where path is the path to the file or directory, and press Enter.
  3. Enter setfacl -R -m default:u:username:rwx path, where username is your account name, and press Enter.

Hiding Configuration Files

By default, files such as .htaccess and .htpasswd are exposed to the web. If you want to hide these files, add these lines to your .htaccess file:

<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>

Password Protecting a Directory with a Static/CGI/PHP App

You can password protect the contents of any Static/CGI/PHP application by using a .htaccess file. This method works for all CGI and PHP-based applications, including AWStats, Drupal, Joomla, Trac, and WordPress.

To enable password protection:

  1. With the control panel, create a Static/CGI/PHP app or identify an existing Static/CGI/PHP app you would like to use.

  2. If necessary, create or modify a website entry which maps the Static/CGI/PHP app to a particular URL.

  3. Open an SSH session into your account.

  4. Switch to the $HOME/webapps/static_cgi_php_app/ directory.

  5. If it does not already exist, create a .htaccess file. Enter touch .htaccess and press Enter.

  6. Open .htaccess in a text editor.

  7. Add these directives to .htaccess:

    AuthUserFile /home/<your_username>/webapps/<webapp_name>/.htpasswd
    AuthName EnterPassword
    AuthType Basic
    require valid-user
    
    # Hide files starting with a dot (.htaccess and .htpasswd in particular)
    <Files .*>
    order allow,deny
    deny from all
    </Files>
    
  8. Save and close the file.

  9. To create the first user with access to the directory, enter htpasswd -c .htpasswd username and press Enter. A New password prompt appears.

    See also

    See Strengthening Passwords for important information about choosing passwords.

  10. Enter the password for the new user and press Enter. A Re-type new password prompt appears.

  11. Reenter the password for the new user and press Enter.

  12. To create additional users with access to the directory, enter htpasswd .htpasswd username and press Enter, then follow the password prompts for the new user.

Note

If you would like to password protect a subdirectory, rather than the entire application, simply create or modify .htaccess in the subdirectory.

Now, when you access the URL associated with the app’s protected directory, your browser will prompt you for a username and password.

Redirecting from HTTP to HTTPS

If a site is only available over HTTPS, then use this method to automatically redirect from http://domain to https://domain:

  1. Create website with a static application for redirecting incoming requests.

    1. Log in to the control panel.

    2. Click Domains / websites ‣ Websites. The list of websites appears.

    3. Click the Add new website button. The Create a new website form appears.

    4. In the Name field, enter a website name.

    5. If applicable, in the Machine menu, click to select the server to host the website.

    6. If applicable, in the IP address menu, click to select the IP address to serve the site.

    7. For each domain name you want to redirect from HTTP to HTTPS, add it to the list of domains. In the Domains field, enter the domain name. Enter one or more domain names. If the domain has not yet been added to the control panel, click the Create link that appears at the bottom of the list of domains to add it.

    8. Click Add an application ‣ Create a new application. The Create a new web app form appears.

    9. In the Name field, enter a name for the application.

    10. In the App category menu, click to select Static.

    11. In the App type menu, click to select Static/CGI/PHP-5.4.

    12. Click the Save button. The application is installed and added to website’s list of applications.

    13. Click the Save button. The website is created and added to the list of websites.

  2. Add the redirect rule.

    1. In a text editor, open ~/webapps/app_name/.htaccess, where app_name is the name of the new Static/CGI/PHP application.

    2. Append the following lines:

      RewriteEngine On
      RewriteCond %{HTTP:X-Forwarded-SSL} !on
      RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
      
    3. Save and close the file.

New incoming requests to the specified domains redirect to HTTPS.

Redirect a Domain with a Static/CGI/PHP App

You can use a Static/CGI/PHP app to redirect one domain to another by using Apache’s URL rewriting feature. For example, you can use a Static/CGI/PHP app to automatically redirect requests arriving at example.com to www.example.com.

To redirect from origin_domain to destination_domain:

  1. Create website with a static application for redirecting incoming requests.

    1. Log in to the control panel.

    2. Click Domains / websites ‣ Websites. The list of websites appears.

    3. Click the Add new website button. The Create a new website form appears.

    4. In the Name field, enter a website name.

    5. If applicable, in the Machine menu, click to select the server to host the website.

    6. If applicable, in the IP address menu, click to select the IP address to serve the site.

    7. For each origin domain, add it to the list of domains. In the Domains field, enter the domain name. Enter one or more domain names. If the domain has not yet been added to the control panel, click the Create link that appears at the bottom of the list of domains to add it.

    8. Click Add an application ‣ Create a new application. The Create a new web app form appears.

    9. In the Name field, enter a name for the application.

    10. In the App category menu, click to select Static.

    11. In the App type menu, click to select Static/CGI/PHP-5.4.

    12. Click the Save button. The application is installed and added to website’s list of applications.

    13. Click the Save button. The website is created and added to the list of websites.

  2. Add the redirect rule.

    1. In a text editor, open ~/webapps/app_name/.htaccess, where app_name is the name of the new Static/CGI/PHP application.

    2. Append the following lines:

      Options +FollowSymLinks
      RewriteEngine on
      RewriteCond %{HTTP_HOST} ^origin_domain$ [NC]
      RewriteRule ^(.*)$ http://destination_domain/$1 [R=301,L]
      

      Thus, the file to redirect example.com to www.example.com would look like this:

      Options +FollowSymLinks
      RewriteEngine on
      RewriteCond %{HTTP_HOST} ^example.com$ [NC]
      RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
      
    3. Save and close the file.

All subsequent requests to a URL at origin_domain are rewritten to corresponding URLs at destination_domain.

Serving a Static/CGI/PHP application from a Subdirectory

Some frameworks and applications serve the publicly reachable site from a subdirectory, rather than a root directory. For example, the source for an application might have a directory structure like this:

demosource/
    demo/
      app/
      config/
      tests/
    www/

in which www is the only directory to be served publicly. In situations like this, use a Symbolic link application. A Symbolic link application works like a Static/CGI/PHP application, except that files are served from a directory you choose (instead of a ~/webapps/app_name/ directory). The directory you choose can be any directory that you have access to (including directories inside other applications).

To create a simple website that serves from a subdirectory:

  1. Log in to the WebFaction control panel.
  2. Click Domains / websites ‣ Websites. The list of websites appears.
  3. Click the Add new website button. The Create a new website form appears.
  4. In the Name field, enter a website name.
  5. In the domains field, enter a domain name.
  6. Click Add an application ‣ Create a new application. The Create a new web app form appears.
  7. In the Name field, enter a name for the application.
  8. In the App category menu, click to select Symbolic link.
  9. In the Extra info field, enter the full path to the subdirectory to be served (for example, /home/demo/demosource/www/). The path must point to an existing directory; the path is not created for you.
  10. Click the Save button. The application is installed and added to the website’s list of applications.
  11. Click the Save button. The website is created and added to the list of websites.

Now, the contents of the directory are served at the root of the specified domain.

Using RewriteBase

If you are using mod_rewrite (activated with the RewriteEngine on directive) you may need to use the RewriteBase directive to get the desired results. The RewriteBase directive sets the base URL for rewrites; in other words, it establishes the starting URL path for all of your subsequent URL rewrites.

In almost all cases, if you are using mod_rewrite and the RewriteEngine on directive, you should also set RewriteBase in your .htaccess file to the corresponding URL path in the control panel.

For example, if your application is mounted at the root URL path (/), then your RewriteBase directive should be RewriteBase /. If the application is mounted elsewhere, the RewriteBase directive should match. For example, if your application is mounted at /blog, then your RewriteBase directive should be RewriteBase /blog.

See also

Apache’s RewriteBase Directive documentation

Troubleshooting

Error: 500 Internal Server Error

A 500 Internal Server Error is a generic error, which indicates that the Apache failed to complete a response. In other words, Apache failed to do something during the request. To resolve these errors, it’s best to look in the error log for the Static/CGI/PHP application responsible for the error. The error log is $HOME/logs/frontend/error_website_php.log, where website is the name of the website entry on which the Static/CGI/PHP application is mounted.

In the following subsections, you’ll find common errors explained with typical solutions.

See also

This sections covers language agnostic causes to 500 Internal Server Error. Please see the PHP-specific documentation for such errors related directly to PHP.

See also

Accessing Logs

Error: Permission denied

If you encounter the 500 Internal Server Error in the browser and this error in your $HOME/logs/frontend/error_website_php.log log file:

[Thu Sep 16 12:00:00 2010] [error] [client 12.345.678.9] (13)Permission denied: exec of '/home/<username>/webapps/<app_name>/path/to/script' failed, referer: http://<domain>/<url_path>/

it means that the permissions for your script are set incorrectly. Your user account must have execute permissions on the file and its parent directory.

To set the correct permissions:

  1. Open an SSH session to your account.
  2. Switch to the directory of the script. Enter cd script_dir, where script_dir is the path to the directory where the offending script is, and press Enter.
  3. Set the file permissions on the script and its parent directory. Enter chmod 711 . script, where script is the file name of the script, and press Enter.

Your script should now run without the Permission denied error.

Error: Premature end of script headers

If you encounter the 500 Internal Server Error in the browser and this error in your log file:

[Thu Sep 16 12:00:00 2010] [error] [client 12.345.678.9] Premature end of script headers: <script name>

a likely cause is that the permissions for your CGI script are set incorrectly. Your user account must have a minimal set of execute permissions on the file and its containing directory such that:

  • the script is executable by the user,
  • the script’s parent directories (up to its containing Static/CGI/PHP application) are executable by the user;
  • the script is not writeable by group or other, and
  • the script’s parent directories (up to its containing Static/CGI/PHP application) are not writeable by group or other.

To set the correct permissions:

  1. Open an SSH session to your account.

  2. Switch to the directory of the script. Enter cd script_dir, where script_dir is the path to the directory where the offending script is, and press Enter.

  3. Set the file permissions on the script and its parent directory. Enter chmod 711 . script, where script is the file name of the script, and press Enter.

    For any additional parent directories enter chmod 711 dirs, where dirs are a space-separated list of paths to directories, and press Enter.

The script’s permissions should now be set appropriately.

Error: No such file or directory

If you encounter the 500 Internal Server Error in the browser and this error in your $HOME/logs/frontend/error_website_php.log log file:

[Thu Sep 16 12:00:00 2010] [error] [client 12.345.678.9] (2)No such file or directory: exec of '/home/<username>/webapps/<app_name>/path/to/script' failed, referer: http://<domain>/<url_path>/

it typically indicates one of these problems:

  1. a CGI script contains \r\n (or CRLF) line endings instead of Unix-standard \n or LF line endings, or
  2. the path specified in the script’s shebang line does not exist.
Incorrect Line Endings

You can verify line endings with the hexdump tool.

In this example, the wrong line ending is represented as 0a0d:

$ hexdump my_file
0000000 2123 752f 7273 6c2f 636f 6c61 622f 6e69
0000010 702f 7479 6f68 326e 352e 0a0d ...

To fix incorrect line endings, use dos2unix:

$ dos2unix my_file
dos2unix: converting file my_file to UNIX format ...
$ hexump my_file
0000000 2123 752f 7273 6c2f 636f 6c61 622f 6e69
0000010 702f 7479 6f68 326e 352e 0a0a ...

Now the file has the correct line endings for use on the WebFaction server. Alternatively, you may reconfigure your STFP client to save uploaded files with the proper line endings.

Incorrect Shebang Line

Many scripts begin with a shebang line to indicate which interpreter is to be used to run the script. For example, a Python 3.4 script’s shebang line might look like this:

#!/usr/bin/env python3.4

If the shebang line points to an interpreter that doesn’t exist, however, the script will fail with an error.

A similar error will appear when the script is run from the command line. For example:

$ ./test.py
-bash: ./test.py: /usr/bin/env pyton2.5: bad interpreter: No such file or directory

This error indicates that the path specified on the shebang line does not exist. In the example, there’s a typo: pyton. Once the typo is corrected, the script will run without error.

Error: Invalid command or Illegal option with .htaccess

If you encounter the 500 Internal Server Error in the browser and one of these errors in your $HOME/logs/frontend/error_website_php.log log file:

[Thu Sep 16 12:00:00 2010] [error] [client 12.345.678.9] /path/to/.htaccess: Invalid command '<token>', perhaps misspelled or defined by a module not included in the server configuration, referer: http://<domain>/<url_path>/
[Thu Sep 16 12:00:00 2010] [error] [client 12.345.678.9] /path/to/.htaccess: Illegal option <token>, perhaps misspelled or defined by a module not included in the server configuration, referer: http://<domain>/<url_path>/

Then it means that there is an error in your .htaccess file. Make sure your .htaccess file does not contain any syntax errors or misspelt directives. Any error in the file will cause the entire .htaccess file to fail.

Error: Request exceeded the limit of 10 internal redirects

If you encounter a 500 Internal Server Error and one of these errors in your $HOME/logs/frontend/error_website_php.log log file:

[Thu Sep 16 12:00:00 2010] [error] [client 12.345.678.9] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace., referer: http://<domain>/<url_path>/

Then it means that Apache was unable to resolve a redirect in your site. Typically, this error can be resolved by setting RewriteBase in the application’s .htaccess file.

Error: 503 Service Unavailable

A 503 Service Unavailable error occurs when a Static/CGI/PHP application is unable to fulfill the incoming request. This typically happens because of heavy traffic and too many requests come in during a short period of time. Minimize this error by optimizing the site to spend less time and resources per request and reducing the total number of requests to the site. For example, cache database queries and serve static content from a separate, static-only application.

URLs without a Trailing Slash Redirect to the Wrong Domain

Static/CGI/PHP applications automatically redirect http://domain/path to http://domain/path/ (note trailing slashes) when path is a directory within the Static/CGI/PHP application. However, if you’ve configured a website record with two or more domains, these redirections may behave unexpectedly. For example, a request to http://original_domain/path may be redirected to http://other_domain/path/.

This unexpected behavior occurs because the Static/CGI/PHP application completes the redirect using an arbitrary domain chosen from the website record. This arbitrarily chosen domain may not be the original domain used in the request. To prevent such cross-domain redirections, please create a separate website record for each domain in use.

Uploaded Files Owned by Apache

In some cases, files uploaded through PHP or WebDAV can become owned by the apache user and group. When files are owned by apache, they cannot be modified in an SSH session or with SFTP.

To prevent this from happening, the setgid flag must be set on the directory where the files are being saved. This will cause files saved in the directory to be owned by the same group as the directory itself—in other words, your user—instead of apache‘s group.

To set the setgid flag for a directory:

  1. Open an SSH session to your account.
  2. Enter chmod g+s directory where directory is the path to the directory where files are owned by apache, and press Enter.