Addon ingress nginx and angular 10 example

Hi guys,

I am struggling to find a working example of a custom Addon that implements ingress and serves static angular 10 files via nginx. So far, I am able to configure the addon ingress + nginx server to serve static html files (they just work). However, when I put the angular compiled /dist files into the root file folder of nginx, I start having problems. It looks like the index.htmk is loaded but then any attempt to load js/css fails. I suspect something with routing or service worker is not working as expected.

Is there anyone who already sorted it out?

I’ve also created a simple Hello-World addon based on an angular 11 hello world + nginx server via addon ingress, to showcase the problem. Find it here

Is there anyone who can help to figure this out? I believe this would be helpful to a number of people.

I solve it thanks to @pvizeli .
I’ve updated the repository with a working example.

Thanks!

Hi,

I was struggling with the same topic and decided to change the angular application and the web server. The topic is closed, but I didn’t found a solution which worked for me:

This is the issue:

  • You need to run the angular application in a subdirectory which is not known at deployment time.
  • So, you have to set it at boot time. Angular doesn’t support this out of the box.
  • The client needs to “know” the base href because all subsequent html calls.
    This can be achieved by replacing the " element in index.html
    This will already enable reading of the static angular files.
  • In order to achieve the same for the http Client calls on the client, the base url must be prepended to the API calls.

This is what needs to be done:

  1. set the HashLocationStrategy by setting useHash: true
    It builds # url’s instead of path url’s they are not processed by the server
...
@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    RouterModule.forRoot(routes, {
      bindToComponentInputs: true,
      useHash: true,
    }),
  ],
...
  1. Change index.html to store base href in sessionStorage
    This is the code:
...
 <base id='base' href="/test">
...
  <script>{
      base = window.document.getElementById('base')
      window.sessionStorage.setItem('base', base.getAttributeNode('href').value)
    }
  </script>
  1. On the server you need to read the X-Ingress-Path from the request header and use it to update the base url
 private setIngressUrl(req: Request) {
    let h = req.header("X-Ingress-Path");
    this.ingressUrl = h ? h : "/";
  }

private sendIndexFile(req: Request, res: express.Response) {
    this.setIngressUrl(req);
    let dir = this.getDirectoryForLanguage(req);
    let file = join(this.angulardir, dir, "index.html");
    let content = fs.readFileSync(file).toString();
    let htmlDom = parse(content.toString());
    if (this.ingressUrl && content && htmlDom) {
      let base = htmlDom.querySelector("base");
      base?.setAttribute("href", join("/", this.ingressUrl, "/"));
      content = htmlDom.toString();
      res.status(200).setHeader("Content-Type", "text/html").send(htmlDom.toString());
    } else res.status(401).setHeader("Content-Type", "text/html").send("Invalid index.html file ");
  }

The approach has the following advantages:

  1. One application in the docker file (nginx is not required)
  2. The same docker file for Homeassistant addon and Standalone (If the X-Ingress-Path is not available in the header, nothing will happen
  3. Only a few changes in the angular and in express application are required

I tried the nginx approach also, but I struggled when it came to angular routing.
I am still not convinced, that it works without modifications in angular.

Hi all,
I’m trying to develop an addon for Hassio as well with Angular and I’m running into similar troubles.
@albertogeniola I tried to follow your example repository but I didn’t get it to work.
In practice using your example repo as guide, I get the following snippet of config inside my addon /etc/nginx.conf:

    # Ingress
    server {
        listen 172.30.32.1:8099 default_server;

        allow   172.30.32.2;
        deny    all;

        server_name _;
        access_log /dev/stdout combined;

        root    /var/www;
        
        location /api/hassio_ingress/6PsWDYhAtZjyVvCpTLWiqYXX43kU_-8z21FbV8qiM9E {
            rewrite  ^/api/hassio_ingress/6PsWDYhAtZjyVvCpTLWiqYXX43kU_-8z21FbV8qiM9E/(.*)  /$1 break;
            try_files $uri$args $uri$args/ $uri/ /index.html;
        }
    }

When I open the web interface for my addon, I see an empty page and in the Chrome Console I see all requests to fetch the polyfill and main.js files are 404ing.

@vovo500 ,
looking at your post at step#3, if I understand correctly you’re using a Nodejs server to serve the Angular app right?
I was trying to use the nginx web server instead having the nginx listening on port 8099 (ingress port) and trying to get some rewrite rule working fine (just like @albertogeniola did 3 years ago)…