From 2a6a2486d7be4d73c82cea5dc285d520891fb98d Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Sat, 2 May 2026 19:48:06 +0200 Subject: [PATCH] docs: explain the optional dedicated activity database The Activity app already supports an `activity_db*`-prefixed connection that the AppInfo registers via `ConnectionFactory::createConnectionParams('activity_')`, falling back to the main Nextcloud DB when none of the keys are set. The behaviour is undocumented outside the source, which makes admins nervous about touching it on busy installations where the activity table grows fastest. Add `docs/database.md` covering: - when a dedicated connection is worth the operational cost, - the full set of `activity_db*` config keys with types/defaults, including driver options and persistent-connection toggle, - a worked `config.php` example for "same engine, separate host", - a TLS driver-options snippet for MySQL, - migration, backup and troubleshooting notes. Link the new doc from the README under a new "Administration" section. Signed-off-by: Frank Karlitschek --- README.md | 4 ++ docs/database.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100755 docs/database.md diff --git a/README.md b/README.md index 43848bb04..ecb66e42e 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,7 @@ In Nextcloud 11 the old extension API was replaced by 3 new interfaces, to bette * [Provider](docs/provider.md) - translate and render activities * [Setting](docs/setting.md) - allow users to control what they want to see in their stream or mail * [Filter](docs/filter.md) - allow to reduce the stream in the web UI by app or setting + +## Administration + +* [Database configuration](docs/database.md) - using a dedicated database for activity events diff --git a/docs/database.md b/docs/database.md new file mode 100755 index 000000000..e8698874c --- /dev/null +++ b/docs/database.md @@ -0,0 +1,128 @@ + + +# Activity database configuration + +The Activity app stores its events in two tables (`activity` and `activity_mq`). +By default these live in the same database as the rest of Nextcloud. + +On large or busy installations the activity log can grow into hundreds of +millions of rows and dominate the size and write load of the main database. To +keep that traffic off the main database, the Activity app supports an +**optional, dedicated database connection**. When configured, only Activity's +two tables are read/written there; everything else continues to use the main +Nextcloud database. + +## When to use a dedicated database + +Consider a separate connection if you are seeing one or more of: + +- The `activity` and `activity_mq` tables are larger than the rest of the + schema combined (check the **Activity** admin section, "Database" panel). +- The main DB is the bottleneck and you want to offload sustained activity + writes to a different host. +- Compliance / retention requirements differ between activity events and the + rest of your Nextcloud data. + +For most installations the default (shared connection) is the right choice. + +## Configuration keys + +All keys go into `config/config.php`. The activity app uses the same connection +factory as the main DB, so the keys mirror the standard ones with an +`activity_` prefix. + +If **all** of `activity_dbuser`, `activity_dbpassword`, `activity_dbname`, +`activity_dbhost`, `activity_dbport` and `activity_dbdriveroptions` are unset, +the app falls back to the main Nextcloud connection. As soon as **any one** of +them is set, the dedicated connection is used and the others must be filled in. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `activity_dbtype` | string | falls back to `dbtype` | `mysql`, `pgsql`, `oci`, or `sqlite3` | +| `activity_dbhost` | string | – | Hostname (and optional `:port`) of the server | +| `activity_dbport` | int | – | Port (alternative to embedding it in `dbhost`) | +| `activity_dbname` | string | – | Database / schema name | +| `activity_dbuser` | string | – | Username | +| `activity_dbpassword` | string | – | Password | +| `activity_dbtableprefix` | string | falls back to `dbtableprefix` | Table prefix (usually `oc_`) | +| `activity_dbdriveroptions` | array | – | Driver-specific PDO options, see below | +| `activity_dbpersistent` | bool | follows main `dbpersistent` | Use persistent connections | + +The `dbtype` key is **not** prefix-required: if `activity_dbtype` is omitted, +the app uses the same engine as the main DB. You can mix engines (e.g. main DB +on PostgreSQL, activity DB on MySQL) but it is rarely worth the operational +cost. + +## Examples + +### Same engine, separate host + +```php + 'mysql', + 'dbhost' => 'main-db.internal', + 'dbname' => 'nextcloud', + 'dbuser' => 'nextcloud', + 'dbpassword' => 'secret', + + // Dedicated activity database on a different host: + 'activity_dbhost' => 'activity-db.internal', + 'activity_dbname' => 'nextcloud_activity', + 'activity_dbuser' => 'nextcloud_activity', + 'activity_dbpassword' => 'another-secret', + // dbtype, tableprefix, etc. inherited from the main DB +]; +``` + +### Driver options (TLS to MySQL) + +```php +'activity_dbdriveroptions' => [ + PDO::MYSQL_ATTR_SSL_CA => '/etc/ssl/certs/db-ca.pem', + PDO::MYSQL_ATTR_SSL_CERT => '/etc/ssl/certs/db-client.pem', + PDO::MYSQL_ATTR_SSL_KEY => '/etc/ssl/private/db-client.key', +], +``` + +## Migrations + +Schema migrations for the two activity tables run against whichever connection +is active for this app. If you switch from the shared connection to a +dedicated one (or back), make sure the target database is up to date — the +easiest path is to enable / disable the app via `occ` so that the migrator +runs against the new connection. + +## Backup and restore + +When using a dedicated connection, your normal Nextcloud database backup will +**not** include the activity tables. Back up the dedicated database +separately, on the same schedule as the main one. + +You can verify what each backup contains with: + +```sql +-- Should be empty in the main DB if a dedicated connection is configured: +SHOW TABLES LIKE 'oc_activity%'; +``` + +## Disk size visibility + +The size of the activity tables on disk is shown on the **Activity** admin +settings page under "Database". Use this to decide whether moving activity to +a dedicated database is worthwhile. + +## Troubleshooting + +- **The app can't connect.** Run `occ config:system:get activity_dbhost` etc. + to confirm what is actually loaded — typos in `config.php` fail silently. +- **Migrations did not run on the dedicated database.** Disable and re-enable + the app, or run `occ maintenance:repair`. +- **You see activity data in *both* databases.** This usually means the app + was used with a shared connection first, then switched. Either drop the + duplicated tables from the main DB after verifying the dedicated DB has the + data, or revert to the shared connection.