Application Server

This documentation can be used as a reference to create both your Production Application Server and Staging Application Server on a single Red Hat Enterprise or CentOS 7 virtual machine. This is achieved by using SNI within Apache 2.

The hostnames that will be referenced throughout this document will be elentra.med.university.edu and staging.med.university.edu. These hostnames should be replaced by your actual DNS hostnames.

  1. SSH into server and sudo to root:

    ssh service@elentra.med.university.edu
    sudo -s
  2. Change the SELINUX variable in /etc/selinux/config to permissive to prevent unforeseen and difficult to diagnose issues:

    SELINUX=permissive
  3. Add the following lines to /etc/hosts file:

    127.0.0.1 elentra.med.university.edu
    127.0.0.1 staging.med.university.edu
  4. Edit the hostname of the virtual machine in the /etc/hostname file:

    elentra.med.university.edu
  5. Install screen, update RHEL, and reboot:

    yum install screen
    screen
    yum update
    reboot
  6. SSH back into server, and install the Inline with Upstream Stable (IUS Community) package.

    ssh service@elentra.med.university.edu
    sudo -s
    screen
    yum -y install https://repo.ius.io/ius-release-el7.rpm \
    https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
  7. Install Apache, OpenSSL, PHP, Git, HTMLDoc, mariadb (client), ClamAV, and NTP packages:

    yum -y install git \
    htmldoc \
    curl \
    wget \
    unzip \
    openssl \
    httpd \
    mod_ssl \
    mod_php73 \
    php73-cli \
    php73-gd \
    php73-devel \
    php73-mysqlnd \
    php73-intl \
    php73-mbstring \
    php73-bcmath \
    php73-ldap \
    php73-imap \
    php73-soap \
    php73-xmlrpc \
    php73-tidy \
    php73-opcache \
    php73-json \
    php73-sodium \
    php73-pecl-redis \
    mariadb103 \
    clamav \
    ntp \
    supervisor
  8. Install wkhtmltopdf from the binary package because the yum package provided by EPEL is broken: curl -SL https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz | tar -xJC /root && cp /root/wkhtmltox/bin/* /usr/bin

  9. Start Apache and Supervisor, and set to start on system startup: systemctl enable httpd systemctl start httpd systemctl enable supervisord systemctl start supervisord

  10. Create a new file called /etc/php.d/elentra.ini and add the following:

    date.timezone = America/Toronto
    display_errors = Off
    error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT
    expose_php = Off
    memory_limit = 512M
    post_max_size = 512M
    session.cookie_secure = 1
    session.cookie_httponly = 1
    session.cookie_samesite = Strict
    upload_max_filesize = 512M
  11. Create an Elentra system user called production, which is used for production deployments:

    useradd -m production
    passwd production
  12. Create and permission the SSH authorized_keys file for the production user.

    cd /home/production
    mkdir /home/production/.ssh
    touch /home/production/.ssh/authorized_keys
    chown -R production:production /home/production/.ssh
    chmod 700 /home/production/.ssh
    chmod 600 /home/production/.ssh/authorized_keys
  13. Add all developers' SSH public keys (i.e. cat ~/.ssh/id_rsa.pub) that are allowed to deploy Elentra to your production environment to the new authorized_keys file.

    vim /home/production/.ssh/authorized_keys
  14. Create an Elentra system user called staging, which is used for staging deployments:

    useradd -m staging
    passwd staging
  15. Create and permission the SSH authorized_keys file for the staging user.

    cd /home/staging
    mkdir /home/staging/.ssh
    touch /home/staging/.ssh/authorized_keys
    chown -R staging:staging /home/staging/.ssh
    chmod 700 /home/staging/.ssh
    chmod 600 /home/staging/.ssh/authorized_keys
  16. Add all developers' SSH public keys (i.e. cat ~/.ssh/id_rsa.pub) that are allowed to deploy Elentra to your staging environment to the new authorized_keys file.

    vim /home/staging/.ssh/authorized_keys
  17. Create and appropriately permission the Apache document root and Elentra storage directories for production.

    mkdir -p /var/www/vhosts/elentra.med.university.edu/storage/
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/annualreports
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/app
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/app/public
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/cache
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/cbme-uploads
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/cbme-uploads/advisor-files
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/community-discussions
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/community-galleries
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/community-shares
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/eportfolio
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/event-files
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/exam-files
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/framework
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/framework/cache
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/framework/cache/data
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/framework/sessions
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/framework/views
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/logs
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/lor
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/msprs
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/resource-images
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/secure-access
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/syllabi
    mkdir /var/www/vhosts/elentra.med.university.edu/storage/user-photos
    chown -R production:production /var/www/vhosts/elentra.med.university.edu
    chmod -R 777 /var/www/vhosts/elentra.med.university.edu/storage/*
  18. Create and appropriately permission the Apache document root and Elentra storage directories for staging.

    mkdir -p /var/www/vhosts/staging.med.university.edu/storage/
    mkdir /var/www/vhosts/staging.med.university.edu/storage/annualreports
    mkdir /var/www/vhosts/staging.med.university.edu/storage/app
    mkdir /var/www/vhosts/staging.med.university.edu/storage/app/public
    mkdir /var/www/vhosts/staging.med.university.edu/storage/cache
    mkdir /var/www/vhosts/staging.med.university.edu/storage/cbme-uploads
    mkdir /var/www/vhosts/staging.med.university.edu/storage/cbme-uploads/advisor-files
    mkdir /var/www/vhosts/staging.med.university.edu/storage/community-discussions
    mkdir /var/www/vhosts/staging.med.university.edu/storage/community-galleries
    mkdir /var/www/vhosts/staging.med.university.edu/storage/community-shares
    mkdir /var/www/vhosts/staging.med.university.edu/storage/eportfolio
    mkdir /var/www/vhosts/staging.med.university.edu/storage/event-files
    mkdir /var/www/vhosts/staging.med.university.edu/storage/exam-files
    mkdir /var/www/vhosts/staging.med.university.edu/storage/framework
    mkdir /var/www/vhosts/staging.med.university.edu/storage/framework/cache
    mkdir /var/www/vhosts/staging.med.university.edu/storage/framework/cache/data
    mkdir /var/www/vhosts/staging.med.university.edu/storage/framework/sessions
    mkdir /var/www/vhosts/staging.med.university.edu/storage/framework/views
    mkdir /var/www/vhosts/staging.med.university.edu/storage/logs
    mkdir /var/www/vhosts/staging.med.university.edu/storage/lor
    mkdir /var/www/vhosts/staging.med.university.edu/storage/msprs
    mkdir /var/www/vhosts/staging.med.university.edu/storage/resource-images
    mkdir /var/www/vhosts/staging.med.university.edu/storage/secure-access
    mkdir /var/www/vhosts/staging.med.university.edu/storage/syllabi
    mkdir /var/www/vhosts/staging.med.university.edu/storage/user-photos
    chown -R staging:staging /var/www/vhosts/staging.med.university.edu
    chmod -R 777 /var/www/vhosts/staging.med.university.edu/storage/*
  19. Generate the SSL private keys required for each of your hostnames:

    mkdir -p /root/certificates/2020
    cd /root/certificates/2020
    openssl genrsa -out elentra.med.university.edu.key 2048
    openssl genrsa -out staging.med.university.edu.key 2048
  20. Generate the SSL certificate signing requests (CSRs) for your certificate authority for each of your hostnames:

    openssl req -new -key elentra.med.university.edu.key -out elentra.med.university.edu.csr
    openssl req -new -key staging.med.university.edu.key -out staging.med.university.edu.csr

    You will be asked a number of questions, answer accordingly, but do not answer enter anything for "Email Address", "A challenge password", or "An optional company name":

    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CA
    State or Province Name (full name) []:Ontario
    Locality Name (eg, city) [Default City]:Kingston
    Organization Name (eg, company) [Default Company Ltd]:Queen's University
    Organizational Unit Name (eg, section) []:Health Sciences Education Technology Unit
    Common Name (eg, your name or your server's hostname) []:elentra.med.university.edu
    Email Address []:
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
  21. If you have a valid Certificate Authority certificate, you should create a .crt file foreach hostname and paste in the certificate text:

    vim /root/certificates/2020/elentra.med.university.edu.crt
    vim /root/certificates/20202020/staging.med.university.edu.crt

    You will also likely have a certificate authority root chain certificate. Also paste this into a file called ca-certificate.crt.

  22. If you are only creating self-signed certificates, you should do this for each hostname:

    openssl x509 -req -days 365 -in elentra.med.university.edu.csr -signkey elentra.med.university.edu.key -out elentra.med.university.edu.crt
    openssl x509 -req -days 365 -in staging.med.university.edu.csr -signkey staging.med.university.edu.key -out staging.med.university.edu.crt
  23. Install the certificates in the Apache virtual host directory:

    mkdir /var/www/vhosts/elentra.med.university.edu/cert/
    cp /root/certificates/2020/elentra.med.university.edu.crt /var/www/vhosts/elentra.med.university.edu/cert/
    cp /root/certificates/2020/elentra.med.university.edu.key /var/www/vhosts/elentra.med.university.edu/cert/
    mkdir /var/www/vhosts/staging.med.university.edu/cert/
    cp /root/certificates/2020/staging.med.university.edu.crt /var/www/vhosts/staging.med.university.edu/cert/
    cp /root/certificates/2020/staging.med.university.edu.key /var/www/vhosts/staging.med.university.edu/cert/
  24. Create the Apache VirtualHosts by creating a file named 000-elentra.conf and placing it /etc/httpd/conf.d/. This file should contain the following:

    # This will limit what information Apache reveals about itself.
    ServerTokens Prod
    ServerSignature Off
    TraceEnable Off
    SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
    # Apache performance tuning options for more connections.
    #<IfModule mpm_prefork_module>
    # MaxRequestWorkers 512
    # ServerLimit 512
    #</IfModule>
    # Production
    <VirtualHost *:80>
    ServerName elentra.med.university.edu
    ServerAdmin sysadmin@med.university.edu
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
    </VirtualHost>
    <VirtualHost *:443>
    ServerName elentra.med.university.edu:443
    ServerAdmin sysadmin@med.university.edu
    SSLEngine on
    SSLProtocol -all +TLSv1.2
    SSLHonorCipherOrder on
    SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
    SSLCertificateFile /var/www/vhosts/elentra.med.university.edu/cert/elentra.med.university.edu.crt
    SSLCertificateKeyFile /var/www/vhosts/elentra.med.university.edu/cert/elentra.med.university.edu.key
    #SSLCACertificateFile /var/www/vhosts/elentra.med.university.edu/cert/ca-certificate.crt
    SSLUseStapling on
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
    Header always set X-Frame-Options DENY
    DocumentRoot /var/www/vhosts/elentra.med.university.edu/current/www-root
    <Directory "/var/www/vhosts/elentra.med.university.edu/current/www-root">
    Options FollowSymLinks
    Require all granted
    AllowOverride all
    </Directory>
    </VirtualHost>
    # Staging
    <VirtualHost *:80>
    ServerName staging.med.university.edu
    ServerAdmin sysadmin@med.university.edu
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
    </VirtualHost>
    <VirtualHost *:443>
    ServerName staging.med.university.edu:443
    ServerAdmin sysadmin@med.university.edu
    SSLEngine on
    SSLProtocol -all +TLSv1.2
    SSLHonorCipherOrder on
    SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
    SSLCertificateFile /var/www/vhosts/staging.med.university.edu/cert/staging.med.university.edu.crt
    SSLCertificateKeyFile /var/www/vhosts/staging.med.university.edu/cert/staging.med.university.edu.key
    #SSLCACertificateFile /var/www/vhosts/staging.med.university.edu/cert/ca-certificate.crt
    SSLUseStapling on
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
    Header always set X-Frame-Options DENY
    DocumentRoot /var/www/vhosts/staging.med.university.edu/current/www-root
    <Directory "/var/www/vhosts/staging.med.university.edu/current/www-root">
    Options FollowSymLinks
    Require all granted
    AllowOverride all
    </Directory>
    </VirtualHost>
  25. Create a new file in the /etc/supervisor.d directory called elentra.ini, and use the following template snippet as a reference to create your own file.

    Please make sure that you have the correct path in command and stdout_logfile, and that user is the correct system account that your existing cron jobs are run as.

    [program:staging]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/vhosts/staging.elentra.med.university.edu/current/www-root/core/library/vendor/elentrapackages/elentra-1x-api/artisan queue:work --queue=high,emails,default,low --env=staging
    autostart=true
    autorestart=true
    user=staging
    numprocs=1
    redirect_stderr=true
    stdout_logfile=/var/www/vhosts/staging.elentra.med.university.edu/storage/logs/worker.log
    [program:production]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/vhosts/elentra.med.university.edu/current/www-root/core/library/vendor/elentrapackages/elentra-1x-api/artisan queue:work --queue=high,emails,default,low --env=production
    autostart=true
    autorestart=true
    user=production
    numprocs=1
    redirect_stderr=true
    stdout_logfile=/var/www/vhosts/elentra.med.university.edu/storage/logs/worker.log
    [group:elentra]
    programs=staging,production
  26. Test your new Apache configuration, then restart Apache and Supervisor.

    apachectl configtest
    systemctl restart httpd
    systemctl restart supervisor