Project

General

Profile

Install Redmine 346 on Centos 75 » History » Version 9

Franck Michel, 2018-10-03 13:32
Apache 2.2 vs. 2.4 warning

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 9 Franck Michel
* Apache 2.4
14 1 Franck Michel
* 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 9 Franck Michel
21
**WARNING**: this installation uses **Apache 2.4** in which there are quite some configuration syntax changes compared to 2.2. Hence, **do NOT mix the configuration below with Apache 2.2 configuration** examples you could find out there, this would likely stem unexpected behaviours as explained on "Apache web site":https://httpd.apache.org/docs/2.4/upgrading.html.
22 1 Franck Michel
23
24
h2. Install MySQL 8 
25
26
Adapted from "this page":https://www.if-not-true-then-false.com/2010/install-mysql-on-fedora-centos-red-hat-rhel/.
27
28
h3. Why MySQL 8?
29
30
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. 
31
32
<pre>
33
[As root/sudo]:
34
  yum update -y
35
  yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
36
  yum --disablerepo=mysql80-community install mysql-community-server mysql-devel
37
  systemctl start mysqld.service
38
  systemctl enable mysqld.service
39
</pre>
40
41
If you prefer to stick to MySQL 5.7, replace the yum install line as follows:
42
<pre>
43
  yum --disablerepo=mysql80-community --enablerepo=mysql57-community install mysql-community-server mysql-devel
44
</pre>
45
46
47
Get the password created at installation and run the secure procedure
48
<pre>
49 2 Franck Michel
  grep 'A temporary password is generated for root@localhost' /var/log/mysqld.log | tail -1
50
  /usr/bin/mysql_secure_installation
51 1 Franck Michel
</pre>
52
53
h3. Bind-address
54
55
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@).
56
57
h3. Default password policy
58
59
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:
60
<pre>
61
  default-authentication-plugin=mysql_native_password
62
</pre>
63
64
65
h2. Install Ruby 2.4
66
67
Adapted from "this page":https://tecadmin.net/install-ruby-previous-stable-centos/.
68
69
<pre>
70
[As root/sudo]:
71
  yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel \
72
       libyaml-devel libffi-devel openssl-devel make \
73
       bzip2 autoconf automake libtool bison iconv-devel sqlite-devel
74
  curl -sSL https://rvm.io/mpapis.asc | gpg --import -
75
  curl -L get.rvm.io | bash -s stable
76
  source /etc/profile.d/rvm.sh
77
  rvm reload
78
  rvm requirements run
79
  rvm install 2.4
80
  rvm list
81
  ruby --version
82
</pre>
83
    
84
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:
85
<pre>
86
  export GEMS=/usr/local/rvm/gems/ruby-2.4.4/gems
87
</pre>
88
89
90
h2. Install Redmine
91
92
Adapted from "this page":https://www.redmine.org/projects/redmine/wiki/RedmineInstall.
93
94
Below, Redmine is installed in directory /home/username/
95
96
h3. Download and untar Redmine, install Ruby packages:
97
98
<pre>
99
[As non-root]:
100
  cd /home/username
101
  wget https://www.redmine.org/releases/redmine-3.4.6.tar.gz
102
  tar xvfz redmine-3.4.6.tar.gz
103
  export REDMINE=/home/username/redmine-3.4.6
104
  cd $REDMINE
105
  cp config/database.yml.example config/database.yml
106
</pre>
107
108
Customize $REDMINE/config/database.yml as explained in the "procedure":https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-3-Database-connection-configuration.
109
110
Install GEMS dependencies:
111
<pre>
112
[As root/sudo]:
113
  cd $REDMINE
114
  gem install bundler
115
  bundle install --without development test
116
  bundle exec rake generate_secret_token
117
  RAILS_ENV=production REDMINE_LANG=en bundle exec rake redmine:load_default_data
118
</pre>
119
120
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):
121
<pre>
122
[As root/sudo]:
123
  cd $REDMINE
124
  bundle exec rails server webrick -e production
125
</pre>
126 2 Franck Michel
and browse to http://localhost:3000/. Alternatively, this other command should work exactly the same:
127 1 Franck Michel
<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 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:
151 1 Franck Michel
<pre>
152
  LoadModule passenger_module /usr/local/rvm/gems/ruby-2.4.4/gems/passenger-5.3.4/buildout/apache2/mod_passenger.so
153
  <IfModule mod_passenger.c>
154
    PassengerRoot /usr/local/rvm/gems/ruby-2.4.4/gems/passenger-5.3.4
155
    PassengerDefaultRuby /usr/local/rvm/gems/ruby-2.4.4/wrappers/ruby
156
  </IfModule>
157
</pre>
158
159
h3. Configure Apache as the front end for Redmine
160
161
*IMPORTANT NOTE*:
162 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.
163 1 Franck Michel
164
As root, create a virtual host entry in /etc/httpd/conf.d/redmine.conf (adapt the paths to your installation):
165
<pre>
166
    <VirtualHost *:80>
167
        ServerName youserver.domain.org
168
        DocumentRoot "/home/username/redmine-3.4.6/public"
169
        
170
        ErrorLog logs/redmine_error_log
171
        LogLevel warn
172
173
        <Directory "/home/username/redmine-3.4.6/public">
174
            Options Indexes ExecCGI FollowSymLinks
175
            Require all granted
176
            AllowOverride all
177
        </Directory>
178
    </VirtualHost>
179
</pre>
180
181
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.
182
<pre>
183
  cd $REDMINE
184
  chown -R apache:apache files log tmp vendor
185
</pre>
186
Restart apache:
187
<pre>
188
  systemctl restart httpd
189
</pre>
190
There you go: browse to http://youserver.domain.org, you should get the login page. Hurah!
191
Login with default login "admin" and password "admin", and of course, change the admin password immediatly.
192
193
194
h3. Email config with sendmail
195
196
As non-root, edit @$REDMINE/config/configuration.yml@ and uncomment the 2 lines concerning sendmail:
197
<pre>
198
    email_delivery:
199
      delivery_method:sendmail
200
</pre>
201
202
And install sendmail if it is not yet installed:
203
<pre>
204
[As root/sudo]:
205
  yum install -y sendmail sendmail-cf
206
</pre>
207
208
h3. LDAP authentication
209
210
Ask the LDAP details to your administrator and set them in the Web interface: Admin > LDAP authentication
211
212 5 Franck Michel
h2. SCM Repos integration - Preliminary
213 1 Franck Michel
214
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.
215
216
The reposman.rb script needs @activeresource@ to work, run this (if this is already installed, this will just do nothing):
217
<pre>
218
[As root]:
219
    cd $REDMINE
220
    gem install activeresource
221
</pre>
222
    
223
To restrict the access to the WS, secure the Apache configuration by adding this to the 
224
VirtualHost configuration (/etc/httpd/conf.d/redmine.conf above). Reminder: this is an Apache 2.4 syntax.
225
<pre>
226
   <Location /sys>
227
      Require host youserver.domain.org sparks-vm5.i3s.unice.fr localhost
228
      Require all denied
229
   </Location>
230
</pre>
231
232
Install Apache packages needed to use the database for authentication (with Git as well as Svn):
233
<pre>
234
[As root/sudo]:
235
    yum install -y mod_perl perl-DBI perl-DBD-MySQL perl-Digest-SHA1 perl-LDAP
236
</pre>
237
238 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".
239 1 Franck Michel
240 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/.
241 1 Franck Michel
<pre>
242
[As root/sudo]:
243
    mkdir /usr/lib64/perl5/vendor_perl/Apache/Authn
244
    ln -s $REDMINE/extra/svn/Redmine.pm /usr/lib64/perl5/vendor_perl/Authn/Apache
245
</pre>
246
247
Optional: to allow for LDAP authentication, install the Simple LDAP modules with CPAN. In my cases, it required dependencies Modules::Build and Params::Validate:
248
<pre>
249
[As root/sudo]:
250
    cpan
251
    install Modules::Build
252
    install Params::Validate
253
    install Authen::Simple::LDAP
254
</pre>
255
256
Update the Apache Redmine configuration (redmine.conf) as shown below:
257
<pre>
258
    PerlLoadModule Apache::Authn::Redmine
259
    PerlLoadModule Redmine
260
261
    # Enable connection pooling (useful for checkouts with many files)
262
    PerlModule DBI
263
    PerlOptions +GlobalRequest
264
265
    # Enable LDAP(S) authentication (optional)
266
    PerlLoadModule Authen::Simple::LDAP
267
    PerlLoadModule IO::Socket::SSL
268
</pre>
269
270
*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:
271
<pre>
272
    Can't call method "prepare" on an undefined value at /usr/lib64/perl5/vendor_perl/Apache/Redmine.pm line 364, <DATA> line 747.\n
273
</pre>
274
A closer look at the regular Apache error_log shows another error:
275
<pre>
276
    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.
277
</pre>
278
279
To fix this, change MySQL's password policy for user redmine (found "here":https://my.oschina.net/johnsken/blog/1840348):
280
<pre>
281
    mysql -uroot -p
282
    mysql> show variables like 'default_authentication_plugin';
283
    +-------------------------------+-----------------------+
284
    | Variable_name                 | Value                 |
285
    +-------------------------------+-----------------------+
286
    | default_authentication_plugin | caching_sha2_password |
287
    +-------------------------------+-----------------------+
288
289
    mysql> select host,user,plugin from mysql.user;
290
    +-----------+------------------+-----------------------+
291
    | host      | user             | plugin                |
292
    +-----------+------------------+-----------------------+
293
    | localhost | mysql.infoschema | caching_sha2_password |
294
    | localhost | mysql.session    | caching_sha2_password |
295
    | localhost | mysql.sys        | caching_sha2_password |
296
    | localhost | redmine          | caching_sha2_password |
297
    | localhost | root             | caching_sha2_password |
298
    +-----------+------------------+-----------------------+
299
300
    mysql> ALTER USER 'redmine'@'localhost' IDENTIFIED WITH mysql_native_password BY '<YOUR REDMINE PASSWORD>';
301
    Query OK, 0 rows affected (0,10 sec)
302
303
    mysql> select host,user,plugin from mysql.user;
304
    +-----------+------------------+-----------------------+
305
    | host      | user             | plugin                |
306
    +-----------+------------------+-----------------------+
307
    | localhost | mysql.infoschema | caching_sha2_password |
308
    | localhost | mysql.session    | caching_sha2_password |
309
    | localhost | mysql.sys        | caching_sha2_password |
310
    | localhost | redmine          | mysql_native_password |
311
    | localhost | root             | caching_sha2_password |
312
    +-----------+------------------+-----------------------+
313
</pre>
314
315
h2. SVN integration
316
317
h3. Repositories access control with Apache 2.4 with mod_dav_svn and mod_perl
318
319
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".
320
321
Make sure SVN CLI packages are already installed.
322
<pre>
323
    yum -y install svn
324
</pre>
325
326
Create the directory where all SVN repos will/have to be stored:
327
<pre>
328
[As root/sudo]:
329
    export SVN=/var/lib/svn
330
    mkdir $SVN
331
    chown apache:apache $SVN
332
    chmod 0750 $SVN
333
</pre>
334
335 3 Franck Michel
Then, there are two options to attach an SVN repository to a project:
336 1 Franck Michel
337 4 Franck Michel
_1. Explicitly attach a repo to a project_
338 3 Franck Michel
339 7 Franck Michel
Copy an existing repository to $SVN, or create an new empty repository, and change its owner, like this:
340 3 Franck Michel
<pre>
341 1 Franck Michel
    svnadmin create $SVN/<repo_name>
342 8 Franck Michel
    chown -R apache:apache $SVN/<repo_name>
343 3 Franck Michel
</pre>
344
345
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.
346 1 Franck Michel
347 3 Franck Michel
348 6 Franck Michel
_2. Automatically create SVN repos for declared projects_
349
You can also ask Redmine to automatically create SVN repos for each declared project: the new repo will be name after the project name.
350 3 Franck Michel
351 1 Franck Michel
<pre>
352
[As root/sudo]:
353
    cd $REDMINE/extra/svn
354
    ruby reposman.rb --redmine https://youserver.domain.org --svn-dir $SVN \
355
                     --owner apache --url http://youserver.domain.org/svn/ \
356
                     --verbose --key=<ws_key>
357
</pre>
358
359
In my case, I had declared a single test project, here is the result:
360
<pre>
361
    querying Redmine for active projects with repository module enabled...
362
    retrieved  projects
363
    processing project test (test)
364
        repository /var/lib/svn/test created
365
        repository /var/lib/svn/test registered in Redmine with url http://youserver.domain.org/svn/test
366
</pre>
367
368
h3. SVN access from Apache
369
370 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).
371 1 Franck Michel
372
Install Apache needed packages: 
373
<pre>
374
[As root/sudo]:
375
    yum install -y mod_dav_svn
376
</pre>
377
378
The installation should add loading of DAV and SVN modules to the Apache configuration. Check and fix this if necessary:
379
<pre>
380
    $ cat /etc/httpd/conf.modules.d/00-dav.conf 
381
    LoadModule dav_module modules/mod_dav.so
382
    LoadModule dav_fs_module modules/mod_dav_fs.so
383
    LoadModule dav_lock_module modules/mod_dav_lock.so
384
385
    $ cat /etc/httpd/conf.modules.d/10-subversion.conf 
386
    LoadModule dav_svn_module     modules/mod_dav_svn.so
387
    LoadModule authz_svn_module   modules/mod_authz_svn.so
388
    LoadModule dontdothat_module  modules/mod_dontdothat.so
389
</pre>
390
391
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.
392
393
<pre>
394
    # Enable SVN access from outside Redmine (web browser, SVN client)
395
    <Location /svn>
396
        DAV svn
397
        SVNParentPath "/var/lib/svn"
398
        SVNReposName "Subversion Repository" 
399
        Require all denied
400
401
        # Uncomment the following line when using subversion 1.8 or newer
402
        # (see http://subversion.apache.org/docs/release-notes/1.8.html#serf-skelta-default)
403
        # SVNAllowBulkUpdates Prefer
404
405
        # If a client tries to svn update which involves updating many files,
406
        # the update request might result in an error Server sent unexpected
407
        # return value (413 Request Entity Too Large) in response to REPORT
408
        # request, because the size of the update request exceeds the limit
409
        # allowed by the server. You can avoid this error by disabling the
410
        # request size limit by adding the line LimitXMLRequestBody 0
411
        LimitXMLRequestBody 0
412
413
        # Only check Authentication for root path, nor again for recursive folder.
414
        # Redmine core does only permit access on repository level, so this
415
        # doesn't hurt security. On the other hand it does boost performance a lot!
416
        SVNPathAuthz off
417
418
        PerlAccessHandler Apache::Authn::Redmine::access_handler
419
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
420
        AuthType Basic
421
        AuthName "Redmine SVN Repository" 
422
        AuthUserFile /dev/null
423
424
        # Read-only access    
425
        <Limit GET PROPFIND OPTIONS REPORT>
426
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
427
            <RequireAny>
428
                Require valid-user
429
                Require local
430
            </RequireAny>
431
        </Limit>
432
433
        # Write access (methods POST, PUT)
434
        <LimitExcept GET PROPFIND OPTIONS REPORT>
435
            Require valid-user
436
        </LimitExcept>
437
438
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
439
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
440
        RedmineDbUser "redmine" 
441
        RedmineDbPass "<password>" 
442
    </Location>
443
</pre>
444
445
h2. Git integration
446
447
Create the directory where all GIT repos will/have to be stored:
448
<pre>
449
[As root/sudo]:
450
    export GIT=/var/lib/git
451
    mkdir $GIT
452
    chown apache:apache $GIT
453
    chmod 0750 $GIT
454
</pre>
455
456 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 ...".
457 1 Franck Michel
458 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:
459 1 Franck Michel
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>