Nginx all php in folder
- Haskell vs. PureScript: The difference is complexity Haskell and PureScript each provide their own unique development advantages, so how should developers choose between these two .
- A quick intro to the MACH architecture strategy While not particularly prescriptive, alignment with a MACH architecture strategy can help software teams ensure application .
- How to maintain polyglot persistence for microservices Managing microservice data may be difficult without polyglot persistence in place. Examine how the strategy works, its challenges.
- GitHub Copilot Chat aims to replace Googling for devs GitHub’s public beta of Copilot Chat rolls out GPT-4 integration that embeds a chat assistant into Visual Studio, but concerns .
- The basics of implementing an API testing framework With an increasing need for API testing, having an efficient test strategy is a big concern for testers. How can teams evaluate .
- The potential of ChatGPT for software testing ChatGPT can help software testers write tests and plan coverage. How can teams anticipate both AI’s future testing capabilities .
- 5 Google Cloud cost optimization best practices Cost is always a top priority for enterprises. For those considering Google Cloud, or current users, discover these optimization .
- How to create and manage Amazon EBS snapshots via AWS CLI EBS snapshots are an essential part of any data backup and recovery strategy in EC2-based deployments. Become familiar with how .
- Prices for cloud infrastructure soar 30% Tough macroeconomic conditions as well as high average selling prices for cloud computing and storage servers have forced .
- API keys: Weaknesses and security best practices API keys are not a replacement for API security. They only offer a first step in authentication — and they require additional .
- Risk & Repeat: Are data extortion attacks ransomware? Ransomware gangs are focusing more on data theft and extortion while skipping the encryption of networks. But should these .
- Cyber insurers adapting to data-centric ransomware threats Cyber insurance carriers and infosec vendors weigh in on how the shift in ransomware tactics is affecting policies and coverage, .
- AWS Control Tower aims to simplify multi-account management Many organizations struggle to manage their vast collection of AWS accounts, but Control Tower can help. The service automates .
- Break down the Amazon EKS pricing model There are several important variables within the Amazon EKS pricing model. Dig into the numbers to ensure you deploy the service .
- Compare EKS vs. self-managed Kubernetes on AWS AWS users face a choice when deploying Kubernetes: run it themselves on EC2 or let Amazon do the heavy lifting with EKS. See .
PHP Apps in a Subdirectory in Nginx
We see how to properly configure Nginx to nest a PHP application in a sub-directory.
In this video, we work through how to put your PHP application in a subdirectory of another site.
For example, we may have an application running at example.org but need a second application running at example.org/blog .
This feels like it should be simple, but it turns out to be more complex and fraught with confusing Nginx configurations! To make matter worse (or, perhaps, to illustrate this point), a quick Google search reveals a TON of confusing, non-working examples.
What We’re Using
The server is Ubuntu 16.04, , we install Nginx 1.13 and PHP 7.2. The example PHP applications are Laravel 5.5.
TL;DR
Here’s the working configuration to have two Laravel apps working, where one application exists in a subdirectory of another.
server < listen 80 default_server; listen [::]:80 default_server; root /var/www/top/public; index index.html index.htm index.php; server_name _; location / < try_files $uri $uri/ /index.php$is_args$args; >location /nested < alias /var/www/nested/public; try_files $uri $uri/ @nested; location ~ \.php$ < include snippets/fastcgi-php.conf; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; >> location @nested < rewrite /nested/(.*)$ /nested/index.php?/$1 last; >location ~ \.php$ < include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; >>
How This Works
Let’s cover some details of the above configuration to see what’s going on.
Project Locations
In this example, the application files of the two applications don’t actually exist within one another. The application top exists in /var/www/top while the «nested» application lives in /var/www/nested .
This is, in my opinion, the prefered setup in this case, as nesting application files where you «physically» put one project’s files inside of another’s gets really messy with most PHP applications’ use of a public directory as a web root.
Your case may change a bit depending on the applications of course, but that shouldn’t change too much of this guide.
The Basic Setup
We start with a basic server configuration, good for serving a single application:
This excludes some stuff you might want in a production app (e.g. cache headers for static assets), but is enough to get a PHP application working fine.
The relevant parts to this guide are:
- root — we define the web root that is used with application top
- index — We define index.php as one of the default files to look for if no file is specified in the URI
- location < try_files . >— We use the standard try_files directive in a block that catches all URI’s. This looks to see if a file or directory sent in the URI exists within the root directory. If it does not exist, it goes to the index.php file, which we know for sure is in the root directory.
Any part of the URI is appended to the root directive. So a URI of /foo/bar will search for a file or directory /var/www/top/public/foo/bar . In combination with the index directive, it also seaches for /var/www/top/public/foo/bar/index.[html|htm|php] .
More interestingly however, the try_files directive will send most requests (except those for static assets — js, css files) to /index.php . Just like with any other URI, that is getting appended to the root , so Nginx will look for /var/www/top/index.php .
The last location ~ \.php$ <. >block is used for any files ending in .php . It sends the file off to PHP-FPM for processing.
Adding an App in a Subdirectory
We run into a few issues when running a second app within a subdirectory. Let’s walk through them.
First, we know we want a second application to run in subdirectory /nested (the subdirectory is arbitrary, I just chose to name it «nested»). So, we create a location block for the «nested» location:
Now we can add to it to get our application running.
We know we have a separate web root for the nested project. Like me, your first inclination may be to set a root to point Nginx to /var/www/nested/public , but this doesn’t end up working! Instead, we need to use an alias :
An alias is similar to root , but it has different behavior.
Nginx combines the root + the given URI to find a file on the disk drive. For example, a URI /foo/bar will instruct Nginx to serve /var/www/top/public/foo/bar . Since that directory doesn’t exist, the try_files part tells Nginx to send the request to /var/www/top/public/index.php .
The included snippets/fastcgi-php.conf configuration takes care of parsing out /foo/bar as the intended URI that the PHP application uses as a route.
The alias does not behave exactly like this. In our example, the /nested URI is aliased to /var/www/nested/public . A URI of /nested will therefore look in /var/www/nested/public for a file to serve. A URI of /nested/foo will instruct Nginx to look in /var/www/nested/public/foo ; the /nested portion is omitted.
Note that distinction — with that alias, Nginx does NOT look for files within /var/www/nested/public/nested/foo , like it would with the root directive.
So, alias has the behavior we want — it won’t try to look for files inside of some nested directory that does not exist. We still need to make a URI like /nested/foo serve from file /var/www/nested/public/index.php , so we have to add another try_files .
That looks very familiar! However, we’re going to have to do some more PHP things specifically in the /nested location, so let’s get a PHP handler in there also:
The PHP handler location block is nested within the location /nested <. >block so we can customize it a bit.
Note that I snuck something into the PHP location block there. I (re)set the SCRIPT_FILENAME FastCGI parameter to $request_filename . This normally is $document_root$fastcgi_script_name , which in our configuration would always point to /var/www/top/public/index.php — the wrong application!
Instead we use $request_filename , which has the following definition in the Nginx docs:
file path for the current request, based on the root or alias directives, and the request URI
So this takes the alias into account correctly, and will pass the correct path to the index.php file in our nested application.
This will appear to work at first! Heading to URI /nested will work fine. What happens is /nested is aliased to /var/www/nested/public and try_files sends that to /index.php , which ends up correctly being /var/www/nested/public/index.php .
However, if our app has a defined route ( foo , for example), and we try to head to URI /nested/foo to reach it, we receive a 404 error! Not only that, it’s a 404 page from the top level app!
This request ends up being handled by the outer PHP handler, which uses $document_root$fastcgi_script_name for the SCRIPT_FILENAME , thus pointing to file /var/www/top/public/index.php and being served by the top level app.
I’ve confirmed and tested the request is handled by the location /nested block, and is then sent to the wrong location ~ \.php$ <. >block. I’m not sure why this happens though! If you do, drop me a tweet @fideloper or email — chris AT this site’s domain.
To get around this issue, we rewrite the URI to put index.php in the correct spot in the eyes of Nginx.
To implement the rewrite, we’ll use a named location:
location /nested < alias /var/www/nested/public; try_files $uri $uri/ @nested; location ~ \.php$ < include snippets/fastcgi-php.conf; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; >> location @nested < rewrite /nested/(.*)$ /nested/index.php?/$1 last; >
We adjust try_files to send requests to @nested , and then define @nested as a named location block.
This location block rewrites the URI so /nested/foo becomes /nested/index.php/foo . The last directive tells Nginx to use the new, rewritten URI and match it against the other location blocks.
Nginx then re-reaches the location /nested <. >block, where it’s parsed correctly! The index.php file is in the correct location on the disk, and the included fastcgi-php.conf configurations parse out the foo route from the rest of the URI as normal (via fastcgi_split_path_info , if you were curious).
Don’t forget the needed change to the SCRIPT_FILENAME FastCGI parameter explained above as well. That sends our correctly-parsed script file path to PHP-FPM.
Testing
Here’s what I did to create this scenario and test out the Nginx configuration:
# Ubuntu 16.04 Server sudo add-apt-repository -y ppa:ondrej/php sudo add-apt-repository -y ppa:nginx/development sudo apt-get update sudo apt-get install -y nginx php7.2-fpm php7.2-cli \ php7.2-pgsql php7.2-sqlite3 php7.2-gd \ php7.2-curl php7.2-memcached \ php7.2-imap php7.2-mysql php7.2-mbstring \ php7.2-xml php7.2-zip php7.2-bcmath php7.2-soap \ php7.2-intl php7.2-readline php7.2-imagick php-msgpack php-igbinary php -r "readfile('http://getcomposer.org/installer');" | sudo php -- --install-dir=/usr/bin/ --filename=composer cd /var/www sudo composer create-project laravel/laravel top sudo composer create-project laravel/laravel nested sudo chown -R www-data: top nested
Specify all php files in Nginx config in order to make said php app more safe (nginx)
I am asking the question in order to gather evidence for going further, and also since I couldn’t readily find a script that would be directed at such config creation for nginx. (Maybe just because it is so easy to write..). Ultimately the goal is extra security, and thus I’m also seeking opinions on how such configuration of Nginx would affect it, and if it is a good idea at all.
1 Answer 1
A web service is usually a public service. Everything (every file) you store within your web root folder or any sub folder of your web root folder is public. You can define exceptions of this behavior in your web server configuration.
To protect files, scripts and folders from public access I recommend to store them not in or below of your web root folder.
Following these generic rules is a good approach in getting a secure web server or web application server.
To be more specific regarding your case I would recommend to store (as Michael Hampton already mentioned) only your index.php (and all required images and public JavaScripts) in your web root folder.
All the PHP classes you will need to provide your API or application should be stored apart from your web root folder as well as your Composer files (usually stored in the folder «vendor»).
/project_root /htdocs (web root folder) index.php favicon.ico robots.txt /images logo.png background.png /javascript script.js /src /php /api /controller /overview get.php /login get.php put.php delete.php post.php /javascript base.js /reload plugin.js /vendor autoload.php
For above example following Nginx config would provide your application:
server < . # take care to deliver public static content if file exists # or execute /index.php if not location / < try_files $uri /index.php; >. # do not execute /index.php if requested image or JavaScript does not exists location ~ ^/(images|javascript)/ < try_files $uri =404; >. # execute PHP files location ~ \.php$ < try_files $uri /index.php; include fastcgi_params; fastcgi_keep_conn on; fastcgi_pass unix:/run/php/php7.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; >>