Developer Area/Developer Environment

From Mahara Wiki
Jump to: navigation, search

This page explains how to set up a copy of Mahara for development purposes.

The short version

Mahara is a fairly standard PHP web application. You mainly need to place it in your web server and give it a database, and a file storage directory. If you haven't set up a PHP web application before, skip to "the long version" down below.

  1. Set up your Apache web server. For development purposes, it is often handy to have the web root sitting inside your home directory.
  2. Retrieve a copy of the Mahara codebase. Place it in your Apache web root.
  3. Create a Mahara "dataroot" directory outside of your web root. Make it read/writeable by Apache.
  4. Create a database instance and database user for Mahara to use.
  5. Edit the Mahara "config.php" file so that Mahara knows the location of its dataroot directory, and its database login credentials.
  6. Run the Mahara installer by visiting your Mahara site in your web browser. If you are missing any required PHP modules, Mahara should tell you. Depending on what you already have installed, you may need one or more of these:
    • If you're on Ubuntu 14.04
      1. php5-pgsql
      2. php5-gd
      3. php5-curl
      4. php5-json
    • If you're on Ubuntu 16.04
      1. php-pgsql
      2. php-gd
      3. php-curl
      4. php-json
      5. php-zip

The long version (for Windows)

If you want to install your developer environment on Windows, please check the Windows instructions.

The long version (for Linux)

The instructions explain one way to set up an installation of Mahara for development purposes. These instructions are specifically for Ubuntu Linux, although the process will probably be quite similar in other Linux versions.

The following instructions are for Ubuntu 12.04-14.04 unless otherwise noted.

1. Install required packages:

sudo apt-get install apache2 make curl wget xvfb git gitk postgresql default-jre php5-cli libapache2-mod-php5 php5-curl php5-gd php5-json php5-ldap php5-pgsql php5-xmlrpc nodejs-legacy npm

If you are using Ubuntu 16.04 or later, you should use the generic "php-*" packages instead of "php5-*". And you'll need to install "php-zip" as well.

sudo apt-get install apache2 make curl wget xvfb git gitk postgresql default-jre php-cli libapache2-mod-php php-curl php-gd php-json php-ldap php-pgsql php-xmlrpc php-zip php-xml php-mbstring nodejs-legacy npm

Note: The Node packages that come with the default installation may be outdated and not new enough for Mahara. You may need to install a later version of Node because Node 0.10 is not enough. You can find various instructions on how to upgrade NodeJS on your distribution depending on your preference on package manager

2. Get a copy of the Mahara code from git. We'll put it under your home directory, in a new directory called "code":

cd ~
mkdir code
cd code
git clone https://git.mahara.org/mahara/mahara.git

Or, if that failed, use:

$ git clone https://github.com/MaharaProject/mahara.git

Or, if you have an account on the Mahara gitlab then do the following:

$ git clone git@git.mahara.org:mahara/mahara.git

3. Give the Apache web server access to your Mahara code directory:

sudo chmod a+rx ~/code/mahara

3a. To avoid a possible 403 error later, confirm that your code directory permissions are also drwxr-xr-x

ls -la ~/

To fix, run:

sudo chmod a+rx ~/code

Your home directory permissions should be drwx--x--x Check with:

ls -la /home

Fix with:

sudo chmod a+x /home

4. Create a PostgreSQL database user:

sudo -u postgres createuser -P -D -R -S maharauser

You'll be prompted for a password. Enter maharapassword for the password.

If Postgres is not available, check its status and if it says that it's inactive, start the service:

service postgresql status
sudo service postgresql start

Now create a database:

sudo -u postgres createdb -Omaharauser mahara-master

5. Using a text editor, copy these contents into a file and save it to ~/code/mahara/htdocs/config.php:

<?php
$cfg = new stdClass();

$branch = 'master';

// database connection details
// valid values for dbtype are 'postgres8' and 'mysql5'
$cfg->dbtype   = 'postgres';
$cfg->dbhost   = 'localhost';
$cfg->dbuser   = 'maharauser';
$cfg->dbname   = "mahara-$branch";
$cfg->dbpass   = 'maharapassword'; 

$cfg->dataroot = "/var/lib/maharadata/$branch";

$cfg->sendemail = true;
$cfg->sendallemailto = '<your email address>';

$cfg->productionmode = false;
$cfg->perftofoot = true;

Make sure to replace <your email address> with your email address.

If you're mainly testing, and you don't find the stack traces in these screen messages particularly useful, adding $cfg->log_backtrace_levels = LOG_LEVEL_ENVIRON; to config.php will display important warning messages on a single line, without stack traces.

6. Create a dataroot directory (this is where Mahara stores uploaded files):

sudo mkdir /var/lib/maharadata
sudo mkdir /var/lib/maharadata/master
sudo chown www-data:www-data /var/lib/maharadata/master

7. Set up a new local domain name "mahara" for your Mahara site, in /etc/hosts:

sudo sh -c "echo '127.0.0.1 mahara' >> /etc/hosts"

8. Increase your PHP "post_max_size" setting to 32M in php.ini:

sudo sh -c "echo 'post_max_size = 32M' >> /etc/php5/cli/php.ini"
sudo sh -c "echo 'post_max_size = 32M' >> /etc/php5/apache2/php.ini"

If you are using Ubuntu 16.04 or later, these files will instead be under /etc/php/7.0:

sudo sh -c "echo 'post_max_size = 32M' >> /etc/php/7.0/cli/php.ini"
sudo sh -c "echo 'post_max_size = 32M' >> /etc/php/7.0/apache2/php.ini"

9. Create an Apache configuration file to point to your copy of Mahara. You can do this by first copying the following contents into a file called "mahara.conf", saved in your home directory.

In Ubuntu 13.10 or later:

 <VirtualHost *:80>
  ServerName mahara
  DocumentRoot /home/<your username>/code/mahara/htdocs
 
  <Directory /home/<your username>/code>
    Options Indexes FollowSymLinks MultiViews
    Require all granted
  </Directory>
 
  ErrorLog /var/log/apache2/error.log
  LogLevel info
 
  CustomLog /var/log/apache2/access.log combined
  DirectoryIndex index.php index.html
 </VirtualHost>

In Ubuntu 13.04 or earlier:

 <VirtualHost *:80>
  ServerName mahara
  DocumentRoot /home/<your username>/code/mahara/htdocs
 
  <Directory /home/<your username>/code>
    Options Indexes FollowSymLinks MultiViews
    Order allow,deny
    Allow from all
  </Directory>
 
  ErrorLog /var/log/apache2/error.log
  LogLevel info
 
  CustomLog /var/log/apache2/access.log combined
  DirectoryIndex index.php index.html
 </VirtualHost>

Then copy the file into your Apache sites-enable directory. The name to give the file will also vary depending on what version of Ubuntu you are using.

  • 13.10 and later: sudo cp ~/mahara.conf /etc/apache2/sites-available/mahara.conf
  • 13.04 and earlier: sudo cp ~/mahara.conf /etc/apache2/sites-available/mahara

If you are upgrading from Ubuntu 12.04-13.04 to 13.10, you may find answers on this page helpful.

10. Enable the site in Apache:

sudo a2ensite mahara
sudo apache2ctl configtest
sudo apache2ctl graceful

11. Set up cron:

sudo vim /etc/cron.d/mahara
* * * * * www-data /usr/bin/php /home/<your username>/code/mahara/htdocs/lib/cron.php

Save your file.

12. Set up npm and gulp

As of Mahara 15.10, the main Mahara git repository includes SCSS files that compile into CSS files, instead of including CSS files directly. We compile these using a Gulp (NodeJS) script that's included with the code. This can easily be invoked via our Makefile by doing "make css", but it requires setting up a couple of additional items first.

First you'll need to run "npm install" from within the Mahara code directory, to get npm to properly set up all the proper caches and such.

cd /home/<your username>/code/mahara
npm install

Once that's finished, you'll need to install the npm "gulp" package using the "-g" (global) flag, so that "gulp" can be run as a CLI command. This requires using sudo.

cd /home/<your username>/code/mahara
sudo npm install -g gulp

13. Build the CSS

Now that this is done, you can build the CSS files. The easiest way to do this is by doing "make css" in the Mahara code directory. This will run the necessary series of instructions written out in the Makefile.

cd /home/<your username>/code/mahara
make css

14. Go to the site in your browser.

http://mahara/

15. You should see the Mahara installer page. If you do, congratulations! Your development environment is now set up.

Adding another branch

1. Create a new local branch for it in git (replace 1.10 / 110 with the version of Mahara for which you want to add a branch)

$ cd ~/code/mahara
$ git checkout -t origin/1.10_STABLE

2. Create the sitedata directory for the new branch:

$ sudo mkdir /var/lib/maharadata/110stable
$ sudo chown www-data:www-data /var/lib/maharadata/110stable

3. Create a database:

$ sudo -u postgres createdb -Omaharauser mahara-110stable

4. Change your ~/code/mahara/htdocs/config.php to point to the 1.10 branch:

$branch = '110stable';

5. Go to the site in your browser to run the Mahara installer:

http://mahara/

 

Switching back to the master branch

1. Change the config.php file:

$branch = 'master';

2. Switch to the right git branch:

$ cd ~/code/mahara/
$ git checkout master

 

Reset the database

1. Delete the old database:

$ sudo -u postgres dropdb mahara-master

2. Create a new one with the same name:

$ sudo -u postgres createdb -Omaharauser mahara-master

3. Go to the site in your browser to run the Mahara installer again:

http://mahara/

If you reset the database a lot, you might want to try out the "maharawipe.sh" utility at https://github.com/agwells/mahara-devtools

Testing a change submitted to Gerrit

1. Go to the change page, for example:

 https://reviews.mahara.org/#change,230

2. In your local repository, switch to the branch listed in the Gerrit change (in this case: master):

$ cd ~/code/mahara
$ git checkout master

3. Update your config.php to use the right branch, too.

4. Copy the "Anonymous Git" URL in the "Download" section of "Patch Set X" and run it in ~/code/mahara to check the branch out, for example:

$ git fetch git://reviews.mahara.org/git/mahara refs/changes/30/230/1 && git checkout FETCH_HEAD
$ make css

5. After finishing the testing, go back to master:

$ git checkout master
$ make css

 

Submitting a change to Gerrit

If you want to contribute a patch to the Mahara project yourself, please check out the wiki page on contributing code. There is also a troubleshooting page in case you run into issues pushing code to Gerrit.

 

Copying a local install to another

This example uses the directory 15stable as an example for the new install and the 14stable install as database and sitedata directory to copy.

1. Do a checkout of the code into a new directory:

$ cd ~
$ mkdir code
$ cd code
$ git clone git@git.mahara.org:mahara/mahara.git 15stable

2. Copy the database:

On Postgres 9

$ sudo -u postgres pg_dump -Fc mahara-14stable > 14stable.pg
$ sudo -u postgres createdb -Omaharauser mahara-15stable
$ sudo -u postgres pg_restore -O -j4 -d mahara-15stable -U maharauser -W -h localhost 14stable.pg

If you've not given the user 'maharauser' full privileges yet (should only need to do this once)

$ sudo -u postgres psql -d mahara-15stable -c 'GRANT ALL PRIVILEGES ON SCHEMA public TO maharauser;'
$ sudo -u postgres psql -d mahara-15stable -c 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO maharauser;'
$ sudo -u postgres psql -d mahara-15stable -c 'GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO maharauser;'
$ sudo -u postgres psql -d mahara-15stable -c 'GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO maharauser;'

On Postgres 8

$ sudo -u postgres pg_dump -Fc mahara-14stable > 14stable.pg
$ sudo -u postgres createdb -Omaharauser mahara-15stable
$ sudo -u postgres pg_restore -O -j4 -d mahara-15stable -U maharauser -W -h localhost 14stable.pg

This may give you the following warning

pg_restore: WARNING:  no privileges could be revoked for "public"
pg_restore: WARNING:  no privileges could be revoked for "public"
pg_restore: WARNING:  no privileges were granted for "public"
pg_restore: WARNING:  no privileges were granted for "public"

3. Change the wwwroot in the new database:

$ sudo -u postgres psql mahara-15stable
delete from config where field = 'wwwroot';
Ctrl + d to exit

4. Create the config file ~/code/mahara/htdocs/config.php:

<?php
$cfg = new StdClass;

$branch = '15stable';

// database connection details
// valid values for dbtype are 'postgres8' and 'mysql5'
$cfg->dbtype   = 'postgres8';
$cfg->dbhost   = 'localhost';
$cfg->dbuser   = 'maharauser';
$cfg->dbname   = "mahara-$branch";
$cfg->dbpass   = 'mahara'; 
$cfg->dbprefix = '''''''; 

$cfg->dataroot = "/var/lib/maharadata/$branch";

$cfg->sendemail = true;
$cfg->sendallemailto = 'your email address';

$cfg->log_dbg_targets     = LOG_TARGET_SCREEN | LOG_TARGET_ERRORLOG;
$cfg->log_info_targets    = LOG_TARGET_SCREEN | LOG_TARGET_ERRORLOG;
$cfg->log_warn_targets    = LOG_TARGET_SCREEN | LOG_TARGET_ERRORLOG;
$cfg->log_environ_targets = LOG_TARGET_SCREEN | LOG_TARGET_ERRORLOG;
$cfg->perftofoot = true;

5. Copy the source sitedata directory into the new sitedata folder:

$ sudo cp -r /var/lib/maharadata/14stable/ /var/lib/maharadata/15stable
$ sudo chown -R www-data:www-data /var/lib/maharadata/15stable

6. Add a new entry to /etc/hosts:

 127.0.0.1 15stable

7. Create a new Apache vhost file in /etc/apache2/sites-available/15stable.conf:

 <VirtualHost *:80>
  ServerName 15stable
  DocumentRoot /home/<your username>/code/15stable/htdocs
 
  <Directory /home/<your username>/code>
    Options Indexes FollowSymLinks MultiViews
    Order allow,deny
    Allow from all
  </Directory>
 
  ErrorLog /var/log/apache2/error.log
  LogLevel info
 
  CustomLog /var/log/apache2/access.log combined
  DirectoryIndex index.php index.html
 </VirtualHost>

8. Enable the site in Apache:

$ sudo a2ensite 15stable
$ sudo apache2ctl configtest
$ sudo apache2ctl graceful

9. Go to the site in your browser to run the Mahara installer:

http://15stable/

 

Elasticsearch

If you want to test the Elasticsearch search plugin, you'll also need to set up and run an Elasticsearch server. See Developer Area/Setting up Elasticsearch.

 

Set up site for local https://

You will need to set up your Mahara developer site with an SSL certificate if you want to use the web services functionality as that is only available over https.

You should already have Apache 2 installed on your computer. Otherwise, Mahara wouldn't run. Install the openssl and ssl-cert packages:

$ sudo apt-get install openssl ssl-cert

1. Enable SSL in Apache 2:

$ cd /etc/apache2/mods-enabled/
$ ls
$ sudo a2enmod ssl
$ service apache2 restart
$ ls

You should see "ssl.conf" and "ssl.load"

2. You'll need to check that the port for SSL traffic is configured.

$ cd ..
$ cat ports.conf

If you see <IfModule ssl_module> Listen 443, you are good to go.

3. Enable SSL also in your Mahara Apache 2 config file.

$ vim sites-available/mahara.conf (or the name of your config file of the site for which you want to enable SSL)

Paste the following into the .conf file after the </VirtualHost> for port 80. The last re-write rules are only necessary if you use the "Clean URL" functionality.

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName mahara

  DocumentRoot /home/'''<your username>'''/code/mahara/htdocs
  <Directory /home/'''<your username>'''/code>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Require all granted
    </Directory>

  ErrorLog /var/log/apache2/mahara-ssl-error.log
  LogLevel info

  CustomLog /var/log/apache2/mahara-ssl-access.log combined

    #   SSL Engine Switch:
    #   Enable/Disable SSL for this virtual host.
    SSLEngine on

    #   A self-signed (snakeoil) certificate can be created by installing
    #   the ssl-cert package. See
    #   /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
    #   If both key and certificate are stored in the same file, only the
    #   SSLCertificateFile directive is needed.
    SSLCertificateFile    /etc/apache2/ssl/apache.pem
    SSLCertificateKeyFile /etc/apache2/ssl/apache.key

    #   Server Certificate Chain:
    #   Point SSLCertificateChainFile at a file containing the
    #   concatenation of PEM encoded CA certificates which form the
    #   certificate chain for the server certificate. Alternatively
    #   the referenced file can be the same as SSLCertificateFile
    #   when the CA certificates are directly appended to the server
    #   certificate for convinience.
    #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt

    #   Certificate Authority (CA):
    #   Set the CA certificate verification path where to find CA
    #   certificates for client authentication or alternatively one
    #   huge file containing all of them (file must be PEM encoded)
    #   Note: Inside SSLCACertificatePath you need hash symlinks
    #         to point to the certificate files. Use the provided
    #         Makefile to update the hash symlinks after changes.
    #SSLCACertificatePath /etc/ssl/certs/
    #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
    #   Certificate Revocation Lists (CRL):
    #   Set the CA revocation path where to find CA CRLs for client
    #   authentication or alternatively one huge file containing all
    #   of them (file must be PEM encoded)
    #   Note: Inside SSLCARevocationPath you need hash symlinks
    #         to point to the certificate files. Use the provided
    #         Makefile to update the hash symlinks after changes.
    #SSLCARevocationPath /etc/apache2/ssl.crl/
    #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl

    #   Client Authentication (Type):
    #   Client certificate verification type and depth.  Types are
    #   none, optional, require and optional_no_ca.  Depth is a
    #   number which specifies how deeply to verify the certificate
    #   issuer chain before deciding the certificate is not valid.
    #SSLVerifyClient require
    #SSLVerifyDepth  10

    #   Access Control:
    #   With SSLRequire you can do per-directory access control based
    #   on arbitrary complex boolean expressions containing server
    #   variable checks and other lookup directives.  The syntax is a
    #   mixture between C and Perl.  See the mod_ssl documentation
    #   for more details.
    #<Location />
    #SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
    #            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
    #            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
    #            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
    #            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \
    #           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
    #</Location>

    #   SSL Engine Options:
    #   Set various options for the SSL engine.
    #   o FakeBasicAuth:
    #     Translate the client X.509 into a Basic Authorisation.  This means that
    #     the standard Auth/DBMAuth methods can be used for access control.  The
    #     user name is the `one line' version of the client's X.509 certificate.
    #     Note that no password is obtained from the user. Every entry in the user
    #     file needs this password: `xxj31ZMTZzkVA'.
    #   o ExportCertData:
    #     This exports two additional environment variables: SSL_CLIENT_CERT and
    #     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
    #     server (always existing) and the client (only existing when client
    #     authentication is used). This can be used to import the certificates
    #     into CGI scripts.
    #   o StdEnvVars:
    #     This exports the standard SSL/TLS related `SSL_*' environment variables.
    #     Per default this exportation is switched off for performance reasons,
    #     because the extraction step is an expensive operation and is usually
    #     useless for serving static content. So one usually enables the
    #     exportation for CGI and SSI requests only.
    #   o StrictRequire:
    #     This denies access when "SSLRequireSSL" or "SSLRequire" applied even
    #     under a "Satisfy any" situation, i.e. when it applies access is denied
    #     and no other module can change it.
    #   o OptRenegotiate:
    #     This enables optimized SSL connection renegotiation handling when SSL
    #     directives are used in per-directory context.
    #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>

    #   SSL Protocol Adjustments:
    #   The safe and default but still SSL/TLS standard compliant shutdown
    #   approach is that mod_ssl sends the close notify alert but doesn't wait for
    #   the close notify alert from client. When you need a different shutdown
    #   approach you can use one of the following variables:
    #   o ssl-unclean-shutdown:
    #     This forces an unclean shutdown when the connection is closed, i.e. no
    #     SSL close notify alert is send or allowed to received.  This violates
    #     the SSL/TLS standard but is needed for some brain-dead browsers. Use
    #     this when you receive I/O errors because of the standard approach where
    #     mod_ssl sends the close notify alert.
    #   o ssl-accurate-shutdown:
    #     This forces an accurate shutdown when the connection is closed, i.e. a
    #     SSL close notify alert is send and mod_ssl waits for the close notify
    #     alert of the client. This is 100% SSL/TLS standard compliant, but in
    #     practice often causes hanging connections with brain-dead browsers. Use
    #     this only for browsers where you know that their SSL implementation
    #     works correctly.
    #   Notice: Most problems of broken clients are also related to the HTTP
    #   keep-alive facility, so you usually additionally want to disable
    #   keep-alive for those clients, too. Use variable "nokeepalive" for this.
    #   Similarly, one has to force some clients to use HTTP/1.0 to workaround
    #   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
    #   "force-response-1.0" for this.
    BrowserMatch "MSIE [2-6]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
    # MSIE 7 and newer should be able to use keepalive
    BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
 
  <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteRule ^/user/([a-z0-9-]+)/?$ /user/view.php?profile=$1&%{QUERY_STRING}
    RewriteRule ^/user/([a-z0-9-]+)/([a-z0-9-]+)/?$ /view/view.php?profile=$1&page=$2&%{QUERY_STRING}
    RewriteRule ^/group/([a-z0-9-]+)/?$ /group/view.php?homepage=$1&%{QUERY_STRING}
    RewriteRule ^/group/([a-z0-9-]+)/([a-z0-9-]+)/?$ /view/view.php?homepage=$1&page=$2&%{QUERY_STRING}
  </IfModule>
</VirtualHost>
</IfModule>

4. Create the SSL folder in /etc/apache2/ if it doesn't already exist:

$ sudo mkdir /etc/apache2/ssl

5. Run the following command to set up your local cert and follow the ensuing steps for generating it:

$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.pem

When it asks you for the "Common name", you can put your local server's name.

6. Restart Apache.

$ sudo service apache2 restart

If you have an error message that pertains to your SSL site, you'll need to fix it first before continuing.

7. Test the Apache config:

$ sudo apache2ctl configtest

8. Delete the old wwwroot as that still points to http://. If you left it, you wouldn't see all assetts.

$ sudo -u postgres psql mahara-master
delete from config where field = 'wwwroot';
Ctrl + d to exit

9. Go to your Mahara URL and use https://. Since you created a self-signed cert, your connection will be untrusted. Proceed anyway.

10. Now you can use your developer site with web services as well.

 

Set up Behat

You can use the automated testing suite from Mahara 15.04 on. There is a separate installation page for Behat.