MySQL / MariaDB¶
Server-level MySQL/MariaDB management: users, databases, replication, tuner, remote access.
All endpoints below are mounted under /api. Authentication: Authorization: Bearer <token> unless noted as public.
Endpoint count: 36
Endpoints¶
| Method | Path | Handler | Guards |
|---|---|---|---|
POST |
/api/mysql/install |
installMySQL |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/monitor-stats |
getMySQLMonitorStats |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/phpmyadmin |
getPHPMyAdminStatus |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/phpmyadmin/install |
installPHPMyAdmin |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/phpmyadmin/login |
pmaAutoLogin |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/phpmyadmin/update |
updatePHPMyAdmin |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/processes |
getMySQLProcesses |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/processes/:id/kill |
killMySQLProcess |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/processes/kill-all |
killAllMySQLProcesses |
RequirePermission(db, "administrative_operations") |
DELETE |
/api/mysql/replication |
removeReplication |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/replication |
getReplicationStatus |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/replication/accept |
acceptReplication |
- |
POST |
/api/mysql/replication/connect |
connectReplication |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/replication/databases |
listDatabasesForReplication |
- |
POST |
/api/mysql/replication/db-sizes |
getDatabaseSizes |
- |
POST |
/api/mysql/replication/dump |
dumpDatabases |
- |
POST |
/api/mysql/replication/dump-db |
dumpSingleDatabase |
- |
POST |
/api/mysql/replication/dump-users |
dumpUsers |
- |
POST |
/api/mysql/replication/init |
initReplication |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/replication/position |
getMasterPosition |
- |
POST |
/api/mysql/replication/setup-master |
setupMasterEndpoint |
- |
GET |
/api/mysql/replication/slaves |
getReplicationSlaves |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/replication/slaves |
addReplicationSlave |
RequirePermission(db, "administrative_operations") |
DELETE |
/api/mysql/replication/slaves/:id |
removeReplicationSlave |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/replication/start |
startReplication |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/replication/start-slave |
startSlaveReplication |
- |
POST |
/api/mysql/replication/sync |
initialSyncReplication |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/replication/sync-stream |
syncStreamSSE |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/restart |
mySQLRestart |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/slow-log |
getMySQLSlowLog |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/status |
getMySQLStatus |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/stop |
mySQLStop |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/sync-users-ha |
syncUsersForHA |
RequirePermission(db, "administrative_operations") |
GET |
/api/mysql/tuner |
getMySQLTuner |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/tuner/apply |
applyMySQLTuning |
RequirePermission(db, "administrative_operations") |
POST |
/api/mysql/tuner/install |
installMySQLTuner |
RequirePermission(db, "administrative_operations") |
Source¶
Handlers for this section live in api/routes/handlers_*.go in the StarkOne source. Each handler binds its request body with gin.ShouldBindJSON(&req) and responds with the standard envelope:
On error:
Reference¶
POST /api/mysql/install¶
Installs MariaDB (default) or MySQL via the system package manager, enables and starts the service, then generates a random root password and writes a credentials file.
Guards: RequirePermission(db, "administrative_operations")
Request body
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | no | "mariadb" (default) or "mysql". On bind error, defaults to "mariadb". |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
500 |
install_failed |
Package install command failed; message contains the combined command output. |
Side effects
- Detects OS via
/etc/redhat-release; runsdnf install(RHEL) orapt-get update && apt-get install(Debian) for the server/client packages, thensystemctl enable --now. - Runs a
CREATE USER/ALTER USER/GRANT ALL/FLUSH PRIVILEGESSQL block setting a random 24-char root password. - Creates
/etc/starkone(0755) and writes/etc/starkone/.mysql.conf(0600) with[client]credentials.
Example
curl -X POST https://panel.example.com:2087/api/mysql/install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"type": "mariadb"}'
GET /api/mysql/monitor-stats¶
Returns live MySQL performance metrics (query rate, connections, buffer hit rate, lock ratio, InnoDB stats, per-database sizes) gathered from information_schema.GLOBAL_STATUS and related queries.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": {
"stats": {
"queries_per_sec": 12,
"connections": 4,
"threads_running": 1,
"slow_queries": 0,
"aborted_connects": 0,
"buffer_hit_rate": 99
},
"locks": {
"table_locks_immediate": 1000,
"table_locks_waited": 2,
"lock_ratio": 0
},
"innodb": {
"buffer_pool_size": "128 MB",
"buffer_pool_used_pct": 60,
"row_reads_per_sec": 50,
"row_writes_per_sec": 5,
"deadlocks": 0
},
"databases": [
{ "name": "appdb", "size": "12 MB", "size_bytes": 12582912 }
]
}
}
Side effects
- Runs read-only
mysqlqueries againstinformation_schemausing the stored root password or/etc/starkone/.mysql.conf.
Example
curl -X GET https://panel.example.com:2087/api/mysql/monitor-stats \
-H "Authorization: Bearer $TOKEN"
GET /api/mysql/phpmyadmin¶
Reports whether phpMyAdmin is installed, its version, install path, and the randomized access URL (generating an alias on first call if none exists).
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": {
"installed": true,
"version": "5.2.1",
"path": "/usr/share/phpmyadmin",
"url": "https://panel.example.com/abcdef12345678/pma/"
}
}
Side effects
- Reads
VERSION/READMEunder/usr/share/phpmyadmin. - If installed but no alias file exists, generates a 14-char alias, writes
/usr/share/phpmyadmin/.pma_alias(0600), and rewrites the phpMyAdmin nginx config.
Example
POST /api/mysql/phpmyadmin/install¶
Downloads and extracts the latest phpMyAdmin tarball, writes its config, configures the webserver and sign-on session handler, and installs a monthly auto-update cron.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
500 |
download_error |
curl download of the phpMyAdmin tarball failed. |
500 |
extract_error |
tar extraction of the tarball failed. |
Side effects
- Downloads to
/tmp/phpmyadmin.tar.gzviacurl, removes/recreates/usr/share/phpmyadmin, extracts withtar. - Writes
config.inc.phpwith a generated 32-char blowfish secret; createstmp/dir; removes the tarball. - Configures nginx/apache (random alias), sets up the sign-on handler, disables
PrivateTmpfor PHP-FPM (writes systemd overrides,daemon-reload, restarts PHP-FPM). - Writes
/etc/cron.monthly/phpmyadmin-update(0755) callingstarkone-cli update_phpmyadmin.
Example
curl -X POST https://panel.example.com:2087/api/mysql/phpmyadmin/install \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/phpmyadmin/login¶
Generates a one-time sign-on token for a stored database user and returns a phpMyAdmin auto-login URL.
Guards: RequirePermission(db, "administrative_operations")
Request body
| Field | Type | Required | Description |
|---|---|---|---|
db_user |
string | yes | The database username to auto-login as. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
400 |
not_installed |
phpMyAdmin is not installed. |
400 |
no_password |
No stored password for the user; reset it first. |
500 |
no_alias |
phpMyAdmin alias not configured. |
500 |
token_error |
Failed to write the one-time login token file. |
Side effects
- Looks up the user's stored password from the panel DB.
- Writes a one-time token JSON file under
/tmp/pma_tokens/(consumed and deleted bysignon.phpon use).
Example
curl -X POST https://panel.example.com:2087/api/mysql/phpmyadmin/login \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"db_user": "user1"}'
POST /api/mysql/phpmyadmin/update¶
Downloads the latest phpMyAdmin, backs up and restores the existing config.inc.php, and reports the old and new versions.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
500 |
download_error |
curl download of the tarball failed. |
500 |
extract_error |
tar extraction failed. |
Side effects
- Downloads to
/tmp/phpmyadmin.tar.gz, removes/recreates/usr/share/phpmyadmin, extracts withtar. - Backs up and restores
config.inc.php, recreatessignon.phpandtmp/, removes the tarball.
Example
curl -X POST https://panel.example.com:2087/api/mysql/phpmyadmin/update \
-H "Authorization: Bearer $TOKEN"
GET /api/mysql/processes¶
Returns the current MySQL process list from information_schema.processlist, ordered by time descending.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": {
"processes": [
{
"id": 42,
"user": "user1",
"host": "localhost",
"db": "appdb",
"command": "Query",
"time": 3,
"state": "Sending data",
"info": "SELECT ..."
}
]
}
}
Errors
| Status | Code | Meaning |
|---|---|---|
500 |
mysql_error |
The mysql query for the process list failed. |
Side effects
- Read-only
mysqlquery using the stored root password or/etc/starkone/.mysql.conf.
Example
POST /api/mysql/processes/:id/kill¶
Kills a single MySQL connection by issuing KILL <id>.
Guards: RequirePermission(db, "administrative_operations")
Path parameters
| Name | Type | Description |
|---|---|---|
id |
string | The MySQL process/connection id to kill (passed verbatim to KILL). |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
500 |
kill_failed |
The KILL command failed. |
Side effects
- Executes
mysql -e "KILL <id>"against the running server.
Example
curl -X POST https://panel.example.com:2087/api/mysql/processes/42/kill \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/processes/kill-all¶
Kills all active (non-Sleep, non-system) MySQL connections and returns the count killed.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Side effects
- Selects process ids where
command != 'Sleep'and the user is notsystem user/event_scheduler, then issuesKILL <id>for each.
Example
curl -X POST https://panel.example.com:2087/api/mysql/processes/kill-all \
-H "Authorization: Bearer $TOKEN"
DELETE /api/mysql/replication¶
Tears down replication: stops the slave thread, resets slave state, and deletes the local replication config row.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Side effects
- Runs
STOP SLAVEandRESET SLAVE ALLviamysql. - Deletes the
mysql_replicationrow (id = 1) from the panel DB.
Example
curl -X DELETE https://panel.example.com:2087/api/mysql/replication \
-H "Authorization: Bearer $TOKEN"
GET /api/mysql/replication¶
Returns the configured replication mode/role plus live status, including slave details (IO/SQL running, lag, relay log) or master details (binlog position, connected slaves).
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": {
"enabled": true,
"mode": "master-slave",
"role": "slave",
"remote_host": "https://203.0.113.10:2087",
"remote_status": "connected",
"lag_seconds": 0,
"token": "...",
"ha_proxy_ip": "",
"replication_status": "syncing",
"slave_details": {
"io_running": true,
"sql_running": true,
"master_host": "203.0.113.10",
"io_state": "Waiting for master to send event",
"relay_log_file": "mysql-relay.000001",
"relay_log_pos": "456",
"exec_master_log_pos": "456"
}
}
}
When not configured, data is returned with enabled: false and empty mode/role fields.
Side effects
- Read-only: queries the panel DB row and runs
mysqlstatus queries (SHOW SLAVE STATUS,SHOW MASTER STATUS,SHOW SLAVE HOSTS); for masters it may probe the remote host over HTTPS. No writes.
Example
curl -X GET https://panel.example.com:2087/api/mysql/replication \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/replication/accept¶
Server-to-server endpoint (token-authenticated): the remote peer calls this to register itself, verifying the waiting token and saving the peer's connection info; returns this server's MySQL version.
Request body
{
"token": "string (required)",
"remote_host": "string (required)",
"remote_token": "string (required)",
"mode": "string (required)",
"role": "string (required)"
}
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's waiting remote_token. |
remote_host |
string | yes | The calling peer's base URL. |
remote_token |
string | yes | The peer's token, saved as peer_token. |
mode |
string | yes | Replication mode (master-slave / master-master). |
role |
string | yes | Role assigned to this server. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match the waiting token. |
Side effects
- Updates the
mysql_replicationrow withremote_host,mode,role, andpeer_token.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/accept \
-H "Content-Type: application/json" \
-d '{"token":"...","remote_host":"https://203.0.113.10:2087","remote_token":"...","mode":"master-slave","role":"slave"}'
POST /api/mysql/replication/connect¶
Initiates a connection to a remote peer: calls the peer's accept endpoint, performs a MySQL version compatibility check, records the slave, and triggers the slave to start replication.
Guards: RequirePermission(db, "administrative_operations")
Request body
{
"remote_host": "string (required)",
"remote_token": "string (required)",
"mode": "string (optional)",
"force_connect": "boolean (optional)"
}
| Field | Type | Required | Description |
|---|---|---|---|
remote_host |
string | yes | Base URL of the remote peer. |
remote_token |
string | yes | Token issued by the remote peer (its waiting token). |
mode |
string | no | master-slave (default) or master-master. |
force_connect |
boolean | no | Skip the MySQL version-mismatch check. |
Response - 200 OK
{
"success": true,
"local_version": "10.11.6-MariaDB",
"remote_version": "10.11.6-MariaDB",
"slave_started": true,
"message": "Slave connected"
}
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
400 |
remote_error |
The remote accept endpoint returned an error. |
409 |
version_mismatch |
Local/remote MySQL major.minor versions differ; use force_connect. |
502 |
connection_failed |
Could not reach the remote server. |
Side effects
- Auto-initializes local
mysql_replicationconfig if missing; updatesmode. - Calls the remote
/api/mysql/replication/acceptand/api/mysql/replication/start-slaveendpoints over HTTPS. - Inserts/updates a row in
mysql_replication_slaves.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/connect \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"remote_host":"https://203.0.113.10:2087","remote_token":"...","mode":"master-slave"}'
POST /api/mysql/replication/databases¶
Server-to-server endpoint (token-authenticated): returns the list of user databases (excluding system schemas) for the slave to sync.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
Side effects
- Read-only
mysqlquery againstinformation_schema.schemata.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/databases \
-H "Content-Type: application/json" \
-d '{"token":"..."}'
POST /api/mysql/replication/db-sizes¶
Server-to-server endpoint (token-authenticated): returns a map of user database name to human-readable size.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
Side effects
- Read-only
mysqlaggregate query againstinformation_schema.tables.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/db-sizes \
-H "Content-Type: application/json" \
-d '{"token":"..."}'
POST /api/mysql/replication/dump¶
Server-to-server endpoint (token-authenticated): streams a full mysqldump --all-databases --master-data=2 as an octet-stream for the slave's initial sync.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
Response - 200 OK
Streamed application/octet-stream body containing the SQL dump (not JSON).
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
500 |
dump_failed |
mysqldump could not be started. |
Side effects
- Spawns
mysqldump(with safe args) and streams its stdout to the response.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/dump \
-H "Content-Type: application/json" \
-d '{"token":"..."}' --output dump.sql
POST /api/mysql/replication/dump-db¶
Server-to-server endpoint (token-authenticated): runs mysqldump for a single named database and returns it as an octet-stream.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
database |
string | yes | Name of the database to dump. |
Response - 200 OK
Returns application/octet-stream with the database's SQL dump (not JSON).
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
500 |
dump_failed |
mysqldump failed. |
Side effects
- Runs
mysqldump <database>with safe args and returns the output.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/dump-db \
-H "Content-Type: application/json" \
-d '{"token":"...","database":"appdb"}' --output appdb.sql
POST /api/mysql/replication/dump-users¶
Server-to-server endpoint (token-authenticated): returns CREATE USER ... IDENTIFIED BY PASSWORD and GRANT statements for all non-system local users as an octet-stream.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
Response - 200 OK
Returns application/octet-stream containing SQL CREATE USER/GRANT statements (not JSON).
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
Side effects
- Read-only
mysqlqueries againstmysql.userandSHOW GRANTS; excludesroot,mysql,mariadb.sys,repl_user, and empty users.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/dump-users \
-H "Content-Type: application/json" \
-d '{"token":"..."}' --output users.sql
POST /api/mysql/replication/init¶
Initializes local replication config, generating a connection token to share with the remote peer.
Guards: RequirePermission(db, "administrative_operations")
Request body
| Field | Type | Required | Description |
|---|---|---|---|
mode |
string | yes | master-slave or master-master. |
role |
string | yes | master or slave (for master-slave). |
Response - 200 OK
{
"success": true,
"connection_token": "...",
"message": "Replication initialized. Share this token with the remote server."
}
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Body failed to bind, or mode is not master-slave/master-master. |
Side effects
- Creates the
mysql_replicationtable if missing; deletes any existingid = 1row and inserts the new config with a generated 32-char token.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/init \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode":"master-slave","role":"master"}'
POST /api/mysql/replication/position¶
Server-to-server endpoint (token-authenticated): returns the current binlog file/position and GTID position from SHOW MASTER STATUS.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
500 |
no_binlog |
Binary log not enabled (no master status). |
Side effects
- Read-only
mysqlqueries (SHOW MASTER STATUS,SELECT @@gtid_binlog_pos).
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/position \
-H "Content-Type: application/json" \
-d '{"token":"..."}'
POST /api/mysql/replication/setup-master¶
Server-to-server endpoint (token-authenticated): called by a slave to have this server configure itself as a master for the given slave IP.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
slave_ip |
string | yes | IP of the slave to authorize. |
Response - 200 OK
The data payload mirrors the result returned by the internal setupMasterReplication helper.
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
500 |
setup_failed |
Master setup failed (e.g. binary logging could not be enabled). |
Side effects
- May edit the MySQL config file to enable
log_bin/server-id/GTID andbind-address = 0.0.0.0, then restart MariaDB/MySQL. - Adds the slave IP to the CSF firewall (
csf -a) and creates therepl_userreplication user.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/setup-master \
-H "Content-Type: application/json" \
-d '{"token":"...","slave_ip":"203.0.113.20"}'
GET /api/mysql/replication/slaves¶
Lists configured replication slaves with their live connection status (cross-checked against SHOW SLAVE HOSTS and the process list).
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": [
{
"id": 1,
"remote_host": "https://203.0.113.20:2087",
"status": "connected",
"created_at": "2026-06-17 10:00:00"
}
]
}
Side effects
- Read-only: queries
mysql_replication_slavesplus twomysqlqueries (2s timeout) to determine live connection status. No writes.
Example
curl -X GET https://panel.example.com:2087/api/mysql/replication/slaves \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/replication/slaves¶
Adds a new slave (in pending state) to this master's slave list.
Guards: RequirePermission(db, "administrative_operations")
Request body
| Field | Type | Required | Description |
|---|---|---|---|
remote_host |
string | yes | Base URL of the slave server. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
400 |
not_master |
This server is not configured as a master. |
500 |
db_error |
Failed to insert the slave row. |
Side effects
- Inserts a row into
mysql_replication_slaveswith statuspending.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/slaves \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"remote_host":"https://203.0.113.20:2087"}'
DELETE /api/mysql/replication/slaves/:id¶
Removes a slave from this master's slave list.
Guards: RequirePermission(db, "administrative_operations")
Path parameters
| Name | Type | Description |
|---|---|---|
id |
string | The mysql_replication_slaves row id to delete. |
Response - 200 OK
Side effects
- Deletes the matching row from
mysql_replication_slaves.
Example
curl -X DELETE https://panel.example.com:2087/api/mysql/replication/slaves/1 \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/replication/start¶
Starts replication based on the stored config: configures this server as master (binlog + repl user) or as slave (points at the master) depending on its role.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
not_configured |
No replication config row exists. |
400 |
not_connected |
Config has no remote_host. |
500 |
setup_failed |
Master or slave setup failed. |
Side effects
- For master role: may edit MySQL config (binlog/GTID/bind-address), restart the service, add the remote IP to CSF, and create
repl_user. - For slave role: configures and starts the slave pointing at the master.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/start \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/replication/start-slave¶
Server-to-server endpoint (token-authenticated): called by the master to have this server (a slave) begin replicating from the given master.
Request body
{
"token": "string (required)",
"master_host": "string (optional)",
"master_ip": "string (optional)",
"master_token": "string (optional)"
}
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | Must match this server's remote_token. |
master_host |
string | no | Master base URL; used to derive the IP if master_ip is empty. |
master_ip |
string | no | Master IP address. |
master_token |
string | no | Token to use when calling back to the master; saved as peer_token. |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Request body failed to bind. |
401 |
invalid_token |
Token does not match. |
400 |
not_slave |
This server is not configured as a slave. |
500 |
setup_failed |
Slave setup failed. |
Side effects
- Updates
mysql_replicationwithremote_hostandpeer_token, then configures and starts the MySQL slave thread.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/start-slave \
-H "Content-Type: application/json" \
-d '{"token":"...","master_host":"https://203.0.113.10:2087","master_ip":"203.0.113.10","master_token":"..."}'
POST /api/mysql/replication/sync¶
Performs an initial sync on a slave: pulls a full mysqldump from the master, restores it locally, sets the binlog position, and restarts the slave.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
not_slave |
This server is not configured as a slave. |
500 |
restore_failed |
Restoring the dump into local MySQL failed. |
502 |
connection_failed |
Could not connect to the master. |
502 |
dump_failed |
Master returned an error for the dump request. |
Side effects
- Runs
STOP SLAVE, pipes the master's/api/mysql/replication/dumpoutput into localmysql, issuesCHANGE MASTER TOwith the new position, thenSTART SLAVE.
Example
curl -X POST https://panel.example.com:2087/api/mysql/replication/sync \
-H "Authorization: Bearer $TOKEN"
GET /api/mysql/replication/sync-stream¶
Streams real-time initial-sync progress (per-database) to the slave via Server-Sent Events, syncing each database and the MySQL users, then setting the GTID position.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Content-Type: text/event-stream. Each event's data is a JSON object:
type is one of progress, success, error, or done.
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
not_slave |
This server is not configured as a slave (sent as JSON before the stream starts). |
In-stream failures are emitted as {"type":"error","message":"..."} events rather than HTTP error codes.
Side effects
- For each master database:
DROP DATABASE/CREATE DATABASElocally, pull/api/mysql/replication/dump-db, restore viamysql. - Pulls
/api/mysql/replication/dump-usersand applies it; setsgtid_slave_pos, runsCHANGE MASTER TO MASTER_USE_GTID = slave_pos, andSTART SLAVE.
Example
curl -N -X GET https://panel.example.com:2087/api/mysql/replication/sync-stream \
-H "Authorization: Bearer $TOKEN"
POST /api/mysql/restart¶
Restarts the running MySQL/MariaDB service.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
not_found |
No active mysql/mysqld/mariadb service found. |
500 |
restart_error |
systemctl restart failed. |
Side effects
- Finds the active service among
mysql,mysqld,mariadband runssystemctl restart.
Example
GET /api/mysql/slow-log¶
Parses the MySQL slow query log and returns up to the 20 most recent slow queries (newest first).
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": {
"queries": [
{
"time": "2026-06-17T10:00:00",
"query_time": "2.5",
"user_host": "user1[user1] @ localhost []",
"query": "SELECT * FROM big_table"
}
]
}
}
If no slow log file is found, returns { "data": { "queries": [], "message": "Slow query log not found" } }.
Side effects
- Read-only: locates the slow log among known paths and runs
tail -500on it.
Example
GET /api/mysql/status¶
Returns MySQL/MariaDB install and runtime status: version, uptime, connections, query counts, buffer pool size, and process memory.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"data": {
"installed": true,
"running": true,
"version": "10.11.6 (MariaDB)",
"uptime": "1d 2h 3m",
"connections": 4,
"max_connections": 151,
"queries": 0,
"slow_queries": 0,
"threads_running": 1,
"buffer_pool_mb": 128,
"process_mb": 210
}
}
Side effects
- Read-only:
mysql -V,systemctl is-active,SHOW GLOBAL STATUS/VARIABLES, andsystemctl show ... MemoryCurrent. No writes.
Example
POST /api/mysql/stop¶
Stops the running MySQL/MariaDB service.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
not_found |
No active mysql/mysqld/mariadb service found. |
500 |
stop_error |
systemctl stop failed. |
Side effects
- Finds the active service among
mysql,mysqld,mariadband runssystemctl stop.
Example
POST /api/mysql/sync-users-ha¶
Recreates local MySQL users (using their stored password hashes) so they can connect from a ProxySQL/HA proxy IP, and syncs them into the ProxySQL admin interface.
Guards: RequirePermission(db, "administrative_operations")
Request body
| Field | Type | Required | Description |
|---|---|---|---|
proxy_ip |
string | yes | IP of the ProxySQL/HA server to authorize and sync to. |
admin_pass |
string | no | ProxySQL admin password (defaults to admin). |
Response - 200 OK
{
"success": true,
"synced": 5,
"proxysql_synced": 5,
"errors": [],
"message": "Synced 5 users for 203.0.113.30 (ProxySQL: 5)"
}
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request |
Body failed to bind, or proxy_ip is empty. |
500 |
query_error |
Failed to query the MySQL user list. |
Side effects
- For each app user:
CREATE USER ... IDENTIFIED BY PASSWORD <hash>for'user'@'<proxy_ip>'andGRANT ALLon its database; creates amonitor@<proxy_ip>user; runsFLUSH PRIVILEGES. - Saves
proxy_iptomysql_replication.ha_proxy_ip. - If reachable, connects to ProxySQL admin (
-P6032 -uradmin) and inserts users intomysql_users, thenLOAD/SAVE MYSQL USERS.
Example
curl -X POST https://panel.example.com:2087/api/mysql/sync-users-ha \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"proxy_ip":"203.0.113.30","admin_pass":"secret"}'
GET /api/mysql/tuner¶
Runs MySQLTuner (if installed) and returns parsed recommendations, suggested variable adjustments, a severity summary, and the detected config file path.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
{
"installed": true,
"results": {
"raw": "...full text report...",
"summary": { "ok": 0, "warnings": 3, "critical": 1, "info": 5 },
"recommendations": [
{ "type": "warning", "message": "innodb_buffer_pool_size (>= 5.0G)", "variable": "innodb_buffer_pool_size", "suggested_value": "5.0" }
],
"variables": [
{ "name": "innodb_buffer_pool_size", "current": "", "suggested": "5.0" }
],
"config_file": "/etc/mysql/mariadb.conf.d/50-server.cnf"
}
}
If MySQLTuner is not installed, returns { "installed": false }. Note: this endpoint does not use the { "data": ... } envelope.
Side effects
- Read-only: runs
perl /usr/local/bin/mysqltuner.pl(with and without--json).
Example
POST /api/mysql/tuner/apply¶
Writes a tuning variable into the MySQL config file (under [mysqld]), normalizing the value, and optionally restarts the service.
Guards: RequirePermission(db, "administrative_operations")
Request body
| Field | Type | Required | Description |
|---|---|---|---|
variable |
string | yes | Variable name to set (dashes are converted to underscores). |
value |
string | yes | Value to apply; cleaned of suggestion text and decimal size suffixes. |
restart |
boolean | no | Whether to restart MySQL after writing (defaults to true when omitted). |
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
400 |
(no code) | Request body failed to bind; message contains the bind error. |
500 |
(no code) | Config file not found, or reading/writing the config failed. |
Side effects
- Edits the MySQL config file in place (writes 0644), inserting or updating the variable under
[mysqld]. - If restart is enabled, runs
systemctl restarton the active MySQL/MariaDB service.
Example
curl -X POST https://panel.example.com:2087/api/mysql/tuner/apply \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"variable":"innodb_buffer_pool_size","value":"512M","restart":true}'
POST /api/mysql/tuner/install¶
Downloads the MySQLTuner Perl script and installs the Perl JSON module.
Guards: RequirePermission(db, "administrative_operations")
Response - 200 OK
Errors
| Status | Code | Meaning |
|---|---|---|
500 |
(no code) | curl download of mysqltuner.pl failed; message contains the output. |
Side effects
- Downloads
mysqltuner.plto/usr/local/bin/mysqltuner.pl(chmod 0755) viacurl. - Installs the Perl JSON module via
apt-get(libjson-perl),dnf, oryum(perl-JSON).
Example