Why the outside check is not enough
If you run Nextcloud, you probably know the official security scan that looks at your instance from the internet and reports what a stranger can see: headers, TLS, version exposure. The admin overview does its part too. Nextcloud already handles throttling, password hashing, headers, two-factor, integrity signatures and so on, and it does it well.
What neither of them sees is the state that builds up while a server is actually used. The account that can still sign in with a password alone. The application password from a sync client you retired months ago that would still work today. The file in the installation that changed when nobody changed it. The configuration file that your web server hands to anyone who asks. That is the gap Sentinel fills: a continuous security check that lives inside your Nextcloud and tells a person when any of it changes.
This tutorial walks through a practical nextcloud hardening session with it, from the first baseline to a weekly cron entry.
Prerequisites
- Nextcloud 34 and PHP 8.4 or newer. Nothing older, on purpose.
- Nextcloud background jobs (Cron) running, for the watchers and the daily summary.
- Nextcloud mail settings configured, if you want e-mail alerts.
- Optional: the EDR daemon (Linux 4.20+, Python 3.9+, root and systemd) and optionally ClamAV via its
clamdsocket.
Installation itself is short. Download the archive from your MediaLab Works account under Licenses, extract it into apps/ (or custom_apps/) owned by the web-server user, enable it, then paste your license key under Administration settings → Sentinel → License. The full steps are in the guide.
Step 1: Take the baseline before you change anything
Do this once you are satisfied the installation is in the state it ought to be in:
sudo -u www-data php occ sentinel:baseline take
The baseline records the installation's code — lib, core, apps, 3rdparty, config, themes — at that moment. It never covers users' files. From then on, only changes since that moment are reported.
After every Nextcloud or app update, approve the changed files once, with a note you will understand later:
sudo -u www-data php occ sentinel:baseline accept --all --note "Nextcloud 34.0.4"
A deliberate patch gets the same treatment. What remains after that is only the unexplained change — which is exactly what you want to look at. Under The files you can adjust which parts of the installation the baseline covers, the file kinds, exclusions, the size limit and the hash.
Step 2: Read the posture page, worst first
The posture page lists findings with the reason and the fix beside each one. In practice you will see things like:
- accounts that can sign in with a password alone;
- stale application passwords;
- idle sessions;
- dormant administrators;
- certificate expiry;
- whether anything is being logged at all.
Work down the list. Each finding says what it means and what happens if you ignore it, and has the action (expire, revoke, remove) right there. The thresholds for "too old" are yours to set under What counts as too old: stale application passwords, idle sessions, dormant administrators and links with no expiry.
Step 3: Probe what your web server actually serves
The self-probe asks your own web server, as an anonymous visitor, for files that must never be served: the configuration, the log, .git directories. Anything that comes back is reported.
You can run it from the terminal too:
sudo -u www-data php occ sentinel:check --probe
Under Asking the server what it serves you switch probing on or off, add extra paths you care about, and set how many days of warning you want before the certificate expires.
Step 4: Watch the ways in
The inventory lists every way into your instance: public links, sessions, application passwords, group membership — with expire, revoke or remove beside each. Combine it with the watchers, which alert you when something changes: an account becoming an administrator, two-factor switched off, a new account, one address working through several accounts, an administrator signing in from a new network, apps enabled or disabled, trusted domains or proxies changed, or a link opened by a crowd it was never sent to.
Sign-ins are remembered by the network an account uses, not the exact address, and trusted domains and proxies are stored only as fingerprints. Under Where people sign in from you decide whether networks are remembered at all, whether new ones warn you, how precise a network is, and which accounts to ignore. Under Public links you tune link usage watching, how big a crowd is worth mentioning, how far above the link's own record, and how many refused password attempts count as guessing.
Step 5: Catch ransomware-like changes
Sentinel does not judge by rate alone. It notices ransomware on a synced laptop by files that stop being what their names claim, by ransom notes and by mass renames. The knobs live under Files changing very fast: the window, the number of rewrites, deletes or renames to one extension, and whether to only alert or to disable the account and end its sessions.
That last part is off by default, and I would keep it that way until you trust the thresholds on your own data. Sentinel changes nothing on its own unless you ask it to.
Step 6: Make sure alerts reach a human
Under Being told, choose from which severity the bell and e-mail are used, add an extra address — ideally one that reaches a phone — set the hour of the daily summary, and press Send a test message. Then read the overview: what state the server is in, what is being watched and what is not, and whether alerts would reach anybody.
Step 7: Put a weekly check in cron
occ sentinel:check prints the report and exits nonzero when something needs attention, which makes a weekly cron entry that mails only on failure a single line:
sudo -u www-data php occ sentinel:check --quiet-when-clean
It also accepts --inventory and --json when you want to feed the output somewhere else.
Optional: EDR daemon and ClamAV
If you want to know which program writes into the data directory, the EDR daemon shipped in apps/sentinel/edr/ runs as root outside Nextcloud and can suspend the offending process:
cd /var/www/nextcloud/apps/sentinel/edr
sudo sh install.sh
sudoedit /etc/sentinel-edr/config.ini # at minimum data_dir
sudo sh install.sh # again, to grant the paths it needs
sudo systemctl enable --now sentinel-edr
Under Which program is writing you tell Sentinel whether the daemon is expected and where it leaves its reports. Separately, A scanner to ask lets you point it at ClamAV: the socket and how much of a file to send. ClamAV scans files that already look wrong.
Tips and troubleshooting
- The integrity section lists many changed files right after installing. No baseline has been taken yet, or an update was not approved. Take the baseline, or run
occ sentinel:baseline accept --all --note "..."after checking. - Nothing is watched although the app is enabled. Background jobs must run (Cron). After a disable and re-enable, open the Sentinel page once: the jobs are put back and the setup check reports it.
- E-mail alerts do not arrive. Check Nextcloud's mail server settings and use Send a test message. Administrators without an e-mail address only get the bell.
- You removed it with
occ app:removeand tables stayed behind. Remove it from inside the app or withocc sentinel:removeinstead. Accounts Sentinel disabled stay disabled until released (--release-accounts), and the EDR daemon keeps running until you stop it withsystemctl disable --now sentinel-edr. - Pausing versus removing. You can pause the watching, switch the app off keeping everything (
occ app:disable sentinel), or remove it with every record it wrote (occ sentinel:remove). - Privacy. There is no telemetry and no cloud account. The only outgoing connection is the daily license check to medialab.works, which sends the subscription key, the instance id, a hashed hardware fingerprint, the app version and a checksum of the app's own files — nothing about your users, their files, sign-ins or events. Everything is kept in four tables: baseline, events, known networks and daily link use.
Wrapping up
Run the baseline, read the posture page, probe what your server serves, and let the watchers and the daily summary tell you when something moves. That is the inside half of nextcloud hardening, and it is the half a remote scan can never see. If you get stuck, the guide has the full reference, the changelog tracks what changed, and the knowledge base and FAQ cover the rest.