Project

General

Profile

Install Redmine 346 on Centos 75 » History » Version 3

Franck Michel, 2018-10-02 14:36
Additions on SVN repos

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
318
h2. SVN integration
319
320
h3. Repositories access control with Apache 2.4 with mod_dav_svn and mod_perl
321
322
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".
323
324
Make sure SVN CLI packages are already installed.
325
<pre>
326
    yum -y install svn
327
</pre>
328
329
Create the directory where all SVN repos will/have to be stored:
330
<pre>
331
[As root/sudo]:
332
    export SVN=/var/lib/svn
333
    mkdir $SVN
334
    chown apache:apache $SVN
335
    chmod 0750 $SVN
336
</pre>
337
338 3 Franck Michel
Then, there are two options to attach an SVN repository to a project:
339
340
h4. Explicitly attach a repo to a project
341
342
Copy an existing repository to $SVN, or create an new empty repository, like this:
343
<pre>
344
    svnadmin create $SVN/<repo_name>
345
</pre>
346
347
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.
348
349
350
h4. Automatically attach SVN repos to declared projects
351
352
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.
353 1 Franck Michel
<pre>
354
[As root/sudo]:
355
    cd $REDMINE/extra/svn
356
    ruby reposman.rb --redmine https://youserver.domain.org --svn-dir $SVN \
357
                     --owner apache --url http://youserver.domain.org/svn/ \
358
                     --verbose --key=<ws_key>
359
</pre>
360
361
In my case, I had declared a single test project, here is the result:
362
<pre>
363
    querying Redmine for active projects with repository module enabled...
364
    retrieved  projects
365
    processing project test (test)
366
        repository /var/lib/svn/test created
367
        repository /var/lib/svn/test registered in Redmine with url http://youserver.domain.org/svn/test
368
</pre>
369
370
h3. SVN access from Apache
371
372 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).
373 1 Franck Michel
374
Install Apache needed packages: 
375
<pre>
376
[As root/sudo]:
377
    yum install -y mod_dav_svn
378
</pre>
379
380
The installation should add loading of DAV and SVN modules to the Apache configuration. Check and fix this if necessary:
381
<pre>
382
    $ cat /etc/httpd/conf.modules.d/00-dav.conf 
383
    LoadModule dav_module modules/mod_dav.so
384
    LoadModule dav_fs_module modules/mod_dav_fs.so
385
    LoadModule dav_lock_module modules/mod_dav_lock.so
386
387
    $ cat /etc/httpd/conf.modules.d/10-subversion.conf 
388
    LoadModule dav_svn_module     modules/mod_dav_svn.so
389
    LoadModule authz_svn_module   modules/mod_authz_svn.so
390
    LoadModule dontdothat_module  modules/mod_dontdothat.so
391
</pre>
392
393
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.
394
395
<pre>
396
    # Enable SVN access from outside Redmine (web browser, SVN client)
397
    <Location /svn>
398
        DAV svn
399
        SVNParentPath "/var/lib/svn"
400
        SVNReposName "Subversion Repository" 
401
        Require all denied
402
403
        # Uncomment the following line when using subversion 1.8 or newer
404
        # (see http://subversion.apache.org/docs/release-notes/1.8.html#serf-skelta-default)
405
        # SVNAllowBulkUpdates Prefer
406
407
        # If a client tries to svn update which involves updating many files,
408
        # the update request might result in an error Server sent unexpected
409
        # return value (413 Request Entity Too Large) in response to REPORT
410
        # request, because the size of the update request exceeds the limit
411
        # allowed by the server. You can avoid this error by disabling the
412
        # request size limit by adding the line LimitXMLRequestBody 0
413
        LimitXMLRequestBody 0
414
415
        # Only check Authentication for root path, nor again for recursive folder.
416
        # Redmine core does only permit access on repository level, so this
417
        # doesn't hurt security. On the other hand it does boost performance a lot!
418
        SVNPathAuthz off
419
420
        PerlAccessHandler Apache::Authn::Redmine::access_handler
421
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
422
        AuthType Basic
423
        AuthName "Redmine SVN Repository" 
424
        AuthUserFile /dev/null
425
426
        # Read-only access    
427
        <Limit GET PROPFIND OPTIONS REPORT>
428
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
429
            <RequireAny>
430
                Require valid-user
431
                Require local
432
            </RequireAny>
433
        </Limit>
434
435
        # Write access (methods POST, PUT)
436
        <LimitExcept GET PROPFIND OPTIONS REPORT>
437
            Require valid-user
438
        </LimitExcept>
439
440
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
441
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
442
        RedmineDbUser "redmine" 
443
        RedmineDbPass "<password>" 
444
    </Location>
445
</pre>
446
447
448
h2. Git integration
449
450
Create the directory where all GIT repos will/have to be stored:
451
<pre>
452
[As root/sudo]:
453
    export GIT=/var/lib/git
454
    mkdir $GIT
455
    chown apache:apache $GIT
456
    chmod 0750 $GIT
457
</pre>
458
459 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 ...".
460 1 Franck Michel
461 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:
462 1 Franck Michel
463
<pre>
464
[As root/sudo]:
465
    # Create a local bare repo
466
    mkdir -p $GIT/test.git
467
    chown apache:apache $GIT/test.git/
468
    cd $GIT/test.git/
469
    git init --bare
470
471
    # Create another repo as a clone of the previous one, make one commit and push.
472
    cd ..
473
    mkdir -p $GIT/test.local.git
474
    cd $GIT/test.local.git/
475
    git init
476
    touch TEST.txt
477
    git add TEST.txt
478
    git commit -m "repository initalization" 
479
    git push $GIT/test.git/ master
480
</pre>
481
482
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.
483
484
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.
485
486
<pre>
487
    #--- Enable Git access from outside Redmine
488
    ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
489
    
490
    SetEnv GIT_PROJECT_ROOT /var/lib/git
491
    SetEnv GIT_HTTP_EXPORT_ALL
492
493
    <Location /git>
494
        SSLRequireSSL
495
        PerlAccessHandler Apache::Authn::Redmine::access_handler
496
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
497
        AuthType Basic
498
        AuthName "Redmine Git Repository" 
499
        AuthUserFile /dev/null
500
        Require all denied
501
        
502
        <Limit GET PROPFIND OPTIONS REPORT>
503
            Options Indexes FollowSymLinks MultiViews
504
            # Match either the valid user or local source conditions (equivalent to "Satisfy any" in Apache 2.2)
505
            <RequireAny>
506
                Require valid-user
507
                Require local
508
            </RequireAny>
509
        </Limit>
510
511
        # Mysql config. You may use localhost instead of <your.mysql.hostname> if MySQL is on the same server
512
        RedmineDSN "DBI:mysql:database=redmine;host=<your.mysql.hostname>"
513
        RedmineDbUser "redmine" 
514
        RedmineDbPass "<password>"
515
        RedmineGitSmartHttp yes
516
    </Location>
517
</pre>