Džuris
Džuris

Reputation: 2234

Nginx separate apps in subdirectories

I am trying to move an app from apache server to nginx. The problem is that there are multiple apps in subdirectories and I can't find a proper way to configure the server.

What I need:

Each of the apps need the same config, so I extracted that in a snippet:

# snippets/app.conf

index index.php index.html index.htm index.nginx-debian.html;

location /system {
    return 403;
}

# [a couple of other 403s excluded]

# Pass non-file URI to index.php
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

# Use PHP
location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}

# Hide .htaccess
location ~ /\.ht {
    deny all;
}

And in the main server file:

# [non-www and http redirects]

server {
    # [listen directives]

    server_name www.example.com;

    root /srv/app;

    include snippets/app.conf;

    location /sub1 {
        root /srv/app/sub1;
        include snippets/app.conf;
    }

    # [other sub-apps included in the same way]

    # [ssl stuff]
}

However, this gives me an error:

nginx: [emerg] location "/system" is outside location "/sub1" in /etc/nginx/snippets/app.conf:5

It's obvious from the error that /system is interpreted as being "absolute" www.example.com/system instead of the nested www.example.com/sub1/system. Can I somehow specify that I want the nested locations to be considered relative? Or I just have to repeat the whole near-identical config for every sub-app changing the prefixes?

Upvotes: 0

Views: 1376

Answers (1)

Džuris
Džuris

Reputation: 2234

It turns out that most of the repeating is not necessary in nginx.

The directives to use fastcgi for .php and hide /.ht files were already regexes so they affect everything. It's enough to specify index once and the default there stuff was redundant if I only want to use index.php.

As all the apps are nested on the filesystem in the same way as on web, specifying root was not necessary either.

What surprised me was that location ^~ /(system|data)/ { ... } matches not only www.example.com/system/, but also www.example.com/sub1/system/. I thought that ^~ should match only if the location start matches the regex...

# [non-www and http redirects]

server {
    # [listen directives]

    server_name www.example.com;

    root /srv/app;

    index index.php;

    location ^~ /(system|data)/ {
        return 403;
    }

    # Use PHP
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }

    # Pass non-file URI to index.php for all locations
    location /sub1/ {
        try_files $uri $uri/ /sub1/index.php?$query_string;
    }

    location /sub2/ {
        try_files $uri $uri/ /sub2/index.php?$query_string;
    }

    # [other sub-apps included in the same way]

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ /\.ht {
        deny all;
    }

    # [ssl stuff]
}

I also tried to replace the separate locations with

location ^~ /(sub1|sub2)/ {
    try_files $uri $uri/ /$1/index.php?$query_string;
}`

but didn't succeed with that - this location somehow didn't ever match and everything got passed to the /index.php in base instead.

Upvotes: 1

Related Questions