Project

General

Profile

Install Redmine 346 on Centos 75 » History » Version 4

Franck Michel, 2018-10-02 14:37

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
211
h3. SCM Repos integration
212
213
214
h4. Preliminary
215
216
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.
217
218
The reposman.rb script needs @activeresource@ to work, run this (if this is already installed, this will just do nothing):
219
<pre>
220
[As root]:
221
    cd $REDMINE
222
    gem install activeresource
223
</pre>
224
    
225
To restrict the access to the WS, secure the Apache configuration by adding this to the 
226
VirtualHost configuration (/etc/httpd/conf.d/redmine.conf above). Reminder: this is an Apache 2.4 syntax.
227
<pre>
228
   <Location /sys>
229
      Require host youserver.domain.org sparks-vm5.i3s.unice.fr localhost
230
      Require all denied
231
   </Location>
232
</pre>
233
234
Install Apache packages needed to use the database for authentication (with Git as well as Svn):
235
<pre>
236
[As root/sudo]:
237
    yum install -y mod_perl perl-DBI perl-DBD-MySQL perl-Digest-SHA1 perl-LDAP
238
</pre>
239
240 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".
241 1 Franck Michel
242 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/.
243 1 Franck Michel
<pre>
244
[As root/sudo]:
245
    mkdir /usr/lib64/perl5/vendor_perl/Apache/Authn
246
    ln -s $REDMINE/extra/svn/Redmine.pm /usr/lib64/perl5/vendor_perl/Authn/Apache
247
</pre>
248
249
Optional: to allow for LDAP authentication, install the Simple LDAP modules with CPAN. In my cases, it required dependencies Modules::Build and Params::Validate:
250
<pre>
251
[As root/sudo]:
252
    cpan
253
    install Modules::Build
254
    install Params::Validate
255
    install Authen::Simple::LDAP
256
</pre>
257
258
Update the Apache Redmine configuration (redmine.conf) as shown below:
259
<pre>
260
    PerlLoadModule Apache::Authn::Redmine
261
    PerlLoadModule Redmine
262
263
    # Enable connection pooling (useful for checkouts with many files)
264
    PerlModule DBI
265
    PerlOptions +GlobalRequest
266
267
    # Enable LDAP(S) authentication (optional)
268
    PerlLoadModule Authen::Simple::LDAP
269
    PerlLoadModule IO::Socket::SSL
270
</pre>
271
272
*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:
273
<pre>
274
    Can't call method "prepare" on an undefined value at /usr/lib64/perl5/vendor_perl/Apache/Redmine.pm line 364, <DATA> line 747.\n
275
</pre>
276
A closer look at the regular Apache error_log shows another error:
277
<pre>
278
    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.
279
</pre>
280
281
To fix this, change MySQL's password policy for user redmine (found "here":https://my.oschina.net/johnsken/blog/1840348):
282
<pre>
283
    mysql -uroot -p
284
    mysql> show variables like 'default_authentication_plugin';
285
    +-------------------------------+-----------------------+
286
    | Variable_name                 | Value                 |
287
    +-------------------------------+-----------------------+
288
    | default_authentication_plugin | caching_sha2_password |
289
    +-------------------------------+-----------------------+
290
291
    mysql> select host,user,plugin from mysql.user;
292
    +-----------+------------------+-----------------------+
293
    | host      | user             | plugin                |
294
    +-----------+------------------+-----------------------+
295
    | localhost | mysql.infoschema | caching_sha2_password |
296
    | localhost | mysql.session    | caching_sha2_password |
297
    | localhost | mysql.sys        | caching_sha2_password |
298
    | localhost | redmine          | caching_sha2_password |
299
    | localhost | root             | caching_sha2_password |
300
    +-----------+------------------+-----------------------+
301
302
    mysql> ALTER USER 'redmine'@'localhost' IDENTIFIED WITH mysql_native_password BY '<YOUR REDMINE PASSWORD>';
303
    Query OK, 0 rows affected (0,10 sec)
304
305
    mysql> select host,user,plugin from mysql.user;
306
    +-----------+------------------+-----------------------+
307
    | host      | user             | plugin                |
308
    +-----------+------------------+-----------------------+
309
    | localhost | mysql.infoschema | caching_sha2_password |
310
    | localhost | mysql.session    | caching_sha2_password |
311
    | localhost | mysql.sys        | caching_sha2_password |
312
    | localhost | redmine          | mysql_native_password |
313
    | localhost | root             | caching_sha2_password |
314
    +-----------+------------------+-----------------------+
315
</pre>
316
317
h2. SVN integration
318
319
h3. Repositories access control with Apache 2.4 with mod_dav_svn and mod_perl
320
321
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".
322
323
Make sure SVN CLI packages are already installed.
324
<pre>
325
    yum -y install svn
326
</pre>
327
328
Create the directory where all SVN repos will/have to be stored:
329
<pre>
330
[As root/sudo]:
331
    export SVN=/var/lib/svn
332
    mkdir $SVN
333
    chown apache:apache $SVN
334
    chmod 0750 $SVN
335
</pre>
336
337 3 Franck Michel
Then, there are two options to attach an SVN repository to a project:
338 1 Franck Michel
339 4 Franck Michel
_1. Explicitly attach a repo to a project_
340 3 Franck Michel
341
Copy an existing repository to $SVN, or create an new empty repository, like this:
342
<pre>
343
    svnadmin create $SVN/<repo_name>
344
</pre>
345
346
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.
347 1 Franck Michel
348 3 Franck Michel
349 4 Franck Michel
_2. Automatically attach SVN repos to declared projects_
350 3 Franck Michel
351
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.
352 1 Franck Michel
<pre>
353
[As root/sudo]:
354
    cd $REDMINE/extra/svn
355
    ruby reposman.rb --redmine https://youserver.domain.org --svn-dir $SVN \
356
                     --owner apache --url http://youserver.domain.org/svn/ \
357
                     --verbose --key=<ws_key>
358
</pre>
359
360
In my case, I had declared a single test project, here is the result:
361
<pre>
362
    querying Redmine for active projects with repository module enabled...
363
    retrieved  projects
364
    processing project test (test)
365
        repository /var/lib/svn/test created
366
        repository /var/lib/svn/test registered in Redmine with url http://youserver.domain.org/svn/test
367
</pre>
368
369
h3. SVN access from Apache
370
371 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).
372 1 Franck Michel
373
Install Apache needed packages: 
374
<pre>
375
[As root/sudo]:
376
    yum install -y mod_dav_svn
377
</pre>
378
379
The installation should add loading of DAV and SVN modules to the Apache configuration. Check and fix this if necessary:
380
<pre>
381
    $ cat /etc/httpd/conf.modules.d/00-dav.conf 
382
    LoadModule dav_module modules/mod_dav.so
383
    LoadModule dav_fs_module modules/mod_dav_fs.so
384
    LoadModule dav_lock_module modules/mod_dav_lock.so
385
386
    $ cat /etc/httpd/conf.modules.d/10-subversion.conf 
387
    LoadModule dav_svn_module     modules/mod_dav_svn.so
388
    LoadModule authz_svn_module   modules/mod_authz_svn.so
389
    LoadModule dontdothat_module  modules/mod_dontdothat.so
390
</pre>
391
392
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.
393
394
<pre>
395
    # Enable SVN access from outside Redmine (web browser, SVN client)
396
    <Location /svn>
397
        DAV svn
398
        SVNParentPath "/var/lib/svn"
399
        SVNReposName "Subversion Repository" 
400
        Require all denied
401
402
        # Uncomment the following line when using subversion 1.8 or newer
403
        # (see http://subversion.apache.org/docs/release-notes/1.8.html#serf-skelta-default)
404
        # SVNAllowBulkUpdates Prefer
405
406
        # If a client tries to svn update which involves updating many files,
407
        # the update request might result in an error Server sent unexpected
408
        # return value (413 Request Entity Too Large) in response to REPORT
409
        # request, because the size of the update request exceeds the limit
410
        # allowed by the server. You can avoid this error by disabling the
411
        # request size limit by adding the line LimitXMLRequestBody 0
412
        LimitXMLRequestBody 0
413
414
        # Only check Authentication for root path, nor again for recursive folder.
415
        # Redmine core does only permit access on repository level, so this
416
        # doesn't hurt security. On the other hand it does boost performance a lot!
417
        SVNPathAuthz off
418
419
        PerlAccessHandler Apache::Authn::Redmine::access_handler
420
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
421
        AuthType Basic
422
        AuthName "Redmine SVN Repository" 
423
        AuthUserFile /dev/null
424
425
        # Read-only access    
426
        <Limit GET PROPFIND OPTIONS REPORT>
427
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
428
            <RequireAny>
429
                Require valid-user
430
                Require local
431
            </RequireAny>
432
        </Limit>
433
434
        # Write access (methods POST, PUT)
435
        <LimitExcept GET PROPFIND OPTIONS REPORT>
436
            Require valid-user
437
        </LimitExcept>
438
439
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
440
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
441
        RedmineDbUser "redmine" 
442
        RedmineDbPass "<password>" 
443
    </Location>
444
</pre>
445
446
h2. Git integration
447
448
Create the directory where all GIT repos will/have to be stored:
449
<pre>
450
[As root/sudo]:
451
    export GIT=/var/lib/git
452
    mkdir $GIT
453
    chown apache:apache $GIT
454
    chmod 0750 $GIT
455
</pre>
456
457 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 ...".
458 1 Franck Michel
459 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:
460 1 Franck Michel
461
<pre>
462
[As root/sudo]:
463
    # Create a local bare repo
464
    mkdir -p $GIT/test.git
465
    chown apache:apache $GIT/test.git/
466
    cd $GIT/test.git/
467
    git init --bare
468
469
    # Create another repo as a clone of the previous one, make one commit and push.
470
    cd ..
471
    mkdir -p $GIT/test.local.git
472
    cd $GIT/test.local.git/
473
    git init
474
    touch TEST.txt
475
    git add TEST.txt
476
    git commit -m "repository initalization" 
477
    git push $GIT/test.git/ master
478
</pre>
479
480
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.
481
482
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.
483
484
<pre>
485
    #--- Enable Git access from outside Redmine
486
    ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
487
    
488
    SetEnv GIT_PROJECT_ROOT /var/lib/git
489
    SetEnv GIT_HTTP_EXPORT_ALL
490
491
    <Location /git>
492
        SSLRequireSSL
493
        PerlAccessHandler Apache::Authn::Redmine::access_handler
494
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
495
        AuthType Basic
496
        AuthName "Redmine Git Repository" 
497
        AuthUserFile /dev/null
498
        Require all denied
499
        
500
        <Limit GET PROPFIND OPTIONS REPORT>
501
            Options Indexes FollowSymLinks MultiViews
502
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
503
            <RequireAny>
504
                Require valid-user
505
                Require local
506
            </RequireAny>
507
        </Limit>
508
509
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
510
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
511
        RedmineDbUser "redmine" 
512
        RedmineDbPass "<password>"
513
        RedmineGitSmartHttp yes
514
    </Location>
515
</pre>