search

Home  >  Q&A  >  body text

Nette behind reverse proxy alias on nginx

<p>I have a Nette application running on an Apache2/Debian 11 server and it works fine. However, we need to use an alias to hide it behind the nginx proxy. </p> <p>Suppose we have a perfect Apache2 environment running on http://127.0.0.1:89/, and we want to access it via nginx set up as a reverse proxy at https://example.com /applications/</p> <p>nginx settings are as follows:</p> <pre class="brush:php;toolbar:false;">location /app/ { proxy_pass http://127.0.0.1:89; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto "https"; proxy_set_header X-Forwarded-Port "443"; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }</pre> <p>While the Apache2 configuration remains unchanged before the proxy attempts: </p> <pre class="brush:php;toolbar:false;"><VirtualHost *:89> ServerAdmin webmaster@localhost DocumentRoot /var/www/app/www/ <Directory /var/www/app/www/> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> </VirtualHost></pre> <p>The problem is that the Nette application still thinks it is running on a path without the "/app" URI part, so all links generated through redirects and link calls (including the $basePath template variable) are invalid. < /p> <p>I also appended the proxy information to the Nette configuration, and since the nginx instance is running on the same server, it looks like this: </p> <pre class="brush:php;toolbar:false;">http: proxy: 127.0.0.1</pre> <p>I tried setting the nginx configuration to forward the /admin path in the forwarded URI: </p> <pre class="brush:php;toolbar:false;">proxy_pass http://127.0.0.1:89/admin;</pre> <p>And also tried fiddling with the Nette router to filter out the "admin/" part (not looking for the AdminPresenter, which is obviously missing): </p> <pre class="brush:php;toolbar:false;">$router->addRoute('[admin/]<presenter>/<action>[/<id>]', 'Homepage: default');</pre> <p>The Nette application generates this error when trying to access the page: </p> <pre class="brush:php;toolbar:false;">TypeError: unpack() expects parameter 2 to be string, bool given in /var/www/app/vendor/nette/http/src/Http/Helpers .php:49 @ http://example.com/app/</pre> <p>Can someone point me in the right direction? </p>
P粉953231781P粉953231781458 days ago615

reply all(1)I'll reply

  • P粉035600555

    P粉0356005552023-09-04 17:09:20

    Ok, answering my own question in case someone else has the same problem. I feel like my solution is a bit of a hack, so feel free to post non-hack answers.

    First, I modified the nginx configuration:

    location /app/ {
        rewrite /app/(.*) /app/ break;
        proxy_pass http://127.0.0.1:89/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto "https";
        proxy_set_header X-Forwarded-Port "443";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    I then modified the Nette configuration to cover all proxies (probably not actually needed):

    http:
        proxy: 0.0.0.0/0

    I also added the "app" route in the router code (not as an optional prefix, but as a regular route):

    $router = new RouteList;
    $router->addRoute('app/<presenter>/<action>[/<id>]', 'Homepage:default');
    $router->addRoute('<presenter>/<action>[/<id>]', 'Homepage:default');
    return $router;

    Also modified the BasePresenter code startup method:

    $this->template->basePath = '/app'.$this->template->basePath;

    Finally, I modified the .htaccess file to rewrite the URLs of all static resources to paths that do not contain the "app" part:

    # Default Nette htaccess contents
    RewriteEngine On
    RewriteRule /\.|^\. - [F]
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]
    
    # Added this line under the default Nette htaccess file
    RewriteRule ^app(/.*|$)  [NC,L]

    The Apache virtual host remains unchanged.

    In this way, nginx passes the complete request URL (including "app") to Apache, and Apache uses the "app" prefix to call the Nette router. Routing now works fine because "application" is part of the URL and is even aware of it by Nette (since it's actually fully present in the request header). This causes $basePath and links/redirect to work.

    However, static resources are not served through the Nette router, so the app/ prefix will cause Apache to not find the file and report a 404. This is why adding a rewrite rule removes the app/ prefix from the URLs of static resources.

    It's hacky, but it works for both proxy and non-proxy access.

    reply
    0
  • Cancelreply