Project

General

Profile

Install Redmine 346 on Centos 75 » History » Version 1

Franck Michel, 2018-10-01 22:38

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
This guide presents an installation procedure for Redmine 3.4.6 on a CentOS 7.
6
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.
7
8
The procedure results of a mix of many different sources for which I give the source URLs in text below.
9
10
Basics like installing CentOS, Apache, or configuring a certificate for Apache are not covered.
11
12
Here is the full configuration I got after this installation:
13
* CentOS Linux release 7.5.1804 (Core) 
14
* Apache 2.4 (this is important as there were quite some configuration syntax changes since 2.2)
15
* MySQL 8.0
16
* Redmine 3.4.6
17
* Ruby 2.4.4
18
* Apache Passenger 5.3.4
19
* Integration with Git and Svn
20
* Integration with LDAP
21
22
23
h2. Install MySQL 8 
24
25
Adapted from "this page":https://www.if-not-true-then-false.com/2010/install-mysql-on-fedora-centos-red-hat-rhel/.
26
27
h3. Why MySQL 8?
28
29
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. 
30
31
<pre>
32
[As root/sudo]:
33
  yum update -y
34
  yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
35
  yum --disablerepo=mysql80-community install mysql-community-server mysql-devel
36
  systemctl start mysqld.service
37
  systemctl enable mysqld.service
38
</pre>
39
40
If you prefer to stick to MySQL 5.7, replace the yum install line as follows:
41
<pre>
42
  yum --disablerepo=mysql80-community --enablerepo=mysql57-community install mysql-community-server mysql-devel
43
</pre>
44
45
46
Get the password created at installation and run the secure procedure
47
<pre>
48
    grep 'A temporary password is generated for root@localhost' /var/log/mysqld.log | tail -1
49
    /usr/bin/mysql_secure_installation
50
</pre>
51
52
h3. Bind-address
53
54
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@).
55
56
h3. Default password policy
57
58
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:
59
<pre>
60
  default-authentication-plugin=mysql_native_password
61
</pre>
62
63
64
h2. Install Ruby 2.4
65
66
Adapted from "this page":https://tecadmin.net/install-ruby-previous-stable-centos/.
67
68
<pre>
69
[As root/sudo]:
70
  yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel \
71
       libyaml-devel libffi-devel openssl-devel make \
72
       bzip2 autoconf automake libtool bison iconv-devel sqlite-devel
73
  curl -sSL https://rvm.io/mpapis.asc | gpg --import -
74
  curl -L get.rvm.io | bash -s stable
75
  source /etc/profile.d/rvm.sh
76
  rvm reload
77
  rvm requirements run
78
  rvm install 2.4
79
  rvm list
80
  ruby --version
81
</pre>
82
    
83
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:
84
<pre>
85
  export GEMS=/usr/local/rvm/gems/ruby-2.4.4/gems
86
</pre>
87
88
89
h2. Install Redmine
90
91
Adapted from "this page":https://www.redmine.org/projects/redmine/wiki/RedmineInstall.
92
93
Below, Redmine is installed in directory /home/username/
94
95
h3. Download and untar Redmine, install Ruby packages:
96
97
<pre>
98
[As non-root]:
99
  cd /home/username
100
  wget https://www.redmine.org/releases/redmine-3.4.6.tar.gz
101
  tar xvfz redmine-3.4.6.tar.gz
102
  export REDMINE=/home/username/redmine-3.4.6
103
  cd $REDMINE
104
  cp config/database.yml.example config/database.yml
105
</pre>
106
107
Customize $REDMINE/config/database.yml as explained in the "procedure":https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-3-Database-connection-configuration.
108
109
Install GEMS dependencies:
110
<pre>
111
[As root/sudo]:
112
  cd $REDMINE
113
  gem install bundler
114
  bundle install --without development test
115
  bundle exec rake generate_secret_token
116
  RAILS_ENV=production REDMINE_LANG=en bundle exec rake redmine:load_default_data
117
</pre>
118
119
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):
120
<pre>
121
[As root/sudo]:
122
  cd $REDMINE
123
  bundle exec rails server webrick -e production
124
</pre>
125
and browse to http://localhost:3000/. 
126
Alternatively, this other command should work exactly the same:
127
<pre>
128
[As root/sudo]:
129
  ruby bin/rails server webrick -e production
130
</pre>
131
132
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.
133
134
135
h3. Install Apache Passenger (an Apache plugin for Ruby environments)
136
137
Adapted from "this page":https://www.vincentliefooghe.net/content/utilisation-apache-passenger-pour-redmine.
138
<pre>
139
[As root/sudo]:
140
  yum install -y httpd-devel libcurl-devel apr-devel apr-util-devel mod_ssl
141
  cd $REDMINE
142
  gem install passenger
143
</pre>
144
145
Find out the installation path of Passenger, and call the Apache module installer, e.g. in my case:
146
<pre>
147
  $GEMS/passenger-5.3.4/bin/passenger-install-apache2-module
148
</pre>
149
150
Follow the steps indicated by the tool. This should include creating an Apache module configuration file.
151
I created /etc/httpd/conf.modules.d/pasenger.conf, you should adapt the Ruby and Passenger paths according to the versions installed above:
152
<pre>
153
  LoadModule passenger_module /usr/local/rvm/gems/ruby-2.4.4/gems/passenger-5.3.4/buildout/apache2/mod_passenger.so
154
  <IfModule mod_passenger.c>
155
    PassengerRoot /usr/local/rvm/gems/ruby-2.4.4/gems/passenger-5.3.4
156
    PassengerDefaultRuby /usr/local/rvm/gems/ruby-2.4.4/wrappers/ruby
157
  </IfModule>
158
</pre>
159
160
h3. Configure Apache as the front end for Redmine
161
162
*IMPORTANT NOTE*:
163
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!
164
See "details":https://httpd.apache.org/docs/2.4/en/howto/access.html.
165
166
As root, create a virtual host entry in /etc/httpd/conf.d/redmine.conf (adapt the paths to your installation):
167
<pre>
168
    <VirtualHost *:80>
169
        ServerName youserver.domain.org
170
        DocumentRoot "/home/username/redmine-3.4.6/public"
171
        
172
        ErrorLog logs/redmine_error_log
173
        LogLevel warn
174
175
        <Directory "/home/username/redmine-3.4.6/public">
176
            Options Indexes ExecCGI FollowSymLinks
177
            Require all granted
178
            AllowOverride all
179
        </Directory>
180
    </VirtualHost>
181
</pre>
182
183
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.
184
<pre>
185
  cd $REDMINE
186
  chown -R apache:apache files log tmp vendor
187
</pre>
188
Restart apache:
189
<pre>
190
  systemctl restart httpd
191
</pre>
192
There you go: browse to http://youserver.domain.org, you should get the login page. Hurah!
193
Login with default login "admin" and password "admin", and of course, change the admin password immediatly.
194
195
196
h3. Email config with sendmail
197
198
As non-root, edit @$REDMINE/config/configuration.yml@ and uncomment the 2 lines concerning sendmail:
199
<pre>
200
    email_delivery:
201
      delivery_method:sendmail
202
</pre>
203
204
And install sendmail if it is not yet installed:
205
<pre>
206
[As root/sudo]:
207
  yum install -y sendmail sendmail-cf
208
</pre>
209
210
h3. LDAP authentication
211
212
Ask the LDAP details to your administrator and set them in the Web interface: Admin > LDAP authentication
213
214
215
h3. SCM Repos integration
216
217
218
h4. Preliminary
219
220
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.
221
222
The reposman.rb script needs @activeresource@ to work, run this (if this is already installed, this will just do nothing):
223
<pre>
224
[As root]:
225
    cd $REDMINE
226
    gem install activeresource
227
</pre>
228
    
229
To restrict the access to the WS, secure the Apache configuration by adding this to the 
230
VirtualHost configuration (/etc/httpd/conf.d/redmine.conf above). Reminder: this is an Apache 2.4 syntax.
231
<pre>
232
   <Location /sys>
233
      Require host youserver.domain.org sparks-vm5.i3s.unice.fr localhost
234
      Require all denied
235
   </Location>
236
</pre>
237
238
Install Apache packages needed to use the database for authentication (with Git as well as Svn):
239
<pre>
240
[As root/sudo]:
241
    yum install -y mod_perl perl-DBI perl-DBD-MySQL perl-Digest-SHA1 perl-LDAP
242
</pre>
243
244
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.
245
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.
246
Therefore, in the config below, I simply changed the "PerlLoadModule Apache::DBI" (that I found in many examples) into "PerlLoadModule DBI".
247
248
Also, link $REDMINE/extra/svn/Redmine.pm into Apache's PERL scripts.
249
You should check the appropriate path, in my case this is /usr/lib64/perl5/vendor_perl/.
250
<pre>
251
[As root/sudo]:
252
    mkdir /usr/lib64/perl5/vendor_perl/Apache/Authn
253
    ln -s $REDMINE/extra/svn/Redmine.pm /usr/lib64/perl5/vendor_perl/Authn/Apache
254
</pre>
255
256
Optional: to allow for LDAP authentication, install the Simple LDAP modules with CPAN. In my cases, it required dependencies Modules::Build and Params::Validate:
257
<pre>
258
[As root/sudo]:
259
    cpan
260
    install Modules::Build
261
    install Params::Validate
262
    install Authen::Simple::LDAP
263
</pre>
264
265
Update the Apache Redmine configuration (redmine.conf) as shown below:
266
<pre>
267
    PerlLoadModule Apache::Authn::Redmine
268
    PerlLoadModule Redmine
269
270
    # Enable connection pooling (useful for checkouts with many files)
271
    PerlModule DBI
272
    PerlOptions +GlobalRequest
273
274
    # Enable LDAP(S) authentication (optional)
275
    PerlLoadModule Authen::Simple::LDAP
276
    PerlLoadModule IO::Socket::SSL
277
</pre>
278
279
*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:
280
<pre>
281
    Can't call method "prepare" on an undefined value at /usr/lib64/perl5/vendor_perl/Apache/Redmine.pm line 364, <DATA> line 747.\n
282
</pre>
283
A closer look at the regular Apache error_log shows another error:
284
<pre>
285
    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.
286
</pre>
287
288
To fix this, change MySQL's password policy for user redmine (found "here":https://my.oschina.net/johnsken/blog/1840348):
289
<pre>
290
    mysql -uroot -p
291
    mysql> show variables like 'default_authentication_plugin';
292
    +-------------------------------+-----------------------+
293
    | Variable_name                 | Value                 |
294
    +-------------------------------+-----------------------+
295
    | default_authentication_plugin | caching_sha2_password |
296
    +-------------------------------+-----------------------+
297
298
    mysql> select host,user,plugin from mysql.user;
299
    +-----------+------------------+-----------------------+
300
    | host      | user             | plugin                |
301
    +-----------+------------------+-----------------------+
302
    | localhost | mysql.infoschema | caching_sha2_password |
303
    | localhost | mysql.session    | caching_sha2_password |
304
    | localhost | mysql.sys        | caching_sha2_password |
305
    | localhost | redmine          | caching_sha2_password |
306
    | localhost | root             | caching_sha2_password |
307
    +-----------+------------------+-----------------------+
308
309
    mysql> ALTER USER 'redmine'@'localhost' IDENTIFIED WITH mysql_native_password BY '<YOUR REDMINE PASSWORD>';
310
    Query OK, 0 rows affected (0,10 sec)
311
312
    mysql> select host,user,plugin from mysql.user;
313
    +-----------+------------------+-----------------------+
314
    | host      | user             | plugin                |
315
    +-----------+------------------+-----------------------+
316
    | localhost | mysql.infoschema | caching_sha2_password |
317
    | localhost | mysql.session    | caching_sha2_password |
318
    | localhost | mysql.sys        | caching_sha2_password |
319
    | localhost | redmine          | mysql_native_password |
320
    | localhost | root             | caching_sha2_password |
321
    +-----------+------------------+-----------------------+
322
</pre>
323
324
325
h2. SVN integration
326
327
328
h3. Repositories access control with Apache 2.4 with mod_dav_svn and mod_perl
329
330
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".
331
332
Make sure SVN CLI packages are already installed.
333
<pre>
334
    yum -y install svn
335
</pre>
336
337
Create the directory where all SVN repos will/have to be stored:
338
<pre>
339
[As root/sudo]:
340
    export SVN=/var/lib/svn
341
    mkdir $SVN
342
    chown apache:apache $SVN
343
    chmod 0750 $SVN
344
</pre>
345
346
_If necessary_, create new (empty) SVN repos for all declared projects:
347
<pre>
348
[As root/sudo]:
349
    cd $REDMINE/extra/svn
350
    ruby reposman.rb --redmine https://youserver.domain.org --svn-dir $SVN \
351
                     --owner apache --url http://youserver.domain.org/svn/ \
352
                     --verbose --key=<ws_key>
353
</pre>
354
355
In my case, I had declared a single test project, here is the result:
356
<pre>
357
    querying Redmine for active projects with repository module enabled...
358
    retrieved  projects
359
    processing project test (test)
360
        repository /var/lib/svn/test created
361
        repository /var/lib/svn/test registered in Redmine with url http://youserver.domain.org/svn/test
362
</pre>
363
364
h3. SVN access from Apache
365
366
At this point, we have Redmine configured to create repositories for existing projects.
367
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
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
443
h2. Git integration
444
445
Create the directory where all GIT repos will/have to be stored:
446
<pre>
447
[As root/sudo]:
448
    export GIT=/var/lib/git
449
    mkdir $GIT
450
    chown apache:apache $GIT
451
    chmod 0750 $GIT
452
</pre>
453
454
Note: Redmine can only deal with bare Git repositories (see http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/).
455
You can get a bare Git repo in two ways: "git init --bare" or "git close --bare ...".
456
457
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.
458
Try this:
459
460
<pre>
461
[As root/sudo]:
462
    # Create a local bare repo
463
    mkdir -p $GIT/test.git
464
    chown apache:apache $GIT/test.git/
465
    cd $GIT/test.git/
466
    git init --bare
467
468
    # Create another repo as a clone of the previous one, make one commit and push.
469
    cd ..
470
    mkdir -p $GIT/test.local.git
471
    cd $GIT/test.local.git/
472
    git init
473
    touch TEST.txt
474
    git add TEST.txt
475
    git commit -m "repository initalization" 
476
    git push $GIT/test.git/ master
477
</pre>
478
479
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.
480
481
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.
482
483
<pre>
484
    #--- Enable Git access from outside Redmine
485
    ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
486
    
487
    SetEnv GIT_PROJECT_ROOT /var/lib/git
488
    SetEnv GIT_HTTP_EXPORT_ALL
489
490
    <Location /git>
491
        SSLRequireSSL
492
        PerlAccessHandler Apache::Authn::Redmine::access_handler
493
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
494
        AuthType Basic
495
        AuthName "Redmine Git Repository" 
496
        AuthUserFile /dev/null
497
        Require all denied
498
        
499
        <Limit GET PROPFIND OPTIONS REPORT>
500
            Options Indexes FollowSymLinks MultiViews
501
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
502
            <RequireAny>
503
                Require valid-user
504
                Require local
505
            </RequireAny>
506
        </Limit>
507
508
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
509
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
510
        RedmineDbUser "redmine" 
511
        RedmineDbPass "<password>"
512
        RedmineGitSmartHttp yes
513
    </Location>
514
</pre>