Skip to content

ProxySQL

ProxySQL load balancing in front of MySQL servers: backends, query rules, users, stats.

All endpoints below are mounted under /api. Authentication: Authorization: Bearer <token> unless noted as public.

Endpoint count: 22

Endpoints

Method Path Handler Guards
POST /api/proxysql/admin-password changeProxySQLAdminPassword RequirePermission(db, "administrative_operations")
DELETE /api/proxysql/backends removeProxySQLBackend RequirePermission(db, "administrative_operations")
GET /api/proxysql/backends listProxySQLBackends RequirePermission(db, "administrative_operations")
POST /api/proxysql/backends addProxySQLBackend RequirePermission(db, "administrative_operations")
PUT /api/proxysql/backends updateProxySQLBackend RequirePermission(db, "administrative_operations")
POST /api/proxysql/backends/max-connections setProxySQLMaxConnections RequirePermission(db, "administrative_operations")
POST /api/proxysql/backends/reset resetProxySQLBackend RequirePermission(db, "administrative_operations")
POST /api/proxysql/install installProxySQL RequirePermission(db, "administrative_operations")
POST /api/proxysql/keepalived/disable disableKeepalived RequirePermission(db, "administrative_operations")
POST /api/proxysql/keepalived/setup setupKeepalived RequirePermission(db, "administrative_operations")
GET /api/proxysql/keepalived/status getKeepalivedStatus RequirePermission(db, "administrative_operations")
POST /api/proxysql/monitor-user setProxySQLMonitorUser RequirePermission(db, "administrative_operations")
GET /api/proxysql/query-rules getProxySQLQueryRules RequirePermission(db, "administrative_operations")
POST /api/proxysql/read-write-split setupProxySQLReadWriteSplit RequirePermission(db, "administrative_operations")
POST /api/proxysql/remove removeProxySQL RequirePermission(db, "administrative_operations")
POST /api/proxysql/reset-stats resetProxySQLStats RequirePermission(db, "administrative_operations")
POST /api/proxysql/restart restartProxySQL RequirePermission(db, "administrative_operations")
POST /api/proxysql/start startProxySQL RequirePermission(db, "administrative_operations")
GET /api/proxysql/stats getProxySQLStats RequirePermission(db, "administrative_operations")
GET /api/proxysql/status getProxySQLStatus RequirePermission(db, "administrative_operations")
POST /api/proxysql/stop stopProxySQL RequirePermission(db, "administrative_operations")
POST /api/proxysql/users addProxySQLUser 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:

{ "data": { ... } }

On error:

{ "error": { "code": "string", "message": "string" } }

Reference

POST /api/proxysql/admin-password

Changes the ProxySQL remote-admin (radmin) password used by the Master panel to reach this node's admin interface.

Guards: RequirePermission(db, "administrative_operations")

Request body

{ "password": "string (required)" }
Field Type Required Description
password string yes New password for the radmin remote-admin account.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing password).
500 change_failed Failed to apply the new credentials on the ProxySQL admin interface.

Side effects

  • Runs SET admin-admin_credentials='admin:admin;radmin:<password>' on the ProxySQL admin interface (port 6032), re-enables remote admin on 0.0.0.0:6032, then loads admin variables to runtime and saves to disk.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/admin-password \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"password": "s3cret"}'

DELETE /api/proxysql/backends

Removes a MySQL backend server from ProxySQL's mysql_servers table.

Guards: RequirePermission(db, "administrative_operations")

Request body

{ "hostname": "string (required)", "port": "int (optional, default 3306)" }
Field Type Required Description
hostname string yes Hostname/IP of the backend to remove.
port int no Backend port; defaults to 3306 when 0/omitted.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing hostname).
500 remove_failed Removal query against the admin interface failed.

Side effects

  • Deletes the matching row from mysql_servers, then loads MySQL servers to runtime and saves to disk.

Example

curl -X DELETE https://panel.example.com:2087/api/proxysql/backends \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"hostname": "203.0.113.10", "port": 3306}'

GET /api/proxysql/backends

Lists all configured MySQL backend servers, merging real-time pool status from stats_mysql_connection_pool.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{
  "data": [
    {
      "hostgroup_id": 0,
      "hostname": "203.0.113.10",
      "port": 3306,
      "status": "ONLINE",
      "weight": 1,
      "max_connections": 100,
      "comment": "primary"
    }
  ]
}

Errors

Status Code Meaning
500 list_error Query against the ProxySQL admin interface failed.

Example

curl -X GET https://panel.example.com:2087/api/proxysql/backends \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/backends

Adds a MySQL backend server to ProxySQL (and auto-provisions a monitor user on that backend).

Guards: RequirePermission(db, "administrative_operations")

Request body

{
  "hostgroup_id": "int (optional, default 0)",
  "hostname": "string (required)",
  "port": "int (optional, default 3306)",
  "weight": "int (optional)",
  "max_connections": "int (optional, default 100)",
  "comment": "string (optional)"
}
Field Type Required Description
hostgroup_id int no Target hostgroup (e.g. 0 = writers, 1 = readers).
hostname string yes Backend hostname/IP.
port int no Backend port; defaults to 3306 when 0/omitted.
weight int no Load-balancing weight.
max_connections int no Max connections to this backend; defaults to 100 when 0/omitted.
comment string no Free-text comment stored on the row.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing hostname).
500 add_failed Insert into mysql_servers failed.

Side effects

  • Inserts a row into mysql_servers, loads MySQL servers to runtime, saves to disk, and attempts to create a monitor user on the backend MySQL server.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/backends \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"hostgroup_id": 0, "hostname": "203.0.113.10", "port": 3306, "weight": 1}'

PUT /api/proxysql/backends

Updates an existing MySQL backend's hostgroup, weight, max connections, and comment.

Guards: RequirePermission(db, "administrative_operations")

Request body

{
  "hostname": "string (required)",
  "port": "int (optional, default 3306)",
  "hostgroup_id": "int (optional)",
  "weight": "int (optional)",
  "max_connections": "int (optional, default 100)",
  "comment": "string (optional)"
}
Field Type Required Description
hostname string yes Backend to update (matched with port).
port int no Backend port; defaults to 3306 when 0/omitted.
hostgroup_id int no New hostgroup assignment.
weight int no New load-balancing weight.
max_connections int no New max connections; defaults to 100 when 0/omitted.
comment string no New comment.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing hostname).
500 update_failed Update query against the admin interface failed.

Side effects

  • Updates the matching mysql_servers row, loads MySQL servers to runtime, and saves to disk.

Example

curl -X PUT https://panel.example.com:2087/api/proxysql/backends \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"hostname": "203.0.113.10", "port": 3306, "weight": 2, "max_connections": 200}'

POST /api/proxysql/backends/max-connections

Sets the maximum connection limit for a single backend server.

Guards: RequirePermission(db, "administrative_operations")

Request body

{
  "hostname": "string (required)",
  "port": "int (optional, default 3306)",
  "max_connections": "int (required)"
}
Field Type Required Description
hostname string yes Backend to update.
port int no Backend port; defaults to 3306 when 0/omitted.
max_connections int yes New max-connections value.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing hostname or max_connections).
500 update_failed Update query against the admin interface failed.

Side effects

  • Updates max_connections on the matching mysql_servers row, loads MySQL servers to runtime, and saves to disk.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/backends/max-connections \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"hostname": "203.0.113.10", "port": 3306, "max_connections": 300}'

POST /api/proxysql/backends/reset

Resets a backend's configuration fields (hostgroup, weight, max connections) to the supplied values.

Guards: RequirePermission(db, "administrative_operations")

Request body

{
  "hostname": "string (required)",
  "port": "int (optional, default 3306)",
  "hostgroup_id": "int (optional)",
  "weight": "int (optional)",
  "max_connections": "int (optional, default 100)"
}
Field Type Required Description
hostname string yes Backend to reset.
port int no Backend port; defaults to 3306 when 0/omitted.
hostgroup_id int no Hostgroup to set.
weight int no Weight to set.
max_connections int no Max connections to set; defaults to 100 when 0/omitted.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing hostname).
500 reset_failed Reset query against the admin interface failed.

Side effects

  • Rewrites the matching mysql_servers row and loads MySQL servers to runtime.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/backends/reset \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"hostname": "203.0.113.10", "port": 3306, "hostgroup_id": 0, "weight": 1}'

POST /api/proxysql/install

Installs ProxySQL on the node and configures the remote-admin interface.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true, "message": "ProxySQL installed" } }

Errors

Status Code Meaning
500 install_failed Package installation or service start failed.

Side effects

  • Detects the OS and installs the proxysql package (downloads the .deb from GitHub on Ubuntu/Debian, or adds a yum/dnf repo on RHEL-family).
  • Runs systemctl enable proxysql and systemctl start proxysql.
  • Configures admin credentials (admin:admin;radmin:radmin) and binds the admin interface to 0.0.0.0:6032, then loads/saves admin variables.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/install \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/keepalived/disable

Stops and disables keepalived (high-availability virtual IP) and removes its config.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
500 disable_failed Reported when the underlying disable operation returns an error (the implementation currently always returns nil).

Side effects

  • Runs systemctl stop keepalived and systemctl disable keepalived, and deletes the keepalived config file.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/keepalived/disable \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/keepalived/setup

Configures a keepalived virtual IP (VRRP) for ProxySQL high availability, installing keepalived if needed.

Guards: RequirePermission(db, "administrative_operations")

Request body

{
  "virtual_ip": "string (required)",
  "priority": "int (optional, default 100)",
  "state": "string (optional, default \"BACKUP\")",
  "peer_ip": "string (optional)",
  "auth_pass": "string (optional)"
}
Field Type Required Description
virtual_ip string yes Floating VIP to advertise via VRRP.
priority int no VRRP priority; defaults to 100 when 0/omitted.
state string no MASTER or BACKUP; defaults to BACKUP when empty.
peer_ip string no IP of the peer node.
auth_pass string no VRRP auth password; reused from existing config or generated when empty.

Response - 200 OK

{ "data": { "success": true, "message": "Virtual IP configured" } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing virtual_ip).
500 setup_failed keepalived installation or configuration failed.

Side effects

  • Installs keepalived if absent.
  • Writes /etc/keepalived/keepalived.conf from a template (detecting the default interface), then runs systemctl enable keepalived and systemctl restart keepalived.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/keepalived/setup \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"virtual_ip": "203.0.113.100", "priority": 150, "state": "MASTER", "peer_ip": "203.0.113.11"}'

GET /api/proxysql/keepalived/status

Returns keepalived install/run status and the VIP configuration parsed from the config file.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{
  "data": {
    "installed": true,
    "running": true,
    "virtual_ip": "203.0.113.100",
    "state": "",
    "is_master": false,
    "priority": 150,
    "interface": "eth0",
    "peer_ip": "203.0.113.11",
    "config_state": "MASTER"
  }
}

Errors

Status Code Meaning
500 status_error Failed to determine keepalived status.

Example

curl -X GET https://panel.example.com:2087/api/proxysql/keepalived/status \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/monitor-user

Configures the MySQL monitor user/password ProxySQL uses to health-check backends.

Guards: RequirePermission(db, "administrative_operations")

Request body

{ "username": "string (required)", "password": "string (required)" }
Field Type Required Description
username string yes Monitor account username.
password string yes Monitor account password.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing username or password).
500 update_failed Failed to apply the monitor credentials.

Side effects

  • Sets the monitor username/password MySQL variables on the admin interface, then loads MySQL variables to runtime and saves to disk.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/monitor-user \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "monitor", "password": "s3cret"}'

GET /api/proxysql/query-rules

Lists the configured ProxySQL query rules ordered by rule ID.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{
  "data": [
    {
      "rule_id": 1,
      "active": 1,
      "match_pattern": "^SELECT.*FOR UPDATE",
      "destination_hostgroup": 0,
      "apply": 1
    }
  ]
}

Errors

Status Code Meaning
500 list_error Query against the admin interface failed.

Example

curl -X GET https://panel.example.com:2087/api/proxysql/query-rules \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/read-write-split

Configures default read/write split query rules (writes to hostgroup 0, reads to hostgroup 1).

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true, "message": "Read/Write split configured" } }

Errors

Status Code Meaning
500 setup_failed Failed to write the query rules.

Side effects

  • Inserts query rules into mysql_query_rules, then loads query rules to runtime and saves to disk.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/read-write-split \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/remove

Uninstalls ProxySQL and removes its data and config.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true, "message": "ProxySQL removed" } }

Errors

Status Code Meaning
500 remove_failed Reported when removal returns an error (the implementation currently always returns nil).

Side effects

  • Runs systemctl stop proxysql and systemctl disable proxysql.
  • Removes the proxysql package via apt (remove + purge) or dnf depending on OS.
  • Deletes /var/lib/proxysql and /etc/proxysql.cnf.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/remove \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/reset-stats

Resets ProxySQL connection-pool statistics counters.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
500 reset_error Reset query against the admin interface failed.

Side effects

  • Reads stats_mysql_connection_pool_reset on the admin interface, which clears the pool counters.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/reset-stats \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/restart

Restarts the ProxySQL service.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
500 restart_failed systemctl restart proxysql failed.

Side effects

  • Runs systemctl restart proxysql.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/restart \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/start

Starts the ProxySQL service.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
500 start_failed systemctl start proxysql failed.

Side effects

  • Runs systemctl start proxysql.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/start \
  -H "Authorization: Bearer $TOKEN"

GET /api/proxysql/stats

Returns per-backend connection-pool statistics.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{
  "data": {
    "connection_pools": [
      {
        "hostgroup": 0,
        "host": "203.0.113.10",
        "port": 3306,
        "status": "ONLINE",
        "conn_used": 2,
        "conn_free": 8,
        "conn_ok": 100,
        "conn_err": 0,
        "queries": 5012
      }
    ]
  }
}

Errors

Status Code Meaning
500 stats_error Query against the admin interface failed.

Example

curl -X GET https://panel.example.com:2087/api/proxysql/stats \
  -H "Authorization: Bearer $TOKEN"

GET /api/proxysql/status

Returns ProxySQL install/run status, version, connection counters, and remote-admin (radmin) credentials.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{
  "data": {
    "installed": true,
    "running": true,
    "version": "2.6.3",
    "active_connections": 4,
    "total_connections": 152034,
    "queries_per_sec": 0,
    "read_queries_per_sec": 0,
    "write_queries_per_sec": 0,
    "radmin_username": "radmin",
    "radmin_password": "radmin"
  }
}

Errors

Status Code Meaning
500 status_error Failed to determine ProxySQL status.

Example

curl -X GET https://panel.example.com:2087/api/proxysql/status \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/stop

Stops the ProxySQL service.

Guards: RequirePermission(db, "administrative_operations")

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
500 stop_failed systemctl stop proxysql failed.

Side effects

  • Runs systemctl stop proxysql.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/stop \
  -H "Authorization: Bearer $TOKEN"

POST /api/proxysql/users

Adds (or replaces) a MySQL application user in ProxySQL's mysql_users table.

Guards: RequirePermission(db, "administrative_operations")

Request body

{
  "username": "string (required)",
  "password": "string (required)",
  "default_hostgroup": "int (optional)"
}
Field Type Required Description
username string yes MySQL username clients authenticate as.
password string yes Password for the user.
default_hostgroup int no Default hostgroup for this user's traffic.

Response - 200 OK

{ "data": { "success": true } }

Errors

Status Code Meaning
400 bad_request Request body failed binding (missing username or password).
500 add_failed Insert into mysql_users failed.

Side effects

  • Deletes any existing row with the same username, inserts a new active mysql_users row, then loads MySQL users to runtime and saves to disk.

Example

curl -X POST https://panel.example.com:2087/api/proxysql/users \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user1", "password": "s3cret", "default_hostgroup": 0}'