Project

General

Profile

Install Redmine 346 on Centos 75 » History » Version 5

Franck Michel, 2018-10-02 14:39

1 1 Franck Michel
h1. Installation of Redmine 3.4.6 on CentOS 7.5 + MySQL 8, Apache 2.4, GIT, SVN, LDAP
2
3
{{>toc}} 
4
5 2 Franck Michel
This guide presents an installation procedure for Redmine 3.4.6 on a CentOS 7. I wrote it as I was painfully going through multiple HOW-TOs and forums, fixing one error after the other. As a result, there was much back-and-forth before coming up with the right procedure. I tried to detail things as much as I felt necessary.
6 1 Franck Michel
7
The procedure results of a mix of many different sources for which I give the source URLs in text below.
8
9
Basics like installing CentOS, Apache, or configuring a certificate for Apache are not covered.
10
11
Here is the full configuration I got after this installation:
12
* CentOS Linux release 7.5.1804 (Core) 
13
* Apache 2.4 (this is important as there were quite some configuration syntax changes since 2.2)
14
* MySQL 8.0
15
* Redmine 3.4.6
16
* Ruby 2.4.4
17
* Apache Passenger 5.3.4
18
* Integration with Git and Svn
19
* Integration with LDAP
20
21
22
h2. Install MySQL 8 
23
24
Adapted from "this page":https://www.if-not-true-then-false.com/2010/install-mysql-on-fedora-centos-red-hat-rhel/.
25
26
h3. Why MySQL 8?
27
28
Basically, I first mistakenly installed MySQL 8. Then I uninstalled it and installed 5.7, but then for some reason I could not complete the installation of Redmine. So I reinstalled MySQL 8, and it works fine so far. 
29
30
<pre>
31
[As root/sudo]:
32
  yum update -y
33
  yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
34
  yum --disablerepo=mysql80-community install mysql-community-server mysql-devel
35
  systemctl start mysqld.service
36
  systemctl enable mysqld.service
37
</pre>
38
39
If you prefer to stick to MySQL 5.7, replace the yum install line as follows:
40
<pre>
41
  yum --disablerepo=mysql80-community --enablerepo=mysql57-community install mysql-community-server mysql-devel
42
</pre>
43
44
45
Get the password created at installation and run the secure procedure
46
<pre>
47 2 Franck Michel
  grep 'A temporary password is generated for root@localhost' /var/log/mysqld.log | tail -1
48
  /usr/bin/mysql_secure_installation
49 1 Franck Michel
</pre>
50
51
h3. Bind-address
52
53
By default, MySQL 8 has a bind-address set to 127.0.0.1. If you want to use another hostname, or if it is on a different server than Redmine, then set property bind-address appropriately in MySQL config file (likely @/etc/my.cnf@).
54
55
h3. Default password policy
56
57
By default, MySQL 8 sets the default password policy to "caching_sha2_password". Redmine can deal with it but not the Apache module that authenticated git/svn users against the database, and this will generate an error when accessing the repository. Therefore, change the default policy in MySQL config file (likely /etc/my.cnf) by uncommenting the line:
58
<pre>
59
  default-authentication-plugin=mysql_native_password
60
</pre>
61
62
63
h2. Install Ruby 2.4
64
65
Adapted from "this page":https://tecadmin.net/install-ruby-previous-stable-centos/.
66
67
<pre>
68
[As root/sudo]:
69
  yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel \
70
       libyaml-devel libffi-devel openssl-devel make \
71
       bzip2 autoconf automake libtool bison iconv-devel sqlite-devel
72
  curl -sSL https://rvm.io/mpapis.asc | gpg --import -
73
  curl -L get.rvm.io | bash -s stable
74
  source /etc/profile.d/rvm.sh
75
  rvm reload
76
  rvm requirements run
77
  rvm install 2.4
78
  rvm list
79
  ruby --version
80
</pre>
81
    
82
Find the Gem installation path and set the $GEMS variable accordingly, we will use it in later steps, e.g. in my case that was:
83
<pre>
84
  export GEMS=/usr/local/rvm/gems/ruby-2.4.4/gems
85
</pre>
86
87
88
h2. Install Redmine
89
90
Adapted from "this page":https://www.redmine.org/projects/redmine/wiki/RedmineInstall.
91
92
Below, Redmine is installed in directory /home/username/
93
94
h3. Download and untar Redmine, install Ruby packages:
95
96
<pre>
97
[As non-root]:
98
  cd /home/username
99
  wget https://www.redmine.org/releases/redmine-3.4.6.tar.gz
100
  tar xvfz redmine-3.4.6.tar.gz
101
  export REDMINE=/home/username/redmine-3.4.6
102
  cd $REDMINE
103
  cp config/database.yml.example config/database.yml
104
</pre>
105
106
Customize $REDMINE/config/database.yml as explained in the "procedure":https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-3-Database-connection-configuration.
107
108
Install GEMS dependencies:
109
<pre>
110
[As root/sudo]:
111
  cd $REDMINE
112
  gem install bundler
113
  bundle install --without development test
114
  bundle exec rake generate_secret_token
115
  RAILS_ENV=production REDMINE_LANG=en bundle exec rake redmine:load_default_data
116
</pre>
117
118
Let's now make sure that Redmine can start using Webricks (later on we shall Apache instead, but that helps checks if there are any issues so far):
119
<pre>
120
[As root/sudo]:
121
  cd $REDMINE
122
  bundle exec rails server webrick -e production
123
</pre>
124 2 Franck Michel
and browse to http://localhost:3000/. Alternatively, this other command should work exactly the same:
125 1 Franck Michel
<pre>
126
[As root/sudo]:
127
  ruby bin/rails server webrick -e production
128
</pre>
129
130
Note that at this point some HOW-TOs recommand the installation of FastCGI. In this configuation described on this page, I found out that was not necessary.
131
132
133
h3. Install Apache Passenger (an Apache plugin for Ruby environments)
134
135
Adapted from "this page":https://www.vincentliefooghe.net/content/utilisation-apache-passenger-pour-redmine.
136
<pre>
137
[As root/sudo]:
138
  yum install -y httpd-devel libcurl-devel apr-devel apr-util-devel mod_ssl
139
  cd $REDMINE
140
  gem install passenger
141
</pre>
142
143
Find out the installation path of Passenger, and call the Apache module installer, e.g. in my case:
144
<pre>
145
  $GEMS/passenger-5.3.4/bin/passenger-install-apache2-module
146
</pre>
147
148 2 Franck Michel
Follow the steps indicated by the tool. This should include creating an Apache module configuration file. I created /etc/httpd/conf.modules.d/pasenger.conf, you should adapt the Ruby and Passenger paths according to the versions installed above:
149 1 Franck Michel
<pre>
150
  LoadModule passenger_module /usr/local/rvm/gems/ruby-2.4.4/gems/passenger-5.3.4/buildout/apache2/mod_passenger.so
151
  <IfModule mod_passenger.c>
152
    PassengerRoot /usr/local/rvm/gems/ruby-2.4.4/gems/passenger-5.3.4
153
    PassengerDefaultRuby /usr/local/rvm/gems/ruby-2.4.4/wrappers/ruby
154
  </IfModule>
155
</pre>
156
157
h3. Configure Apache as the front end for Redmine
158
159
*IMPORTANT NOTE*:
160 2 Franck Michel
Directives Allow, Deny, Order are obsolete as of Apache 2.4, but you can still use them for compatibility reasons. However, mixing the new Require directives with the former ones has unexpected results. So, _do not blindly copy/paste examples you shall find on the Web_, most of them are deprecated and will screw your configuration! See "details":https://httpd.apache.org/docs/2.4/en/howto/access.html.
161 1 Franck Michel
162
As root, create a virtual host entry in /etc/httpd/conf.d/redmine.conf (adapt the paths to your installation):
163
<pre>
164
    <VirtualHost *:80>
165
        ServerName youserver.domain.org
166
        DocumentRoot "/home/username/redmine-3.4.6/public"
167
        
168
        ErrorLog logs/redmine_error_log
169
        LogLevel warn
170
171
        <Directory "/home/username/redmine-3.4.6/public">
172
            Options Indexes ExecCGI FollowSymLinks
173
            Require all granted
174
            AllowOverride all
175
        </Directory>
176
    </VirtualHost>
177
</pre>
178
179
Give Apache write access to some directories. Check the Apache user by looking for propertues @User@ and @Group@ in the Apache main configuraton file (in /etc/httpd/conf or /etc/apache/conf). This is "apache" in my case, but could also be "www-data" in different packagings.
180
<pre>
181
  cd $REDMINE
182
  chown -R apache:apache files log tmp vendor
183
</pre>
184
Restart apache:
185
<pre>
186
  systemctl restart httpd
187
</pre>
188
There you go: browse to http://youserver.domain.org, you should get the login page. Hurah!
189
Login with default login "admin" and password "admin", and of course, change the admin password immediatly.
190
191
192
h3. Email config with sendmail
193
194
As non-root, edit @$REDMINE/config/configuration.yml@ and uncomment the 2 lines concerning sendmail:
195
<pre>
196
    email_delivery:
197
      delivery_method:sendmail
198
</pre>
199
200
And install sendmail if it is not yet installed:
201
<pre>
202
[As root/sudo]:
203
  yum install -y sendmail sendmail-cf
204
</pre>
205
206
h3. LDAP authentication
207
208
Ask the LDAP details to your administrator and set them in the Web interface: Admin > LDAP authentication
209
210 5 Franck Michel
h2. SCM Repos integration - Preliminary
211 1 Franck Michel
212
Enable the Web Service for repository management: go to "Administration -> Settings -> Repository" and check "Enable WS for repository management", then clik on "Generate a key" to create a new WS key and save the key that you will use below.
213
214
The reposman.rb script needs @activeresource@ to work, run this (if this is already installed, this will just do nothing):
215
<pre>
216
[As root]:
217
    cd $REDMINE
218
    gem install activeresource
219
</pre>
220
    
221
To restrict the access to the WS, secure the Apache configuration by adding this to the 
222
VirtualHost configuration (/etc/httpd/conf.d/redmine.conf above). Reminder: this is an Apache 2.4 syntax.
223
<pre>
224
   <Location /sys>
225
      Require host youserver.domain.org sparks-vm5.i3s.unice.fr localhost
226
      Require all denied
227
   </Location>
228
</pre>
229
230
Install Apache packages needed to use the database for authentication (with Git as well as Svn):
231
<pre>
232
[As root/sudo]:
233
    yum install -y mod_perl perl-DBI perl-DBD-MySQL perl-Digest-SHA1 perl-LDAP
234
</pre>
235
236 2 Franck Michel
Unlike in other HOW-TOs, there should be no need to use CPAN to install the DBI Perl module for Apache, it must have been installed with perl-DBI. Check where @DBI.pm@ was installed. In my case, it was in /usr/lib64/perl5/vendor_perl, not in /usr/lib/perl5/Apache as often mentioned in other HOW-TOs. Therefore, in the config below, I simply changed the "PerlLoadModule Apache::DBI" (that I found in many examples) into "PerlLoadModule DBI".
237 1 Franck Michel
238 2 Franck Michel
Also, link $REDMINE/extra/svn/Redmine.pm into Apache's PERL scripts. You should check the appropriate path, in my case this is /usr/lib64/perl5/vendor_perl/.
239 1 Franck Michel
<pre>
240
[As root/sudo]:
241
    mkdir /usr/lib64/perl5/vendor_perl/Apache/Authn
242
    ln -s $REDMINE/extra/svn/Redmine.pm /usr/lib64/perl5/vendor_perl/Authn/Apache
243
</pre>
244
245
Optional: to allow for LDAP authentication, install the Simple LDAP modules with CPAN. In my cases, it required dependencies Modules::Build and Params::Validate:
246
<pre>
247
[As root/sudo]:
248
    cpan
249
    install Modules::Build
250
    install Params::Validate
251
    install Authen::Simple::LDAP
252
</pre>
253
254
Update the Apache Redmine configuration (redmine.conf) as shown below:
255
<pre>
256
    PerlLoadModule Apache::Authn::Redmine
257
    PerlLoadModule Redmine
258
259
    # Enable connection pooling (useful for checkouts with many files)
260
    PerlModule DBI
261
    PerlOptions +GlobalRequest
262
263
    # Enable LDAP(S) authentication (optional)
264
    PerlLoadModule Authen::Simple::LDAP
265
    PerlLoadModule IO::Socket::SSL
266
</pre>
267
268
*Possible authentication issue*: MySQL 8 sets the default password policy to "caching_sha2_password". @Redmine.pm@ is not compatible with that and will generate a weird error in the Apache redmine_error_log, like this:
269
<pre>
270
    Can't call method "prepare" on an undefined value at /usr/lib64/perl5/vendor_perl/Apache/Redmine.pm line 364, <DATA> line 747.\n
271
</pre>
272
A closer look at the regular Apache error_log shows another error:
273
<pre>
274
    DBI connect('database=redmine;host=127.0.0.1','redmine',...) failed: Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory at /usr/lib64/perl5/vendor_perl/Apache/Redmine.pm line 557.
275
</pre>
276
277
To fix this, change MySQL's password policy for user redmine (found "here":https://my.oschina.net/johnsken/blog/1840348):
278
<pre>
279
    mysql -uroot -p
280
    mysql> show variables like 'default_authentication_plugin';
281
    +-------------------------------+-----------------------+
282
    | Variable_name                 | Value                 |
283
    +-------------------------------+-----------------------+
284
    | default_authentication_plugin | caching_sha2_password |
285
    +-------------------------------+-----------------------+
286
287
    mysql> select host,user,plugin from mysql.user;
288
    +-----------+------------------+-----------------------+
289
    | host      | user             | plugin                |
290
    +-----------+------------------+-----------------------+
291
    | localhost | mysql.infoschema | caching_sha2_password |
292
    | localhost | mysql.session    | caching_sha2_password |
293
    | localhost | mysql.sys        | caching_sha2_password |
294
    | localhost | redmine          | caching_sha2_password |
295
    | localhost | root             | caching_sha2_password |
296
    +-----------+------------------+-----------------------+
297
298
    mysql> ALTER USER 'redmine'@'localhost' IDENTIFIED WITH mysql_native_password BY '<YOUR REDMINE PASSWORD>';
299
    Query OK, 0 rows affected (0,10 sec)
300
301
    mysql> select host,user,plugin from mysql.user;
302
    +-----------+------------------+-----------------------+
303
    | host      | user             | plugin                |
304
    +-----------+------------------+-----------------------+
305
    | localhost | mysql.infoschema | caching_sha2_password |
306
    | localhost | mysql.session    | caching_sha2_password |
307
    | localhost | mysql.sys        | caching_sha2_password |
308
    | localhost | redmine          | mysql_native_password |
309
    | localhost | root             | caching_sha2_password |
310
    +-----------+------------------+-----------------------+
311
</pre>
312
313
h2. SVN integration
314
315
h3. Repositories access control with Apache 2.4 with mod_dav_svn and mod_perl
316
317
Adapted from "this page":https://www.redmine.org/projects/redmine/wiki/HowTo_configure_Redmine_for_advanced_Subversion_integration, section "Using apache/mod_dav_svn/mod_perl".
318
319
Make sure SVN CLI packages are already installed.
320
<pre>
321
    yum -y install svn
322
</pre>
323
324
Create the directory where all SVN repos will/have to be stored:
325
<pre>
326
[As root/sudo]:
327
    export SVN=/var/lib/svn
328
    mkdir $SVN
329
    chown apache:apache $SVN
330
    chmod 0750 $SVN
331
</pre>
332
333 3 Franck Michel
Then, there are two options to attach an SVN repository to a project:
334 1 Franck Michel
335 4 Franck Michel
_1. Explicitly attach a repo to a project_
336 3 Franck Michel
337
Copy an existing repository to $SVN, or create an new empty repository, like this:
338
<pre>
339
    svnadmin create $SVN/<repo_name>
340
</pre>
341
342
Then, on the web interface, select the project you want to attach the repo to, go to Settings > Repositories > New repository. The repo URL should be @/var/lib/svn/<repo_name>@ in the example above.
343 1 Franck Michel
344 3 Franck Michel
345 4 Franck Michel
_2. Automatically attach SVN repos to declared projects_
346 3 Franck Michel
347
You can also ask Redmine to automatically attach SVN repos to declared projects, the only requirement is that the project and the repository have the same name.
348 1 Franck Michel
<pre>
349
[As root/sudo]:
350
    cd $REDMINE/extra/svn
351
    ruby reposman.rb --redmine https://youserver.domain.org --svn-dir $SVN \
352
                     --owner apache --url http://youserver.domain.org/svn/ \
353
                     --verbose --key=<ws_key>
354
</pre>
355
356
In my case, I had declared a single test project, here is the result:
357
<pre>
358
    querying Redmine for active projects with repository module enabled...
359
    retrieved  projects
360
    processing project test (test)
361
        repository /var/lib/svn/test created
362
        repository /var/lib/svn/test registered in Redmine with url http://youserver.domain.org/svn/test
363
</pre>
364
365
h3. SVN access from Apache
366
367 2 Franck Michel
At this point, we have Redmine configured to create repositories for existing projects. We now have to configure Apache to allow browsing the repos from outside Redmine (typically with an SVN client but also simply with a web browser).
368 1 Franck Michel
369
Install Apache needed packages: 
370
<pre>
371
[As root/sudo]:
372
    yum install -y mod_dav_svn
373
</pre>
374
375
The installation should add loading of DAV and SVN modules to the Apache configuration. Check and fix this if necessary:
376
<pre>
377
    $ cat /etc/httpd/conf.modules.d/00-dav.conf 
378
    LoadModule dav_module modules/mod_dav.so
379
    LoadModule dav_fs_module modules/mod_dav_fs.so
380
    LoadModule dav_lock_module modules/mod_dav_lock.so
381
382
    $ cat /etc/httpd/conf.modules.d/10-subversion.conf 
383
    LoadModule dav_svn_module     modules/mod_dav_svn.so
384
    LoadModule authz_svn_module   modules/mod_authz_svn.so
385
    LoadModule dontdothat_module  modules/mod_dontdothat.so
386
</pre>
387
388
Update the Apache Redmine configuration (redmine.conf) as shown below. Note that there is no need for a <Location /svn-private> section as shown in older HOW-TOs.
389
390
<pre>
391
    # Enable SVN access from outside Redmine (web browser, SVN client)
392
    <Location /svn>
393
        DAV svn
394
        SVNParentPath "/var/lib/svn"
395
        SVNReposName "Subversion Repository" 
396
        Require all denied
397
398
        # Uncomment the following line when using subversion 1.8 or newer
399
        # (see http://subversion.apache.org/docs/release-notes/1.8.html#serf-skelta-default)
400
        # SVNAllowBulkUpdates Prefer
401
402
        # If a client tries to svn update which involves updating many files,
403
        # the update request might result in an error Server sent unexpected
404
        # return value (413 Request Entity Too Large) in response to REPORT
405
        # request, because the size of the update request exceeds the limit
406
        # allowed by the server. You can avoid this error by disabling the
407
        # request size limit by adding the line LimitXMLRequestBody 0
408
        LimitXMLRequestBody 0
409
410
        # Only check Authentication for root path, nor again for recursive folder.
411
        # Redmine core does only permit access on repository level, so this
412
        # doesn't hurt security. On the other hand it does boost performance a lot!
413
        SVNPathAuthz off
414
415
        PerlAccessHandler Apache::Authn::Redmine::access_handler
416
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
417
        AuthType Basic
418
        AuthName "Redmine SVN Repository" 
419
        AuthUserFile /dev/null
420
421
        # Read-only access    
422
        <Limit GET PROPFIND OPTIONS REPORT>
423
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
424
            <RequireAny>
425
                Require valid-user
426
                Require local
427
            </RequireAny>
428
        </Limit>
429
430
        # Write access (methods POST, PUT)
431
        <LimitExcept GET PROPFIND OPTIONS REPORT>
432
            Require valid-user
433
        </LimitExcept>
434
435
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
436
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
437
        RedmineDbUser "redmine" 
438
        RedmineDbPass "<password>" 
439
    </Location>
440
</pre>
441
442
h2. Git integration
443
444
Create the directory where all GIT repos will/have to be stored:
445
<pre>
446
[As root/sudo]:
447
    export GIT=/var/lib/git
448
    mkdir $GIT
449
    chown apache:apache $GIT
450
    chmod 0750 $GIT
451
</pre>
452
453 2 Franck Michel
Note: Redmine can only deal with bare Git repositories (see http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/). You can get a bare Git repo in two ways: "git init --bare" or "git close --bare ...".
454 1 Franck Michel
455 2 Franck Michel
In the case of a fresh new local repository (git init --bare), Redmine will be able to display its content only after the first commit. Try this:
456 1 Franck Michel
457
<pre>
458
[As root/sudo]:
459
    # Create a local bare repo
460
    mkdir -p $GIT/test.git
461
    chown apache:apache $GIT/test.git/
462
    cd $GIT/test.git/
463
    git init --bare
464
465
    # Create another repo as a clone of the previous one, make one commit and push.
466
    cd ..
467
    mkdir -p $GIT/test.local.git
468
    cd $GIT/test.local.git/
469
    git init
470
    touch TEST.txt
471
    git add TEST.txt
472
    git commit -m "repository initalization" 
473
    git push $GIT/test.git/ master
474
</pre>
475
476
Now that there is commit in your bare repo, you can browse it via Redmine: create a project and attach test.git as the main repo. Then go to the Repository tab, you should see the log of the first commit.
477
478
Update the Apache Redmine configuration (redmine.conf) as shown below. Note that there is no need for a <Location /git-private> section as shown in older HOW-TOs.
479
480
<pre>
481
    #--- Enable Git access from outside Redmine
482
    ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
483
    
484
    SetEnv GIT_PROJECT_ROOT /var/lib/git
485
    SetEnv GIT_HTTP_EXPORT_ALL
486
487
    <Location /git>
488
        SSLRequireSSL
489
        PerlAccessHandler Apache::Authn::Redmine::access_handler
490
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
491
        AuthType Basic
492
        AuthName "Redmine Git Repository" 
493
        AuthUserFile /dev/null
494
        Require all denied
495
        
496
        <Limit GET PROPFIND OPTIONS REPORT>
497
            Options Indexes FollowSymLinks MultiViews
498
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
499
            <RequireAny>
500
                Require valid-user
501
                Require local
502
            </RequireAny>
503
        </Limit>
504
505
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
506
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
507
        RedmineDbUser "redmine" 
508
        RedmineDbPass "<password>"
509
        RedmineGitSmartHttp yes
510
    </Location>
511
</pre>