mirror of
https://github.com/webinstall/webi-installers.git
synced 2026-08-23 22:16:48 +00:00
feat: add MariaDB
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
---
|
||||
title: MariaDB (MySQL)
|
||||
homepage: https://mariadb.com/
|
||||
tagline: |
|
||||
MariaDB: The original MySQL, renamed due to Oracle acquiring the trademark
|
||||
---
|
||||
|
||||
To update or switch versions, run `webi mariadb@stable` (or `@v11`, `@lts`,
|
||||
etc).
|
||||
|
||||
### Files
|
||||
|
||||
These are the files / directories that are created and/or modified with this
|
||||
install:
|
||||
|
||||
```text
|
||||
~/.config/envman/PATH.env
|
||||
~/.local/opt/mariadb/
|
||||
~/.local/share/mariadb/
|
||||
~/.my.cnf
|
||||
~/.config/mariadb/my.cnf
|
||||
~/.local/share/mariadb/my.cnf
|
||||
```
|
||||
|
||||
## Cheat Sheet
|
||||
|
||||
> MariaDB is the original authors' successor to MySQL, after Oracle's
|
||||
> acquisition of the MySQL trademark. Although [Postgres](../postgres/) is
|
||||
> generally recommended for new projects, projects that previously used MySQL or
|
||||
> MariaDB can continue to gain benefit from the continued development of
|
||||
> MariaDB.
|
||||
|
||||
Connect as the default admin, the root admin, or a remote (`%`) user:
|
||||
|
||||
```sh
|
||||
mysql 'dbname'
|
||||
sudo mysql -u root 'dbname'
|
||||
mysql -u 'dbuser' -p -h '127.0.0.1' -P 3306 'dbname'
|
||||
```
|
||||
|
||||
Manage MariaDB as a system service with [serviceman](../serviceman/):
|
||||
|
||||
```sh
|
||||
curl https://webi.sh/serviceman | sh
|
||||
|
||||
# Linux and macOS
|
||||
serviceman add --name 'mysqld' --workdir ~/.local/opt/mariadb/ -- \
|
||||
mariadbd --defaults-file="$HOME/.local/share/mariadb/my.cnf"
|
||||
|
||||
# On Linux, with systemd
|
||||
sudo systemctl restart systemd-journald
|
||||
sudo systemctl restart 'mysqld'
|
||||
sudo journalctl -xef --unit 'mysqld'
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- Use UTF-8 (not Swedish)
|
||||
- Vertical Rows
|
||||
- Create an App User and DB
|
||||
- Backup and Restore
|
||||
- Connect via SSH Proxy
|
||||
- Remove default users
|
||||
|
||||
### Switch from Swedish to UTF-8
|
||||
|
||||
This is done automatically if installed by Webi, and in MariaDB 11.6+.
|
||||
|
||||
Edit your `my.cnf` files as follows:
|
||||
|
||||
```sh
|
||||
[server]
|
||||
character-set-server = utf8mb4
|
||||
collation-server = utf8mb4_unicode_ci
|
||||
init-connect = 'SET NAMES utf8mb4'
|
||||
```
|
||||
|
||||
```sh
|
||||
[client]
|
||||
default-character-set = utf8mb4
|
||||
```
|
||||
|
||||
You can then update old tables:
|
||||
|
||||
```sql
|
||||
ALTER DATABASE your_database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
See <https://chatgpt.com/c/67941f5a-9390-800e-86e7-2e8bd56117f7>.
|
||||
|
||||
In some cases it may be simpler better to **backup and restore** (see table of
|
||||
contents) the databases due to foreign key constraints.
|
||||
|
||||
### How to View Rows Vertically
|
||||
|
||||
Use `\G` instead of `;` for a single query
|
||||
|
||||
```sh
|
||||
SELECT * FROM `mysql`.`global_priv` \G
|
||||
```
|
||||
|
||||
### How to Create an App User + DB
|
||||
|
||||
You create a database, a user (typically of the same name), a password
|
||||
(typically random via `xxd` or <https://pw.bnna.net>), and grant the app admin
|
||||
privileges on its database.
|
||||
|
||||
```sql
|
||||
USE `mysql`;
|
||||
CREATE DATABASE `appdb`;
|
||||
CREATE USER 'appuser'@'%' IDENTIFIED BY 'super-secret';
|
||||
GRANT ALL PRIVILEGES ON `appdb`.* TO 'appuser'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
Here's a script for doing the same:
|
||||
|
||||
```sh
|
||||
mariadb-create-app 'foobar'
|
||||
```
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
|
||||
# USAGE
|
||||
# mariadb-create-app [app-name]
|
||||
#
|
||||
# EXAMPLE
|
||||
# mariadb-create-app 'foobar'
|
||||
|
||||
main() {(
|
||||
b_appname="${1:-$(hostname)}"
|
||||
|
||||
b_dbname="${b_appname}"
|
||||
b_user="${b_dbname}"
|
||||
b_password="$(xxd -l8 -p /dev/urandom | sed 's/..../&-/g; s/-$//')"
|
||||
|
||||
mariadb -e "
|
||||
USE \`mysql\`;
|
||||
CREATE DATABASE IF NOT EXISTS \`${b_dbname}\`;
|
||||
CREATE USER '${b_user}'@'%' IDENTIFIED BY '${b_password}';
|
||||
GRANT ALL PRIVILEGES ON \`${b_dbname}\`.* TO '${b_user}'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
"
|
||||
|
||||
echo "${b_password}" > ./"${b_appname}-password.txt"
|
||||
|
||||
echo ""
|
||||
echo "Password in ./${b_appname}-password.txt"
|
||||
echo ""
|
||||
echo "mysql://${b_user}:********@localhost:3306/${b_dbname}"
|
||||
echo "mariadb -u ${b_user} -p ${b_dbname}"
|
||||
echo ""
|
||||
)}
|
||||
```
|
||||
|
||||
### How to Backup and Restore
|
||||
|
||||
Backup a single database:
|
||||
|
||||
```sh
|
||||
my_ts="$(date "+%F_%H.%M.%S")"
|
||||
mysqldump -u username -p --force --hex-blob --databases 'dbname' \
|
||||
--triggers --routines --events \
|
||||
--add-drop-table --add-drop-triggers \
|
||||
--skip-set-charset --single-transaction > ./"backup.${ts}.sql"
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- `--force` **is always necessary** and should be the default - it will continue
|
||||
the backup in the case that inconsistencies are found - such as a _View_
|
||||
referencing a column that no longer exists (which is not checked during
|
||||
`ALTER TABLE`)
|
||||
- `--skip-set-charset` to accept the default `utf8` rather than accidentally
|
||||
recreating tables as legacy `latin1-swedish`
|
||||
- `--add-drop-table` and `--add-drop-triggers` do not need to be used if your
|
||||
user has the ability to drop and recreate the database
|
||||
- `--databases 'dbname'` omits ``USE `dbname`;``, which allows you to easily
|
||||
restore to a different database name
|
||||
|
||||
Destructive Restore (drop that database and then restore it):
|
||||
|
||||
```sh
|
||||
mysql -u username -p -e 'DROP DATABASE `dbname`';
|
||||
mysql -u username -p 'dbname' < ./backup.sql
|
||||
```
|
||||
|
||||
### Connect via SSH Proxy
|
||||
|
||||
1. Create a proxy (ignore warnings)
|
||||
```sh
|
||||
#ssh user@server -fnNT -L <local-port>:<remote-host>:<remote-port>
|
||||
ssh ${USER}@${b_hostname} -fnNT -L 13306:localhost:3306
|
||||
```
|
||||
2. Connect via `mysql`, `mariadb`, Sequel Ace, etc:
|
||||
```sh
|
||||
mysql -u remote-user -h 127.0.0.1 -P 13306
|
||||
```
|
||||
|
||||
**Notes**
|
||||
|
||||
- connect with a user that has the host `%` and DOES NOT have a `localhost` or
|
||||
`127.0.0.1` entry - otherwise the client may "upgrade" to a socket connection
|
||||
and fail.
|
||||
- you may need to remove the wildcard `localhost` users (see below)
|
||||
|
||||
### Remove Default Access `localhost` Users
|
||||
|
||||
You may not be able to connect via an SSH proxy if the default users exist. \
|
||||
(it may match `` `%`@`localhost` `` instead of `` `app`@`%` `` and deny the
|
||||
password)
|
||||
|
||||
```sql
|
||||
USE `mysql`;
|
||||
DELETE FROM `global_priv` WHERE `User` = '';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
Executable
+165
@@ -0,0 +1,165 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
__init_mariadb() {
|
||||
set -e
|
||||
set -u
|
||||
|
||||
###################
|
||||
# Install mariadb #
|
||||
###################
|
||||
|
||||
# Every package should define these 6 variables
|
||||
pkg_cmd_name="mariadb"
|
||||
|
||||
pkg_dst_cmd="${HOME}/.local/opt/mariadb/bin/mariadb"
|
||||
pkg_dst_bin="${HOME}/.local/opt/mariadb/bin"
|
||||
pkg_dst_dir="${HOME}/.local/opt/mariadb"
|
||||
pkg_dst="${pkg_dst_dir}"
|
||||
|
||||
pkg_src_cmd="${HOME}/.local/opt/mariadb-v${WEBI_VERSION}/bin/mariadb"
|
||||
pkg_src_dir="${HOME}/.local/opt/mariadb-v${WEBI_VERSION}"
|
||||
pkg_src="${pkg_src_dir}"
|
||||
|
||||
pkg_get_current_version() {
|
||||
# 'mariadb --version' has output in this format:
|
||||
# mariadb (mariadbQL) 17.0
|
||||
# This trims it down to just the version number:
|
||||
# 17.0
|
||||
mariadb --version 2> /dev/null | head -n 1 | cut -d' ' -f3
|
||||
}
|
||||
|
||||
pkg_install() {
|
||||
# mkdir -p $HOME/.local/opt
|
||||
mkdir -p "$(dirname "$pkg_src")"
|
||||
|
||||
# mv ./mariadb-11.4.4-linux-systemd-x86_64 "$HOME/.local/opt/mariadb-v11.4.4"
|
||||
mv ./"mariadb-"* "$pkg_src"
|
||||
}
|
||||
|
||||
pkg_link() {
|
||||
# ln -s "$HOME/.local/opt/mariadb-v17.0" "$HOME/.local/opt/mariadb"
|
||||
# for the old mariadb version
|
||||
ln -s "$pkg_src" "$pkg_dst"
|
||||
if ! test -d ~/.local/opt/mysql; then
|
||||
rm -f ~/.local/opt/mysql
|
||||
ln -s "mariadb-v${WEBI_VERSION}" ~/.local/opt/mysql
|
||||
fi
|
||||
}
|
||||
|
||||
#shellcheck disable=SC2059
|
||||
pkg_post_install() {
|
||||
b_hostname="$(hostname)"
|
||||
|
||||
if ! test -e ~/.config/mariadb; then
|
||||
mkdir -p ~/.config/mariadb
|
||||
chmod 0700 ~/.config/mariadb/
|
||||
fi
|
||||
|
||||
if ! test -e ~/.local/share/mariadb; then
|
||||
mkdir -p ~/.local/share/mariadb/
|
||||
chmod 0700 ~/.local/share/mariadb/
|
||||
mkdir -p ~/.local/share/mariadb/run/
|
||||
chmod 0750 ~/.local/share/mariadb/run/
|
||||
mkdir -p ~/.local/share/mariadb/var/
|
||||
chmod 0750 ~/.local/share/mariadb/var/
|
||||
else
|
||||
mkdir -p ~/.local/share/mariadb/run/
|
||||
mkdir -p ~/.local/share/mariadb/data/
|
||||
mkdir -p ~/.local/share/mariadb/var/
|
||||
fi
|
||||
|
||||
printf " $(t_path '~''/.my.cnf') $(t_dim '(sources client & server config)') "
|
||||
if test -e ~/.my.cnf; then
|
||||
printf -- "$(t_dim 'Found')\n"
|
||||
else
|
||||
{
|
||||
echo '[client]'
|
||||
echo '!include /home/app/.config/mariadb/my.cnf'
|
||||
echo ''
|
||||
echo '[server]'
|
||||
echo '!include /home/app/.local/share/mariadb/my.cnf'
|
||||
} > ~/.my.cnf
|
||||
printf -- "Created\n"
|
||||
fi
|
||||
|
||||
printf " $(t_path '~''/.config/mariadb/my.cnf') $(t_dim '(client config)') "
|
||||
if test -e ~/.config/mariadb/my.cnf; then
|
||||
printf -- "$(t_dim 'Found')\n"
|
||||
else
|
||||
{
|
||||
echo '[client]'
|
||||
echo ' default-character-set = utf8mb4'
|
||||
echo ''
|
||||
echo " socket = $HOME/.local/share/mariadb/run/mariadbd.sock"
|
||||
echo " #host = ${b_hostname}"
|
||||
echo ' #port = 3306'
|
||||
echo " #user = ${USER}"
|
||||
echo " #password = (none)"
|
||||
echo " #database = (none)"
|
||||
} > ~/.config/mariadb/my.cnf
|
||||
printf -- "Created\n"
|
||||
fi
|
||||
|
||||
printf " $(t_path '~''/.local/share/mariadb/my.cnf') $(t_dim '(server config)') "
|
||||
if test -e ~/.local/share/mariadb/my.cnf; then
|
||||
printf -- "$(t_dim 'Found')\n"
|
||||
else
|
||||
{
|
||||
echo '[server]'
|
||||
echo " character-set-server = utf8mb4"
|
||||
echo " collation-server = utf8mb4_unicode_ci"
|
||||
echo " init-connect = 'SET NAMES utf8mb4'"
|
||||
echo ''
|
||||
echo " bind-address = 127.0.0.1"
|
||||
echo " port = 3306"
|
||||
echo " socket = $HOME/.local/share/mariadb/run/mariadbd.sock"
|
||||
echo ''
|
||||
echo " basedir = $HOME/.local/opt/mariadb/"
|
||||
echo " datadir = $HOME/.local/share/mariadb/data/"
|
||||
echo " pid-file = $HOME/.local/share/mariadb/run/mariadbd.pid"
|
||||
echo " #log-error = $HOME/.local/share/mariadb/var/error.log"
|
||||
} > ~/.local/share/mariadb/my.cnf
|
||||
printf -- "Created\n"
|
||||
fi
|
||||
|
||||
printf " $(t_path '~''/.local/share/mariadb/data/') $(t_dim '(database)') "
|
||||
if test -e ~/.local/share/mariadb/data; then
|
||||
printf -- "$(t_dim 'Found')\n"
|
||||
else
|
||||
printf -- "Initializing ... "
|
||||
mkdir -p ~/.local/share/mariadb/data/
|
||||
chmod 0700 ~/.local/share/mariadb/data/
|
||||
# echo ""
|
||||
# echo " Consider joining MariaDB's strong and vibrant community:"
|
||||
# echo " https://mariadb.org/get-involved/"
|
||||
# echo ""
|
||||
~/.local/opt/mariadb/scripts/mariadb-install-db --defaults-file="$HOME/.my.cnf" > /dev/null
|
||||
printf -- "OK\n"
|
||||
fi
|
||||
webi_path_add "$(dirname "$pkg_dst_cmd")"
|
||||
}
|
||||
|
||||
pkg_done_message() {
|
||||
b_hostname="$(hostname)"
|
||||
|
||||
echo ""
|
||||
echo " Installed $(t_pkg "mariadb") $(t_dim "(mysql)") as $(t_link '~''/.local/opt/mariadb/bin/mariadb')"
|
||||
|
||||
echo ""
|
||||
echo "To run manually"
|
||||
echo " $(t_cmd 'mariadbd-safe') --defaults-file=\"$(t_path "$HOME/.my.cnf")\""
|
||||
#mariadbd-safe --defaults-file=$HOME/.my.cnf --print-defaults
|
||||
echo ""
|
||||
echo "To install as a system service"
|
||||
# export MARIADB_HOME=$HOME/.local/opt/mariadb/
|
||||
echo " $(t_cmd 'serviceman') add --name mariadb --workdir $(t_path '~''/.local/opt/mariadb/') -- \\"
|
||||
echo " $(t_cmd 'mariadbd') --defaults-file=\"$(t_path "$HOME/.my.cnf")\""
|
||||
echo ""
|
||||
echo "To connect with a client:"
|
||||
echo " $(t_cmd 'mariadb') -u 'root' -h 'localhost' $(t_dim '# all-privileges admin')"
|
||||
echo " $(t_cmd 'mariadb') -u '${USER}' -h 'localhost' $(t_dim '# all-privileges admin')"
|
||||
}
|
||||
}
|
||||
|
||||
__init_mariadb
|
||||
@@ -0,0 +1,181 @@
|
||||
'use strict';
|
||||
|
||||
let Fetcher = require('../_common/fetcher.js');
|
||||
|
||||
let Releases = module.exports;
|
||||
|
||||
let PRODUCT = `mariadb`;
|
||||
// `https://downloads.mariadb.org/rest-api/${PRODUCT}/${minor}/`
|
||||
// `https://downloads.mariadb.org/rest-api/mariadb/10.5/`
|
||||
// https://github.com/MariaDB/mariadb-documentation/issues/41
|
||||
|
||||
Releases.latest = async function () {
|
||||
let packages = [];
|
||||
let versionData = await getVersionIds();
|
||||
for (let verData of versionData.major_releases) {
|
||||
let isVersion = /^\d+[.]\d+$/.test(verData.release_id);
|
||||
if (!isVersion) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let releaseData = await getReleases(verData.release_id);
|
||||
let versions = Object.keys(releaseData.releases);
|
||||
for (let ver of versions) {
|
||||
let relData = releaseData.releases[ver];
|
||||
for (let fileData of relData.files) {
|
||||
let packageData = pluckData(verData, relData, fileData);
|
||||
if (!packageData) {
|
||||
continue;
|
||||
}
|
||||
packages.push(packageData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let all = { releases: packages };
|
||||
return all;
|
||||
};
|
||||
|
||||
/** @type {Object.<String?, String>} */
|
||||
let channelsMap = {
|
||||
// 'Long Term Support': 'stable',
|
||||
// 'Short Term Support': 'stable',
|
||||
// 'Rolling': null,
|
||||
Stable: 'stable',
|
||||
RC: 'rc',
|
||||
Alpha: 'preview',
|
||||
null: 'preview',
|
||||
};
|
||||
|
||||
/** @type {Object.<String, String>} */
|
||||
let cpusMap = {
|
||||
x86_64: 'amd64',
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {MajorRelease} verData
|
||||
* @param {Release} relData
|
||||
* @param {File} fileData
|
||||
*/
|
||||
function pluckData(verData, relData, fileData) {
|
||||
let lts =
|
||||
verData.release_status === 'Stable' &&
|
||||
verData.release_support_type === 'Long Term Support';
|
||||
let cpu = fileData.cpu || '';
|
||||
cpu = cpu.trim();
|
||||
|
||||
let isNotBinary = !fileData.os || !cpu; // "Source" or some such
|
||||
if (isNotBinary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let isDebug = /debug/.test(fileData.file_name);
|
||||
if (isDebug) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let pkgData = {
|
||||
name: fileData.file_name,
|
||||
version: relData.release_id,
|
||||
lts: lts,
|
||||
channel: channelsMap[verData.release_status],
|
||||
date: relData.date_of_release,
|
||||
os: fileData.os?.toLowerCase(),
|
||||
arch: cpusMap[cpu] || cpu,
|
||||
hash: fileData.checksum.sha256sum,
|
||||
download: fileData.file_download_url,
|
||||
};
|
||||
|
||||
return pkgData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {String} ISODate - YYYY-MM-DD (ISO 8601 format)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef MajorRelease
|
||||
* @prop {String} release_id - version-like for stable versions, otherwise a title
|
||||
* @prop {String} release_name - same as id for MariaDB
|
||||
* @prop {String} release_status - Stable|RC|Alpha
|
||||
* @prop {String?} release_support_type - Long Term Support|Short Term Support|Rolling|null
|
||||
* @prop {ISODate?} release_eol_date
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef MajorReleasesWrapper
|
||||
* @prop {Array<MajorRelease>} major_releases
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef Release
|
||||
* @prop {String} release_id - "11.4.4" or "11.6.0 Vector"
|
||||
* @prop {String} release_name - "MariaDB Server 11.8.0 Preview"
|
||||
* @prop {ISODate} date_of_release
|
||||
* @prop {String} release_notes_url
|
||||
* @prop {String} change_log
|
||||
* @prop {Array<File>} files - release assets (packages, docs, etc)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef ReleasesWrapper
|
||||
* @prop {Object.<String, Release>} releases
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef File
|
||||
* @prop {Number} file_id
|
||||
* @prop {String} file_name
|
||||
* @prop {String?} package_type - "gzipped tar file" or "ZIP file"
|
||||
* @prop {String?} os - "Linux" or "Windows"
|
||||
* @prop {String?} cpu - "x86_64" (or null)
|
||||
* @prop {Checksum} checksum
|
||||
* @prop {String} file_download_url
|
||||
* @prop {String?} signature
|
||||
* @prop {String} checksum_url
|
||||
* @prop {String} signature_url
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef Checksum
|
||||
* @prop {String?} md5sum
|
||||
* @prop {String?} sha1sum
|
||||
* @prop {String?} sha256sum
|
||||
* @prop {String?} sha512sum
|
||||
*/
|
||||
|
||||
/**
|
||||
* @returns {Promise<MajorReleasesWrapper>}
|
||||
*/
|
||||
async function getVersionIds() {
|
||||
let url = `https://downloads.mariadb.org/rest-api/${PRODUCT}/`;
|
||||
let resp = await Fetcher.fetch(url, {
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
|
||||
let result = JSON.parse(resp.body);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} verId
|
||||
* @returns {Promise<ReleasesWrapper>}
|
||||
*/
|
||||
async function getReleases(verId) {
|
||||
let url = `https://downloads.mariadb.org/rest-api/${PRODUCT}/${verId}`;
|
||||
let resp = await Fetcher.fetch(url, {
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
|
||||
let result = JSON.parse(resp.body);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (module === require.main) {
|
||||
Releases.latest().then(function (all) {
|
||||
let normalize = require('../_webi/normalize.js');
|
||||
all = normalize(all);
|
||||
let json = JSON.stringify(all, null, 2);
|
||||
console.info(json);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user