Jeremy David
Jeremy David

Reputation: 246

How to install symfony2 app in a subdirectory in nginx

I need to install multiple symfony2 applications on the same host but on different subdirectories (or location blocks).

With this config nginx throws a "file not found" or redirect loop message when trying to access any url.

Example:

/login -> /base/login
/app1 -> /base/app1
/app2 -> /base/app2

Current Config:

root /base/default; #Points to an empty directory

# Login Application
location ^~ /login {
    alias /base/login/web;
    try_files $uri app_dev.php;
}

# Anything else
location ~ ^/([\w\-]+) {
    alias /base/$1/web;
    try_files $uri app_dev.php;
}

location / {
    # Redirect to the login
    rewrite ^ /login redirect;
}

# Handle PHP
location ~ \.php$ {
    include fastcgi_params;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
    fastcgi_param HTTPS off;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

Upvotes: 5

Views: 7565

Answers (3)

Houssem BDIOUI
Houssem BDIOUI

Reputation: 114

Based on dcaillibaud's answer, here's a more generic configuration, allowing to support multiple Symfony (version 2 or 3) projects under the root web path, using some regular expression magic:

server {
    # other specific directives...

    root /var/www;

    location ~ ^/([^/]+)/dev(/.*)$ {
        location ~ \.php { deny all; }
        set $sf2_root /$1;
        set $sf2_prefix /$1/dev;
        set $sf2_ctrl app_dev.php;
        expires off;
        try_files $sf2_root/web$2 @sf2;
    }
    location ~ ^/([^/]+)(/.*)$ {
        location ~ \.php { deny all; }
        set $sf2_root /$1;
        set $sf2_prefix /$1;  
        set $sf2_ctrl app.php;
        try_files $sf2_root/web$2 @sf2;
    }
    location @sf2 {
        expires off;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$sf2_root/web/$sf2_ctrl;
        fastcgi_param SCRIPT_NAME       $sf2_prefix/$sf2_ctrl;
        fastcgi_param REQUEST_URI       $sf2_prefix$2;
    }
}

So basically, you'll have: www.domain.com/project pointing to your PROD environment and www.domain.com/project/dev pointing to your DEV environment

Please replace the line: fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; with your appropriate backend

This can also be easily adapted for newer Symfony projects using index.php script instead of app(_dev).php, changing the web/public path, and setting some ENV variables.

I think this approach, answers better the original question.

Upvotes: 0

Congelli501
Congelli501

Reputation: 2593

Here is a simpler configuration for symfony2 on the "/front/" subdirectory. Route generation and assets work fine.

The configuration

set $frontRoot /your/project/path/web;
set $sfApp app_dev.php; # Change to app.php for prod

location /front/ { # Static files
    root $frontRoot;
    rewrite ^/front/(.*)$ /$1 break;
    try_files $uri @sfFront;
}

location @sfFront { # Symfony
    fastcgi_pass phpfcgi;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $frontRoot/$sfApp;
    fastcgi_param SCRIPT_NAME /front/$sfApp;
    fastcgi_param REQUEST_URI /front$uri?$args;
    fastcgi_param HTTPS off;
}

Some explanation

The trick is to make symfony believe app.php script is in /front/, so it generates routes and assets with this path.

I looked at what apache was giving to MOD-PHP to use the same values.

  • SCRIPT_FILENAME: The absolute path to the PHP file. Here, it is always /your/project/path/app_dev.php
  • REQUEST_URI: The URI the user entered. Here, we have to manually re-add /front at the begining of the path as it was removed by the file serving location (via rewrite ^/front/(.*)$ /$1 break;)
  • SCRIPT_NAME: The value is /front/app_dev.php. This is the most important part. Symfony will cut app_dev.php and prepend /front to all its routes.

Upvotes: 4

dcaillibaud
dcaillibaud

Reputation: 351

After hours spended to find this (sf2 doc doesn't explain how cgi parameters are needed and interpreted, you need to go through Request.php to understand), so I share this.

This is a config which seems ok with sf2 in a directory {subdir} (and web access to others files than {subdir}/web/* prohibited).

It works for me with php-fpm (socket).

Of course, replace "{subdir}" by your /path/from/docroot/to/symfony_root/

dev environnement can be choosen by adding "dev" to "{subdir}" (since app_dev.php in the url no longer works with this conf)

server {

  # general directives

  location ~ ^/{subdir}(/.*)$ {   
    try_files /{subdir}/web$1 @sf2;
  }
  location ~ ^/{subdir}dev(/.*)$ {
    expires off;
    try_files /{subdir}/web$1 @sf2dev;
  }
  location @sf2 {
    expires off;
    fastcgi_pass   {your backend};
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/{subdir}/web/app.php;
    fastcgi_param SCRIPT_NAME       /{subdir}/app.php;
    fastcgi_param REQUEST_URI       /{subdir}$1;
  }
  location @sf2dev {
    expires off;
    fastcgi_pass   {your backend};
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/{subdir}/web/app_dev.php;   
    fastcgi_param SCRIPT_NAME       /{subdir}dev/app_dev.php;       
    fastcgi_param REQUEST_URI       /{subdir}dev$1;     
  }


  # other location directives

  # if some others apps needs php, put your usual location to cactch php here

}

I Hope it helps (and there isn't any misconfiguration), given without any guarantee...

Of course you can pick out prod/dev conf if you don't need. And you can use var and only one @sf2 location instead :

  set $sf2_root /{subdir};
  location ~ ^/{subdir}(/.*)$ {   
    set $sf2_prefix /{subdir};  
    set $sf2_ctrl app.php;
    try_files $sf2_root/web$1 @sf2;
  }
  location ~ ^/{subdir}dev(/.*)$ {
    set $sf2_prefix /{subdir}dev;
    set $sf2_ctrl app_dev.php;
    expires off;
    try_files $sf2_root/web$1 @sf2;
  }
  location @sf2 {
    expires off;
    fastcgi_pass   {your backend};
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$sf2_root/web/$sf2_ctrl;
    fastcgi_param SCRIPT_NAME       $sf2_prefix/$sf2_ctrl;
    fastcgi_param REQUEST_URI       $sf2_prefix$1;
  }

Upvotes: 16

Related Questions