Customer Portal: installation and setup

The Customer Portal is a website your company runs on its own server. Your customers sign in with a code sent to them by email, and see their hires, deliveries, certificates and billing.


→
These instructions are also inside every download as START-HERE.html, where they are in English, Spanish, French, Italian, German and Portuguese.

This page takes you from the download to a portal that runs as a service, answers over HTTPS, is connected to Business Central and has its first customer invited. Work through the sections in order. Sections 2 and 3 are alternatives: follow the one for your server. The portal is a preview, so expect details to change before its first full release.

A dark block is something you type, and the line above it says where. A light block is the contents of a file.

→
Keep this page open while you install. The copy of these instructions in the download sits in the portal's folder, and the install script closes that folder to ordinary users. Afterwards it opens only for an administrator (on Linux, only for root), so this page is the one to keep open.

1 Before you start

Get these in place before you install anything. At the end of this section you will have four values, which the portal asks for in section 5.

Business Central

A server that is always on

A web address and a certificate

The portal's own Microsoft Entra app

The portal signs in to Business Central as an app of its own, not as a person. Register that app in the Microsoft Entra admin center:

  1. App registrations, then New registration. Give it a name such as Essential Rental Customer Portal, choose Accounts in this organizational directory only, and leave the redirect URI empty.
  2. On the app's Overview, note the Application (client) ID and the Directory (tenant) ID.
  3. Certificates & secrets, then New client secret. Copy the secret's Value at once, because it is shown only once, and note the date it expires.
  4. API permissions, Add a permission, Dynamics 365 Business Central, Application permissions. Tick API.ReadWrite.All, choose Add permissions, then Grant admin consent.

The app in Business Central

Business Central has to be told about the app and what it may do.

  1. Search for Microsoft Entra Applications and choose New.
  2. In Client ID, enter the Application (client) ID you noted.
  3. Fill in Description, for example Essential Rental Customer Portal.
  4. Set State to Enabled.
  5. Under User Permission Sets, add H2B CUSTOMER PORTAL and nothing else. That set opens the portal's own pages in Essential Rental to the app, and no others.
Illustration. The real screen can differ in detail. The card as it should look when you have finished: the client ID from Entra, the state Enabled, and one permission set.

The environment name

The name of the Business Central environment the portal will read, for example Production. The Business Central admin center lists your environments.

An email account in Business Central

Business Central sends the portal's emails: the sign-in codes and the invitations. Have an email account set up in Business Central for them to come from. Section 6 assigns it.

Have these four to hand

Tenant ID
The Directory (tenant) ID from the app's Overview in Entra.
Environment name
From the Business Central admin center.
Client ID
The Application (client) ID from the app's Overview in Entra.
Client secret
The Value you copied when you made the secret.

2 Install on Windows Server

Skip this section if the portal will run on Linux.

Extract the win-x64 zip and move the folder inside it to C:\EssentialRentalPortal, so that the program is C:\EssentialRentalPortal\EssentialRentalPortal.exe. Do not keep it inside a user's own folders, such as Downloads or the Desktop: the script closes the folder to ordinary users.

Then open PowerShell with Run as administrator and run the install script:

PowerShell, as administrator

cd C:\EssentialRentalPortal
powershell -ExecutionPolicy Bypass -File .\install\install.ps1

The script ends with The Essential Rental Customer Portal is installed and running., then the address the portal listens on, which is http://localhost:5080 for now, and the latest setup-code line from the portal's log. Section 5 uses the setup code.

What the script did

To check the service at any time, run Get-Service EssentialRentalPortal. The script is safe to run again, and running it again is how an update is finished (section 7).

If the script says the portal was installed but did not start, the reason is in the newest file in the logs folder and in the Windows event logs. Section 8 has more.

3 Install on Linux

Skip this section if the portal runs on Windows.

Unzip the download, move its folder to /opt/essential-rental-portal, and run the install script. On an ARM server the zip is named linux-arm64: use that name in place of linux-x64.

Before a second attempt, delete any folder already extracted here and any zip of another version: the commands below take every EssentialRentalPortal-*-linux-x64 they find.

If the server has no unzip, install it first with sudo apt-get install unzip or sudo dnf install unzip.

A terminal on the server, in the folder holding the zip

unzip EssentialRentalPortal-*-linux-x64.zip
sudo mv EssentialRentalPortal-*-linux-x64 /opt/essential-rental-portal
sudo sh /opt/essential-rental-portal/install/install.sh

The script ends with The Essential Rental Customer Portal is installed and running., then the address the portal listens on, which is http://localhost:5080 for now, and the latest setup-code line from the portal's log. Section 5 uses the setup code.

The one library the server must have

The portal needs the ICU library. When it is missing, the script stops and says so. Install it, then run the script again.

A terminal on the server: Debian or Ubuntu

sudo apt-get install libicu-dev

A terminal on the server: Red Hat, Fedora, Rocky or Alma

sudo dnf install libicu

What the script did

To check the service at any time, run systemctl status essential-rental-portal. The script is safe to run again, and running it again is how an update is finished (section 7).

The folder must be one the account can reach, so not under /home. The script refuses a path with a space or another special character in it.

A server with no browser

First-run setup (section 5) is a web page. On a server with no browser, do one of these:

A terminal on your own computer

ssh -L 5080:localhost:5080 you@your-server

A Linux without systemd

The install script needs systemd and stops without it. The portal itself does not: it is one program, EssentialRentalPortal, which runs until it is stopped and keeps everything in its own folder. Start it with whatever the system uses to keep a program running, as an account that owns the folder and is not root. Without systemd, an account that is not root cannot listen on port 443, so use route B in section 4. The rest of this page then applies, apart from the systemctl and journalctl commands. The macOS download is the same: it has no install script.

4 HTTPS

Your customers must reach the portal over HTTPS, and the portal holds you to it: it refuses to listen on a plain http:// address other than localhost. There are two routes. Choose one.

Route A: the portal serves HTTPS itself

The certificate is a .pfx file with its password, or the two .pem files Let's Encrypt writes, fullchain.pem and privkey.pem. Keep it in a folder named certificate inside the portal's folder, where the portal's account can read it.

Windows

Make the folder C:\EssentialRentalPortal\certificate and copy the .pfx into it. Copy it, do not move it: a moved file keeps the access rules of the place it came from, and the portal's account may not be able to read it. Then tell the portal its address and its certificate, using your file's name in place of portal.pfx, and restart it:

PowerShell, as administrator

cd C:\EssentialRentalPortal
.\EssentialRentalPortal.exe configure --listen https://portal.example.com --certificate certificate\portal.pfx --password 'your-pfx-password'
Restart-Service EssentialRentalPortal

Keep the single quotes: inside double quotes PowerShell changes a $ or a backtick in the password.

The install script does not open the firewall. Allow the portal's port through it:

PowerShell, as administrator

New-NetFirewallRule -DisplayName "Essential Rental Customer Portal" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow

Linux, with a Let's Encrypt certificate

Let's Encrypt keeps privkey.pem where only root can read it. So first copy both files into the portal's folder and give them to the portal's account:

A terminal on the server

sudo mkdir -p /opt/essential-rental-portal/certificate
sudo cp -L /etc/letsencrypt/live/portal.example.com/fullchain.pem /etc/letsencrypt/live/portal.example.com/privkey.pem /opt/essential-rental-portal/certificate/
sudo chown -R essentialrental:essentialrental /opt/essential-rental-portal/certificate
sudo chmod 600 /opt/essential-rental-portal/certificate/fullchain.pem /opt/essential-rental-portal/certificate/privkey.pem

Then tell the portal its address and its certificate, and restart it. Run configure as the portal's account, as shown, so that its check proves that account can read the files:

A terminal on the server

sudo -u essentialrental /opt/essential-rental-portal/EssentialRentalPortal configure --listen https://portal.example.com --certificate /opt/essential-rental-portal/certificate/fullchain.pem --key /opt/essential-rental-portal/certificate/privkey.pem
sudo systemctl restart essential-rental-portal

The install script does not open the firewall. If the server has one, open port 443 in it.

What configure does

configure checks that the certificate loads before it saves anything. It then saves the settings in portal.settings.json, with the password encrypted, and says what it saved: the address, and the certificate with the date it is valid until. When something is wrong it says what, and saves nothing.

After the restart the portal answers at https://portal.example.com, and no longer at http://localhost:5080. If it does not start, the newest file in its logs folder says why (section 8).

Both kinds of certificate work on both systems: name a .pfx with --certificate and --password, or .pem files with --certificate and --key.

!
A password typed on a command line stays in that shell's history. Clear the history afterwards if anyone else uses the account.

When the certificate is renewed

Replace the file or files under the same names, by copying, not moving. The portal serves the new certificate within about a minute, with no restart.

For Let's Encrypt, a renewal hook does the copying. Save this as /etc/letsencrypt/renewal-hooks/deploy/essential-rental-portal.sh:

The file /etc/letsencrypt/renewal-hooks/deploy/essential-rental-portal.sh

#!/bin/sh
cp -L /etc/letsencrypt/live/portal.example.com/fullchain.pem /etc/letsencrypt/live/portal.example.com/privkey.pem /opt/essential-rental-portal/certificate/
chown essentialrental:essentialrental /opt/essential-rental-portal/certificate/fullchain.pem /opt/essential-rental-portal/certificate/privkey.pem
chmod 600 /opt/essential-rental-portal/certificate/fullchain.pem /opt/essential-rental-portal/certificate/privkey.pem

Then mark it executable:

A terminal on the server

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/essential-rental-portal.sh

A .pfx whose password has changed is the one case that needs more: run configure again with --certificate and --password, then restart the portal.

Route B: behind a reverse proxy

The portal stays on http://localhost:5080, which is how the install script left it. When the proxy runs on the same server there is nothing to configure in the portal.

The proxy must:

With these, the portal marks its sign-in cookie Secure, sends HSTS, and records each visitor's own address.

nginx

nginx: a server block in its configuration

server {
    listen 443 ssl;
    server_name portal.example.com;
    ssl_certificate     /etc/letsencrypt/live/portal.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/portal.example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:5080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

IIS

IIS needs two additions installed, URL Rewrite and Application Request Routing. Then, in IIS Manager:

  1. At the server, open Application Request Routing's Server Proxy Settings and tick Enable proxy. Application Request Routing adds the visitor's address to X-Forwarded-For itself.
  2. Have IIS pass the Host header through: open Configuration Editor at the server, choose the section system.webServer/proxy, and set preserveHostHeader to True.
  3. In URL Rewrite, choose View Server Variables and add HTTP_X_FORWARDED_PROTO to the allowed server variables.
  4. Give the site an HTTPS binding for portal.example.com. The rule below passes on only requests that arrived over HTTPS, so a visit over plain HTTP never reaches the portal: IIS answers it itself, usually with its own "not found" page. If the site also has an HTTP binding, remove it, or add a redirect to HTTPS in IIS if you want such visits to end up on HTTPS.
  5. Save this as the site's web.config.

The site's web.config

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Essential Rental Customer Portal" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="^on$" />
          </conditions>
          <serverVariables>
            <set name="HTTP_X_FORWARDED_PROTO" value="https" />
          </serverVariables>
          <action type="Rewrite" url="http://localhost:5080/{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

A Synology NAS

In DSM, open Control Panel, Login Portal, Advanced, Reverse Proxy, and choose Create.

Illustration. The real screen can differ in detail. The rule on a Synology NAS. The source is the address your customers use; the destination is the portal on the same machine. The two headers are on the other tab.

Check the proxy

Whichever proxy you use, ask the portal for its sign-in page through it:

A terminal on another computer

curl -sI https://portal.example.com/sign-in

Look in the answer for a Strict-Transport-Security line, which some proxies show in lower case. It means the portal knows the visitor is on HTTPS. The first line of the answer does not matter: this command asks for the headers alone, which the portal answers with 302 until first-run setup is done and with 404 afterwards. No such line means the proxy is not sending X-Forwarded-Proto, or is not a proxy the portal believes.

Do this check before first-run setup is finished and before the address is public: until the Strict-Transport-Security line appears, a visitor through the proxy can look like the server itself.

A proxy on another machine, or a network in front

The portal believes a proxy on its own machine, and nobody else. A proxy on another machine, or a network such as Cloudflare's in front of your proxy, has to be listed before the portal believes what it says about the visitor. Until it is, the portal records that proxy's or network's address as the visitor's.

Windows: PowerShell, as administrator, in C:\EssentialRentalPortal

.\EssentialRentalPortal.exe configure --trusted-proxies "192.168.1.5"
Restart-Service EssentialRentalPortal

Linux: a terminal on the server

sudo -u essentialrental /opt/essential-rental-portal/EssentialRentalPortal configure --trusted-proxies "192.168.1.5"
sudo systemctl restart essential-rental-portal
→
Setup through a proxy always asks for the setup code, whatever the proxy sends.

5 First-run setup

Setup is one page, where you connect the portal to Business Central. It is protected by a setup code.

The setup code

The portal makes a new 8-digit setup code every time it starts, and writes it to its log. The install script showed you the one from that start. If the portal has been restarted since, as section 4 does, the code has changed. To see the latest:

Windows: PowerShell, as administrator

Select-String -Path C:\EssentialRentalPortal\logs\portal-*.log -Pattern "setup code" | Select-Object -Last 1

Linux: a terminal on the server

sudo sh -c 'grep -h "setup code" /opt/essential-rental-portal/logs/portal-*.log | tail -n 1'

The line ends with the code.

Open setup

Open the portal's address followed by /setup.

Connect to Business Central

  1. Enter the four values from section 1: Tenant ID, Environment name, Client ID of the portal's Entra app and Client secret.
  2. Choose Test connection. The page answers Connected. and lists the companies in the environment, with each one's licence and whether the portal is switched on there. Until you have done section 6, every company reads Switched off, and that is expected. If the page says The connection did not work:, the reason follows: check the four values, the admin consent in Entra, and the app's card in Business Central.
  3. Leave Listen address as it is: it is the address the portal was installed with, or the one you set in section 4.
  4. Choose Finish setup. The portal's sign-in page opens, and setup is done.
Illustration. The real screen can differ in detail. The portal's setup page. The numbers match the steps above. The company is shown as it reads once section 6 is done: licensed, switched on, and the main company.

Leave Developer mode off. Everything else about the portal is set in Business Central, which is the next section.

When the client secret is about to expire

Make a new secret in Entra, as in section 1. Open setup with the setup code, enter the new secret in Client secret, and choose Save. The portal uses it within a minute, with no restart.

6 Finishing in Business Central

Do this in each company the portal serves.

The setup wizard

Search for Customer Portal Setup, which is also on the Essential Rental Setup page, and choose Setup Wizard. After its welcome page, its steps are:

  1. The portal address. In Portal Address, enter the address your customers will type, such as https://portal.example.com. Invitation emails show it.
  2. The email account. Use Choose Email Account. Portal emails come only from the account assigned to the Customer Portal email scenario, never from your default account.
  3. How the portal looks. The two brand colours, and the Main Company and Show Powered By settings. When the portal serves several companies, tick Main Company in the one whose name and logo belong on the sign-in page.
  4. Send a test email. Choose Send Test Email, and check that it arrives. The first time, Business Central may ask you to allow the connection.
  5. Finish, which is available once the test email has been sent. It switches the portal on for this company and starts the job that sends portal emails.

That job is a job queue entry that sends every minute and runs as you, the person who finished the wizard. So your user needs the right to send from the email account you chose.

Illustration. The real screen can differ in detail. The wizard on its step for the portal address. Finish stays unavailable until the test email on the last step has been sent.

Portal users

People are given access customer by customer.

  1. On a customer's card, choose Portal Users, then Invite.
  2. Enter the person's Full Name and Email. Business Central emails them an invitation within about a minute, and the portal picks up a new person in about the same time.
  3. They open the portal and sign in with a code sent to that address. There is no password.

Can See Billing decides, for each person and customer, whether that person sees balances and invoices. It is off until you tick it.

Illustration. The real screen can differ in detail. One customer's portal users. The first person has signed in and can see billing. The second has been invited and has not signed in yet.

Is it working?

Customer Portal Setup shows both halves. Under Email, Sender Job says whether portal emails are going out. Under Portal Website, Last In Touch says when the portal last reported. The portal reports every 15 minutes, so a newly installed portal can take that long to appear.

7 Updating, backing up, moving and uninstalling

Updating

When Essential Rental and the portal both have a new version, update Essential Rental in Business Central first. Then update the portal. Your settings, data and logs are not in the zip, so they stay as they are.

Windows

  1. In PowerShell, as administrator, run Stop-Service EssentialRentalPortal.
  2. Extract the new zip, and copy everything in the folder it extracts over the files in C:\EssentialRentalPortal. Copy from that folder only: anything left from an earlier version's zip is the old program.
  3. Run install.ps1 again, as in section 2. It starts the service.

Linux

Download the new zip into an empty folder, or first delete the earlier zip and any folder extracted from it. The commands below take every EssentialRentalPortal-*-linux-x64 they find.

A terminal on the server, in a folder that holds the new zip and nothing from an earlier version

sudo systemctl stop essential-rental-portal
unzip EssentialRentalPortal-*-linux-x64.zip
sudo cp -a EssentialRentalPortal-*-linux-x64/. /opt/essential-rental-portal/
sudo sh /opt/essential-rental-portal/install/install.sh

Backing up and moving

Everything the portal keeps is in its folder: portal.settings.json, data (the database, the keys that encrypt the secrets, and cached files) and logs. To back it up, stop the service, copy the folder, and start the service.

Linux: a terminal on the server

sudo systemctl stop essential-rental-portal
sudo tar -czf /root/essential-rental-portal-backup.tar.gz -C /opt essential-rental-portal
sudo systemctl start essential-rental-portal

The portal's data is a copy of what Business Central holds. A lost portal can be installed afresh, and will read it all again.

Moving to another server

Copy the whole folder to the new server, run the install script there, and point the web address at the new server.

Uninstalling

Windows: PowerShell, as administrator, in C:\EssentialRentalPortal

powershell -ExecutionPolicy Bypass -File .\install\uninstall.ps1

Linux: a terminal on the server

sudo sh /opt/essential-rental-portal/install/uninstall.sh

Either script removes the service and leaves the settings, data and logs where they are. On Linux the account essentialrental stays too. Delete the folder to remove the rest and, on Linux, remove the account with sudo userdel essentialrental.

8 Troubleshooting

Where the logs are

In logs, inside the portal's folder. There is one file a day, named portal- and the date, and 30 days are kept. On Windows, warnings and errors are also in the Application event log under EssentialRentalPortal. On Linux, the journal has them too:

Linux: a terminal on the server

sudo journalctl -u essential-rental-portal -n 50

The service will not start

The last line of the newest log file says The portal did not start. and then why. The usual reasons:

Fix the cause, then start the service again: Restart-Service EssentialRentalPortal on Windows, sudo systemctl restart essential-rental-portal on Linux.

configure will not save

When configure cannot use what it was given, it says what is wrong and saves nothing. It never repeats the password, and when an option is mistyped its message names the option and not what followed it.

A lost setup code

The code is written to the log at every start, and section 5 has the command that finds it. Restarting the portal makes a new one, which is also the way out when setup says there were too many wrong codes.

Sign-in emails do not arrive

In Business Central, Customer Portal Setup says why under Email, and its Email Queue shows what went out and what is waiting.

"The portal hasn't been in touch"

Business Central says this when the portal has been silent too long. Check that the service is running, that the server can reach the internet, and that the client secret has not expired (section 5).

The connection is not secure, or sign-in will not stick

Behind a proxy, run the check in section 4: the proxy must send X-Forwarded-Proto. On IIS, also check that the request reached the site over HTTPS (section 4). The portal ignores the setting ASPNETCORE_FORWARDEDHEADERS_ENABLED, which some guides say to turn on, and says so once in its log. When the portal serves HTTPS itself, its log names the certificate it serves and the date it is valid until, and warns when it has expired.

A browser still shows the old colours

A new brand colour shows at once. If something in front of the portal, such as a proxy's or a network's cache, still serves the old page, clear that cache.