How do I install erpnext into a suburl / subdirectory (e.g. https://projects.example.com/erpnext/

Hey folks,

I need to install erpnext into a suburl / subdirectory. Here is my current setup:

  • There is an existing machine & desired domain, https://projects.example.com.
  • I want ERPNext installed in https://projects.example.com/erpnext/
  • I do NOT want to make a separate machine or domain name like https://erpnext.projects.example.com (I know this is the “preferred way”, but isn’t tenable in this case.)
  • SSL, etc, is already completely set up and other project services used by various teams are already running and working fine, e.g.
    • https://projects.example.com/bugzilla/
    • https://projects.example.com/gitlab/
    • https://projects.example.com/taiga/
    • … etc …
  • I’ve already set up ERPNext in Docker and have it working on the machine as http://localhost:9001, and it’s being proxied to by nginx fromhttps://projects.example.com/erpnext– this works, except ERPNext doesn’t know it’s installed in a subdir so none of the links and other resource references are right.

Most web apps have an internal setting to say what suburl / subdir it’s installed in. Trying to use a front-end rewrite engine is not reliable, and I haven’t been able to find anything like this for ERPNext (or in Frappe).

Can someone please point me in the right direction?

Thank you! =)

Hi @wjl,

To accomplish this, you will need to customize the Nginx configuration for ERPNext. You would modify server and location blocks to control how web traffic is interpreted and routed.

I recommend learning more about Nginx, and experimenting with its configuration files (the main file is named nginx.conf.

https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms

Hi @brian_pond!

Thanks for the reply.

I am pretty familiar with nginx, as that’s what we’re using for our own front-end stuff. I’m basing our install on the official docker repository (frappe_docker), so I’ll try modifying the configuration in the erpnext-front container as you suggest.

However, most web apps also need to know their starting URL internally, and almost every one I’ve worked with has some sort of internal configuration variable for setting this. Is there also configuration that needs to happen inside the frappe-server that it proxies to? I would expect that it must need to know this in order to generate URLs in various contexts, including non-web ones, like emails, etc. Is this really not the case for ERPNext?

In any case, I’ll give this a try, but I’d be interested to know if anyone is actually running this way successfully. It’s easy to just point to nginx configuration, but I have some doubts if that’s going to be all that’s required to make this work. I’d be pleasantly surprised to be wrong. =)

When it comes to the inner workings of Python WSGI web servers generally, and Gunicorn specifically, I am not an expert. So I don’t want to lead you astray. Hopefully another forum user with more knowledge can answer your questions.

The solution greatly varies depending on if you choose to use Port-based vs. DNS-based multitenancy. Setup Multitenancy.

I can say that email specifically is 100% independent from URL, domain, Site, You can configure any email domain you like, regardless of whether it’s remotely related to anything else.

Thanks for the pointers.

I will see what I can accomplish messing with the erpnext-nginx container configuration, but I would really love to hear from someone that has actually set up ERPNext on a suburl. I’ll give it a shot, but I don’t think that tweaking nginx is going to really help.

As for mutlitenancy, the link you sent doesn’t seem to be applicable to what I’m trying to do. As I understand frappe’s terminology, I’m running a single “bench” (one instance of frappe and erpnext), so I’m not doing “multitenancy” at that level. We already have DNS mutlitenancy (many logical servers handled by the same nginx instance(s)) taken care of at a level way above web apps. For ERPNext, if I want another instance, I’ll spin up another set of completely independent docker containers. But that said, I’ll take another look at the frappe docs you linked too and see if I missed something that would help here. I was hoping I wouldn’t have to become a frappe expert just to set a URL subpath!

What I meant about email is that if ERPNext ever needs to generate an email that says “click here https://projects.example.com/erpnext/reset_password” or something, it needs some way to know that URL.

Anyway, thanks again for the response. If it helps for context, I’m a computer engineer with over 25 years of experience. I’m very familiar with nginx, docker, and web apps in general. I’ve dabbled in Python WSGI, and played with gunicorn a little, but I’m a newbie there. I’ve never used (or heard of frappe) except in the current context of setting up erpnext.

To give some more examples of what I’m trying to figure out:

  • In taiga, this is configured in their docker setup by setting “TAIGA_SUBPATH”: “/taiga” in their docker-compose.yml
  • In bugzilla, this is configured by setting urlbase to “/bugzilla” in their localconfig.
  • In dockwiki, this is configured by setting basedir to “/docuwiki” in their online admin settings.
  • In gitlab, this is configured by setting their relative_url_root to “/gitlab” in several of their config yml files.
  • In openproject, this is configured by setting rails_relative_url_root to “/openproject” in their configuration.yml file.

All of these of course require some setting in their frontend nginx, but the app itself still needs to know this information. All of these are well-documented and easy to find with a simple web search.

I’ve spent hours looking for how to make this similar setting in ERPNext / Frappe. I haven’t yet been successful, which makes me think either I’m missing something obvious (in which case, hopefully someone here can educate me), or ERPNext / Frappe don’t have a way to easily support this, in which case I’ll probably file a bug about it.

This bug was reported in 2019 and seems to be asking for exactly what I’m asking for here: Allow relative url positioning on server. <myhost>/<somepath>/<ERPNext_Root> · Issue #20132 · frappe/erpnext · GitHub

I commented on that bug and linked to this forum topic.

If anyone knows for a fact that this actually works currently, please let us all know how to do it, and consider replying in that bug as well.

I’ve filed a similar bug against Frappe, here: Enable hosting from a relative url (aka subdir, suburl) like https://example.com/erpnext/ · Issue #15960 · frappe/frappe · GitHub

two things needed to serve a site.

custom header

site named directory in frappe-bench/sites

https://github.com/frappe/frappe/blob/733718abf316fea3e2adcc2db6ec213846f44c75/frappe/__init__.py#L189-L189

try this locally to understand,

bench start

If you have site.localhost, app.localhost as 2 sites then try:

curl -H "X-Frappe-Site-Name: site.localhost" http://0.0.0.0:8000/api/method/version
{"message":"13.20.1"}

curl -H "X-Frappe-Site-Name: app.localhost" http://0.0.0.0:8000/api/method/version
{"message":"13.20.1"}

curl -H "X-Frappe-Site-Name: doesnotexist.localhost" http://0.0.0.0:8000/api/method/version
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>doesnotexist.localhost does not exist</p>

Use this header in the proxy of your setup. I think you may have to override Host header as well because nginx container takes host header.

If you don’t want to try override host header then, override the nginx conf using SKIP_NGINX_TEMPLATE_GENERATION variable as mentioned here https://github.com/frappe/frappe_docker/blob/main/docs/environment-variables.md#frappe-nginx-and-erpnext-nginx and then you can pass custom nginx with the host line removed.

With this let the incoming confguration be anything set headers to appropriate site.

Example: all.example.com/site -> site.localhost

we’ll have to try! there is host_name key in site_config.json that may help

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.