Devilbox: Nuxt/Vue CLI, reverse proxy and Content-Security-Policy woes.

Created on 17 Jul 2019  Â·  6Comments  Â·  Source: cytopia/devilbox

ISSUE TYPE

  • Bug Report

Checklist

OS / ENVIRONMENT

  1. Host operating system and version: Fedora 29 x86_64
  2. (Windows) Native Docker or Docker Toolbox:
  3. Docker version: 18.09.7.
  4. Docker Compose version: 1.24.0.
  5. (Linux) Is SELinux enabled?: Yep.
  6. What git commit hash are you on?: fdb6cffb3b32081a6f994cb01736f87cf15b1b1f

SUMMARY

I'm having various issues with running Nuxt (and also vue-cli projects) behind a reverse proxy. I was following your documentation on the matter. Yesterday it was mostly working but today it's just kaput.

One of the issues is relating to CSP headers (even though the nginx config file I copied for the reverse proxy, as per the docs, doesn't set any CSP headers).

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src http: https:". Either the 'unsafe-inline' keyword, a hash ('*snip*'), or a nonce ('nonce-...') is required to enable inline execution.

The only thing that happened since yesterday is a dnf update which I suppose means Docker versions and such may have changed. But everything else is the same?

The thing is there are no CSP-related headers in the browser devtools. So how can it be complaining about them?

Something, somewhere, presumably relating to Devilbox, is putting them there and it sure as hell isn't my nginx.yml (which is included below).

The other issue I honestly don't think it relates to you guys but maybe you can shed some light on it, it's some issue with Webpack Dev Server / Hot Module Reloading / secure Websockets. I have the exact same issue with a vue-cli app that is also sitting behind an nginx reverse proxy in my Devilbox.

Socket connection to 'wss://myProject.local/_loading/ws' failed: Error during WebSocket handshake: Unexpected response code: 500

STEPS TO REPRODUCE


I can and will happily throw together a repository for a minimal vue-cli project and a minimal nuxt project that causes the issue (for me) if you want - just let me know first.

Also if someone is willing to help me figure out how to get Nuxt and Vue CLI apps configured properly, I'll happily contribute to the section of the docs on Node projects for those specific cases so that others don't have to face these issues in future.


Here is my project's .devilbox/nginx.yml.

vhost: |
  server {
    listen      __PORT____HTTP_PROTO____DEFAULT_VHOST__;
    server_name __VHOST_NAME__;

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

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

    location / {
      proxy_set_header Host              $host;
      proxy_set_header X-Real-IP         $remote_addr;
      proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_pass https://php:8001;
    }

    __REDIRECT__
    __SSL__
    __ALIASES__
    __DENIES__
    __SERVER_STATUS__
    __CUSTOM__
  }

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;
    }


Here is the only really relevant section of my nuxt.config.js.

if (IS_DEV) {
  config.server = {
    // // Vue CLI doesn't care but Nuxt seems to require 0.0.0.0 here. ¯\_(ツ)_/¯
    host: "0.0.0.0",
    port: 8001,
    https: {
      ca: readFileSync("/ca/devilbox-ca.srl"),
      key: readFileSync("/ca/devilbox-ca.key"),
      cert: readFileSync("/ca/devilbox-ca.crt")
    }
  };
}

EXPECTED BEHAVIOUR

That node apps behind reverse proxies work when following the docs.

ACTUAL BEHAVIOUR

Various issues.

OTHER INFORMATION

Start command

$ docker-compose up...

File and user permissions (Linux & MacOS)

$ id

$ ls -la

$ ls -la data/www
bug

Most helpful comment

I don't use MongoDB nor do I know anything about it.

As for a Vue CLI project, I think this is all I did is this:

// my-cli-project/vue.config.js
const { readFileSync } = require("fs");

module.exports = {
  devServer: {
    public: "your-project.local:443", // replace .local if you use another TLD
    https: {
      key: readFileSync("/ca/devilbox-ca.key"),
      cert: readFileSync("/ca/devilbox-ca.crt"),
      ca: readFileSync("/ca/devilbox-ca.srl")
    },
    hot: true,
    disableHostCheck: true
  }
};
# my-cli-project/.devilbox/nginx.yml
vhost: |
  server {
    listen       __PORT____HTTP_PROTO____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;
      proxy_pass https://php:8000;
    }

    __REDIRECT__
    __SSL__
    __ALIASES__
    __DENIES__
    __SERVER_STATUS__
    __CUSTOM__
  }

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;
    }

Make sure to change proxy_pass https://php:8000; if you are not using port 8000.

// my-cli-project/.devilbox/my-cli-project.js
const { spawn } = require("child_process");

// You need to change this port if you aren't using port 8000.
spawn("npm", ["run", "serve", "--", "--port", "8000"], { stdio: "inherit" });

Again, change 8000 if that's not the right port.

Now modify your-devilbox-repository/autostart/run-node-js-projects.sh:

NODE_PROJECTS=(
        "/shared/httpd/my-cli-project/.devilbox/my-cli-project.js" # 8000
)

That's pretty much all I did.

@robots4life

All 6 comments

If you require any other information I'll gladly provide it upon request, thank you.

I think I figured out the cause of the CSP issue... let's call it PEBKAC... as for the WebSocket errors, I honestly don't know, I'm gonna guess it's a Webpack Dev Server problem so maybe I'll try to get help there as trying to get Nuxt support is like trying to get blood out of a stone and I doubt anyone here even uses stuff from the Vue world like Nuxt.

But just in case anyone knows why the WebSockets won't work... I'll leave this open for now.

If not then feel free to close it.

Just in case some poor guy in 18 months time stumbles upon this issue via Google:

We need to configure nginx to upgrade the connection to a WebSocket.

Add these after the proxy_pass line in nginx.yml:

      proxy_set_header Connection "Upgrade";
      proxy_set_header Upgrade    $http_upgrade;

Yes, it was that simple.

@sustained Could you make a repo and show the steps needed to get vue-cli working with Devilbox? That would be awesome.

Started to use Devilbox with Node and MongoDB and having issues creating a MongoDB database with Adminer. So yeah, any help or documentation or an example repo would be great.

edit
This is the issue I am having with trying to create a MongoDB database in case you managed that part through Devilbox.

I don't use MongoDB nor do I know anything about it.

As for a Vue CLI project, I think this is all I did is this:

// my-cli-project/vue.config.js
const { readFileSync } = require("fs");

module.exports = {
  devServer: {
    public: "your-project.local:443", // replace .local if you use another TLD
    https: {
      key: readFileSync("/ca/devilbox-ca.key"),
      cert: readFileSync("/ca/devilbox-ca.crt"),
      ca: readFileSync("/ca/devilbox-ca.srl")
    },
    hot: true,
    disableHostCheck: true
  }
};
# my-cli-project/.devilbox/nginx.yml
vhost: |
  server {
    listen       __PORT____HTTP_PROTO____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;
      proxy_pass https://php:8000;
    }

    __REDIRECT__
    __SSL__
    __ALIASES__
    __DENIES__
    __SERVER_STATUS__
    __CUSTOM__
  }

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;
    }

Make sure to change proxy_pass https://php:8000; if you are not using port 8000.

// my-cli-project/.devilbox/my-cli-project.js
const { spawn } = require("child_process");

// You need to change this port if you aren't using port 8000.
spawn("npm", ["run", "serve", "--", "--port", "8000"], { stdio: "inherit" });

Again, change 8000 if that's not the right port.

Now modify your-devilbox-repository/autostart/run-node-js-projects.sh:

NODE_PROJECTS=(
        "/shared/httpd/my-cli-project/.devilbox/my-cli-project.js" # 8000
)

That's pretty much all I did.

@robots4life

@sustained Thank you indeed. Will give this a shot for sure. Once I get things up and running I wil document this in an example repo.

I got the app to work with MongoDB and will make an example repo for that as well. Perhaps @cytopia can then somehow link to those or use them in the docs so people have a working boilerplate that they can start with easily while using Devilbox.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

taliptako picture taliptako  Â·  4Comments

normance picture normance  Â·  4Comments

hurrtz picture hurrtz  Â·  5Comments

Novitsh picture Novitsh  Â·  6Comments

msyhr picture msyhr  Â·  7Comments