URLs start with HTP to avoid “new users can only put in 2 links”
I really hope the answer to my question is yes since we have committed to a switch to Strapi and this is a make or break requirement.
I have been working on this for the better part of a day and I am no stranger to Docker, Nginx, etc. I am convinced Strapi can work this way but wow, what a bizarre problem. It should be super simple and I am wondering now if Strapi is doing something unusual in the backend?
Goal:
docker-compose.yml runs several self-contained Strapi instances, one per client, each in their own container. The same docker-compose also includes nginx and portainer. The root of Nginx is bound to HTP://cms.ourdomain.com (HTTPS and certs will be added after this issue is solved). Each strapi instance is reverse_proxied as a subdirectory. HTTP://cms.ourdomain.com/client-1, HTP://cms.ourdomain.com/client-2, etc.
The best that I can achieve is the “Let’s get started” screen BUT, only the HTML has been returned and rendered. All images are broken and a quick inspection shows that all other URL have NOT been proxied. For example, instead of seeing cms.ourdomain.com/client-1/favicon.ico I see cms.ourdomain.com/favicon.ico. Put another way, it seems that only the first request is proxied.
FWIW this is being developed in Ubuntu 20.04 in WSL2 but will be deployed to AWS infrastructure.
Yes Strapi can containerized and sitting behind Nginx (it’s recommended especially for SSL and Load Balancing). However there are few key things to note.
@DMehaffy Thank you for responding. I saw those links before but discarded them as they seemed unusually complex for setting up a simple Docker container and not relevant to my simple use-case. I will return to them later this morning. Meanwhile, a couple of (hopefully) quick questions:
The documentation clearly describes the how but not the why. What is the rationale for creating the upstream.conf and could I not simply proxy_pass 127.0.0.1:1337; in the location block of strapi.conf?
What is it about the Strapi architecture that requires a code change, as illustrated in config/server.js? This is not a critique, just a genuine question to understand the architecture.
Is the code snippet shown for config/server.js the entire code for that file? Presumably, that would be added in COPY clause of a custom Strapi Dockerfile? Or is the intent that one docker-compose ups the stack, which won’t work right away, and then edits config/server.js in the Strapi container?
This is a general best practice, usually you would have a single Nginx instance to handle multiple domains, ect and it’s much easier to maintain a single upstream config as Nginx will complain if you have multiple upstream blocks spread across multiple virtual host configs. The upstream block is generally used for load balancing and scaling, by hard coding the ip:port in the virtual host file you will be unable to scale the number of instances.
There are two main keys that can modify core parts of the Strapi variables to properly load routes:
server.js => url => This is used to tell the Strapi React admin panel how to connect to the backend and is compiled into the React admin panel during the build phase (the backend is not built). It’s also used throughout the application as a variable for things like the email plugin (injecting the public link into password reset emails) and the 3rd party auth providers (for redirects)
server.js => admin.url => this is optional and is used to change the route to access the admin panel, say from /admin to /dashboard and is relative (usually) combined with the above url
It is not, only as an example, you should read through the following documentation to understand the structure of the server.js config file
@DMehaffy Thanks for those answers, they helped immensely.
I am able to run my environment using the Sub-Folder Split example which is closest to my use-case where I need to expose a dashboard to content managers and consume an API from the existing site build process.
However, my hope is to be able to deploy the dashboard such that the URL is “rooted” a level above the API. For example https://mydomain.com/client-01 and https://mydomain.com/client-02 would both resolve to the client-specific dashboards with https://mydomain.com/client-01/api and https://mydomain.com/client-02/api resolving to the respective APIs. Doing so provides a better experience for the non-technical content managers and editors as they will intuitively go to the respective client folder.
Unfortunately. I have not been able to get this to work despite editing the paths in server.js (and making corresponding changes to the nginx conf files). I can achieve
you need to adjust this line, it’s specifically replacing the /api/ with just / so if you are adding onto the path you need to adjust it to something like
rewrite ^/client-01/api/(.*)$ /$1 break;
All the rewrite is doing is removing that string from the request sent to Strapi.
In my most recent example I was testing right off the root of my domain. E.g. I removed all the client sub folder references to reduce the possibility of other issues. So I believe rewrite ^/api/(.*)$ /$1 break; would be correct for https://cms.mydomain.com/api?
Silly question but I don’t know what you mean by virtual host file. Are you referring to the nginx conf file? Here’s everything regardless. The NGinx image is from nginx:stable although I did try nginx:latest with no difference in results. Both upstream.conf and strapi.conf are being loaded from conf.d, not sites-enabled.
FWIW I am rebuilding Strapi from inside the container with strapi build after I make changes as well as reloading nginx with nginx -s reload. I am seeing lots of Uncaught SyntaxError: Unexpected token '<' in the browser console.
Let me take a look, your strapi.conf is what is referred to as a virtual host config as it’s bound to a specific server_name. Generally you would have multiple files based on a server_name instead of just throwing all of these into the default nginx.conf. And no biggie on where it’s loaded from, the sites-enabled is a debian thing, I know most other distros (or whatever your docker container is based on) don’t have that folder so conf.d is fine
Another common alias for “virtual host” is “server block” with both referring to running multiple “virtual hosts” on the same port, IE port 80 or port 443, ect.
Yes, but to clarify, for simple testing. I was eliminating the client subfolders in an attempt to get things working, and then I was going to add the client subfolders back in. But the premise remains, the dashboard is served from the “client” root and the API from the client /api.
Hi, @DMehaffy I know you are busy but wondering if you had a chance to look into this particular scenario? Alternatively, if it is something not currently supported I can live with that and work around it.
I’m sorry this got thrown in my backlog and I accidently skipped over it, I’ll setup a test instance right now to do some testing.
Short term I would suggest using the /admin or /dashboard and simply putting a 301 redirect html file in the Strapi public folder as index.html to redirect to the actual admin path.
Note in that config I am currently trying to static serve the admin instead of allowing Strapi to serve it to bypass the restrictions for serving the admin on the root, this is also a good idea if you plan to scale the Strapi backend, cuts load from the backend for serving the admin and you only need to build the admin once and serve it from Nginx
Also feel free to sign in to those two admin panels and create some content types, I’ll leave the server up for a few days while I wait for our engineering team to take a look at the bug report and so I can apply some changes and make a copy of the config for future examples
@DMehaffy, in light of the bug that you have uncovered, my team can certainly live with the requirement of navigating to the admin folder for now. It is not a make-or-break issue, just a nice-to-have convenience.
I can update the NGinx conf file in the future when the bug has been resolved. Meanwhile, I will keep an eye on this space for any updates.
You could replace the normal index.html in the public folder with a simple html refresh redirect to the admin path though instead of showing the status page.