gnu: services: Add mysql-service.
Commit Message
* gnu/services/database.scm (<mysql-configuration>): New record type.
(%mysql-accounts, mysql-service-type): New variables.
(mysql-configuration-file, %mysql-activation, mysql-shepherd-services)
(mysql-services): New procedures.
* doc/guix.texi (Database Services): Document it.
---
doc/guix.texi | 19 +++++++-
gnu/services/databases.scm | 107 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 124 insertions(+), 2 deletions(-)
Comments
Hello!
宋文武 <iyzsong@gmail.com> skribis:
> * gnu/services/database.scm (<mysql-configuration>): New record type.
> (%mysql-accounts, mysql-service-type): New variables.
> (mysql-configuration-file, %mysql-activation, mysql-shepherd-services)
> (mysql-services): New procedures.
> * doc/guix.texi (Database Services): Document it.
[...]
> +@deffn {Scheme Procedure} mysql-service [#:config (mysql-configuration)]
> +Return a service that runs @command{mysqld}, the MySQL database server.
s/MySQL/MySQL or MariaDB/
> +@deftp {Data Type} mysql-configuration
> +Data type representing the configuration of @var{mysql-service}.
> +
> +@table @asis
> +@item @code{mysql} (default: @var{mariadb})
> +Package object of the MySQL database server, can be either @var{mariadb}
> +or @var{mysql}.
> +@end table
> +@end deftp
Do you have plans to extend this type eventually?
> +(define (%mysql-activation config)
Please add a docstring. IIUC it initializes the ‘mysql’ database for
user ‘mysql’, and that database contains configuration info, right?
Otherwise LGTM!
If you want, it would be awesome if you could come up with a (gnu tests
databases) module that would run a GuixSD with the mysql service, and
then spawn a mysql client to make sure the basics work as expected.
Thank you for working on it!
Ludo’.
ludo@gnu.org (Ludovic Courtès) writes:
> Hello!
>
> 宋文武 <iyzsong@gmail.com> skribis:
>
>> * gnu/services/database.scm (<mysql-configuration>): New record type.
>> (%mysql-accounts, mysql-service-type): New variables.
>> (mysql-configuration-file, %mysql-activation, mysql-shepherd-services)
>> (mysql-services): New procedures.
>> * doc/guix.texi (Database Services): Document it.
>
> [...]
>
>> +@deffn {Scheme Procedure} mysql-service [#:config (mysql-configuration)]
>> +Return a service that runs @command{mysqld}, the MySQL database server.
>
> s/MySQL/MySQL or MariaDB/
OK.
>
>> +@deftp {Data Type} mysql-configuration
>> +Data type representing the configuration of @var{mysql-service}.
>> +
>> +@table @asis
>> +@item @code{mysql} (default: @var{mariadb})
>> +Package object of the MySQL database server, can be either @var{mariadb}
>> +or @var{mysql}.
>> +@end table
>> +@end deftp
>
> Do you have plans to extend this type eventually?
Not yet, should I use a simple keywoard argument instead?
>
>> +(define (%mysql-activation config)
>
> Please add a docstring. IIUC it initializes the ‘mysql’ database for
> user ‘mysql’, and that database contains configuration info, right?
Yes, it does what ‘mysql_install_db’ and ‘mysql_secure_installation’
do (which doesn’t work directly now due to missing coreutils, etc.
in PATH).
And now I realize that this doesn't work for mysql,
I need to rename this to ‘%mariadb-activation’ and write
another ‘%mysql-activation’.
>
> Otherwise LGTM!
>
> If you want, it would be awesome if you could come up with a (gnu tests
> databases) module that would run a GuixSD with the mysql service, and
> then spawn a mysql client to make sure the basics work as expected.
>
Sure, I’ll look that later.
iyzsong@member.fsf.org (宋文武) skribis:
> ludo@gnu.org (Ludovic Courtès) writes:
>
>> Hello!
>>
>> 宋文武 <iyzsong@gmail.com> skribis:
[...]
>>> +@deftp {Data Type} mysql-configuration
>>> +Data type representing the configuration of @var{mysql-service}.
>>> +
>>> +@table @asis
>>> +@item @code{mysql} (default: @var{mariadb})
>>> +Package object of the MySQL database server, can be either @var{mariadb}
>>> +or @var{mysql}.
>>> +@end table
>>> +@end deftp
>>
>> Do you have plans to extend this type eventually?
> Not yet, should I use a simple keywoard argument instead?
No, that’s fine, just wondering.
>>> +(define (%mysql-activation config)
>>
>> Please add a docstring. IIUC it initializes the ‘mysql’ database for
>> user ‘mysql’, and that database contains configuration info, right?
> Yes, it does what ‘mysql_install_db’ and ‘mysql_secure_installation’
> do (which doesn’t work directly now due to missing coreutils, etc.
> in PATH).
OK, would be worth mentioning in a comment.
> And now I realize that this doesn't work for mysql,
> I need to rename this to ‘%mariadb-activation’ and write
> another ‘%mysql-activation’.
Oh, then maybe an additional configuration knob is needed to choose
between MariaDB and MySQL?
Thanks,
Ludo’.
@@ -7985,7 +7985,7 @@ web site} for more information.
@node Database Services
@subsubsection Database Services
-The @code{(gnu services databases)} module provides the following service.
+The @code{(gnu services databases)} module provides the following services.
@deffn {Scheme Procedure} postgresql-service [#:postgresql postgresql] @
[#:config-file] [#:data-directory ``/var/lib/postgresql/data'']
@@ -7997,6 +7997,23 @@ The PostgreSQL daemon loads its runtime configuration from
@var{data-directory}.
@end deffn
+@deffn {Scheme Procedure} mysql-service [#:config (mysql-configuration)]
+Return a service that runs @command{mysqld}, the MySQL database server.
+
+The optional @var{config} argument specifies the configuration for
+@command{mysqld}, which should be a @code{<mysql-configuraiton>} object.
+@end deffn
+
+@deftp {Data Type} mysql-configuration
+Data type representing the configuration of @var{mysql-service}.
+
+@table @asis
+@item @code{mysql} (default: @var{mariadb})
+Package object of the MySQL database server, can be either @var{mariadb}
+or @var{mysql}.
+@end table
+@end deftp
+
@node Mail Services
@subsubsection Mail Services
@@ -27,7 +27,9 @@
#:use-module (guix records)
#:use-module (guix gexp)
#:use-module (ice-9 match)
- #:export (postgresql-service))
+ #:export (postgresql-service
+ mysql-service
+ mysql-configuration))
;;; Commentary:
;;;
@@ -143,3 +145,106 @@ and stores the database cluster in @var{data-directory}."
(postgresql postgresql)
(config-file config-file)
(data-directory data-directory))))
+
+
+;;;
+;;; MySQL.
+;;;
+
+(define-record-type* <mysql-configuration>
+ mysql-configuration make-mysql-configuration
+ mysql-configuration?
+ (mysql mysql-configuration-mysql (default mariadb)))
+
+(define %mysql-accounts
+ (list (user-group
+ (name "mysql")
+ (system? #t))
+ (user-account
+ (name "mysql")
+ (group "mysql")
+ (system? #t)
+ (home-directory "/var/empty")
+ (shell #~(string-append #$shadow "/sbin/nologin")))))
+
+(define mysql-configuration-file
+ (match-lambda
+ (($ <mysql-configuration> mysql)
+ (plain-file "my.cnf" "[mysqld]
+datadir=/var/lib/mysql
+socket=/run/mysqld/mysqld.sock
+"))))
+
+(define (%mysql-activation config)
+ (let ((mysql (mysql-configuration-mysql config))
+ (my.cnf (mysql-configuration-file config)))
+ #~(begin
+ (use-modules (ice-9 popen)
+ (guix build utils))
+ (let* ((mysqld (string-append #$mysql "/bin/mysqld"))
+ (user (getpwnam "mysql"))
+ (uid (passwd:uid user))
+ (gid (passwd:gid user))
+ (datadir "/var/lib/mysql")
+ (rundir "/run/mysqld"))
+ (mkdir-p datadir)
+ (chown datadir uid gid)
+ (mkdir-p rundir)
+ (chown rundir uid gid)
+ ;; Initialize the database when it doesn't exist.
+ (when (not (file-exists? (string-append datadir "/mysql")))
+ (let ((p (open-pipe* OPEN_WRITE mysqld
+ (string-append "--defaults-file=" #$my.cnf)
+ "--bootstrap"
+ "--user=mysql")))
+ ;; Create the system database, according to 'mysql_install_db'.
+ (display "create database mysql;\n" p)
+ (display "use mysql;\n" p)
+ (for-each
+ (lambda (sql)
+ (call-with-input-file
+ (string-append #$mysql "/share/mysql/" sql)
+ (lambda (in) (dump-port in p))))
+ '("mysql_system_tables.sql"
+ "mysql_performance_tables.sql"
+ "mysql_system_tables_data.sql"
+ "fill_help_tables.sql"))
+ ;; Remove the anonymous user and disable root access from
+ ;; remote machines, according to 'mysql_secure_installation'.
+ (display "
+DELETE FROM user WHERE User='';
+DELETE FROM user WHERE User='root' AND
+ Host NOT IN ('localhost', '127.0.0.1', '::1');
+FLUSH PRIVILEGES;
+" p)
+ (close-pipe p)))))))
+
+(define (mysql-shepherd-service config)
+ (list (shepherd-service
+ (provision '(mysql))
+ (documentation "Run the MySQL server.")
+ (start (let ((mysql (mysql-configuration-mysql config))
+ (my.cnf (mysql-configuration-file config)))
+ #~(make-forkexec-constructor
+ (list (string-append #$mysql "/bin/mysqld")
+ (string-append "--defaults-file=" #$my.cnf))
+ #:user "mysql" #:group "mysql")))
+ (stop #~(make-kill-destructor)))))
+
+(define mysql-service-type
+ (service-type
+ (name 'mysql)
+ (extensions
+ (list (service-extension account-service-type
+ (const %mysql-accounts))
+ (service-extension activation-service-type
+ %mysql-activation)
+ (service-extension shepherd-root-service-type
+ mysql-shepherd-service)))))
+
+(define* (mysql-service #:key (config (mysql-configuration)))
+ "Return a service that runs @command{mysqld}, the MySQL database server.
+
+The optional @var{config} argument specifies the configuration for
+@command{mysqld}, which should be a @code{<mysql-configuration>} object."
+ (service mysql-service-type config))