P Persmon Cloud
persmon-vps · Hostinger KVM 4 · London

One server, every Persmon service.

This page is the map of persmon.cloud: what runs on the box, what each thing is for, how a request travels from a browser to a container, and how the whole thing is kept backed up, patched and watched.

Compute
4 vCPU · 16 GB
Ubuntu 24.04 LTS, kernel 6.8
Storage
200 GB NVMe
≈ 19% used
Containers
44
13 Coolify resources
Public sites
checking…
Last maintenance
22 Sep 2026
patched · rebooted · pruned
Reachability is tested from your browser, so it reflects your network too.
Architecture

How the pieces fit

Every public hostname resolves to the same IP. Traefik reads the hostname and hands the request to the right container over Docker's private networks. Nothing but ports 22, 80 and 443 is open to the internet.

Browser / client https://app.persmon.cloud Hostinger DNS *.persmon.cloud → 187.124.114.79 1 · resolve ufw + fail2ban allow 22 · 80 · 443 ban brute-force IPs 2 Traefik (coolify-proxy) reads Host: header Let's Encrypt TLS http → https redirect :80 / :443 3 Appshms · ishasha-ops · jasper-os · mhf-votes · hello Supabase stackkong · auth · rest · storage · studio · db Coolify dashboardcoolify.persmon.cloud Toolsn8n · Vaultwarden · FileBrowser · Dozzle · Beszel Uptime Kumamonitors + Telegram alerts This pagepersmon.cloud · static nginx 4 · route by hostname Data (never public) postgres · redis · minio private Docker networks Ports open to the internet: 22 (SSH, key-only) · 80 · 443. Everything else is reachable only from inside the server.
Entry pointContainer or groupDashed = internal only
Applications

Products running on the box

Each app is a Coolify resource built from a Git repository. Coolify builds the image on the server, starts the container, and tells Traefik which hostname belongs to it.

Persmon HMS

Demo
qxq6bwdn4bgsktex7asnspa0.persmon.cloud

Multi-tenant hotel property-management system with point-of-sale. This is the public demo host, reseeded with fresh sample data every night at 03:30.

How it runs

Five containers: a web front end, an api, a dedicated postgres, a redis cache and a caddy sidecar that serves the built front end and proxies /api to the backend. Backed up nightly at 02:30.

webapipostgresrediscaddy

Ishasha Ops

Live tenant
hu3cxoqqjym6hhblwmlzldbr.persmon.cloud

The same HMS platform, deployed as an isolated instance for Ishasha Junction Hotel. Real bookings, real staff, real data — so it has its own database and its own 02:45 backup.

How it runs

Identical stack to the demo (web, api, postgres, redis, caddy) but a completely separate Coolify resource and Docker network. A bug on the demo cannot touch this tenant's data.

webapipostgresrediscaddy

Jasper OS

Private
me.persmon.cloud

Jasper's personal life dashboard — the one app on this server that is for a single person. Scheduled jobs run every 15 minutes; the database is backed up at 02:50.

How it runs

An app container plus its own db. Deploys are triggered by a webhook on push. Background jobs are fired by a host-side cron (jasper-os-cron.sh) rather than inside the container, so they survive redeploys.

apppostgreswebhook deploy

MHF Votes

Event · 2026
2jerl0k48yli3voeaelmkspe.persmon.cloud

Public voting platform for the 1st National Sickle Cell Awards 2026. Isolated on purpose: its own auth service, its own gateway, its own database. Ballots are counted in every nightly backup log.

How it runs

Four containers: web, auth, an authgw that fronts the auth service, and db. Staff accounts, SMTP and secrets are managed by dedicated scripts on the host.

webauthauthgwpostgres

persmon-hello

Canary
hello.persmon.cloud

The first app ever deployed here and still the quickest health check: if hello answers, DNS, the firewall, Traefik, TLS and Coolify are all working.

How it runs

Auto-deploys on every push to the private persmon-hello repository through the Coolify GitHub App. One container, no database.

git push → deploy

Uganda Bookshop

Staging
no public domain yet

Next.js storefront for Uganda Bookshop, currently in staging. Catalogue and cover images were imported on 21 Sep; the storefront goes public once the domain is pointed here.

How it runs

A single Coolify application in its own project. Uses the self-hosted Supabase stack below for auth and data.

next.jssupabase

OMS demo

Outside Coolify
internal only

An order-management demo started directly with Docker from ~/oms-build, refreshed by a cron job every 10 minutes. The only application container Coolify does not manage.

How it runs

Plain docker run — no Traefik labels, so it has no public hostname. Logs go to ~/oms-cron.log.

dockercron */10
Platform

What everything else stands on

These services are not products — they are the machinery that builds, routes, stores and secures the products above.

Coolify

Control plane
coolify.persmon.cloud

Self-hosted platform-as-a-service. Think of it as a private Heroku: it connects to GitHub, builds images, runs containers, wires up domains and certificates, and shows logs and a terminal in the browser.

How it runs

Six containers: coolify (the app), coolify-db (Postgres), coolify-redis (queues), coolify-realtime (websockets for live logs), coolify-sentinel (metrics) and coolify-proxy (Traefik). It talks to Docker through the local socket and to the host over SSH on 127.0.0.1.

v4.x6 containers

Traefik

Reverse proxy
coolify-proxy · :80 :443

The only container that listens on the internet. Watches Docker for labels, so a new app with a domain is routable within seconds. Requests and renews Let's Encrypt certificates automatically.

How it runs

Managed by Coolify. Attached to every app's private network so it can reach each container by name. Redirects all HTTP to HTTPS. Certificates live in acme.json inside /data/coolify/proxy.

let's encrypthttp→https

Supabase (self-hosted)

Backend-as-a-service
supabase.persmon.cloud

Postgres with batteries: instant REST API, authentication, file storage and a web studio. Used by newer projects such as Uganda Bookshop instead of writing a backend from scratch.

How it runs

A trimmed nine-container stack: kong (API gateway) in front of auth, rest, storage, meta, realtime and studio, with db (Postgres) and minio (S3-compatible object store) behind them. Only Kong and Studio are exposed through Traefik.

kongauthreststoragestudiominio

Postgres 17

Shared database
persmon-postgres · internal

A standalone Postgres server for apps that need a plain database without the Supabase layer. Reachable only from containers on its Docker network; never from the internet.

How it runs

Coolify-managed database resource. Included in the 03:00 full backup; its data directory is a named Docker volume on the NVMe disk.

postgres 17internal
Utilities

Tools for running the server

Each of these is a small self-hosted app that replaces a paid SaaS. All are Coolify resources with their own subdomain and password.

n8n

Automation
persmon-n8n

Visual workflow automation — the self-hosted alternative to Zapier. Connects webhooks, schedules, HTTP calls and the other services on this box.

How it runs

Three containers: n8n (editor + API), postgresql (workflow store) and task-runners (executes code nodes in isolation).

n8npostgrestask-runners

Vaultwarden

Passwords
persmon-vaultwarden

Bitwarden-compatible password manager, stored on Persmon's own disk. Works with the official Bitwarden browser extensions and mobile apps.

How it runs

One Rust container with an SQLite database; sign-ups are closed after the first account. Included in nightly backups.

bitwarden api

FileBrowser

Files
persmon-filebrowser

A web file manager over ~/files. Upload, download and share files from a browser without SFTP.

How it runs

One container with a bind mount to the host folder, so files are also visible in the shell.

bind mount

Dozzle

Logs
persmon-dozzle

Live, searchable logs for every container in one screen. The first place to look when something misbehaves.

How it runs

Reads the Docker socket read-only; stores nothing.

docker socket (ro)

Beszel

Metrics
persmon-beszel

Lightweight CPU, memory, disk and network graphs for the host and each container, with history. The lighter cousin of Grafana.

How it runs

A beszel hub plus a beszel-agent that samples the host every few seconds.

hubagent

Uptime Kuma

Monitoring
uptime-kuma

Pings every public site every minute and pushes alerts to Telegram (@persmon_vps_alerts_bot) when one goes down or a certificate nears expiry. Backup scripts also send a heartbeat here, so a backup that silently stops running raises an alert.

How it runs

One container with an SQLite database. Push monitors receive heartbeats from the nightly cron jobs.

telegrampush heartbeats
Protection

Backups, patches and the perimeter

Nightly schedule (UTC)

TimeJobWhat it protects
02:15mhf-backupMHF Votes database + ballot count
02:30hms-backupPersmon HMS demo database
02:45ishasha-backupIshasha Ops live database
02:50jasper-os-backupJasper OS database
03:00persmon-backupFull archive: Coolify config, volumes, tool data, checksums · heartbeat to Uptime Kuma
03:30hms-reseedResets the public HMS demo to clean sample data
nightlyPC pullOff-site copy of ~/backups to Jasper's workstation

Backups are kept in ~/backups with SHA-256 checksums. A restore drill script exists and has been exercised.

Perimeter

  • ufw firewallDefault deny. Inbound: 22, 80, 443 only. Forwarded traffic may reach containers on 80/443 (Traefik) — nothing else.
  • SSH hardenedKey-only login, root disabled, password auth off. Admin user persmon; every action that needs root goes through sudo.
  • fail2banBans IPs that hammer SSH.
  • unattended-upgradesSecurity patches install themselves; kernel updates wait for a chosen reboot window.
  • SecretsTokens live in ~/.* files with mode 600 and in Coolify's encrypted store — never in repositories or this page.
  • AlertsUptime Kuma → Telegram for outages, expiring certificates and missed backups.
How it works

Two journeys worth understanding

A request, from browser to container

  1. DNSEvery *.persmon.cloud name points at the same IPv4 address. The hostname is the only thing that distinguishes one app from another.
  2. Firewallufw lets the packet in on 443. fail2ban has already dropped anyone who was brute-forcing SSH.
  3. TraefikTerminates TLS with the site's Let's Encrypt certificate, reads the Host header, and looks up which container declared that hostname in its Docker labels.
  4. Private networkThe request crosses a Docker bridge network that only that app and Traefik are attached to. The app's database sits on the same network and is unreachable from anywhere else.
  5. AppThe container answers; Traefik streams the response back. Nothing on the box ever sees the internet directly except Traefik.

A deploy, from git push to live

  1. PushCode lands on the main branch of a repository the Coolify GitHub App can see.
  2. WebhookGitHub calls Coolify. Coolify queues a build through Redis.
  3. BuildCoolify clones the repo on the server and builds an image with BuildKit (Nixpacks/Railpack or your Dockerfile).
  4. SwapThe new container starts on the app's network; Traefik picks up its labels; the old container is stopped. Health checks decide when traffic moves.
  5. ObserveLive build logs in Coolify, runtime logs in Dozzle, resource graphs in Beszel, and an Uptime Kuma check within a minute.
Operations

Where things live, and what changed

On the host

PathContents
/data/coolifyCoolify state, proxy config, certificates
/var/lib/dockerImages, volumes, container layers (~20 GB)
~/backupsNightly dumps + checksums + job logs
~/*.shBackup, reseed and cron scripts (referenced by crontab — do not move)
~/archiveOld script copies and audit snapshots (safe to delete after 30 days)
~/transfersLarge one-off files moved to or from the VPS
~/filesWhat FileBrowser serves

Changelog

  • Maintenance: 22 packages upgraded (Docker 29.8), Coolify updated, rebooted onto kernel 6.8.0-139, 1.8 GB of unused images pruned, home folder organised. Firewall rule for the proxy made reboot-proof. Jev trial connector removed. This page launched at persmon.cloud.

  • Uganda Bookshop staging imported (catalogue + covers).

  • Jasper OS deployed at me.persmon.cloud with webhook deploys and 15-minute jobs; backup scripts revised, Uptime Kuma push heartbeats added for every job.

  • MHF Votes stack deployed in isolation for the National Sickle Cell Awards 2026.

  • Build phase closed; operations runbook adopted. Reboots only in chosen windows.

  • Postgres 17, trimmed Supabase, backups with off-site pull, Uptime Kuma + Telegram, and the utilities toolbox (n8n, Vaultwarden, FileBrowser, Dozzle, Beszel) all brought up in one long day.

  • VPS provisioned, hardened, Coolify installed, first app (hello) auto-deploying from GitHub.