Docs
Installation
What you need, DNS, and installing ClientOS on your server with one command.
This page takes you from an empty server to a running ClientOS. You run one command on the server, and do the rest in your browser: name your two addresses, add the DNS records the page shows you, and create your agency and its owner account. Plan on about 15 minutes, most of it waiting for DNS.
What you need#
- A Linux server with a public IP address, running Ubuntu 22.04 or 24.04, or Debian 12. Any provider works: Hetzner, DigitalOcean, Vultr, Linode, AWS Lightsail and so on.
- A domain you can add DNS records to, for example
youragency.com. ClientOS uses two addresses under it, which you choose. - An email address for the HTTPS certificates. Let's Encrypt writes to it only if a renewal ever fails.
- Your license key,
CLOS-XXXX-XXXX-XXXX-XXXX. It's in your account at vibemonk.com, under Licenses.
Server size#
| Minimum | Comfortable | |
|---|---|---|
| CPU | 1 | 2 |
| Memory | 2 GB | 4 GB |
| Free disk | 10 GB | 20 GB |
The installer refuses a server with less than 2 GB of memory or 10 GB of free disk. On a server with very little memory it adds a 4 GB swap file for you.
You don't install anything else yourself. The installer sets up Docker if it's missing, and ClientOS brings its own database, Redis, file storage and web server.
Ports 80 and 443#
ClientOS brings its own web server, Caddy, which gets and renews the HTTPS certificates. Ports 80 and 443 must be free, so don't install it on a server that already runs nginx or Apache. If ufw is active, the installer opens both ports for you. If your provider has a cloud firewall (AWS security groups, Hetzner or DigitalOcean firewalls), allow both there too.
Your two addresses#
You choose two addresses, for example:
| Address | What it is |
|---|---|
clients.youragency.com | Your clients sign in here. Your public service pages, forms and pay links live here too. |
team.youragency.com | Your team works here. |
Any names work, as long as both are under the same domain: youragency.com and admin.youragency.com is fine too. That's what lets one sign-in work across both. Your team's address is kept separate from your clients' on purpose, so nothing on a client page can reach your team's screens.
You don't need addresses for the API or for file storage: they run on your client portal's address.
1. Download the installer#
In your account at vibemonk.com, open Licenses and download the ClientOS installer. It's a small file, clientos-kit-VERSION.tar.gz: ClientOS itself is downloaded later with your license key.
Copy it to the server, for example:
scp clientos-kit-*.tar.gz root@YOUR_SERVER_IP:
2. Run it#
On the server:
tar xzf clientos-kit-*.tar.gz
cd clientos
sudo ./install.sh --license-key CLOS-XXXX-XXXX-XXXX-XXXX
It then:
- installs Docker, if it isn't there yet;
- adds a swap file, if the server has very little memory;
- checks your license key and finds the newest release it includes;
- writes
deploy/.envwith freshly generated passwords and secrets; - downloads ClientOS, checks every file's fingerprint and loads it;
- prints a link to open in your browser.
Open this in your browser to finish:
http://203.0.113.5/?t=k3J9...
Keep the terminal open. The setup key appears there when you need it.
3. Connect your addresses in the browser#
Open the link. Enter your two addresses and your email. The page then shows the two DNS records to add at the company you bought your domain from:
Type Name Value
A clients YOUR_SERVER_IP
A team YOUR_SERVER_IP
A wildcard record, *.youragency.com, works too.
On Cloudflare, set the records to DNS only (grey cloud). Let's Encrypt needs to reach your server directly to issue the first certificates. You can turn the proxy on later; see Cloudflare's proxy below.
The page checks every few seconds. It doesn't just look for the records: it sends a request to each address and marks it Connected once that request arrives at your server. If an address points somewhere else, it tells you where, and what to change. When both are connected, press Connect.
ClientOS starts and gets its HTTPS certificates, which usually takes a minute or two. Then your browser moves on to the setup page by itself.
4. Finish setting up#
The setup page, https://team.youragency.com/setup, asks for the setup key your terminal is showing. The license step already has your key: press Next and ClientOS binds it to your domain. Then enter your agency's details and create the owner account.
First run walks through the setup page and what to connect afterwards.
Lost the setup key? Run
sudo clientos setup-keyon the server.
Keep the folder you ran the installer from. It holds deploy/.env and, later, your backups. Don't move it after installing.
Without the browser#
To install in one line, for example from a provisioning script, pass your addresses as options. Add the DNS records first:
sudo ./install.sh --portal-domain clients.youragency.com --admin-domain team.youragency.com \
--email [email protected] --license-key CLOS-XXXX-XXXX-XXXX-XXXX --yes
With --yes, the installer carries on even if DNS isn't right yet. Certificates are issued as soon as it is. Running it again is always safe: on a server that's already installed, it keeps deploy/.env as it is and only fetches the images and restarts.
What's running#
Everything runs in Docker on this one server. Only Caddy has open ports.
| Container | What it does |
|---|---|
caddy | The web server. Gets the HTTPS certificates and routes your two addresses. |
postgres | PostgreSQL 18. All of your data. |
redis | Realtime presence only (who's online, who's typing). Holds nothing you need to back up. |
minio | File storage, served on your client portal's address. You can switch to a Cloudflare R2 bucket later. |
migrate | Runs on every start: applies database migrations, sets up the API's database login and seeds the defaults, then exits. |
api | The API, served on your client portal's address under /v1. Starts only after migrate has finished. |
portal, admin | The two web apps. Start once the API is healthy. |
The files live in the folder you installed from:
| Path | What it is |
|---|---|
deploy/.env | Your configuration and secrets, written by the installer. See Configuration. |
deploy/docker-compose.yml | The whole stack. Replaced by updates, so don't edit it. |
backups/ | Created by clientos backup. See Updates and backups. |
Two things still need your accounts, and you connect both in the admin after setup:
- Resend, for all email: sign-in codes, invitations and notifications. Nothing can be emailed until you connect it.
- Payment gateways: Stripe, PayPal, NOWPayments, CoinGate or BTCPay Server.
Cloudflare Turnstile, Google sign-in for clients and a Cloudflare R2 bucket for files are optional.
Cloudflare's proxy#
If you want Cloudflare's proxy (orange cloud) in front of ClientOS, turn it on only after setup is finished, then:
- Put Cloudflare's IPv4 and IPv6 ranges from cloudflare.com/ips, separated by spaces, in
EXTRA_TRUSTED_PROXIESindeploy/.env. - Run
sudo clientos startto apply it. - In Cloudflare, set SSL/TLS to Full (strict).
Without step 1, every visitor looks like a Cloudflare server, so they all share one rate limit and the signed-in devices screen shows Cloudflare's addresses.
Webhook URLs#
ClientOS receives webhooks on your client portal's address. Most are registered for you when you connect the service in the admin. PORTAL below is that address, for example clients.youragency.com.
| Source | URL | Registered |
|---|---|---|
| Payment gateways (Stripe, PayPal, NOWPayments, CoinGate, BTCPay Server) | https://PORTAL/v1/payments/webhooks/PROVIDER | Automatically when you connect the gateway, where the provider allows it. The gateway card tells you if it couldn't. |
| Resend delivery events (delivered, bounced, complained) | https://PORTAL/v1/mail/webhooks/resend | Automatically when you connect Resend, if the key is allowed to. Otherwise the dialog asks for the signing secret of one you add in Resend. |
| Resend inbound email into tickets | https://PORTAL/v1/mail/webhooks/inbound | You add it in Resend and paste its signing secret in Settings → Tickets. See Support tickets. |
| Your website's lead forms | https://PORTAL/v1/lead-capture | You add the snippet the admin generates to your website. See Leads and tracking. |
| Google sign-in redirect URI | https://PORTAL/v1/auth/callback/google | You add it in Google Cloud. See Configuration. |
Installed ClientOS before addresses were chosen in the browser? Your server keeps its four addresses (
portal.,admin.,api.andfiles.under your domain), and your webhooks keep working athttps://api.YOUR_DOMAIN/….
When the installer stops#
| It says | What to do |
|---|---|
run it as root | Run it with sudo. |
this installer is for a Linux server | Run it on the server, not on your own computer. |
ClientOS needs at least 2 GB of memory or 10 GB of free disk | Pick a bigger server. |
port 80 is already in use (or 443) | Another web server is running. Stop and disable it, then run the installer again. |
| The browser link doesn't open | Your provider's firewall is blocking port 80. Allow ports 80 and 443 there, then run the installer again. Or install without the browser. |
must be under the same domain | Your two addresses need a common domain, like clients.youragency.com and team.youragency.com. |
does not look like a ClientOS license key | Copy the key again from your account. It looks like CLOS-XXXX-XXXX-XXXX-XXXX. |
The license server refused, then a reason | The reason says what's wrong: a mistyped key, a revoked one, or one already active on another domain. Release it from your account at vibemonk.com, under Licenses. |
A file did not match its checksum, or the download stopped | Nothing was installed. Run the installer again; it picks up the files already downloaded. |
does not carry Vibemonk's signature | Nothing was installed. Contact Vibemonk support. |
the database migration failed or the API did not come up | The log is printed above the message. Send it to support if it isn't clear. |
Next: First run#
ClientOS is running, but it has no owner yet and can't send email. Continue with First run.