Project

General

Profile

Install Redmine 346 on Centos 75 » History » Version 10

Franck Michel, 2018-10-03 13:34

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 10 Franck Michel
*IMPORTANT NOTE*:
22
This installation uses **Apache 2.4** in which there are quite some configuration syntax changes compared to 2.2. 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.
23 1 Franck Michel
24
25
h2. Install MySQL 8 
26
27
Adapted from "this page":https://www.if-not-true-then-false.com/2010/install-mysql-on-fedora-centos-red-hat-rhel/.
28
29
h3. Why MySQL 8?
30
31
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. 
32
33
<pre>
34
[As root/sudo]:
35
  yum update -y
36
  yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
37
  yum --disablerepo=mysql80-community install mysql-community-server mysql-devel
38
  systemctl start mysqld.service
39
  systemctl enable mysqld.service
40
</pre>
41
42
If you prefer to stick to MySQL 5.7, replace the yum install line as follows:
43
<pre>
44
  yum --disablerepo=mysql80-community --enablerepo=mysql57-community install mysql-community-server mysql-devel
45
</pre>
46
47
48
Get the password created at installation and run the secure procedure
49
<pre>
50 2 Franck Michel
  grep 'A temporary password is generated for root@localhost' /var/log/mysqld.log | tail -1
51
  /usr/bin/mysql_secure_installation
52 1 Franck Michel
</pre>
53
54
h3. Bind-address
55
56
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@).
57
58
h3. Default password policy
59
60
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:
61
<pre>
62
  default-authentication-plugin=mysql_native_password
63
</pre>
64
65
66
h2. Install Ruby 2.4
67
68
Adapted from "this page":https://tecadmin.net/install-ruby-previous-stable-centos/.
69
70
<pre>
71
[As root/sudo]:
72
  yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel \
73
       libyaml-devel libffi-devel openssl-devel make \
74
       bzip2 autoconf automake libtool bison iconv-devel sqlite-devel
75
  curl -sSL https://rvm.io/mpapis.asc | gpg --import -
76
  curl -L get.rvm.io | bash -s stable
77
  source /etc/profile.d/rvm.sh
78
  rvm reload
79
  rvm requirements run
80
  rvm install 2.4
81
  rvm list
82
  ruby --version
83
</pre>
84
    
85
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:
86
<pre>
87
  export GEMS=/usr/local/rvm/gems/ruby-2.4.4/gems
88
</pre>
89
90
91
h2. Install Redmine
92
93
Adapted from "this page":https://www.redmine.org/projects/redmine/wiki/RedmineInstall.
94
95
Below, Redmine is installed in directory /home/username/
96
97
h3. Download and untar Redmine, install Ruby packages:
98
99
<pre>
100
[As non-root]:
101
  cd /home/username
102
  wget https://www.redmine.org/releases/redmine-3.4.6.tar.gz
103
  tar xvfz redmine-3.4.6.tar.gz
104
  export REDMINE=/home/username/redmine-3.4.6
105
  cd $REDMINE
106
  cp config/database.yml.example config/database.yml
107
</pre>
108
109
Customize $REDMINE/config/database.yml as explained in the "procedure":https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-3-Database-connection-configuration.
110
111
Install GEMS dependencies:
112
<pre>
113
[As root/sudo]:
114
  cd $REDMINE
115
  gem install bundler
116
  bundle install --without development test
117
  bundle exec rake generate_secret_token
118
  RAILS_ENV=production REDMINE_LANG=en bundle exec rake redmine:load_default_data
119
</pre>
120
121
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):
122
<pre>
123
[As root/sudo]:
124
  cd $REDMINE
125
  bundle exec rails server webrick -e production
126
</pre>
127 2 Franck Michel
and browse to http://localhost:3000/. Alternatively, this other command should work exactly the same:
128 1 Franck Michel
<pre>
129
[As root/sudo]:
130
  ruby bin/rails server webrick -e production
131
</pre>
132
133
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.
134
135
136
h3. Install Apache Passenger (an Apache plugin for Ruby environments)
137
138
Adapted from "this page":https://www.vincentliefooghe.net/content/utilisation-apache-passenger-pour-redmine.
139
<pre>
140
[As root/sudo]:
141
  yum install -y httpd-devel libcurl-devel apr-devel apr-util-devel mod_ssl
142
  cd $REDMINE
143
  gem install passenger
144
</pre>
145
146
Find out the installation path of Passenger, and call the Apache module installer, e.g. in my case:
147
<pre>
148
  $GEMS/passenger-5.3.4/bin/passenger-install-apache2-module
149
</pre>
150
151 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:
152 1 Franck Michel
<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 2 Franck Michel
h3. Configure Apache as the front end for Redmine
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 7 Franck Michel
Copy an existing repository to $SVN, or create an new empty repository, and change its owner, like this:
338 3 Franck Michel
<pre>
339 1 Franck Michel
    svnadmin create $SVN/<repo_name>
340 8 Franck Michel
    chown -R apache:apache $SVN/<repo_name>
341 3 Franck Michel
</pre>
342
343
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.
344 1 Franck Michel
345 3 Franck Michel
346 6 Franck Michel
_2. Automatically create SVN repos for declared projects_
347
You can also ask Redmine to automatically create SVN repos for each declared project: the new repo will be name after the project name.
348 3 Franck Michel
349 1 Franck Michel
<pre>
350
[As root/sudo]:
351
    cd $REDMINE/extra/svn
352
    ruby reposman.rb --redmine https://youserver.domain.org --svn-dir $SVN \
353
                     --owner apache --url http://youserver.domain.org/svn/ \
354
                     --verbose --key=<ws_key>
355
</pre>
356
357
In my case, I had declared a single test project, here is the result:
358
<pre>
359
    querying Redmine for active projects with repository module enabled...
360
    retrieved  projects
361
    processing project test (test)
362
        repository /var/lib/svn/test created
363
        repository /var/lib/svn/test registered in Redmine with url http://youserver.domain.org/svn/test
364
</pre>
365
366
h3. SVN access from Apache
367
368 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).
369 1 Franck Michel
370
Install Apache needed packages: 
371
<pre>
372
[As root/sudo]:
373
    yum install -y mod_dav_svn
374
</pre>
375
376
The installation should add loading of DAV and SVN modules to the Apache configuration. Check and fix this if necessary:
377
<pre>
378
    $ cat /etc/httpd/conf.modules.d/00-dav.conf 
379
    LoadModule dav_module modules/mod_dav.so
380
    LoadModule dav_fs_module modules/mod_dav_fs.so
381
    LoadModule dav_lock_module modules/mod_dav_lock.so
382
383
    $ cat /etc/httpd/conf.modules.d/10-subversion.conf 
384
    LoadModule dav_svn_module     modules/mod_dav_svn.so
385
    LoadModule authz_svn_module   modules/mod_authz_svn.so
386
    LoadModule dontdothat_module  modules/mod_dontdothat.so
387
</pre>
388
389
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.
390
391
<pre>
392
    # Enable SVN access from outside Redmine (web browser, SVN client)
393
    <Location /svn>
394
        DAV svn
395
        SVNParentPath "/var/lib/svn"
396
        SVNReposName "Subversion Repository" 
397
        Require all denied
398
399
        # Uncomment the following line when using subversion 1.8 or newer
400
        # (see http://subversion.apache.org/docs/release-notes/1.8.html#serf-skelta-default)
401
        # SVNAllowBulkUpdates Prefer
402
403
        # If a client tries to svn update which involves updating many files,
404
        # the update request might result in an error Server sent unexpected
405
        # return value (413 Request Entity Too Large) in response to REPORT
406
        # request, because the size of the update request exceeds the limit
407
        # allowed by the server. You can avoid this error by disabling the
408
        # request size limit by adding the line LimitXMLRequestBody 0
409
        LimitXMLRequestBody 0
410
411
        # Only check Authentication for root path, nor again for recursive folder.
412
        # Redmine core does only permit access on repository level, so this
413
        # doesn't hurt security. On the other hand it does boost performance a lot!
414
        SVNPathAuthz off
415
416
        PerlAccessHandler Apache::Authn::Redmine::access_handler
417
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
418
        AuthType Basic
419
        AuthName "Redmine SVN Repository" 
420
        AuthUserFile /dev/null
421
422
        # Read-only access    
423
        <Limit GET PROPFIND OPTIONS REPORT>
424
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
425
            <RequireAny>
426
                Require valid-user
427
                Require local
428
            </RequireAny>
429
        </Limit>
430
431
        # Write access (methods POST, PUT)
432
        <LimitExcept GET PROPFIND OPTIONS REPORT>
433
            Require valid-user
434
        </LimitExcept>
435
436
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
437
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
438
        RedmineDbUser "redmine" 
439
        RedmineDbPass "<password>" 
440
    </Location>
441
</pre>
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 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 ...".
455 1 Franck Michel
456 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:
457 1 Franck Michel
458
<pre>
459
[As root/sudo]:
460
    # Create a local bare repo
461
    mkdir -p $GIT/test.git
462
    chown apache:apache $GIT/test.git/
463
    cd $GIT/test.git/
464
    git init --bare
465
466
    # Create another repo as a clone of the previous one, make one commit and push.
467
    cd ..
468
    mkdir -p $GIT/test.local.git
469
    cd $GIT/test.local.git/
470
    git init
471
    touch TEST.txt
472
    git add TEST.txt
473
    git commit -m "repository initalization" 
474
    git push $GIT/test.git/ master
475
</pre>
476
477
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.
478
479
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.
480
481
<pre>
482
    #--- Enable Git access from outside Redmine
483
    ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
484
    
485
    SetEnv GIT_PROJECT_ROOT /var/lib/git
486
    SetEnv GIT_HTTP_EXPORT_ALL
487
488
    <Location /git>
489
        SSLRequireSSL
490
        PerlAccessHandler Apache::Authn::Redmine::access_handler
491
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
492
        AuthType Basic
493
        AuthName "Redmine Git Repository" 
494
        AuthUserFile /dev/null
495
        Require all denied
496
        
497
        <Limit GET PROPFIND OPTIONS REPORT>
498
            Options Indexes FollowSymLinks MultiViews
499
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
500
            <RequireAny>
501
                Require valid-user
502
                Require local
503
            </RequireAny>
504
        </Limit>
505
506
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
507
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
508
        RedmineDbUser "redmine" 
509
        RedmineDbPass "<password>"
510
        RedmineGitSmartHttp yes
511
    </Location>
512
</pre>