CoreCP

Config drop-ins

Sooner or later a machine needs one setting CoreCP does not model: an

Written for: Administrator

Sooner or later a machine needs one setting CoreCP does not model: an innodb_buffer_pool_size that fits this server's memory, an nginx timeout for a customer's slow importer, a Redis maxmemory policy. A drop-in is where that setting goes — in the service's own include directory, written from /etc/corecp like everything else, and applied with a net under it.

In the panel: Servers → the server → Quick actions → Config drop-ins, or directly at /nodes/<server>/dropins.

Which services take one

root@web1:~# corectl dropin list
Config drop-ins:
  apache    —          /etc/apache2/conf-available/zz-corecp-custom.conf  config test
  mariadb   6 lines    /etc/mysql/conf.d/zz-corecp-custom.cnf             health check + rollback
  nginx     —          /etc/nginx/conf.d/zz-corecp-custom.conf            config test
  php       —          /opt/corecp/php/84/etc/conf.d/zz-corecp-custom.ini config test
  redis     —          /etc/redis/zz-corecp-custom.conf                   health check + rollback

A drop-in may not set: bind-address, datadir, identity, include, logpath, socket …
Accounts have no drop-ins: PHP goes through the policy, the database through its per-user limits.

The file is always called zz-corecp-custom.*. That is not decoration: an include directory is read in sorted order, and the last file wins — so your setting beats CoreCP's own corecp.cnf and anything an addon dropped beside it.

The PHP drop-in renders once per installed series, into every interpreter's own ini scan directory. A setting that applied to PHP 8.4 and not to 8.3 would be a support case nobody could reproduce.

Writing one

The text never travels on the command line — a configuration block is multi-line, and /proc/<pid>/cmdline is world-readable. So it comes from a file or from standard input:

root@web1:~# cat > /tmp/tuning.cnf <<'EOF'
[mysqld]
innodb_buffer_pool_size = 2G
max_connections = 300
EOF

root@web1:~# corectl dropin set mariadb --file /tmp/tuning.cnf --note "8 GB machine, 2026-08"
drop-in mariadb applied (/etc/mysql/conf.d/zz-corecp-custom.cnf)

--note becomes a comment line at the top, so the reason stays next to the setting instead of in a ticket.

What happens when you apply

  1. The forbidden list. Every line is read before anything is written.
  2. Placed atomically. A temporary file, then a rename — no service ever reads a half-written file.
  3. The service's own config test, where it has one: nginx -t, apachectl configtest, and for PHP the ini parser itself, pointed at the candidate. A failure puts the previous file back and the running service never saw the new one.
  4. Applied. nginx and Apache reload; MariaDB, Redis and the FPM pools restart, because they read their configuration once.
  5. The health check. MariaDB has to answer, Redis has to say PONG, the web server has to be running.
  6. The automatic rollback, when step 5 fails: the previous file goes back, the service is restarted again, and the change is reported as refused. The text you sent is not saved — a file in /etc/corecp that the machine is not running would be exactly the second source of truth this engine avoids.

MariaDB and Redis have no config test at all — Redis has never had one, and mysqld --validate-config only arrived in MariaDB 13.1 while Ubuntu 26.04 ships 11.8 (we measured it: on 11.8 the flag is silently ignored). For those two, steps 5 and 6 are the whole net, which is why they are there for every service and not only for the ones without a validator: a configuration that tests clean and a daemon that then refuses to start is not hypothetical.

root@web1:~# corectl dropin set mariadb --file /tmp/too-big.cnf
[corecp] the health check for mariadb failed after the drop-in was placed — rolling back
[corecp] rolled back: mariadb is running on its previous configuration
error: the drop-in was placed and mariadb did not stay healthy (…), so it was rolled
back automatically. mariadb is running again on the previous configuration; the
refused text is not saved

What a drop-in may never set

corectl refuses these by name, and says what would break:

ClassWhy
socketCoreCP renders the sockets services reach each other on. Moving one leaves the other half pointing at a path nothing serves.
identityThe user and group a service runs as decide which files it can read. CoreCP sets them per account and per pool.
bind-addressAddresses come from the IP manager and the firewall. A bind here is invisible to both, and the usual result is a database reachable from the internet.
datadirWhere the data lives is what the backups, the restores and the disk accounting read. A server that moved its data directory keeps running and gets backed up empty.
includeA further include takes the configuration somewhere this machine's state does not describe.
logpathThe statistics, the log viewer and the log rotation read the paths CoreCP renders. A log that moved is a log nobody rotates.
root@web1:~# corectl dropin set mariadb --file /tmp/bad.cnf
error: this drop-in sets 2 thing(s) a drop-in may not set:
  line 2: datadir = /srv/elsewhere — where the data lives is what the backups, …
  line 3: bind-address = 0.0.0.0 — the addresses a service answers on come from …

This is not a security boundary — an administrator with a root shell can edit any file on the machine. It is the boundary between a setting CoreCP does not model and a second, invisible source of truth for one it does. The same check runs at every reconcile, so a file edited by hand on the machine is reported and not rendered rather than silently applied.

Going back

The five previous versions stay on the machine, under /etc/corecp/rendered/dropins/<service>/:

root@web1:~# corectl dropin history mariadb
Kept versions of the mariadb drop-in (newest first):
  1   4 lines    112 bytes  [mysqld]
  2   6 lines    168 bytes  [mysqld]

Restore one with: corectl dropin rollback mariadb --version <n>

root@web1:~# corectl dropin rollback mariadb --version 1
drop-in mariadb applied (/etc/mysql/conf.d/zz-corecp-custom.cnf)

Removing the drop-in altogether puts the service back on CoreCP's own configuration, and keeps the text as a version:

root@web1:~# corectl dropin remove redis
the redis drop-in is gone; redis-server runs on CoreCP's own configuration again

Accounts have none of this

There is no per-account drop-in and there will not be one. A customer changes PHP through the PHP policy — an allow-list with ceilings, where every value is checked before it is rendered — and their database through the per-user limits (MAX_USER_CONNECTIONS and friends). Raw configuration text from an account would be a directive nobody validated, in a file every other account's service reads.

Drop-ins are server-admin and up, in the panel and on the API alike. A reseller who reaches the routes gets 403 from the router, not from a check somebody remembered to write.