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
- The forbidden list. Every line is read before anything is written.
- Placed atomically. A temporary file, then a rename — no service ever reads a half-written file.
- 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. - Applied. nginx and Apache reload; MariaDB, Redis and the FPM pools restart, because they read their configuration once.
- The health check. MariaDB has to answer, Redis has to say
PONG, the web server has to be running. - 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/corecpthat 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 savedWhat a drop-in may never set
corectl refuses these by name, and says what would break:
| Class | Why |
|---|---|
socket | CoreCP renders the sockets services reach each other on. Moving one leaves the other half pointing at a path nothing serves. |
identity | The user and group a service runs as decide which files it can read. CoreCP sets them per account and per pool. |
bind-address | Addresses 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. |
datadir | Where 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. |
include | A further include takes the configuration somewhere this machine's state does not describe. |
logpath | The 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 againAccounts 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.