Skip to content
Andy Kemp Consulting

Install#

Two steps: create the Entra app on your Windows or Mac machine, which gives you a setup code, then run the installer on the Ubuntu server and paste the code in. Check the Requirements first.

Step 1: Create the Entra app (Windows or Mac)#

Download either the whole hapman.zip and extract it, or just the script, New-HAPManApp.ps1. Then, from the folder you extracted HAPMan to:

pwsh ./deploy/New-HAPManApp.ps1 -HostName hapman.contoso.com -AssignTo you@contoso.com

If you downloaded the script on its own, run pwsh ./New-HAPManApp.ps1 with the same parameters.

A browser opens: sign in as a Global Administrator, or a Cloud Application Administrator who is also a Privileged Role Administrator. The first run also installs the Microsoft Graph PowerShell modules, which takes a few minutes.

The script creates, or updates if it already exists:

  • the HAPMan app registration, single tenant, with the redirect URI https://<hostname>:8443/auth/callback,
  • the HAPMan.Admin app role,
  • the enterprise app, with Assignment required on,
  • admin consent for sign-in only (openid, profile, offline_access), so nobody sees a consent prompt,
  • the role, assigned to the users or groups in -AssignTo (or to you, if you leave it out),
  • a client secret, valid for 12 months.

It then prints a setup code starting HAPMAN1. and copies it to your clipboard.

Treat the setup code like a password

The code holds the tenant ID, client ID, client secret and its expiry date. It can't be shown again: if you lose it, run the script again for a new one.

Parameters#

Parameter Default What it does
-HostName hapman.andykemp.com HAPMan's DNS name. Always set this.
-Port 8443 HAPMan's port, if you'll choose a different one in the installer
-AssignTo You Users (UPN) or groups (display name) to give the HAPMan.Admin role, comma separated
-SecretMonths 12 How long the client secret lasts, 1 to 24 months
-TenantId Your home tenant Sign in to a specific tenant
-ShowValues Off Also print the tenant ID, client ID and secret separately

The script is safe to run again: it updates the existing HAPMan app rather than creating another one, and adds a new secret each time. That's also how you rotate the secret.

On Windows#

  • Windows blocks the script. Files downloaded from the internet are marked as such. Unblock it first:

    Unblock-File .\deploy\New-HAPManApp.ps1
    
  • Windows PowerShell 5.1 works too, if you don't have PowerShell 7:

    powershell -ExecutionPolicy Bypass -File .\deploy\New-HAPManApp.ps1 -HostName hapman.contoso.com -AssignTo you@contoso.com
    
  • "Assembly with same name is already loaded": another version of the Graph modules is already loaded in that window. Open a new PowerShell window, or run pwsh -NoProfile, and try again. See Troubleshooting.

Step 2: Install on the Ubuntu server#

sudo apt update && sudo apt install -y unzip
curl -LO https://downloads.andykemp.com/hapman/latest/hapman.zip
unzip hapman.zip && cd hapman
sudo ./install.sh

One run does the rest:

  1. Installs HAProxy, Python, and certbot with the Cloudflare plugin.
  2. Creates the locked-down hapman service account, the apply helper and its single sudo rule.
  3. Copies the app to /opt/hapman, with its own Python virtual environment.
  4. Asks for HAPMan's hostname and port (8443 by default). Ports below 1024, including 80 and 443, are refused because HAProxy needs them for your routes.
  5. Asks how to set up Entra ID. Choose 1 and paste the setup code from step 1. The installer warns you if the code was made for a different hostname or port.
  6. Asks for the Cloudflare API token and an email address for expiry notices, gets a Let's Encrypt certificate for HAPMan, and sets up automatic renewal, with a HAPMan restart after each one.
  7. Starts HAPMan and tells you the URL.

Browse to https://hapman.contoso.com:8443 and sign in.

The sign-in page

If UFW is active, the installer suggests a rule to allow HAPMan from your LAN only, for example:

sudo ufw allow from 192.168.0.0/16 to any port 8443 proto tcp

Don't forget to allow 80, 443 and any TCP route ports through UFW for HAProxy too.

Recommended

Add a Conditional Access policy for the HAPMan app that requires phishing-resistant MFA and a compliant device.

Other ways to set up Entra ID#

When the installer asks how to set up the app registration:

Option When to use it
1 Paste a setup code The usual way. You ran New-HAPManApp.ps1 on Windows or Mac.
2 Create it from this server You have no Windows or Mac machine to hand. The installer puts PowerShell 7 on the server, runs the same script and signs you in with a device code, which you complete in any browser, such as on your phone. It asks which UPN to give the role to.
3 Enter the values by hand You created the app registration yourself. The installer shows the redirect URI to register, then asks for the tenant ID, client ID, secret, its expiry date, the app role (HAPMan.Admin, or none) and an optional allow-list of UPNs.

If option 2 doesn't finish, the installer falls back to asking for a setup code. With option 3, set an app role, an allow-list or both, or nobody can sign in.

A quick test with a self-signed certificate#

To try HAPMan before DNS and the Cloudflare token are ready:

sudo ./install.sh --self-signed

Your browser will warn about the certificate. When you're ready, switch to Let's Encrypt:

sudo ./install.sh --reconfigure

Installer options#

Command What it does
sudo ./install.sh First install, or update to the version in this folder. Keeps settings, routes and certificates.
sudo ./install.sh --reconfigure Asks the hostname, port, Entra and certificate questions again, including a new Cloudflare token
sudo ./install.sh --entra Only asks for a new setup code, for a rotated secret or a changed redirect URI. Leaves the certificate alone.
sudo ./install.sh --self-signed Uses a self-signed certificate instead of Let's Encrypt
sudo ./install.sh --help Shows these options

Next steps#

  1. Add your first routes and apply them: Using HAPMan, or follow the worked example.
  2. The first apply replaces Ubuntu's sample /etc/haproxy/haproxy.cfg. The original is kept as /etc/haproxy/haproxy.cfg.hapman-prev.
  3. Point your router's port forwards at the VM. Never forward HAPMan's port (8443).