Skip to content

fix(mariadb,mysql plugin): ignore /etc/mysql config files, for better isolation (#2904) - #2906

Open
jefft wants to merge 2 commits into
jetify-com:mainfrom
jefft:jefft/mysql-plugin-ignore-etc-mysql
Open

jefft wants to merge 2 commits into
jetify-com:mainfrom
jefft:jefft/mysql-plugin-ignore-etc-mysql

Conversation

@jefft

@jefft jefft commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2904.

By default, mariadbd reads /etc/mysql/mariadb.cnf, and if the system has another version of MariaDB installed, those config files can cause the Devbox mariadbd to fail (e.g. requesting loading plugins not available).

Devbox services ought to be isolated from their environment. This commit causes devbox mariadbd (and mysqld) to only read from $MYSQL_CONF (typically devbox.d/mariadb/my.cnf).

Additionally, wrap the client/admin binaries (mariadb, mariadb-admin, mariadb-dump, mysqldump, mysql, mysqladmin) with --defaults-file and --socket so they also ignore /etc/mysql and connect to the correct socket.

How was it tested?

Mariadb

Optionally, create a deliberately broken config option in the default mariadb.cnf as a canary:

echo -e "[server]\nunknown_param_to_break_mariadbd_devbox_testing=true" | sudo tee -a /etc/mysql/mariadb.cnf

Then run:

mkdir /tmp/mariadbtest
cd /tmp/mariadbtest
devbox init
devbox add mariadb
devbox run mariadbd --verbose --help | grep ^port   # prints 3306
echo "port = 13306" >> devbox.d/mariadb/my.cnf  # Set a nonstandard port
devbox run mariadbd --verbose --help | grep ^port   # prints 13306, showing my.cnf is used
devbox services up -b
devbox run mariadb -e "show variables where variable_name in ('datadir', 'port', 'log_error', 'socket');"
devbox run mariadb -e "status;"

For me the latter prints:

jturner@jturner-desktop:/tmp/mariadbtest$ devbox run mariadb -e "show variables where variable_name in ('datadir', 'port', 'log_error', 'socket');"
Info: Running script "mariadb" on /tmp/mariadbtest
+---------------+---------------------------------------------------------+
| Variable_name | Value                                                   |
+---------------+---------------------------------------------------------+
| datadir       | /tmp/mariadbtest/.devbox/virtenv/mariadb/data/          |
| log_error     | /tmp/mariadbtest/.devbox/virtenv/mariadb/run/mysql.log  |
| port          | 13306                                                   |
| socket        | /tmp/mariadbtest/.devbox/virtenv/mariadb/run/mysql.sock |
+---------------+---------------------------------------------------------+

jturner@jturner-desktop:/tmp/mariadbtest$ devbox run mariadb -e "status;"
Info: Running script "mariadb" on /tmp/mariadbtest
--------------
/tmp/mariadbtest/.devbox/nix/profile/default/bin/mariadb from 11.8.8-MariaDB, client 15.2 for Linux (x86_64) using readline 5.1

Connection id:          4
Current database:
Current user:           jturner@localhost
SSL:                    Cipher in use is TLS_AES_256_GCM_SHA384, cert is OK
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server:                 MariaDB
Server version:         11.8.8-MariaDB MariaDB Server
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
UNIX socket:            /tmp/mariadbtest/.devbox/virtenv/mariadb/run/mysql.sock
Uptime:                 1 min 0 sec

Threads: 1  Questions: 9  Slow queries: 0  Opens: 17  Open tables: 10  Queries per second avg: 0.150
--------------

mysql80

mkdir /tmp/mysqltest
cd /tmp/mysqltest
devbox init
devbox add mysql80
devbox run mysqld --verbose --help | grep ^port    # prints 3306
echo "port = 23306" >> devbox.d/mysql80/my.cnf  # Set a nonstandard port
devbox run mysqld --verbose --help | grep ^port   # prints 23306, showing my.cnf is used
devbox services up -b
devbox run mysql -uroot -e "show variables where variable_name in ('datadir', 'port', 'log_error', 'socket');"
devbox run mysqladmin -uroot  create mydb     # Show mysqladmin wrapper works
devbox run mysql -uroot mydb -e "select database();"  # prints 'mydb'
devbox run mysqldump -uroot mydb    # prints sql

For me the latter commands show:

jturner@jturner-desktop:/tmp/mysqltest$ devbox run mysql -uroot -e "show variables where variable_name in ('datadir', 'port', 'log_error', 'so
cket');"
Info: Running script "mysql" on /tmp/mysqltest
+---------------+-------------------------------------------------------+
| Variable_name | Value                                                 |
+---------------+-------------------------------------------------------+
| datadir       | /tmp/mysqltest/.devbox/virtenv/mysql80/data/          |
| log_error     | /tmp/mysqltest/.devbox/virtenv/mysql80/run/mysql.log  |
| port          | 23306                                                 |
| socket        | /tmp/mysqltest/.devbox/virtenv/mysql80/run/mysql.sock |
+---------------+-------------------------------------------------------+

jturner@jturner-desktop:/tmp/mysqltest$ devbox run mysqladmin -uroot  create mydb              
Info: Running script "mysqladmin" on /tmp/mysqltest                    
jturner@jturner-desktop:/tmp/mysqltest$ devbox run mysql -uroot mydb -e "select database();"
Info: Running script "mysql" on /tmp/mysqltest
+------------+
| database() |
+------------+
| mydb       |
+------------+

This change (#2904) finishes the job begun by #2524. Also obsoletes (fixes in a nicer way) #2522.

Community Contribution License

All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.

By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.

@jefft
jefft force-pushed the jefft/mysql-plugin-ignore-etc-mysql branch 2 times, most recently from e4e043f to a85fad6 Compare July 8, 2026 16:19
@jefft

jefft commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

In testing, I neglected to test mysql, mysqldump etc under mariadb. They were broken.

In the latest force-push I removed all mysql wrappers of mariadb commands. This leaves symlinks, which the package natively provides:

(devbox) jturner@jturner-desktop:/tmp/testmariadb$ ls -la $(which mysql mysqld mysqld_safe mysqldump mysql_install_db)
lrwxrwxrwx root root  7 B Thu Jan  1 10:00:01 1970 /tmp/testmariadb/.devbox/nix/profile/default/bin/mysql ⇒ mariadb
lrwxrwxrwx root root 18 B Thu Jan  1 10:00:01 1970 /tmp/testmariadb/.devbox/nix/profile/default/bin/mysql_install_db ⇒ mariadb-install-db
lrwxrwxrwx root root  8 B Thu Jan  1 10:00:01 1970 /tmp/testmariadb/.devbox/nix/profile/default/bin/mysqld ⇒ mariadbd
lrwxrwxrwx root root 13 B Thu Jan  1 10:00:01 1970 /tmp/testmariadb/.devbox/nix/profile/default/bin/mysqld_safe ⇒ mariadbd-safe
lrwxrwxrwx root root 12 B Thu Jan  1 10:00:01 1970 /tmp/testmariadb/.devbox/nix/profile/default/bin/mysqldump ⇒ mariadb-dump

The symlinks behave exactly as we want:

(devbox) jturner@jturner-desktop:/tmp/testmariadb$ mariadb -sNBe "select 1;"
1
(devbox) jturner@jturner-desktop:/tmp/testmariadb$ mysql -sNBe "select 1;"
/tmp/testmariadb/.devbox/nix/profile/default/bin/mysql: Deprecated program name. It will be removed in a future release, use '/nix/store/s60l117jfi8y1p567im85rykwjarl13q-mariadb-server-11.8.8/bin/mariadb' instead
1
(devbox) jturner@jturner-desktop:/tmp/testmariadb$ mysqldump --all-databases 
/tmp/testmariadb/.devbox/nix/profile/default/bin/mysqldump: Deprecated program name. It will be removed in a future release, use '/nix/store/s60l117jfi8y1p567im85rykwjarl13q-mariadb-server-11.8.8/bin/mariadb-dump' instead
/*M!999999\- enable the sandbox mode */ 
-- MariaDB dump 10.19-11.8.8-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: 
-- ------------------------------------------------------
-- Server version       11.8.8-MariaDB
...

jefft added 2 commits July 31, 2026 12:20
…ox wrapper

The intention of mariadb/flake.nix is to invoke these commands with Devbox-specific flags:

mariadb-safe --defaults-file=$MYSQL_CONF --basedir=$out --datadir=$MYSQL_DATADIR --pid-file=$MYSQL_PID_FILE
mariadb-install-db --basedir=$out --datadir=$MYSQL_DATADIR --pid-file=$MYSQL_PID_FILE --basedir=$MYSQL_BASEDIR

but that was not happening - the upstream Nix versions were being used with no extra flags.

Notably this caused mariadb-install-db to inherit settings from /etc/mysql. If e.g.
/etc/mysql/mariadb.conf.d/50-server.cnf sets 'user=mysql', mariadb-install-db fails.

A second, hidden-till-now bug is that flake.nix wrapped `mariadb_install_db` and `mariadbd_safe`, when the correct
upstream scripts are `mariadb-install-db` and `mariadbd-safe`.
… isolation (jetify-com#2904)

By default, mariadbd reads /etc/mysql/mariadb.cnf, and if the system has
another version of MariaDB installed, those config files can cause the
Devbox mariadbd to fail (e.g. requesting loading plugins not available).

This commit causes devbox mariadbd (and mysqld) to only read from
$MYSQL_CONF (typically devbox.d/mariadb/my.cnf).

Additionally, wrap the client/admin binaries (mariadb, mariadb-admin,
mariadb-dump, mysqldump, mysql, mysqladmin) with --defaults-file and
--socket so they also ignore /etc/mysql and connect to the correct
socket.

Fixes jetify-com#2904
@jefft
jefft force-pushed the jefft/mysql-plugin-ignore-etc-mysql branch from 829a0ed to 48ef009 Compare August 4, 2026 12:56
mikeland73 added a commit that referenced this pull request Sep 13, 2026
## Summary

This bump fixes a process-compose bug where services with
`process_healthy` dependencies would hang forever (stuck in Pending
state) when the target process had no readiness_probe or liveness_probe
configured.

process-compose v1.116.0 (commit
[85686e5](F1bonacc1/process-compose@85686e5))
adds a nil-check in waitIfNeeded() that returns a clear error instead of
blocking on a channel that is never closed for processes without probes.

Changes made:

1. `go.mod`: changed github.com/f1bonacc1/process-compose v1.64.1 to
v1.116.0
2. `internal/devbox/util.go`: changed const processComposeVersion =
"1.110.0" to "1.116.0"
3. `go mod tidy`: updated go.sum and indirect dependencies

Fixes #2915

## How was it tested?

First build a devbox with a working
#2909 isolated
#2906 mariadb plugin (unless
those have been merged), plus this PR:

```sh
cd /tmp
git clone git@github.com:jetify-com/devbox.git
direnv allow /tmp/devbox
cd devbox
git remote add jefft git@github.com:jefft/devbox.git
git fetch jefft
git checkout -b merge-plugin-fixes main
git merge jefft/jefft/nginx-plugin-fix-2908
git merge jefft/jefft/mysql-plugin-ignore-etc-mysql
git merge jefft/jefft/process-compose-1.116-fix-2915
devbox run build
```

Then using modified repro script from #2915:

```bash
cat > /tmp/mariadb_testhealth.sh <<'EOF'
#!/bin/bash -eu

if [[ -d /tmp/mariadb_testhealth ]]; then
        ( cd /tmp/mariadb_testhealth && devbox services down >/dev/null 2>&1 || : )
  rm -r /tmp/mariadb_testhealth
fi
mkdir /tmp/mariadb_testhealth
cd /tmp/mariadb_testhealth
devbox init
devbox add mariadb
echo "port = $(( 10000 + RANDOM % 50000))" >> devbox.d/mariadb/my.cnf
cat > my_database_using_app <<'EOF2'
#!/bin/bash
# Connect to MariaDBD via unix socket as root.
sudo mariadb --show-warnings -u root --socket "$MYSQL_UNIX_PORT" -e "select 1;"
EOF2
chmod +x ./my_database_using_app

cat > process-compose.yml <<'EOF2'
version: "0.5"

processes:

  myapp:
    depends_on:
      mariadb:
        condition: process_healthy
    command: ./my_database_using_app
EOF2
devbox services up -b
sleep 1
echo "myapp should be Skipped:"
devbox services ls
echo "We should see an error in the process-compose log:"
grep ERR /tmp/process-compose-$USER.log
EOF

# Put our compiled version of devbox ahead of others in PATH
PATH=/tmp/devbox/dist:$PATH bash /tmp/mariadb_testhealth.sh
```

With the fixed process-compose the myapp service is in Skipped, and the
log contains a clear error message:

```
Starting all services: mariadb_logs, myapp, mariadb 
Process-compose is now running on port 40249
To stop your services, run `devbox services stop`
myapp should be Skipped:
Services running in process-compose:
PID            NAME                NAMESPACE        STATUS         AGE        HEALTH        RESTARTS        EXIT CODE
1673011        mariadb             default          Running        1s         -             0               0
1673058        mariadb_logs        default          Running        0s         -             1               1
0              myapp               default          Skipped        0s         -             0               1
We should see an error in the process-compose log:
26-07-11 02:46:21.849 ERR health dependency defined in 'myapp' but no health check exists in 'mariadb'
26-07-11 02:46:21.850 ERR Error: health dependency defined in 'myapp' but no health check exists in 'mariadb'
26-07-11 02:46:21.850 ERR Error: process myapp won't run
jturner@jturner-desktop:/tmp/devbox$ 
```

## Community Contribution License

All community contributions in this pull request are licensed to the
project
maintainers under the terms of the
[Apache 2 License](https://www.apache.org/licenses/LICENSE-2.0).

By creating this pull request, I represent that I have the right to
license the
contributions to the project maintainers under the Apache 2 License as
stated in
the
[Community Contribution
License](https://github.com/jetify-com/opensource/blob/main/CONTRIBUTING.md#community-contribution-license).

---------

Co-authored-by: Mike Landau <mikeland86@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
mikeland73 pushed a commit that referenced this pull request Sep 13, 2026
…cies (#2915) (#2917)

## Summary

Adds readiness_probe to mariadb, mysql, redis, valkey (using native CLI
ping commands), and apache, nginx (using http_get probes).  PostgreSQL
already had one (pg_isready).

This enables consumers to use `condition: process_healthy` in their
depends_on configuration, ensuring downstream services do not start
until their dependencies are actually accepting connections.

Fixes (along with #2916) #2915

## How was it tested?

First build a devbox with a working
#2909 isolated
#2906 mariadb plugin (unless
those have been merged), plus this PR:

```sh
cd /tmp
git clone git@github.com:jetify-com/devbox.git devbox-2915
direnv allow /tmp/devbox-2915
cd devbox-2915
git remote add jefft git@github.com:jefft/devbox.git
git fetch jefft
git checkout -b merge-plugin-fixes main
git merge --no-edit jefft/jefft/nginx-plugin-fix-2908
git merge --no-edit jefft/jefft/mysql-plugin-ignore-etc-mysql
git merge --no-edit jefft/jefft/plugin_readiness_probes-fix-2915
devbox run build
```

Then to illustrate scripts waiting for their services to come up:

```bash
cat > /tmp/testhealth.sh <<'EOF'
#!/bin/bash -eu

if [[ -d /tmp/testhealth ]]; then
        ( cd /tmp/testhealth && devbox services down >/dev/null 2>&1 || : )
  rm -r /tmp/testhealth
fi
mkdir /tmp/testhealth
cd /tmp/testhealth

cat > devbox.json <<'EOF2'
{
  "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/main/.schema/devbox.schema.json",
  "packages": [
    "mariadb@latest",
    "apache@latest",
    "nginx@latest",
    "redis@latest",
    "valkey@latest"
  ],
  "env": { 
    "HTTPD_PORT": "11101",
    "NGINX_WEB_PORT": "11102",
    "VALKEY_PORT": "11103"
  },
  "shell": {
    "init_hook": [
      "echo 'Welcome to devbox!' > /dev/null"
    ],
    "scripts": {
      "test": [
        "echo \"Error: no test specified\" && exit 1"
      ]
    }
  }
}
EOF2
devbox services ls   # create devbox.d/* dirs

echo "port = $(( 10000 + RANDOM % 50000))" >> devbox.d/mariadb/my.cnf
cat > my_database_using_app <<'EOF2'
#!/bin/bash
# Connect to MariaDBD via unix socket as root.
sudo mariadb --show-warnings -u root --socket "$MYSQL_UNIX_PORT" -e "select 1;"
EOF2
chmod +x ./my_database_using_app

cat > process-compose.yml <<'EOF2'
version: "0.5"

processes:

  mariadb_tester:
    depends_on:
      mariadb:
        condition: process_healthy
    command: ./my_database_using_app

  apache_tester:
    depends_on:
      apache:
        condition: process_healthy
    command: curl http://localhost:11101

  nginx_tester:
    depends_on:
      nginx:
        condition: process_healthy
    command: curl http://localhost:11102

  valkey_tester:
    depends_on:
      valkey:
        condition: process_healthy
    command: valkey-cli -p $VALKEY_PORT ping

EOF2
which devbox
devbox services up
EOF

# Put our compiled version of devbox ahead of others in PATH
PATH=/tmp/devbox-2915/dist:$PATH bash /tmp/testhealth.sh
```

The `*_tester` dependent services now work, coming up (after a delay) as
Completed::

```bash
jturner@jturner-desktop:/tmp/testhealth$ devbox services ls
Services running in process-compose:
PID            NAME                  NAMESPACE        STATUS           AGE        HEALTH        RESTARTS        EXIT CODE
1982981        mariadb_logs          default          Running          5s         -             0               0
1982980        redis                 default          Running          5s         Ready         0               0
1982983        apache                default          Running          5s         Ready         0               0
1982984        apache-access         default          Running          5s         -             0               0
1983151        mariadb_tester        default          Completed        0s         -             0               0
1983126        apache_tester         default          Completed        0s         -             0               0
1983127        valkey_tester         default          Completed        0s         -             0               0
1982982        nginx                 default          Running          5s         Ready         0               0
1982978        nginx-error           default          Running          5s         -             0               0
1982974        nginx-access          default          Running          5s         -             0               0
1982977        valkey                default          Running          5s         Ready         0               0
1982976        apache-error          default          Running          5s         -             0               0
1983125        nginx_tester          default          Completed        0s         -             0               0
1982973        mariadb               default          Running          5s         Ready         0               0
```


[devbox_dependent_services.webm](https://github.com/user-attachments/assets/51e78b8f-a848-4a36-9ac0-2745852f8e4a)


## Community Contribution License

All community contributions in this pull request are licensed to the
project
maintainers under the terms of the
[Apache 2 License](https://www.apache.org/licenses/LICENSE-2.0).

By creating this pull request, I represent that I have the right to
license the
contributions to the project maintainers under the Apache 2 License as
stated in
the
[Community Contribution
License](https://github.com/jetify-com/opensource/blob/main/CONTRIBUTING.md#community-contribution-license).
mikeland73 added a commit that referenced this pull request Sep 14, 2026
…oject dir work (#2960)

## Summary

Fixes #2631.

Several builtin plugins reference an absolute project path in their
process-compose **service command** without wrapping it in double
quotes:

| Plugin | command (before) |
| --- | --- |
| `apache` | `apachectl start -f $HTTPD_CONFDIR/httpd.conf ...`, `tail
-f $HTTPD_ERROR_LOG_FILE`, `tail -f $HTTPD_ACCESS_LOG_FILE` |
| `caddy` | `caddy run --config=$CADDY_CONFIG` |
| `php` | `php-fpm -y {{ .DevboxDir }}/php-fpm.conf --nodaemonize` |
| `redis` | `redis-server $REDIS_CONF --port $REDIS_PORT` |
| `valkey` | `valkey-server $VALKEY_CONF --port $VALKEY_PORT` |

Each of these variables/templates expands to the project's **absolute
path** (for example `$CADDY_CONFIG` → `{{ .DevboxDir }}/Caddyfile`,
`$REDIS_CONF` → `{{ .DevboxDir }}/redis.conf`). An unquoted reference is
word-split by the shell whenever the project directory contains a space,
so the service fails to start. This is the same class of bug as the
`init_hook` fix in #2876 — now applied to the plugin **service
commands** that run under `devbox services`.

### Fix

Wrap each path reference in double quotes, matching the pattern the
`postgresql` plugin already uses (`pg_isready -p "${PGPORT:-5432}"` and
`-k "$PGHOST"`). Ports and other non-path values are left unquoted.
After the fix, e.g.:

```yaml
command: "caddy run --config=\"$CADDY_CONFIG\""
command: "php-fpm -y \"{{ .DevboxDir }}/php-fpm.conf\" --nodaemonize"
```

The affected plugins' `version` fields are bumped, consistent with how
prior plugin behavior changes are versioned.

The `mariadb`, `mysql`, and `nginx` plugins have the same unquoted-path
pattern in their service commands, but they currently have other
in-flight PRs touching those exact files (#2906, #2911, #2909). They
were intentionally left out of this PR to avoid conflicts and can be
quoted in those PRs or a small follow-up.

## How was it tested?

- Added `plugins/service_command_quoting_test.go`, which scans every
builtin plugin's `process-compose.yaml` and asserts that templated paths
(`{{ ... }}`) and known path-bearing env vars in service commands are
quoted. It reuses the shell-quoting model from the existing
`init_hook_quoting_test.go`. Verified it **fails** on the old (unquoted)
content and **passes** on the fix.
- `go test ./plugins/ ./internal/plugin/`, `go vet ./plugins/`, and
`gofmt` are clean.

cc @arent-groebner — thanks for the report.

## Community Contribution License

All community contributions in this pull request are licensed to the
project
maintainers under the terms of the
[Apache 2 License](https://www.apache.org/licenses/LICENSE-2.0).

By creating this pull request, I represent that I have the right to
license the
contributions to the project maintainers under the Apache 2 License as
stated in
the
[Community Contribution
License](https://github.com/jetify-com/opensource/blob/main/CONTRIBUTING.md#community-contribution-license).

---
_Generated by [Claude
Code](https://claude.ai/code/session_017vU39wucKJwc6SGydhzoiN)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

mariadb reads and get confused by /etc/mysql/ config files

1 participant