Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working on NodeJS project - use nginx as reverse proxy / upstream Node app #240

Closed
mrpsiho opened this issue May 1, 2018 · 32 comments
Closed

Comments

@mrpsiho
Copy link

mrpsiho commented May 1, 2018

Hi! Hope you are doing well. I have a question about using devilbox while working on NodeJS project. In essence, I would like to ask how to access my Node app via custom domain like 'node-app.loc'?

I start my Node app inside a container via terminal and it is up and running on localhost:3000. But I am lost how to access it? Visiting http://node-app.loc gives me Error 403 Forbidden. I guess I could achieve what I need by modifying nginx.yml within '.devilbox' folder of my project folder, however, I don't know what exactly to put inside this config file. Please, help.

@cytopia cytopia self-assigned this May 1, 2018
@cytopia cytopia added the feature label May 1, 2018
@cytopia
Copy link
Owner

cytopia commented May 1, 2018

This needs to be automated ;-)
I still have https support on the agenda and will come to this issue afterwards.

For now, have a look at vhost-gen to generate yourself a reverse proxy config.

@jebog
Copy link

jebog commented Jul 17, 2018

Thanks i think this is the answer for my question i will and will make a feed back

@stkrzysiak
Copy link

I'm curious what the plan is to implement this, I notice that vhost_gen takes an r flag for this yet the nginx container never passes -r(from what I can tell), so it seems that the fix for this would be on the container level, perhaps a check for rproxy in create-vhost.sh? If I'm anywhere in the ballpark on how this might work then let me know and I'll make some time to work on it this weekend and maybe have a PR at some point.

For others trying to sort this out, here's a gist with how I got it to work with my node project on port 3000. The important pieces are the IP, port, and the php_fpm ...enable: false piece. Without that last piece vhost_gen fails.

@cytopia
Copy link
Owner

cytopia commented Aug 14, 2018

@stkrzysiak this is my current plan for setting it up:

  1. The webserver have a TCP API on some port that is accessable by the PHP container
  2. The API is able to create and delete vhosts (reverse) on call
  3. The PHP container will use watcher to monitor new/released listening ports
  4. The PHP container will then trigger the API of the webserver adding/removing vhosts

Workflow sounds pretty simple. Once I have the API server finished and integrated into all web server it should more or less be a self-writer ;-)

@science695
Copy link

Have you thought about having it watch for changes in a proxy config file instead of a complicated API setup?

i.e.:

PROXY_CONF_DIR=proxy_conf/

and in there, each host to proxy would have a config file:

nodesubdomain.yml

(or env or whatever format)

That would have the 4 or 5 config settings for what ip/port to forward to.

I am doing something similar to this by having a new folder for that project (in the projects folder), and then I put in a custom .devilbox/apache24.yml file which added the reverse proxy.

@ekam230
Copy link

ekam230 commented Nov 7, 2018

Please, write step-by-step manual for use nodejs server on port in devilbox stack.

my attempts weren't crowned with success

@science695
Copy link

science695 commented Nov 7, 2018

  1. Make a folder for this project (or move it) in the folder where devilbox is looking for projects.
  2. Make a .devilbox/ folder inside it.
  3. Copy in the appropriate virtualhost template for your setup (nginx, apache22, apache24, ...):
    https://devilbox.readthedocs.io/en/latest/vhost-gen/customize-specific-virtual-host.html?highlight=virtual%20host#templates-explained
  4. Edit that file and change all the proxy lines to proxy to your host:port

SetHandler proxy:fcgi://PHP_ADDR:PHP_PORT

would change to:

SetHandler proxy:http://172.168.238.1:PORT

  1. If just changing that one line, you may need to put this ip and port in the several proxy lines.

I'm sorry there are no step-by-step instructions. What you are asking has no easy configurable option, and is only possible with this type of advanced configuration.

@cytopia
Copy link
Owner

cytopia commented Dec 27, 2018

Status update

There are two components to making this work:

  1. Auto-starting node application
  2. Reverse proxy for node application

The auto-start feature is currently PR-ed and will be merged soon. It will allow you to automatically have any node/npm (or others) spin up during Devilbox startup: #446

The second part will only require some documentation to copy/paste working vhost-gen configs into the project directory. So I will have to create three config templates:

  1. Apache 2.2
  2. Apache 2.4
  3. Nginx

@cytopia
Copy link
Owner

cytopia commented Dec 28, 2018

@mrpsiho @jebog @stkrzysiak @science695 @ekam230

Status

I have successfully managed to get Node up and running behind Nginx reverse proxy:

Goal:

When the Devilbox starts up, the Node project should automatically start and be available via the vhosts.php intranet page by:

Project info

  • Project directory node
  • Node project port: 8000
  • Node projcet hostname: php (will always be php)
  • Path (inside container): /shared/httpd/node/node (where the *.js file is)

Reverse vhost for Nginx

How to customize individual vhosts: https://devilbox.readthedocs.io/en/latest/vhost-gen/customize-specific-virtual-host.html

/shared/httpd/node/.devilbox/nginx.yml (path inside the container):

---

vhost: |
  server {
      listen       __PORT____DEFAULT_VHOST__;
      server_name  __VHOST_NAME__;

      access_log   "__ACCESS_LOG__" combined;
      error_log    "__ERROR_LOG__" warn;

      location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        # CHANGE: The port will be the only thing to adjust for projects
        proxy_pass http://php:8000;
      }
  __REDIRECT__
  __SSL__
  __ALIASES__
  }

# ------------------------------------------------------------------------------------------
# Do not change anything below this line
# ------------------------------------------------------------------------------------------
vhost_type:
  docroot: ""
  rproxy: ""

features:
  ssl: |
    ssl_certificate           __SSL_PATH_CRT__;
    ssl_certificate_key       __SSL_PATH_KEY__;
    ssl_protocols             __SSL_PROTOCOLS__;
    ssl_prefer_server_ciphers __SSL_HONOR_CIPHER_ORDER__;
    ssl_ciphers               __SSL_CIPHERS__;

  redirect: |
    return 301 https://__VHOST_NAME__:__SSL_PORT__$request_uri;

  php_fpm: ""

  alias: |
    location ~ __ALIAS__ {
        root  __PATH__;
    __XDOMAIN_REQ__
    }

  deny: |
    location ~ __REGEX__ {
        deny all;
    }

  server_status: |
    location ~ __REGEX__ {
        stub_status on;
        access_log off;
    }

  xdomain_request: |
    if ( $http_origin ~* (__REGEX__) ) {
        add_header "Access-Control-Allow-Origin" "$http_origin";
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Max-Age' 0;
        return 200;
    }

Autostart script:

https://devilbox.readthedocs.io/en/latest/advanced/custom-startup-commands.html

cfg/php-startup-7.2/node.sh (path in the Devilbox git directory)

# https://github.com/Unitech/pm2
npm install pm2 -g
su -c 'cd /shared/httpd/node/node; pm2 start index.js' -l devilbox

Todo:

  • I will include pm2 by default as it is a very good process manager for node projects and comes in very handy for autostart
  • I will add a more detailed documentation explaining each step

@cytopia
Copy link
Owner

cytopia commented Dec 28, 2018

pm2 will be bundled with the next round of PHP images (#449). I will add also CI tests to ensure it will work with Apache 2.2, Apache 2.4 and Nginx.

@cytopia
Copy link
Owner

cytopia commented Dec 29, 2018

I've now added vhost-gen templates for reverse proxies that only need copy/paste into the project directory making it easier to set them up.

Additionally reverse proxy projects are also added to integration tests via Travis CI to ensure they work on all Webservers and with all PHP images.

@cytopia
Copy link
Owner

cytopia commented Dec 31, 2018

Update

Reverse proxing applications feature is now finished in above mentioned PR. Currently not only NodeJS applications can easily be proxied, but also any other custom container can be attached and proxied to the webserver with valid HTTPS and even have it be displayed in the vhost section of the intranet:

Examples:

  • Custom Python Django projects in its own container
  • NodeJS projects in PHP container or in custom container
  • Sphinx documentation
  • Custom Go project in its own container

Looks like this feature will now allow to extend the Devilbox with whatever programming language you wanna go with.

I will post the documentation in the coming days

@cytopia
Copy link
Owner

cytopia commented Dec 31, 2018

Done

Its now working like a charm:

General

NodeJS Specific

@cytopia cytopia closed this as completed Dec 31, 2018
@felixmosh
Copy link
Contributor

@cytopia first of all THANK YOU for your awesome job, this env is amazing! 👏🏽
I'm trying to implement the node + nginx reverse proxy tutorial (https://devilbox.readthedocs.io/en/latest/examples/setup-reverse-proxy-nodejs.html) and looks like the nginx is not reversing to node.

I've checked with PM2 that the node process is alive, I've curled it with the port (in my case it is 3000) and it works, but when I try to access it from the host, I get the DevilBox interface.

What can be the issue?

@cytopia
Copy link
Owner

cytopia commented Feb 3, 2019

@felixmosh was this issue resolved by your PR: https://github.com/cytopia/devilbox/pull/492/files?

@felixmosh
Copy link
Contributor

Of course no :), I've changed in nginx-reverse.yml to port 3000 as what I use.

@cytopia
Copy link
Owner

cytopia commented Feb 3, 2019

If not, can you paste the resulting vhost config of your project. You can find it on the vhost page, when you click on the wheel:

screenshot 2019-02-03 19-36-45 selection

@felixmosh
Copy link
Contributor

felixmosh commented Feb 3, 2019

Oh, you are right! I've mapped the wrong url (I have a different config for apache).

Now, I get 403 Forbidden from nginx.
This is my config

server {
    listen       443 ssl http2;
    server_name  test-mysql.loc;

    access_log   "/var/log/nginx-stable/test-mysql_ssl-access.log" combined;
    error_log    "/var/log/nginx-stable/test-mysql_ssl-error.log" warn;


    ssl_certificate           /etc/httpd/cert/mass/test-mysql.loc.crt;
    ssl_certificate_key       /etc/httpd/cert/mass/test-mysql.loc.key;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               HIGH:!aNULL:!MD5;

    # Define the vhost to serve files
    root         "/shared/httpd/test-mysql/";
    index        index.php index.html index.htm;


    # PHP-FPM Definition
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php?$ {
        try_files $uri = 404;
        include fastcgi_params;
    
        # https://stackoverflow.com/questions/1733306/nginx-errors-readv-and-recv-failed/51457613#51457613
        fastcgi_keep_conn off;
    
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
    
        fastcgi_pass php:9000;
        fastcgi_read_timeout 180;
    
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

    # Alias Definition
    location ~ /devilbox-api/ {
        root  /var/www/default/api;
        # Allow cross domain request from these hosts
        if ( $http_origin ~* (http(s)?://(.*)$) ) {
            add_header "Access-Control-Allow-Origin" "$http_origin";
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
            add_header 'Access-Control-Max-Age' 0;
            return 200;
        }
    }

    # Deny Definition
    location ~ /\.git {
        deny all;
    }
    
    # Deny Definition
    location ~ /\.ht.* {
        deny all;
    }


    # Custom directives

}
server {
    listen       80;
    server_name  test-mysql.loc;

    access_log   "/var/log/nginx-stable/test-mysql-access.log" combined;
    error_log    "/var/log/nginx-stable/test-mysql-error.log" warn;



    # Define the vhost to serve files
    root         "/shared/httpd/test-mysql/";
    index        index.php index.html index.htm;


    # PHP-FPM Definition
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php?$ {
        try_files $uri = 404;
        include fastcgi_params;
    
        # https://stackoverflow.com/questions/1733306/nginx-errors-readv-and-recv-failed/51457613#51457613
        fastcgi_keep_conn off;
    
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
    
        fastcgi_pass php:9000;
        fastcgi_read_timeout 180;
    
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

    # Alias Definition
    location ~ /devilbox-api/ {
        root  /var/www/default/api;
        # Allow cross domain request from these hosts
        if ( $http_origin ~* (http(s)?://(.*)$) ) {
            add_header "Access-Control-Allow-Origin" "$http_origin";
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
            add_header 'Access-Control-Max-Age' 0;
            return 200;
        }
    }

    # Deny Definition
    location ~ /\.git {
        deny all;
    }
    
    # Deny Definition
    location ~ /\.ht.* {
        deny all;
    }


    # Custom directives

}

@cytopia
Copy link
Owner

cytopia commented Feb 3, 2019

This is not a reverse proxy config, it's the normal forward config. How does your nginx.yml (project specific vhost-gen config) look like? Take the one you can find on the intranet vhost-page, when you click on the funnel (next to the wheel) - see my screenshot above.

@felixmosh
Copy link
Contributor

I don't have a funnel, 😒
image

@cytopia
Copy link
Owner

cytopia commented Feb 3, 2019

This is because you simply missed step 5 (the reverse proxy setup):

https://devilbox.readthedocs.io/en/latest/examples/setup-reverse-proxy-nodejs.html#add-reverse-proxy-vhost-gen-config-files

@felixmosh
Copy link
Contributor

I did it, the only thing I didn't done is copy all the *-reverse.yml files (cause I'm using only nginx)

@cytopia
Copy link
Owner

cytopia commented Feb 4, 2019

You will actually need to copy nginx.yml-example-rproxy (from cfg/vhost-gen) into your project: ./devilbox/nginx.yml

@felixmosh
Copy link
Contributor

That is what I've done, the file suppose to be at test-mysql/.devilbox/nginx.yml (with a dot before devilbox, HTTPD_TEMPLATE_DIR=.devilbox)

@cytopia
Copy link
Owner

cytopia commented Feb 4, 2019

Yes, did you then restart the Devilbox?

@felixmosh
Copy link
Contributor

Yeap, I've even tried to docker-compose rm -f

@cytopia
Copy link
Owner

cytopia commented Feb 4, 2019

Are you on the latest master branch?

@felixmosh
Copy link
Contributor

Yes, I'm on latest master, I'm invoking docker-compose up httpd php mysql maybe that is the difference?

@felixmosh
Copy link
Contributor

WOW! 🎊
I've added bind to the execution command and that worked!

docker-compose up httpd php mysql bind solved!

@cytopia
Copy link
Owner

cytopia commented Feb 4, 2019

Hmm strange. Bind should actually autostart, no matter what. That's how it's been defined in docker-compose.yml.

@cytopia
Copy link
Owner

cytopia commented Dec 23, 2022

FYI: @felixmosh @ekam230 @stkrzysiak @mrpsiho @jebog

This has now been automated: #942

@agathasweb
Copy link

I noticed something intriguing, maybe it's my lack of experience. But when I use the reverse proxy for PHP to listen to my vue on port 8080 and I need to use PHP in the same environment, PHP no longer works, only vuejs. Is that right or did I configure something wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants