Laravel - NGINX + Apache reverse proxy 404 on all routes - laravel

i'm setting up a project in Laravel which makes use of a custom vagrant box based on Ubuntu 14.04 and which runs NGINX and Apache in a typical reverse proxy setup.
Now, the issue is that something along the way is not registering the URL path, so when i enter http://mydomain.test/hello what i ultimately get is just a http://mydomain.test/index.php on the other end and it seems to completely forget about the route param.
I'm using Apache 2.4.7 with Mod PHP and the Apache config is as follows.
<VirtualHost 127.0.0.1:8080>
ServerName application.test
ServerAlias www.application.test
DocumentRoot "/home/vagrant/application/public"
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
<Directory "/home/vagrant/application/public">
Require all granted
AllowOverride all
</Directory>
</VirtualHost>
As indicated Apache is listening on Port 8080 and NGINX is listening on port 80 with the following config.
server {
listen 80;
server_name application.test www.application.test;
root /home/vagrant/application/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$is_args$args;
}
location ~ \.php$ {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /\. {
deny all;
}
}
I can confirm that all Laravel requirements are being fulfilled, so i have MBString, OpenSSL, etc... I can also confirm that the rewrite module is working as i can add a redirect clause to my .htaccess and it does get executed as expected.
This is my .htaccess file.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Am i possibly missing something here? I've configured NGINX and PHP-FPM before but it's my first time doing it with Apache, i've gone through multiple similar questions but none of the proposed fixes has yet worked for me and that's why i ask this question.
Thank you in advance for your help
EDIT
Some progress.
If i set the location config for NGINX as follows
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Then it works, but to the best of my knowledge then this means that even static file requests would end up proxied to Apache.
location ~ \.php$ doesn't seem to work as the laravel pretty url doesn't end with a ".php" suffix i guess. But how would one go about making these two play nice with one another?
The idea i guess is that you have a default location that directs to index.php and when that index.php file is triggered then nginx receives another HTTP request that matches your php location block and will proxy the request to Apache.
The issue is that during this second request, all knowledge of the URI was lost and the URI is now just "index.php" so as far as Apache knows you're always making requests to /index.php.
I still don't know how to fix it though.

So i think i've figured it out, if you have a similar problem, a possible solution is to add the $uri variable to the try_files directive
server {
listen 80;
server_name application.test www.application.test;
root /home/vagrant/application/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php$uri;
}
location ~ \.php {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /\. {
deny all;
}
}
That way, when nginx calls your index.php it'll call it like http://application.test/index.php/hello and this is the URL that Apache ultimately receives and processes through PHP.
So then, .htaccess comes into play, Laravel does it's thing and everything works, and this still only affects PHP files, your static files should still be served directly by NGINX.
If you find anything wrong with this approach please let me know.
UPDATE
A dumb mistake on my end later down the line lead me to believe something else was wrong, every route seemed to display the contents of my "/" root route.
After trying to use Homestead instead of my custom setup i was surprised to find it affected Homestead as well, so it had to be related to my app itself and not the Server.
Basically it was the Exception handler returning the root view because my requests were missing some data required by my FormRequests, after changing my Exception handler class to handle JSON responses it worked as expected.
If you fall into this kind of trap, try to make sure your app works with Homestead, if it does then there's something wrong with your vagrant setup, if not, then it's your Laravel app that's to blame.
If your Exception Handler just does the typical render, then be wary of the fact it'll attempt to redirect to the previous route, which if you're developing an API with Postman will be "/".

Related

Base URL is non-www which results in routes non-www

I have a Laravel 8 project running on an Nginx Webserver in a Docker container through an Nginx Reverse Proxy.
So DNS -> Reverse Proxy -> Docker Webserver container -> PHP-FPM container
The problem is that when I use Laravel's route() it is missing the www resulting in login not working (as well as assets etc).
Because I AM on the www domain (because of Nginx redirect) but the route endpoint is non-www (so a different site, token issue I believe).
In my .env I have APP_URL set which I believe is only for CLI commands and additionally I have ASSET_URL set, which works for the asset() functions. I should not have to use ASSET_URL if the source of the problem, my setup, is correct (which it clearly is not).
I CAN bypass the problem by using URL::forceRootUrl(config('app.url')); in my router, that forces the APP_URL set in my .env to be used in the RouteUrlGenerator (I believe)
Output of \URL::to('/') is https://example.com, so NON-WWW (obv. WITHOUT using URL::forceRootUrl(config('app.url'));)
Even though my browser's URL is including www, so https://www.example.com/blabla.
I would say something is wrong in my setup, either my DNS, Nginx Reverse Proxy, or Nginx Webserver configs but I can't figure out what it is...
I hope it is just a simple redirect fix somehow.
I have also already restarted my servers etc and done a php artisan optimize:clear and also config:cache and config:clear to be sure.
Please find below my configs:
DNS via CloudFlare (proxied):
A example.com 123.123.123.123 Proxied
A www 123.123.123.123 Proxied
CNAME * example.com DNS Only
My Nginx Reverse Proxy config:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:8012;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
My Nginx webserver config:
server {
# listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
# listen 80 default_server;
index index.html index.htm index.php;
server_name www.example.com;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9012;
fastcgi_index index.php;
include fastcgi_params;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME /var/www/example.com/public/$fastcgi_script_name;
# fastcgi_param SCRIPT_FILENAME $document_root/example.com.au/$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
# Support Clean (aka Search Engine Friendly) URLs & enable Gzip compression:
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
My "default" Laravel 8 .htaccess:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
My .env:
APP_NAME=SomeSite.com
APP_ENV=production
APP_KEY=base64:sdljkldasjkasjasdjklaslkasd
APP_DEBUG=true
APP_URL=https://www.example.com#Used for CLI function such as artisan...
#ASSET_URL=https://asseturl.test#Only used in asset()
TRUSTPROXIES=*
...
Solution is moving the 301 redirect from Nginx Webserver to Nginx Reverse Proxy (superior level).
This is the following part of the configuration file:
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
Edit: I suspect it's related to the part:
proxy_set_header Host $host;

Spring Boot firewall behind Apache2: malicious String "//"

I am using a Spring Boot fat jar for serving backend and static files. I need to let it run behind an apache2. But I am getting the malicious string errors for "//" from the firewall:
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String "//"
at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlacklistedUrls(StrictHttpFirewall.java:369) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:336) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:194) ~[spring-security-web-5.2.1.RELEASE.jar!/:5.2.1.RELEASE]
...
My application properties are:
server:
port: 9001
address: 127.0.0.1
forward-headers-strategy: framework
And my apache2 virtual host is:
<VirtualHost *:80>
ServerName XXX
ProxyPreserveHost on
RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443
ProxyPass / http://localhost:9001/
ProxyPassReverse / http://localhost:9001/
RewriteEngine on
RewriteCond %{SERVER_NAME} =XXX
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Where "XXX" is the servername.
What am I missing here? I don't really want to reconfigure the firewall because I think there must be a solution without changing it.
To answer my question: I forgot to change the ssl confgiuration with:
<VirtualHost *:443>
...
</VirtualHost>
So if you have the same problem it may be the missing changes in the right config.

Installing Laravel application on main domain (without using subdomains)

Server: DigitalOcean (Ubuntu)
I am setting a server. I have a Laravel application that is currently setup to be accessed via subdomain, e.g. subdomain.mydomain.com. But I would like to access my application from the main domain, not subdomain.
For instance: instead of subdomain.domain.com, I would like to use domain.com. Below is my 000-default.conf configuration.
<VirtualHost *:80>
ServerName mydomain.com
ServerAlias www.mydomain.com
DocumentRoot "/var/www/html/myapplication/public"
<Directory "/var/www/html/myapplication/public/">
AllowOverride All
</Directory>
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.mydomain.com [OR]
RewriteCond %{SERVER_NAME} =mydomain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Any help is highly appreciated!
You are missing the configuration for the php interpreter. i suggest you copy your old subdomain config and just change ServerName, ServerAlias.
here's an example of what you are missing:
location ~ .php$ {
set $path_info $fastcgi_path_info;
root /var/www/html/myapplication/public;
fastcgi_index app.php;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
try_files $uri $uri/ /app.php$is_args$args /index.php$is_args$args;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Laravel 4 Routing (controller not found)

Help please, i am using Laravel4 but for some reason i can not get it to work on my mac at home,i have no problems with the mac at work, either i am missing something obvious or my mac is set up different.
the problem i am having is that i can only get the HomeController To Work if i try to use the Test Controller i get Controller method not found. the whooops error gives Controller Method Not Found
REDIRECT_URL /test
GATEWAY_INTERFACE CGI/1.1
SERVER_PROTOCOL HTTP/1.1
REQUEST_METHOD GET
QUERY_STRING
REQUEST_URI /test
SCRIPT_NAME /index.php
PATH_INFO /test
PATH_TRANSLATED redirect
my routes
Route::controller('test', 'TestController');
and my Test Controller
class TestController extends BaseController {
public function getIndex()
{
return View::make('test.index');
}
}
my htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
rewrites are enabled
am i missing the obvious?
thanks for any help
I had a similar situation in my local development environment. The Laravel 4 app that was deployed on my remote server was working perfectly, however I couldn't get it to work on my local machine. The problem was that only the root folder of the app (/public - Home Controller) was accessible and none of my routes were working.
The problem was in the configuration of Apache which was not allowing loading of .htaccess files. My solution was to define a new Directory statement for my sites path as follows:
<Directory "/path/to/your/sites">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
You may insert this in httpd.conf or in any configuration file that is being loaded. If there is already a definition for that path, you should update it accordingly. In my case I added the code above to my httpd-vhosts.conf file along with the virtual host definition:
<VirtualHost *:80>
ServerAdmin your#email.com
DocumentRoot "/path/to/your/sites/laravel/public"
ServerName laravel.dev
ServerAlias www.laravel.dev
</VirtualHost>
Finally add this line to your /etc/hosts
127.0.0.1 laravel.dev
In this way, you can reach your local environment via this URI: http://laravel.dev

mod_rewrite to remove SSO(single sign on) - junction name in URL

I have a SSO url -
http://<server>/<junction>/<application_context>/ssoLogin.do
e.g. http://pingu.intranet.com/tms/mint/ssoLogin.do
Once user hits this url. SSO junction appends headers and redirects to Apache webserver. My goal is to remove the SSO junction name once the request reaches Apache(where I am using ProxyPass and AJP to connect to Tomcat App).
Issue is mod_rewrite is picking the URI - /mint/ssoLogin.do. so I can not remove the junction name /tms. e.g. rewrite.log says
init rewrite engine with requested uri /mint/js/jquery/jquery.min.js
My conf file looks like
ProxyPreserveHost On
# define the balancer, with http and/ or ajp connections
<Proxy balancer://application_cl>
BalancerMember ajp://pingu01.intranet.com:8009 route=node1 disablereuse=on retry=0
BalancerMember ajp://pingu02.intranet.com:8009 route=node2 disablereuse=on retry=0
</Proxy>
# Vendor Product ProxyPass Settings
ProxyPass /mint balancer://application_cl/mint stickysession=JSESSIONID|jsessionid nofailover=On
ProxyPassReverse /mint balancer://application_cl/mint
# Custom settings to remove junction name for proper javascript loading
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/tms/
RewriteRule ^/tms/(.*) /$1
</IfModule>
# RequestHeader settings(as per Product documentation)
SetEnvIf X-Forwarded-Proto .+ HAVE_X_FORWARDED_PROTO
RequestHeader set X-Forwarded-Proto "http" env=!HAVE_X_FORWARDED_PROTO

Resources