EDIT
After a comment, Nah explained better his needs. So you want to proxy the request from nginx to a service also to handle the Angular App. In this case what you want to do is to receive a request like: user1.myportal.com
and to proxy it to a service in the form http://<IP>:<PORT>/user1
. To achieve this, I'm going to modify my "Solution B" with the right configuration:
http {
# Handle angular Single page Application.
server {
listen 80;
server_name ~^(?<user_id>.+)\.myportal\.com$;
location / {
proxy_pass http://12.12.12.12:3000/$user_id$request_uri
}
}
# handle api.myportal.com and identity.myportal.com
server {
listen 80;
server_name api.myportal.com;
location / {
proxy_pass http://127.0.0.1:9000;
}
}
server {
listen 80;
server_name identity.myportal.com;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
}
As you can see you should use the user_id
variable from the server_name
regex to build the path for the proxy_pass
directive.
The $request_uri
variable is used to handle all paths with params. So that URLs like user1.myportal.com/path/to/something?key=value
are proxied to 12.12.12.12:3000/user1/path/to/something?key=value
.
The above example is working because the proxy_pass
directive is used with an IP address and NGINX can resolve it. If you want to use an hostname you have to declare a resolver.
Original answer
You are almost there. What I don't see it's a proper configuration to serve (or proxy) the angular application (that is just made by static assets).
Also, you don't need to use odd if statements
. It's better to define all subdomains in their own server section. Nginx will give precedence to server_names with the "exact name", and then wildcard and regex. (here you can find more info about this).
Finally, I did not understand if you want that users just do the first access to their space with a custom subdomain like user1.myportal.com
and then they are redirected to myportal.com/user1
or if you want that they continue their navigation through the original url they used (user1.myportal.com
). I would go for the second approach because it's more versatile and maybe less odd from a user point of view.
I imagine that with both approach, the angular application logic must be ready to know that the username is after the host at the beggining of the path (myportal.com/user1
) OR in the subdomain (user1.myportal.com
).
My solutions do not require a secondary domain for your services. You can use them if you want but it's not needed, it's only about choices and there is not a better way to go for this.
Solution A ->
Angular app is matched with user1.myportal.com
and is then redirected to myportal.com/user1
.
http {
# Handle angular Single page Application.
server {
listen 80;
server_name myportal.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ $uri.html /index.html;
# if you want here you can proxy pass to any service that is serving your angular static assets instead of using the try files directive.
}
}
# Redirect user1.myportal.com like domains to myportal.com/user1
server {
listen 80;
server_name ~^(?<user_id>.+)\.myportal\.com$;
location / {
return 301 http://myportal.com/$user_id;
}
}
# handle api.myportal.com and identity.myportal.com
server {
listen 80;
server_name api.myportal.com;
location / {
proxy_pass http://127.0.0.1:9000;
}
}
server {
listen 80;
server_name identity.myportal.com;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
}
This approach could work but like I told you I find it a bit odd, users will be redirected to a new page. Also, you can have problem handling paths. I imagine you want an URL like user1.myportal.com/pictures
should be redirected to user1.myportal.com/user1/pictures
. To handle this, you should change the return 301 http://myportal.com/$user_id;
to something like return 301 http://myportal.com/$user_id$request_uri;
.
Solution B ->
Angular app is matched with user1.myportal.com
. No redirect are involved and user continue their navigation with the original url
http {
# Handle angular Single page Application.
server {
listen 80;
server_name ~^(?<user_id>.+)\.myportal\.com$;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ $uri.html /index.html;
# if you want here you can proxy pass to any service that is serving your angular static assets instead of using the try files directive.
}
}
# handle api.myportal.com and identity.myportal.com
server {
listen 80;
server_name api.myportal.com;
location / {
proxy_pass http://127.0.0.1:9000;
}
}
server {
listen 80;
server_name identity.myportal.com;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
}
As you can see the second solution is not using any redirect. I would go with solution B, it's cleaner and convenient for users. Also you don't have to handle the "path problem". Urls like user1.myportal.com/pictures
will just work. Again: I assume you can control the logic (and the router) of the Angular Single Page Application and you know that for Single Page Apps you have to serve always the index.html file, for each path. Then, the client side logic is responsable of routing the user to the right view according to the URL path, and if needed to the url subdomains too.
Both my solutions just shows the basic configuration needed. SSL, https to http redirect and fine tuning params are not included to give you a concise but usefull prototype.