Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rosspeterson's avatar

Custom Domain hosting on forge ... is this "hack" OK?

We have a multitenant app hosted on a forge server using tenancy package which allows tenants to specify a unique subdomain of our app domain or their own domain (pointing DNS at our server).

The main site contains all the goodness including environment, code, database, queues, schedules, deployment, wildcard cert, etc., and this all works fine with tenant subdomains.

When a tenant wants to bring their domain to us, the "hack" we are using is to create a new site (their domain) on the server using a "custom domain" nginx template which is identical to the default template except for a hardcoded root path pointing at our main site. (It may make sense to hardcode the logs to the main site as well ...). Forge spins up the default site directory with its empty public folder, but the site is otherwise "dumb", with no database, queues, etc. Add the let's encrypt SSL & this all works great, too.

Before we begin leveraging API's to automate the provisioning of the custom tenant domains, the question is whether this is a sustainable system. Each tenant using their own domain has (unbeknownst to them) their own site & nginx daemon on the server. We charge for this and need to decide whether the technical cost merits a high price (discouraging its use) or is just fine, even for hundreds of sites. (We should point out that the nice forge feature allowing the addition of alias domains in the main site's meta settings might offer an alternative solution, but did not give us the warm fuzzies when it comes to frequent updates to the main site nginx config and SSL certs.)

Experience or thoughts from anyone?

0 likes
8 replies
martinbean's avatar

@rosspeterson Why not just generate an SSL certification using something like LetsEncrypt when a tenant adds a domain to your application?

For example, if I add a domain to an app in Heroku, Heroku gives me a CNAME record value and creates an SSL certificate for that domain.

rosspeterson's avatar

@martinbean Good suggestion, thanks! We're tied to Forge for the time being (and are generally very satisfied with it), so this is really about working with Forge admin & configuration. (Forge does allow use of LetsEncrypt for certs and that's what we do, in fact!)

martinbean's avatar

@rosspeterson Using Forge doesn’t mean you can’t programatically create an SSL certificate when a domain record is created in your app.

rosspeterson's avatar

@martinbean But I also need an nginx server block for all of the custom domains AFAIK. How are you handling with Heroku?

martinbean's avatar

@rosspeterson Just use a wildcard block, rather than specific domains? Otherwise you’re going to need to constantly update your nginx.conf file and do a deployment every time you want to onboard a customer, or a customer wants to update their domain, or a customer leaves your platform…

rosspeterson's avatar
rosspeterson
OP
Best Answer
Level 3

For anyone interested, I submitted the query directly to Forge email channel and received prompt & helpful advice. So far we have landed on the following setup to best support the scenario:

  1. Provision load balancer on web server LAN/region! (We use DigitalOcean droplets so $4/mo.)
  2. Add sites + certs on load balancer for our main domain (w/ subdomain wildcard) and each custom domain, terminating SSL there, and point to port 80 on web app server. This is all easily managed via the admin UI and/or Forge API.
  3. Add load balancer private IP to TrustProxies middleware.
  4. Remove SSL certs & custom domain sites/aliases from web app server (nginx for main domain updated to listen on 80 by default then).
  5. In web app server networking, restrict port 80 firewall to load balancer private IP!
  6. Update web app server main site nginx config server block, commenting out listen & server_name directives and replacing with "wildcard" listen 80 default_server;.
  7. On web app server, remove the symbolic link 000-catch-all.conf from /etc/nginx/sites-enabled

Now we only touch our web app server for code deployments and can handle provisioning and de-provisioning of custom domains on the load balancer! Tests are looking good so far and we will update here if any further issues arise.

Kudos to Forge support for their extensive advice even though our plan only provides "basic support"!

luckykenlin's avatar

@rosspeterson Your best answer is greatly appreciated.

How can you execute step 2?

Is it possible to make it interact with tenant creation or add a domain via the Forge API?

Thank you

AthulR's avatar

@luckykenlin, they are talking about creating a new server in Forge with the type of load balancer.

Please or to participate in this conversation.