Skip to main content

Files (drive)

Applies to: SimpleTwo 0.9.x, drive 0.5, agent 0.5.116 · Checked: 06.10.2026

drive is the role that stores the files a person keeps, as opposed to the files they sent to a chat or by mail. Everybody has a personal space, home; every identity group has a shared space. In the clients it is the Files tab on iOS, macOS and Android (how people use it).

The role keeps no bytes of its own. Files live in object storage (the s3 role or the organisation's store) in the simpletwo-drive bucket, and an object's key is the file's path: the bucket is a real tree of directories that can be walked without SimpleTwo. Its own database on postgres holds what the files do not: the change journal clients sync on, the name index for search, the bin, versions, external links and their counters, unfinished uploads.

1. What you need first​

WhatWhyWithout it
the postgres role or an external clusterthe role's own database; the coordinator creates itthe role does not start: it has no in-memory mode
object storage — the s3 role or Settings → External storesthe files' bytesthe role starts but accepts only files up to 32 KB (they fit in a catalogue row); a larger upload answers no_object_store, /healthz shows object_store: none
a public DNS name with an A record to the drive host's public address, and port 443 reachable from the internetclients reach the role over HTTPS; the role obtains its Let's Encrypt certificate itself (TLS-ALPN-01 on 443)no certificate, no drive_url, no Files tab in the clients (see §3)
the coordinator and the role on one session keythe role verifies tokens itselfthe coordinator hands the key over; nothing to type

Host size is 2 vCPU / 4 GB: there are no bytes on the host, the working set is the catalogue in postgres. But every download and every upload passes through the role (no client is ever given the store's address), so the role is bounded by bandwidth, not disk. There has been no load run for it yet — see sizing.

Count storage separately from chat and mail attachments. The product's figures are still assumptions, not measurements: 15–20 GB per person when existing file shares are carried in, and 3–5 GB per person a year on top.

The organisation's store

With external storage the drive's bucket is always called simpletwo-drive — the console has no field for its name. The role creates the bucket at start if it is missing; if the key does not allow that, create the bucket beforehand.

2. Installation​

  1. Servers & deploys → Add a host, role drive.
  2. Fill in:
    • Public DNS name — e.g. files.s2.<domain>. Its A record must point at this host's public address. This is the name clients get, external links https://<name>/d/<token> point at it, and the role orders its certificate for it.
    • Private address — the host's leg toward postgres and storage. The database's and the store's access rules are narrowed to this /32; nothing needs redeploying, postgres and s3 pick the new address up within about a minute.
    • Listen address — :8088 by default. Plain HTTP on the host's private address, used by the coordinator and the other services.
  3. Run the generated command on the host. The agent installs the service, opens 8088 and — if the host has a public name — 443. The service obtains a Let's Encrypt certificate for its name itself (TLS-ALPN-01 on 443, like the calendar); no front and no port 80 are needed. The certificate is kept in /var/lib/simpletwo/drive-acme. The contact address for the certificate authority is the installation-wide one.
  4. Wait for the name to be announced to clients — see the next section.

Check on the role's host and from outside:

curl -fsS http://<private address>:8088/healthz
curl -fsS https://<public name>/healthz
curl -fsS https://s2.<domain>/.well-known/simpletwo.json

The first two answers must carry "ok": true and an "object_store" that is not none. The third must carry drive_url with https://<public name> (it appears within a couple of minutes of the second request answering).

Before drive 0.5 and agent 0.5.116

In earlier releases the coordinator image did not contain the drive service itself (the host joined but installed nothing), the role had no TLS of its own, and drive_url was written only when the host's settings were saved. Upgrade the coordinator and the agent, then press Redeploy on the drive host.

3. The public name and drive_url​

Clients learn where the drive is from the discovery document (/.well-known/simpletwo.json): the drive_url field. No field, no Files tab: that is the client honestly saying the installation has no drive, instead of showing buttons that do not work.

The coordinator announces drive_url as it does for mail and identity: once a minute it opens https://<public name>/healthz and publishes https://<public name> only when it is the drive service that answers. Once it stops answering, the field is withdrawn after 15 minutes and the tab hides. Hence the requirements:

  • the name comes from the host's row (the Public DNS name field when adding the host or in the host's Settings) and must resolve to the drive host's public address;
  • the host's port 443 must be reachable from the internet — for Let's Encrypt and for clients;
  • the certificate must be valid: clients do not open an address without one.

There is no drive switch in Settings → Product options: only a missing drive_url hides the tab. The iOS, macOS and Android clients read drive_url from the same discovery document as the mail and calendar addresses.

4. Spaces and rights​

  • Personal space (personal:<login>) — for everybody who has signed in to a client. Only the owner sees it; the administrator does not see its content.
  • Group space (group:<group>) — for every group the person's token carries. The role keeps no list of groups: remove somebody from a group in identity and with their next token they lose its space as well, with nothing to synchronise.
In this version
  • All members of a group have the same rights in its space: read, upload, rename and delete. There are no read-only roles inside a space yet.
  • Assigning the Drive feature in identity does not restrict access yet. The role is given identity's address but does not read the assignment feed: a personal space is created when the tab is first opened, and the Drive feature's state in identity does not reach "ready".
  • The role accepts only the coordinator's session token. It does not verify identity's platform token (platform_token: identity) — an installation with a drive should not switch to it yet.
  • What happens to a leaver's personal space is not decided: the files stay, there is no policy.

5. Quotas​

A person's space is set where mail's and chats' are — by a quota template: Console → Settings → Quotas, the Files part (space and largest file). Details — quotas.

  • The quota is checked when an upload starts, on the declared size, not after the bytes have crossed the network. A space with no room answers quota_spent, a file over the limit too_large.
  • Over quota only writes are refused. Reading, downloading and external links keep working; nothing is deleted.
  • The role's own ceiling on one file is 2 GB (DRIVE_MAX_UPLOAD_MB); a template can only lower it.
  • A group space's quota is set on the console's Files tab (below) — there are no templates for groups. A personal space's quota cannot be changed there: the role answers "a person's quota comes from the quota plan"; change the person's template instead.

6. The console's Files tab​

Console → Files — two cards:

  • What the drive holds — how many files and spaces, how much is charged to people and how much is actually stored, and the difference — what deduplication saves (the same file kept by forty people is stored once). Also the number of unfinished uploads.
  • Spaces — find spaces by person or group, biggest first: whose, how much is used, the quota in GB. 0 means the installation's default. A quota below what is already stored deletes nothing: new files are refused.

The cards reach the role through the coordinator and need permissions: the totals settings:read, the list of spaces users:read, a quota users:write. There is no device sync state ("who downloaded what") in the console and there will not be: the service does not know it.

A person can issue a link https://<public name>/d/<token> to a file for somebody outside the organisation. The access level is read (download), comment (leave a remark about the file) or write (put a new version of the file); read by default. A link may have an expiry, a password and a download allowance; revocation bites on the next byte, because a link's bytes always pass through the role. The role records every download: when, from which address, how many bytes. The token is shown once and stored only as a hash — the same link cannot be issued again.

The link policy defaults to "allowed for everybody", and it is not in the console yet

The role can switch links off, allow them only to named groups, impose an expiry and cap the level (/v1/control/links/policy), but the coordinator has not brought that setting into the console yet. Until it does, external links are allowed to everybody, with no mandatory expiry and at any level. If that does not suit the organisation, hold off opening the drive to people until the setting is in the console: /d/ cannot be closed while leaving the clients' access open — the service serves both on one name and one port.

The clients have no "share a link" button yet, nor a comments screen: links are created and comments read only through the role's API (reference). Other limits of this version: a link is issued for a file only, not a folder; there is no page for the recipient — a link without a password downloads the file straight away in a browser, and a browser cannot open a password link by itself (the password travels in the request body or the X-S2-Link-Password header, never in the address).

8. The bin, versions and sync rules​

  • Deleted items go to the space's bin and stay there 30 days (DRIVE_BIN_DAYS), then are erased. Bytes are erased only when no other file points at the same content.
  • Earlier versions of a file are kept on every overwrite and go with the file when the bin erases it.
  • What does not sync. The installation has a list of exclusion masks (*.tmp, ~$*, .DS_Store and so on) a person may add to but not shorten. The role stores it and hands it to clients, but the console has no field for it: the default list built into the client applies.

9. Backup and restore​

The bucket is the record of which files exist; the database is a derived index. Therefore:

  • Back up the simpletwo-drive bucket — the main thing and the largest. On the s3 role it is the ZFS dataset simpletwo/s3 (snapshots and zfs send); on external storage, by its own tools.
  • Every hour the role puts a snapshot of the catalogue into each space (<space>/.catalogue.json): the bin, versions, links, comments. Connect the same bucket to a new database and you lose only what changed after the last snapshot; the files themselves are never lost.
  • The role's database is backed up with the other postgres databases (pg_dump) — see upgrade and backup.
Encryption at rest

The role does not encrypt files: the decision is to encrypt below it, with ZFS. Today the agent creates the dataset without encryption, and it cannot be switched on for an existing dataset — only by creating a new one with encryption=on and copying the data over. The installation's encryption switch does not cover the drive.

10. Not in this version​

  • WebDAV (Finder, Explorer), a drive web page and an outward S3 API.
  • A sync folder on the computer ("like Dropbox"): decided, the daemon does not exist yet.
  • Files in the Windows client: the sidebar has a Files section, but it is an empty screen.
  • In the clients: rename, move, versions, a bin with restore, search and external links exist in the role, but the apps have no buttons for them yet.
  • Server-side preview, antivirus checking of uploads (ICAP), content search — search is by name only.
  • Migration of existing file shares.
  • There will be no SMB: that is a decision, not a backlog item.

If something does not work​

SymptomLikely cause
No Files tab/.well-known/simpletwo.json has no drive_url: the coordinator has not reached https://<public name>/healthz (§3)
https://<public name>/healthz does not answerno A record to the drive host, 443 closed from outside, no public name on the host, or the certificate not issued yet — see the service's log on the host
No simpletwo-drive service on the drive hostthe coordinator predates the drive 0.5 release: its image had no role binary; upgrade and press Redeploy
Small files upload, large ones get no_object_storethe role was given no store: no s3 role and no external store; /healthz → object_store: none
quota_spentthe space is full: the person's template or the group's quota on the Files tab
No group spacethe group is not in the person's token: check membership in identity; the change shows after the token is renewed
Host in error, "no dsn in the desired state"no postgres and no external cluster