Welcome Guest, Not a member yet? Register   Sign In
NGINX: Multiple CI Apps on a Single Domain Not Working
#1

(This post was last modified: 07-04-2024, 11:46 PM by sillyquota. Edit Reason: Changed topic to something more specific )

How can I make https://api.domain.com/appname show the contents of /home/www/api.domain.com/appname/public
+ and retain the ability to show /home/www/api.domain.com/index.php at https://api.domain.com/
+ and retain the ability to host other unrelated php-based api backends at https://api.domain.com/anotherAPIthing or any other arbitrary URI structure on api.domain.com?


I have CI4.5.3 installed at /home/www/api.domain.com/appname. My domain (api.domain.com) root is /home/www/api.domain.com.

I do not want to change the main(outer-most) docroot of https://api.domain.com/ because I would like to have multiple api backends hosted there (for example api.domain.com/appname, api.domain.com/anotherapp, etc..). If I change the main docroot then I can only use https://api.domain.com for my 'appname' app.

I've tried so many different configurations I can't even remember all of them... Here is my current configuration (which does not work for me)
Code:
server {
    listen serverip:443 ssl;
    http2 on;
    server_name api.domain.com www.api.domain.com;
    root /home/www/api.domain.com/;
    index index.php index.html index.htm;

    ssl_certificate /etc/pki/tls/certs/api.domain.com.bundle;
    ssl_certificate_key  /etc/pki/tls/private/api.domain.com.key;
    include /etc/nginx/ssl.conf;
    include /etc/nginx/basicheaders.conf;
    include /etc/nginx/nocache.conf;

  location /appname {
      root /home/www/api.domain.com/appname/public/;
#      alias /home/www/api.domain.com/appname/public/;

#      try_files $uri $uri/ /index.php$is_args$args;

      location ~ [^/]\.php(/|$) {
          include /etc/nginx/fastcgi.conf;
          if (!-f $document_root$fastcgi_script_name) {
              return  404;
          }
          fastcgi_pass    unix:/opt/alt/php-fpm83/usr/var/sockets/www.sock;
          fastcgi_index  index.php;
      }
  }


  location / {
    location ~ [^/]\.php(/|$) {
      include /etc/nginx/fastcgi.conf;
      if (!-f $document_root$fastcgi_script_name) {
        return  404;
      }
      fastcgi_pass    unix:/opt/alt/php-fpm83/usr/var/sockets/www.sock;
      fastcgi_index  index.php;
      }
  }
...
}


With the above configuration I get the following error when trying to access my CI app via https://api.domain.com/appname:
Code:
2024/07/05 00:29:39 [error] 72934#72934: *14 "/home/www/api.domain.com/appname/public/appname/index.php" is not found (2: No such file or directory), client: REDACTED, server: api.domain.com, request: "GET /appname/ HTTP/2.0", host: "api.domain.com"
However https://api.domain.com does load /home/www/api.domain.com/index.php as desired/expected.

I'm not very good at nginx configurating but I've tried using rewrites as well and they always end up with infinite redirects or attempting to access "/home/www/api.domain.com/appname/public/appname/public/index.php" or "/home/www/api.domain.com/appname/public/appname/appname/appname/appname/appname/" etc
Reply
#2

(This post was last modified: 07-10-2024, 02:18 PM by bogus.)

Basically you need to use two different <VirtualHost> entries in your virtual host configuration file.
To my knowing (and if it is okay to do so I don't do it) it is not possible to have two ServerName entries in ONE <VirtualHost> directive.
Further I'd first get rid of all the 443 related stuff for testing - its just confusing and you can add that, configure and test it later when the rest is up and running.
The two <VirtualHosts> entries each need to have a <DocumentRoot> of course and an own ServerName part which is used to identify the host.
I'd also put much of the stuff you posted in the main configuration file.
It makes things easier to configure, files slicker and many configuration settings need to be defined once only anyway.

Hope that helps.
The only absolute knowledge attainable by man is that life is meaningless. (Tolstoi)
Reply
#3

(This post was last modified: 07-11-2024, 01:53 AM by bogus.)

This is a snippet of my apache2.conf on my remote server with some personal remarks.

Code:
# Computername and port so the computer can identify itself. The system Apache
# runs on has no assigned ip addresses - they are provided. If working with
# several DNS (provider) entries masked on one ip address the <ServerName>
# directive must be taken care of in the <VirtualHost> directives for each of
# the DNS entries or it won't work. You can't have it defined here and in
# the <VirtualHost> directives.

#ServerName example.com:80

ServerAdmin info@your_server.com
ServerSignature Email

... snip

# Include the virtual host configurations:
IncludeOptional sites-enabled/*.conf



This is the vhost to the apache2.conf above:

Code:
# --- Vhosts configuration -----------------------------------------------------#
#
# --- mod_autoindex.so standard host --- #
#
# If no matching name-based virtual host is found, then the first listed one
# is used. (including subdomain resolution)


# --- Default auto indexed --- #
<VirtualHost *:80>

    DocumentRoot /srv/http/somewhere/
   
    <Directory "/srv/http/somewhere">

blablabla...

# In case you want to have a directory with authenticatio:
# Authentication is setup on directory basis
<Directory "/srv/http/somewhere/AUTHENTICATED">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

# Doesn't hide the folder but its content
<Directory "/srv/http/somewhere/css">
    Options -Indexes -FollowSymlinks
</Directory>
</VirtualHost>



# --- Main site --- #
<VirtualHost *:80>

    Servername somewhere.com:80

    DocumentRoot /srv/http/somewhere_else/
 
    <Directory "/srv/http/somewhere_else">
        AllowOverride All
        Options +Indexes +FollowSymLinks
        Require all granted
    </Directory>
</VirtualHost>




# --- Subdomain --- #
<VirtualHost *:80>

    ServerName map.somewhere.com:80
   
    DocumentRoot /srv/http/you-name-it/
   
        <Directory "/srv/http/map">
        AllowOverride All
        Options +Indexes +FollowSymLinks
        Require all granted
    </Directory>
</VirtualHost>



# --- Error pages --- #
# Using a 'hack' so we don't need to set up a directory 'error' under each
# site's document root in a vhost environment by creating a common global one.
Alias /error /srv/http/error
<Directory /srv/http/error/>
    AllowOverride None
    Options None
    Require all granted
</Directory>
The only absolute knowledge attainable by man is that life is meaningless. (Tolstoi)
Reply
#4

(This post was last modified: 07-14-2024, 04:02 PM by sillyquota.)

Hey thanks for the replies! Apologies for the late response, I've been extremely busy of late.

I did however set aside some time to really think this through and I was able to find the solution to my issue. Unfortunately I don't have the complete config file as my server is having issues with the hard drive but this is the resolution I implemented:
Code:
server {
    listen serverip:443 ssl;
    http2 on;
    server_name api.domain.com www.api.domain.com;
    root /home/domaincom/api.domain.com/;
    index index.php index.html index.htm;

    ssl_certificate /etc/pki/tls/certs/api.domain.com.bundle;
    ssl_certificate_key  /etc/pki/tls/private/api.domain.com.key;
    include /etc/nginx/ssl.conf;
    include /etc/nginx/basicheaders.conf;
    include /etc/nginx/nocache.conf;

    # prevent access to sensitive folders
    # alternatively you can replace 'return 404;' with 'deny all;'
    location ~* ^/(app|public|tests|vendor|writable)(/|$) { return 404; }
    location ~* ^/v1/(app|public|tests|vendor|writable)(/|$) { return 404; }
    location ~* ^/v2/beta/(app|public|tests|vendor|writable)(/|$) { return 404; }
    # EDIT: you could probably do something like `location ~* /(app|public|tests|vendor|writable)(/|$) { return 404; }`, get rid of the others, and not need to add additional rules as more apps are added

    # serve app1 via https://api.domain.com/v1
    # app1 approot located at /home/domaincom/api.domain.com/v1/
    #  eg: app1 files would be located throughout
    #  /home/domaincom/api.domain.com/v1/{app,public,writable,tests, ... }
    location ~ /v1 {
        alias /home/domaincom/api.domain.com/v1/public/;

        location ~ [^/]\.php(/|$) {
            rewrite ^/v1/(.*)$ /$1 break;
            alias /home/domaincom/api.domain.com/v1/public/;
            include /etc/nginx/fastcgi.conf;
            if (!-f $document_root$fastcgi_script_name) { return  404; }
            fastcgi_pass    unix:/usr/var/php-fpm/domaincom.sock;
            fastcgi_index  index.php;
        }
    }

    # serve app2 via https://api.domain.com/v2/beta/
    # app2 approot located at /home/domaincom/api.domain.com/v2/
    location ~ /v2/beta/ {
        alias /home/domaincom/api.domain.com/v2/public/;

        location ~ [^/]\.php(/|$) {
            rewrite ^/v2/beta/(.*)$ /$1 break;
            alias /home/domaincom/api.domain.com/v2/public/;
            include /etc/nginx/fastcgi.conf;
            if (!-f $document_root$fastcgi_script_name) { return  404; }
            fastcgi_pass    unix:/usr/var/php-fpm/domaincom.sock;
            fastcgi_index  index.php;
        }
    }

    # serve PHP files (any, not just CodeIgniter) located anywhere within
    # docroot (root /home/domaincom/api.domain.com/) unless otherwise blocked
    location ~ [^/]\.php(/|$) {
        include /etc/nginx/fastcgi.conf;
        if (!-f $document_root$fastcgi_script_name) { return  404; }
        fastcgi_pass    unix:/usr/var/php-fpm/domaincom.sock;
        fastcgi_index  index.php;
    }
}
This allows you to host multiple CI apps on https://api.domain.com under various directories while also being able to serve regular (non-CI) PHP content anywhere else on api.domain.com (as long as the location isn't disallowed)

NOTE: Some of this was reconstructed from memory because my server is offline for repair so YMMV, but I'm pretty sure this is how I got it working. I imagine this might be a bit of an edge-case since this places the approot within the webserver docroot (against most recommendations) and requires explicit location-blocking of sensitive directories. This was as much a learning exercise as it was a necessity for my situation Smile
Reply
#5

(07-10-2024, 02:10 PM)bogus Wrote: Basically you need to use two different <VirtualHost> entries in your virtual host configuration file.
To my knowing (and if it is okay to do so I don't do it) it is not possible to have two ServerName entries in ONE <VirtualHost> directive.
Further I'd first get rid of all the 443 related stuff for testing - its just confusing and you can add that, configure and test it later when the rest is up and running.
The two <VirtualHosts> entries each need to have a <DocumentRoot> of course and an own ServerName part which is used to identify the host.
I'd also put much of the stuff you posted in the main configuration file.
It makes things easier to configure, files slicker and many configuration settings need to be defined once only anyway.

Hope that helps.

I had this problem too, it drove me crazy. Thanks for this helpful information, I solved the problem that was bothering me for a long time.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB