jjethwa / rundeck

GNU General Public License v3.0
123 stars 137 forks source link

Setting up mysql not obvious. Docs not clear. #74

Open tombburnell opened 7 years ago

tombburnell commented 7 years ago

I figured out that to connect to a mysql instance you need to do the following:

mysql needs to be configured to listen on 0.0.0.0

you need to set your environment as NO_LOCAL_MYSQL=true DATABASE_URL=jdbc:mysql://myhost/?autoReconnect=true

Putting the db name in the URL seems to have no effect, it always tries to connect to rundeckdb. DATABASE_URL=jdbc:mysql://myhost/rundeck?autoReconnect=true

grant ALL PRIVILEGES on rundeckdb. to 'rundeck'@'%' identified by 'yourpassword'; grant ALL PRIVILEGES on mysql. to 'rundeck'@'%' identified by 'yourpassword';

Why does it need access to mysql database?

jjethwa commented 7 years ago

Hi @tombburnell

Sorry about the lack of documentation. I'll try to detail that when I get time. The standard use case for the container is with the built in MySQL instance. We would need to tweak the setup script to allow other database names besides the standard rundeckdb. So try using the default, rundeckdb, for now. Also, make sure to set

DATABASE_ADMIN_PASSWORD
DATABASE_ADMIN_USER

These were added in the latest commit so your MySQL admin account can create and grant the necessary privileges to the rundeck user on rundeckdb.

dougereed commented 7 years ago

@jjethwa Can you confirm that a default local database configuration works? I am not passing any db related environment variables into the container and keep getting a fresh install failing with this error.

=>Initializing rundeck - This may take a few minutes
=>/etc/rundeck check OK
=>Initializing local MySQL...
[ ok ] Starting MariaDB database server: mysqld.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
[FAIL] Stopping MariaDB database server: mysqld failed!
jjethwa commented 7 years ago

Hi @dougereed

Can you provide the docker run line you're using? It looks like you're using the latest tag. I just pushed changes to switch from Debian Jessie to Stretch, but a fresh install was tested without the issue you're seeing.

dougereed commented 7 years ago

@jjethwa

docker run --rm -p 4440:4440 -e SERVER_URL='http://192.168.1.178:4440' -e RUNDECK_PASSWORD='xxxxxxxxxx' --name rundeck -t jordan/rundeck:latest
jjethwa commented 7 years ago

Hi @dougereed

That looks basic enough 😕 , I'm not sure why it's throwing an error for you. I just tried using the same command and had no issues. Can you try pulling the latest container down again or better yet one of the tagged releases as they are more for Production use? What version of docker are you using and what platform? Have you tried it without the --rm option? The --rm option is meant for transient containers mostly.

dougereed commented 7 years ago

@jjethwa Falling back to 2.8.2 works well. I'll debug for awhile and let you know what I find. Appreciate the support.

dougereed commented 7 years ago

@jjethwa Ok. I've narrowed it down to mapping a host directory structure onto the container's data volumes. I left this out of the original docker run command line to just try to simplify. When I re-tested what I sent you it works fine with the latest image.

Here is the complete docker run command. Falling back to 2.8.2 does work with with the external data volumes. I'm removing everything under /container_storage/rundeck, with a rm -rf /container_storage/rundeck, between runs so it's a clean container start. I also checked your Dockerfile to make sure nothing changed around the volumes between 2.8.2 and latest.

Docker is running on Ubuntu 16.04, and the version is:

Docker version 17.06.0-ce, build 02c1d87

sudo docker run  -p 4440:4440 \
         -e SERVER_URL='http://192.168.2.178:4440' \
         -e RUNDECK_PASSWORD='xxxxxxxxxxxx' \
         -v /container_storage/rundeck/etc:/etc/rundeck \
         -v /container_storage/rundeck/var:/var/rundeck \
         -v /container_storage/rundeck/lib:/var/lib/rundeck/.ssh \
         -v /container_storage/rundeck/lib-mysql:/var/lib/mysql \
         -v /container_storage/rundeck/log:/var/log/rundeck \
         -v /container_storage/rundeck/opt:/opt/rundeck-plugins \
         -v /container_storage/rundeck/lib-logs:/var/lib/rundeck/logs \
         -v /container_storage/rundeck/lib-storage:/var/lib/rundeck/var/storage \
         --name rundeck -t jordan/rundeck:latest

Here is the full output of the run command.

=>Initializing rundeck - This may take a few minutes
=>Generating rundeck key
Generating public/private rsa key pair.
Your identification has been saved in /var/lib/rundeck/.ssh/id_rsa.
Your public key has been saved in /var/lib/rundeck/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:7ilX0LigxWoFMY6XjwfBlj8nBsBsOT57CQ/k8PIfg/U rundeck@87708f640002
The key's randomart image is:
+---[RSA 4096]----+
| o.++o           |
|. Bo*+           |
| B.o==   o       |
|. B..+X + .      |
| o O.Oo=So       |
|  + X.E.. .      |
|   + o  ..       |
|    . ....       |
|       oo        |
+----[SHA256]-----+
=>/etc/rundeck empty...setting up defaults
=>Generating ssl cert
=>Initializing local MySQL...
=>MySQL datadir is empty...initializing
Installing MariaDB/MySQL system tables in '/var/lib/mysql' ...
2017-07-07 23:42:10 139841563652672 [Note] /usr/sbin/mysqld (mysqld 10.1.23-MariaDB-9+deb9u1) starting as process 94 ...
OK
Filling help tables...
2017-07-07 23:42:16 140702056849984 [Note] /usr/sbin/mysqld (mysqld 10.1.23-MariaDB-9+deb9u1) starting as process 123 ...
OK
Creating OpenGIS required SP-s...
2017-07-07 23:42:19 140183503090240 [Note] /usr/sbin/mysqld (mysqld 10.1.23-MariaDB-9+deb9u1) starting as process 152 ...
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER !
To do so, start the server, then issue the following commands:

'/usr/bin/mysqladmin' -u root password 'new-password'
'/usr/bin/mysqladmin' -u root -h 87708f640002 password 'new-password'

Alternatively you can run:
'/usr/bin/mysql_secure_installation'

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the MariaDB Knowledgebase at http://mariadb.com/kb or the
MySQL manual for more instructions.

You can start the MariaDB daemon with:
cd '/usr' ; /usr/bin/mysqld_safe --datadir='/var/lib/mysql'

You can test the MariaDB daemon with mysql-test-run.pl
cd '/usr/mysql-test' ; perl mysql-test-run.pl

Please report any problems at http://mariadb.org/jira

The latest information about MariaDB is available at http://mariadb.org/.
You can find additional information about the MySQL part at:
http://dev.mysql.com
Consider joining MariaDB's strong and vibrant community:
https://mariadb.org/get-involved/

=>Starting MySQL...ignore warning about debian-sys-maint user, it will be granted permissions momentarily
[ ok ] Starting MariaDB database server: mysqld.
[FAIL] Stopping MariaDB database server: mysqld failed!

This seems to be this line in /opt/run. https://github.com/jjethwa/rundeck/blob/master/content/opt/run#L117

jjethwa commented 7 years ago

Thanks so much, @dougereed I was able to reproduce the issue when using a volume for /var/lib/mysql (empty and with a populated DB already). It looks like there is a change with MariaDB and Debian. See: https://mariadb.atlassian.net/browse/MDEV-8375

I think I have a fix. Testing a bit more 😄

jjethwa commented 7 years ago

Hi @dougereed

Seems to be working well in my tests. Can you pull latest again and let me know? 😃

dougereed commented 7 years ago

@jjethwa - Thanks for the help. I pulled in your change and can also verify everything works.

doreplado commented 6 years ago

Not clear on the resolution here. I'm using the latest image and it still ignores the db I specify in the DATABASE_URL. Should I open a separate issue?

jjethwa commented 6 years ago

Hi @doreplado

If you're using an external MySQL/MariaDB instance, you need to set NO_LOCAL_MYSQL to true and set DATABASE_URL. Try that and let me know if it works 😄

jonguenther commented 6 years ago

I am trying to setup rundeck to use my mysql container, but it'll always exit with ERROR 2003 (HY000): Can't connect to MySQL server on 'mydomain' (110 "Connection timed out"). This, however, only occurs inside the container. I can connect to the database without any problems from any other container or machine.

My docker-compose.yml looks like this:

version: '2'
services:
  rundeck:
    image: jordan/rundeck
    volumes:
    - ./volume/etc:/etc/rundeck
    - ./volume/rundeck:/var/rundeck
    - ./volume/ssh:/var/lib/rundeck/.ssh
    - ./volume/logs:/var/log/rundeck
    - ./volume/rundeck_gui_log:/var/lib/rundeck/logs
    - ./volume/storage:/var/lib/rundeck/var/storage
    - ./volume/plugins:/opt/rundeck-plugins
    - ./volume/mysql:/var/lib/mysql
    environment:
    # reverse proxy
    - VIRTUAL_HOST=rundeck.mydomain
    - VIRTUAL_PORT=4440
    - LETSENCRYPT_HOST=rundeck.mydomain
    - LETSENCRYPT_EMAIL=sysadmin@mydomain
    # rundeck
    - EXTERNAL_SERVER_URL=https://rundeck.mydomain
    #- RUNDECK_WITH_SSL=false
    - DATABASE_URL=jdbc:mysql://mydomain:1337/rundeck?autoReconnect=true
    - RUNDECK_PASSWORD=verysecurepasswordbecauseiamnotusingsecrets
    - NO_LOCAL_MYSQL=true
    - RUNDECK_ADMIN_PASSWORD=somepass
    #- SKIP_DATABASE_SETUP=true
    expose:
    - 8814
    #restart: always
    #ports:
    # - 4440:4440

Note that I use an nginx reverse proxy in another container.

Is there a way to fix this or am I doing something wrong?

jjethwa commented 6 years ago

Hi @jonguenther

Are you able to connect to the remote database using the (MySQL/MariaDB) client inside the container? Try with the DNS name first and if that doesn't work, try the IP.

daaru00 commented 6 years ago

Hi @jjethwa

I've the same problem using a MySQL image, this is my docker-compose

version: '3'
services:
  rundeck:
    image: jordan/rundeck
    container_name: "rundeck"
    environment:
      DATABASE_URL: jdbc:mysql://rundeck-db/rundeckdb?autoReconnect=true
      RUNDECK_PASSWORD: dbpassword
      EXTERNAL_SERVER_URL: http://rundeck.docker:80
      NO_LOCAL_MYSQL: "true"
      GUI_BRAND_HTML: "Rundeck Test"
    ports:
     - "80"
    links:
     - mysql:rundeck-db

  mysql:
    image: "mysql:5.7"
    container_name: "rundeck-db"
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "true"
      MYSQL_USER: rundeck
      MYSQL_PASSWORD: dbpassword
      MYSQL_DATABASE: rundeckdb

I receiving ERROR 1044 (42000) at line 2: Access denied for user 'rundeck'@'%' to database 'rundeckdb' error on container startup.

I can login to the database from the inside of mysql container using: mysql -u rundeck -pdbpassword rundeckdb

I'm doing something wrong?

jjethwa commented 6 years ago

Hi @daaru00

I'm currently away from my laptop for another few days, but will look into the issue as soon as I'm back :smile: Can you login to the database from the Rundeck container using the CLI?

daaru00 commented 6 years ago

Can you login to the database from the Rundeck container using the CLI?

yes, I can connect without problem

evolv34 commented 6 years ago

Hi @daaru00 This configuration worked for me

version: '2.1'

services: 
  rundeck:
      image: <rundeck image name>
      hostname: rundeck
      healthcheck:
        test: ["CMD", "curl", "-f", "http://localhost:4440/menu/home"]
        interval: 50s
        timeout: 30s
        retries: 3
      depends_on:
        database:
          condition: service_healthy
      links:
        - database:database
      ports:
        - "4441:4440"
      environment:
        EXTERNAL_SERVER_URL: http://localhost:4440
        SKIP_DATABASE_SETUP: "false"
        NO_LOCAL_MYSQL: "true"
        DATABASE_URL: jdbc:mysql://database/rundeckdb
        DATABASE_ADMIN_USER: root
        RUNDECK_PASSWORD: root
        RUNDECK_STORAGE_PROVIDER: db

  database:
   image: mysql:5.6
   restart: always
   ports:
     - 3306:3306
   healthcheck:
     test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
     timeout: 20s
     retries: 10
   environment:
     MYSQL_ROOT_PASSWORD: root

. Hope it is helpful

sixcorners commented 6 years ago

I'm pretty sure an older version of this image let you use set the database name..

ddavison commented 6 years ago

after hours of research, i've isolated the problem to the SKIP_DATABASE_SETUP variable.

according to

 if [[ "${DATABASE_URL}" == *"mysql"* && "${SKIP_DATABASE_SETUP}" != "true" ]]; then
        echo "=>Initializing remote MySQL setup"
        (
         echo "CREATE DATABASE IF NOT EXISTS rundeckdb;"
         echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE, CREATE VIEW, ALTER, INDEX, EXECUTE ON rundeckdb.* TO 'rundeck'@'%' IDENTIFIED BY '${RUNDECK_PASSWORD}';"
         echo "quit"
         ) |
         mysql --host=$(echo ${DATABASE_URL} | grep -oP "(?<=jdbc:mysql:\/\/)(.*)(?=\/)") --user=${DATABASE_ADMIN_USER} --password=${DATABASE_ADMIN_PASSWORD}

since you are using the mysql:5.7 image (mariadb:10.3 in my case), the database is already setup. Since you didn't pass DATABASE_ADMIN_USER or DATABASE_ADMIN_PASSWORD, it's defaulting to rundeck, it's not able to connect.

since the rundeck user by default doesn't have elevated permissions, it can't create the database. I believe this is why we were getting the permission denied issue.

jjethwa commented 6 years ago

Thanks so much for researching and finding the issue, @ddavison 😄

I've added the details to the README: https://github.com/jjethwa/rundeck/commit/155db62ea3cdcc428f6a69b4f75a9f9f89b9e3f6

Do you have any suggestions that might make it easier? Thanks again!

ddavison commented 6 years ago

this issue in particular refers to the lack of documentation. considering commit 155db62, i believe we can close this issue. your commit looks clear! 👍

dbolotin commented 6 years ago

The following seems to be connected to the issue.

This commit seems to be wrong.

Because here: https://github.com/jjethwa/rundeck/blob/master/content/opt/run#L141 Access is still granted to the user rundeck, with password ${RUNDECK_PASSWORD}.

So, either:

In my case current code leads to:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
    at com.mysql.jdbc.Util.getInstance(Util.java:372)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:958)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872)
    at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2149)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2074)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:208)
    ... 16 more
Caused by: java.sql.SQLException: Access denied for user 'root'@'172.19.0.5' (using password: YES)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3835)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3771)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:870)
    at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1659)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1206)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2239)
    at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2090)
    ... 24 more

here is my docker-compose file:

       ....
                NO_LOCAL_MYSQL: "true"
                DATABASE_URL: "jdbc:mysql://db:3306/rundeckdb?autoReconnect=true"
                DATABASE_ADMIN_USER: "root"
                DATABASE_ADMIN_PASSWORD: "{{db_root_password}}"
                RUNDECK_PASSWORD: "{{db_rundeck_password}}"
      .....

I suggest renaming variable RUNDECK_PASSWORD to DATABASE_PASSWORD. And adding DATABASE_PASSWORD variable.

I can try to make a PR with the suggested modifications if you wish.

UPD: Here is my workaround for now:

                RUNDECK_PASSWORD: "{{db_root_password}}"
jjethwa commented 6 years ago

Hi @dbolotin

Thanks for looking into it! I don't think we want to revert the entire commit as it contains the Postgres setup. From the stacktrace you posted, it looks like the initial setup ( https://github.com/jjethwa/rundeck/blob/master/content/opt/run#L140-L144 ) fails due to restrictions for the root user. The default behaviour of MySQL/MariaDB restricts the root account to local access only for security reasons. I'm not 100% sure why setting the RUNDECK_PASSWORD variable to the db_root_password var works for you though 😕

dbolotin commented 6 years ago

I checked it, access was opened for 'root'@'%'.

Initial setup was executed successfully, setting ${RUNDECK_PASSWORD} for the rundeck DB user. The database was also created successfully.

While downstream, initialisation script sets ${DATABASE_ADMIN_USER} (root in my case) as DB username to be used by Rundeck itself. At the same time it sets password (here) to ${RUNDECK_PASSWORD} which obviously differs from the password for the root DB user.

jjethwa commented 6 years ago

Ah, I missed that @dbolotin https://github.com/jjethwa/rundeck/blob/master/content/opt/run#L182 definitely needs to be the rundeck user, not the admin user. I'll make the change now 😄