NGINX : Allow users to password protect directories themselves? - hosting

To my knowledge Nginx can only password protect directories from within the configuration file(s). That works nicely, but is not a real option for end-users who A) can not edit the configs and B) would break the configs if they could
Right now I am thinking about a webbased representation of the directory structure where they can point and click - rewriting the configs and re-kill-HUP-ing Nginx...
But somehow the whole idea feels like I am about to rewrite cPanel v0.0.1 ;-)
Anybody here had the same problem and came up with an elegant and maintainable solution?
I have full control over the server.
Thanks!

You don't really want users to change the configs, do you?
For password-protection, a htpasswd-file is sufficient, if the realm always stays the same.
And nginx itself can check for a file existense.
So, this is what could do the job:
location ~ ^/([^/]*)/(.*) {
if (-f $document_root/$1/.htpasswd) {
error_page 599 = #auth;
return 599;
}
}
location #auth {
auth_basic "Password-protected";
auth_basic_user_file $document_root/$1/.htpasswd;
}
Works for me with nginx-0.7.65.
0.6.x and earlier releases are probably no-go

Related

Extending Nginx config on Beanstalk doesn't rewrite urls properly

I have an existing Laravel API application running on Beanstalk. It's been lagging in updates on EBS, so currently I'm in the process of upgrading the platforms and CI/CD for this app. There one remaining problem I'm running into, which leaves me scratching my head at the 'but it should work'-level.
What I want
All URLs containing https://example.com/index.php/endpoint to be redirected to https://example.com/endpoint and show the same content as https://example.com/index.php/endpoint would (incl. subsequent the URL's slugs)
How I'm trying to do this
Due to this wonderful answer by cnst, I have the configuration below that seems to work for many (incl. some other online sources).
server{
index index.php;
if ($request_uri ~* "^(.*/)index\.php/*(.*)$") {
return 301 $1$2;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
# Remove from everywhere index.php
if ($request_uri ~* "^(.*/)index\.php(/?)(.*)") {
return 301 $1$3;
}
}
if (!-d $request_filename) {
rewrite ^/(.+)/$ /$1 permanent;
}
if ($request_uri ~* "\/\/") {
rewrite ^/(.*) /$1 permanent;
}
}
I'm putting this configuration in a file located at my_project/.platform/nginx/conf.d/proxy.conf, which according to AWS' documentation, should upload with the project and extend the nginx configuration. As far as I can tell, it does pick it up, since any typo will result in an error after eb deploy. I can also see on the server it has been added to /etc/nginx/conf.d/proxy.conf.
The Problem
Even though the extending proxy.conf is being deployed and the configuration in it seems to be picked up, the application won't pick up the rewrite and leave the application URLs running with the index.php instead of the rewrite.
https://example.com/index.php/endpoint → works
https://example.com/endpoint → results in a server generated 404
Nginx logs show 2021/02/12 14:23:24 [error] 7523#0: *35 open() "/var/www/html/public/api" failed (2: No such file or directory) which tells me it has searched for a file and never tried running it through index.php.
The Questions
What am I missing in my configuration?
Or is it something about EBS that I overlooked or misunderstood?
Is the index.php angry since I'm trying to hide its face from public view?
Solution moved from the question to an answer:
I gave it a weekend to see if anyone would know and went back to work.
First thing, I did is see if Beanstalk was picking up any
configuration, so I put an invalid variable in and see if that would
break the server. It didn't...
Second, I checked if my Beanstalk instance was actually using Nginx
(default) or got switch to Apache (httpd) for some reason (it includes
both). Via its GUI config I could easily tell it's Nginx.
Third, I viewed the nginx.conf on the server and checked how other
.conf files were being included. Part of it is seen here;
http {
[...]
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
[...]
}
server {
listen 80 default_server;
access_log /var/log/nginx/access.log main;
[...]
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
}
}
Here lays the problem; I was including a file at the conf.d/*.conf
level with a second nginx server configuration block, which is
effectively overwritten with the standard server configuration block
by Beanstalks own config.
So there's two solutions here;
override the entire nginx.conf by including a new .platform/nginx/nginx.conf in your project, where you extend the
server block with your own config
or, in my opinion more gracefully, add .platform/nginx/elasticbeanstalk/proxy.conf to your project,
extending the server block specifically (but remove any server
blocks from your own config)
Solution 2 will gard that AWS can always update its default nginx.conf
without you having to watch out for it (unless they change the
location of the elasticbeanstalk configs).
I did try putting my configuration in
.platform/nginx/elasticbeanstalk/proxy.conf before, but that would
break the server, since I was including a server block, causing it
to double nest.
Lesson here;
add .platform/nginx/nginx.conf to override your entire Beanstalk Nginx configuration
add .platform/nginx/conf.d/your_conf.conf for any extensions to the http block
add .platform/nginx/conf.d/elasticbeanstalk/your_conf.conf for any extensions to the server block (or nesting within)

Multiple Laravel Projects on a single domain with NGINX

At work we have a single staging server with a staging domain, something like https://staging.example.com. We recently decided to switch from Apache to NGINX on a new server and we're having issues with our Laravel routing.
All of our laravel apps sit in sub-directories on the staging server, like so.
https://staging.example.com/app1/public
https://staging.example.com/app2/public
I've tried configuring the NGINX conf file as specified in the Laravel docs but get a 404 when accessing any 2nd level route, i.e. https://staging.example.com/app1/public/a/b
Using something like the below config, I can access all the routes in an app.
location #laravel {
rewrite /app1/public/(.*)$ /app1/public/index.php?$1;
}
location / {
try_files $uri $uri/ #laravel;
}
However, we have many apps hosted on this server and we don't want to have to update an NGINX conf file every time we want to add an app to the server.
Is there a way of constructing a rewrite to apply to any sub-directory and keep Laravel's routing system working?
Note: I've also tried this rewrite rewrite (.*)/(.*)$ $1/index.php?$2 and that doesn't work for 2nd level routes.
Your first capture is probably too greedy, you should limit it by using:
rewrite ^(/[^/]+/[^/]+)/(.*)$ $1/index.php?$2 last;
See this useful resource on regular expressions.

The photos don't appear after an update to vTiger 6.2

After an update or a fresh install of vtiger 6.2, it's possible that contact photos don't appear. It looks like a dead link.
Problem
vTiger 6.2 puts all your uploads (incl. user & product pictures) into /storage and denys access to this folder from the web through a htaccess-File (/storage/.htaccess):
deny from all
These files will only be accessible by the webserver/php directly, which is perfect from a security point of view and it should be kept that way (deleting this htaccess-file is a very bad thing, cause then everybody outside will be able to read your files given he has the right path)!!!
The correct way to deal with these files inside the Web-Application would be to never reference the files directly in HTML (<img src="path/to/file">, cause you would not see them due to the htaccess-File) but to always route their data through a gateway-PHP-Script which checks if the requesting user is authenticated (<img src="file.php?filename=path/to/file">). The PHP-Script can (as I said above) bypass the Apache/htaccess-Security cause it directly accesses the filesystem. This is done in the Document-Section where you can see that downloading a file leads to "http://domain/index.php?module=Documents&action=DownloadFile&record=10&fileid=11"
However, unfortunatly vTiger has places in its Web-Application where it still references files in /storage directly in HTML as with User Pictures and Product Pictures therefor they are not shown.
UPDATE: Bugfix
I found that the Apps Contacts, Users and Products have this problem.
I bugfixed them in 2 steps:
Add Actions for each App as Gateway-Scripts
Create the files (vTiger is installed on /opt/vtiger)
/opt/vtiger/modules/Users/actions/DownloadPicture.php
<?php
class Users_DownloadPicture_Action extends Vtiger_Action_Controller {
public function checkPermission(Vtiger_Request $request) {
$moduleName = $request->getModule();
if(!Users_Privileges_Model::isPermitted($moduleName, 'DetailView', $request->get('record'))) {
throw new AppException(vtranslate('LBL_PERMISSION_DENIED', $moduleName));
}
}
public function process(Vtiger_Request $request) {
$userRecordModel = Vtiger_Record_Model::getInstanceById($request->get('record'), $request->getModule());
$userPictureDetails = $userRecordModel->getImageDetails();
$pictureData = file_get_contents($userPictureDetails[0]['path'] . '_' . $userPictureDetails[0]['orgname']);
header("Content-type: image/jpeg");
header("Pragma: public");
header("Cache-Control: private");
echo $pictureData;
}
}
?>
/opt/vtiger/modules/Products/actions/DownloadPicture.php
The same but: class Products_Download...
/opt/vtiger/modules/Contacts/actions/DownloadPicture.php
The same but: class Contacts_Download...
Adapt the Templates to serve Image-Tags with the Gateway-Script
Go in the files, find the <img ... >-Tag and change its src-Attribute:
/opt/vtiger/layouts/vlayout/modules/Users/ListViewContents.tpl
index.php?module={$MODULE}&action=DownloadPicture&record={$LISTVIEW_ENTRY->get('id')}
/opt/vtiger/layouts/vlayout/modules/Users/PreferenceDetailViewHeader.tpl
index.php?module={$MODULE}&action=DownloadPicture&record={$RECORD->get('id')}
/opt/vtiger/layouts/vlayout/modules/Users/UserViewHeader.tpl
index.php?module={$MODULE}&action=DownloadPicture&record={$RECORD->get('id')}
/opt/vtiger/layouts/vlayout/modules/Vtiger/DetailViewBlockView.tpl
index.php?module={$MODULE}&action=DownloadPicture&record={$RECORD->get('id')}
/opt/vtiger/layouts/vlayout/modules/Vtiger/uitypes/Image.tpl
index.php?module={$MODULE}&action=DownloadPicture&record={$RECORD_ID}
/opt/vtiger/layouts/vlayout/modules/Contacts/DetailViewHeaderTitle.tpl
index.php?module={$MODULE}&action=DownloadPicture&record={$RECORD->get('id')}
Now it is for sure you can see your pictures everywhere, but without beeing logged in you cannot access the files!
Possible open problem: I do not know so much about rights management in vTiger to tell you that now only users with access rights on the records have access to the files. It is possible that now every user can access them. If somebody knows how to control this. Please comment!
Hope everything works out, as by me.
Servus
Lukas
To solve that, simply yourself connect to your server through an FTP client. Empty or remove the ".htaccess" file in the "/storage" folder.
That's it!
Or in the .htaccess file change from:
deny from all
to:
Options -Indexes
I rewrote my .htaccess file from "deny from all" to…
# If the URI is an image then we allow accesses
SetEnvIfNoCase Request_URI "\\.(gif|jpe?g|png|bmp)$" let_me_in
Order Deny,Allow
Deny from All
# Allow accesses only if an images was requested
Allow from env=let_me_in
Now my images show up.

Allowing AJAX requests to service behind nginx proxy based on request_method

I'm new to Nginx, so pardon me if I'm being obtuse. I have a service that is sitting behind an nginx proxy, and I am using auth_basic to prevent anyone from currently being able to hit it. I want to allow an Angular app to hit this service, but I want to control who is allowed to perform particular request methods (GET, POST, DEL, OPTIONS), and using auth_basic doesn't seem like the best bet, since I don't want to hardcode the login/password into the JS (duh). The only way I can figure out how to do this is to say:
if ($request_method = OPTIONS)
{
proxy_pass_header Access-Control-Allow-Origin *;
proxy_pass_header Access-Control-Allow_Methods GET, OPTIONS;
etc...
}
At this point, I'd allow GET and OPTIONS requests from anyone, but I want to restrict POST, DEL to only from certain locations (such as internally, or from a trusted IP). Currently, though, if I put proxy_pass_header into that block, it says that the directive is not allowed. I've seen other examples where people use add_header inside an if block like that, so I'm confused why that isn't working.
So first of all, is this the best way of doing things, and if not, does someone have another recommendation? If it is the best way of handling things, what am I doing wrong here?
Any help would be appreciated. I find the nginx documentation to be very confusing.
You could use deny/allow directives from ngx_http_access_module.
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
http://nginx.org/en/docs/http/ngx_http_access_module.html

nginx proxy_pass to Jboss+Spring/Websphere+Portal projects

I have an nginx up at the front serving as a proxy to two servers, one running Websphere Portal Server and one running Spring on a Jboss server.
I'm currently having problems with the proxying of certain requests, for instance, I have the following:
server{
listen:8080;
server_name:localhost;
location /jbossSpring/ {
proxy_pass http://177.21.1.15:9000/Spring_project/;
}
location /webspherePortal/ {
proxy_pass http://177.21.1.15:9400/Portal_project/;
}
}
Now, this does the proxy from localhost:8080/jbossSpring/ and localhost:8080/webpsherePortal/ correctly, however, the pages I get keep requesting files that are located on localhost:8080/Spring_project/ and localhost:8080/Portal_project/.
Is there anyway for me to handle these in nginx? or do I have to modify the Spring/Portal projects to get the right url? (path dependencies probably?)
You may achieve this result by using http rewrite module, documented at ngx_http_rewrite_module
To give an idea, I guess your rewrites shall look like below (I haven't validated this)
server {
...
rewrite ^/Spring_project/(.*) /jbossSpring/$1 last;
rewrite ^/Portal_project/(.*) /webspherePortal/$1 last;
...
}

Resources