plegall / Piwigo-community

11 stars 23 forks source link

NGINX reverse proxy - file upload not possible #47

Open GoSinus opened 4 years ago

GoSinus commented 4 years ago

Hi all :) i´m very happy with piwigo and the plugin but if I use piwigo behind the reverse proxy then it is not possible to upload files. Access locally via LAN and local IP (192.168.1.xxx) works fine. Does anybody have a idea how can I solve this issue?

Error: 10gvja4.js:135 Mixed Content: The page at 'https://xyz.selfhost.eu/piwigo/index.php?/add_photos&category_id=1' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://xyz.selfhost.eu/ws.php?method=pwg.images.upload&format=json'. This request has been blocked; the content must be served over HTTPS.

I think the request via HTTP are wrong but i don´t know, how can I change this.

Many thanks in advance

wburgers commented 4 years ago

I changed my proxy configuration to include

                sub_filter      http:// https://;

That seems to fix this issue.

Extra explanation: The page you see on screen includes a form with a form action. Nginx proxy is only configured to scan the headers of a response from te piwigo server and modify them, but the form action url is sent in the response body. The sub_filter directive tells nginx to scan the response body from the piwigo server and replace http:// with https://. Now the form action will no longer be set to http:// and will work fine over https.

plainlytbrown commented 4 years ago

@wburgers

Thanks for the explanation. It makes a lot of sense. I'm kind of new at this whole reverse proxy situation. Where does the sub_filter need to be added in the example.com.conf file? Here is my current setup.

server {

listen443;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

server_name  example.com;
location / {
proxy_pass http://IP:Port;
}
location /service/streams/webrtc {

proxy_read_timeout 60s;
proxy_pass http://IP:Port;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}

I can access Piwigo, with the setup but I am not able to upload photos and I'm not sure where the sub_filter would even be placed. Thanks so much in advance for the help.

wburgers commented 4 years ago

@plainlytbrown Here is the documentation for the sub_filter directive. http://nginx.org/en/docs/http/ngx_http_sub_module.html

So it should be placed on the same level as a proxy_pass directive.

Here is my setup for piwigo (changed the host to "example.com"):

server{
        listen          80; #redirect traffic from port 80 to https
        server_name     example.com www.example.com;
        return 301      https://$server_name$request_uri;
}

server {
        listen                          443 ssl http2;
        access_log                      /var/log/nginx/example.access.log;
        error_log                       /var/log/nginx/example.error.log;
        server_name                     example.com www.example.com;
        add_header                      Strict-Transport-Security max-age=63072000;
        ssl_protocols                   TLSv1.2 TLSv1.3;
        ssl_certificate                 /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key             /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_prefer_server_ciphers       On;
        ssl_dhparam                     /etc/ssl/dhparams.pem;
        ssl_ciphers                     'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

        ssl_session_cache   shared:SSL_example:10m;
        ssl_session_timeout 120m;

        location /.well-known { #used for letsencrypt
                alias   /var/example.com/.well-known;
        }

        location / {
                proxy_pass              http://backend_IP:PORT;
                proxy_set_header        Host $host;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_redirect          http:// https://;
                proxy_buffering         on;
                proxy_cache             static_cache;
                proxy_cache_valid       200  1d;
                proxy_cache_use_stale   error timeout invalid_header updating http_500 http_502 http_503 http_504;
                proxy_connect_timeout   600;
                proxy_send_timeout      600;
                proxy_read_timeout      600;
                send_timeout            600;
                sub_filter              http:// https://;
        }
}

Hope this helps 👍

plainlytbrown commented 4 years ago

@wburgers

This Helped out tremendously! I can now upload photos to piwigo!

I'm using piwigo in a docker container located on a synology nas. Synology has its own reverse proxy, but it has very limited options, because it is done through a graphical interface, and after reading your comment that I would have to add the sub_filter, I realized my Synology nas wouldn't work. I have a Raspberry Pi that wasn't doing anything so I started googling how to use it as a nginx reverse proxy, which after reading may be my best friend for securing my applications open to the internet.

So long story short your post lead me down a rabbit hole for the last week or so, and has only helped me to feel like soon my applications will be even more secure, and is helping me become more comfortable in a terminal.

UIC commented 3 years ago

Is there any corresponding solution (sub_filter) for traefik ver 2?

DocEverdream commented 3 years ago

Is there any corresponding solution (sub_filter) for traefik ver 2?

Same issue here. Could anyone help us?

wburgers commented 3 years ago

I've never used Traefik. I suggest creating a new issue here at github, or ask a question on stackoverflow about Traefik. This may be a good starting point: https://stackoverflow.com/questions/50235740/rewriting-content-urls-with-traefik

Gratobuchr commented 3 years ago

Hi guys, any idea to do the same with letsencrypt on an unRaid server. My configuration file is as follows:

server { listen 443 ssl; listen [::]:443 ssl;

server_name piwigo.*;

include /config/nginx/ssl.conf;

client_max_body_size 0;

# enable for ldap auth, fill in ldap details in ldap.conf
#include /config/nginx/ldap.conf;

# enable for Authelia
#include /config/nginx/authelia-server.conf;

location / {
    # enable the next two lines for http auth
    #auth_basic "Restricted";
    #auth_basic_user_file /config/nginx/.htpasswd;

    # enable the next two lines for ldap auth
    #auth_request /auth;
    #error_page 401 =200 /ldaplogin;

    # enable for Authelia
    #include /config/nginx/authelia-location.conf;

    include /config/nginx/proxy.conf;
    resolver 127.0.0.11 valid=30s;
    set $upstream_app piwigo;
    set $upstream_port 80;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}

}

ckayfish commented 3 years ago

I added these to my location. Without "Accept-Encoding" it wasn't finding the string to replace, possibly it was gzipped.Without turning "sub_filter_once" off, it would only replace the first instance of the string. I consider this a hack solution, but it works.

  proxy_set_header Accept-Encoding "";
  sub_filter_once  off;
  sub_filter       'http://'    'https://';
filipiff commented 2 years ago

Is there any corresponding solution (sub_filter) for traefik ver 2?

Had the same problem with Traefik v2 using linuxserver/piwigo image and solved by adding the following two lines in config.inc.php using the plugin LocalFiles editor:

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) $_SERVER['HTTPS']='on';

see also: https://github.com/Piwigo/Piwigo/pull/483#issue-70988750

christian-nils commented 2 years ago

It might not be the place, but I will leave this for people that are looking for the equivalent with Apache2:

RequestHeader unset Accept-Encoding

<Location />
    ProxyPass http://localhost:80/
    ProxyPassReverse http://localhost:80/
    AddOutputFilterByType SUBSTITUTE text/html
    Substitute "s|http://|https://|i"
</Location>

The first line was necessary for me.