Skip to main content

Overview

This guide covers installing OpenEyes for production use. For development environments, see the Quick Start Guide.
Important Safety NoticeOpenEyes is provided under AGPL v3.0 license with NO WARRANTY. Any user deploying OpenEyes in a clinical environment must:
  • Undertake a comprehensive safety assessment
  • Ensure deployment matches local clinical safety requirements
  • Comply with relevant data protection regulations (GDPR, HIPAA, etc.)
  • Implement proper backup and disaster recovery procedures
  • Obtain appropriate support contracts for clinical use

System Requirements

Server Requirements

  • Recommended: Ubuntu 20.04 LTS or 22.04 LTS
  • RHEL/CentOS 7/8 (with adjustments)
  • Debian 10/11

Software Requirements

Based on composer.json specifications:
{
  "require": {
    "php": "^7.4 || ^8.0 || ^8.1",
    "ext-json": "^7.4 || ^8.0 || ^8.1",
    "ext-dom": "*",
    "ext-libxml": "*",
    "ext-openssl": "*",
    "ext-soap": "*",
    "yiisoft/yii": "1.1.28"
  }
}
Required PHP Extensions:
  • php-json
  • php-dom
  • php-xml / php-libxml
  • php-openssl
  • php-soap
  • php-mysql or php-mysqli
  • php-gd
  • php-curl
  • php-mbstring
Database:
  • MySQL 5.7+ or MariaDB 10.3+
  • InnoDB storage engine
  • 128MB+ innodb_log_file_size
  • 128MB+ max_allowed_packet
Web Server:
  • Apache 2.4+ with mod_rewrite
  • OR Nginx 1.18+

Installation Steps

1

Install System Dependencies

Update system and install required packages:
# Update system
sudo apt update && sudo apt upgrade -y

# Install PHP 8.1 and extensions
sudo apt install -y php8.1 php8.1-cli php8.1-fpm \
  php8.1-mysql php8.1-json php8.1-xml php8.1-soap \
  php8.1-gd php8.1-curl php8.1-mbstring php8.1-dom

# Install Apache
sudo apt install -y apache2

# Enable required Apache modules
sudo a2enmod rewrite ssl headers

# Install MySQL
sudo apt install -y mysql-server-8.0

# Install Composer
curl -sS https://getcomposer.org/installer | sudo php -- \
  --install-dir=/usr/local/bin --filename=composer

# Install Git
sudo apt install -y git
Verify PHP version:
php -v  # Should show 7.4, 8.0, or 8.1
2

Configure MySQL Database

Create the OpenEyes database and user:
# Connect to MySQL
sudo mysql
Execute the following SQL:
-- Create database
CREATE DATABASE openeyes CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Create user with strong password
CREATE USER 'openeyes'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD_HERE';

-- Grant privileges
GRANT ALL PRIVILEGES ON openeyes.* TO 'openeyes'@'localhost';
FLUSH PRIVILEGES;

-- Exit MySQL
EXIT;
Configure MySQL for OpenEyes by editing /etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
innodb_log_file_size = 128M
max_allowed_packet = 128M
net_buffer_length = 1000000

# For production, enable binary logging
log_bin = /var/log/mysql/mysql-bin.log
binlog_expire_logs_seconds = 604800
Restart MySQL:
sudo systemctl restart mysql
Replace STRONG_PASSWORD_HERE with a secure password. Store it securely for later configuration.
3

Clone OpenEyes Repository

Clone to the web server directory:
# Create directory
sudo mkdir -p /var/www/openeyes
cd /var/www/openeyes

# Clone repository (stable master branch)
sudo git clone -b master https://github.com/AppertaFoundation/openeyes.git .

# Set ownership
sudo chown -R www-data:www-data /var/www/openeyes
For a specific version:
git checkout tags/v3.0  # Replace with desired version
4

Install PHP Dependencies

Install dependencies using Composer:
cd /var/www/openeyes
sudo -u www-data composer install --no-dev --optimize-autoloader
The --no-dev flag excludes development dependencies for production.
5

Configure Database Connection

OpenEyes reads database configuration from environment variables or /etc/openeyes/db.conf.Option 1: Environment Variables (Recommended for Docker/containerized deployments)Set in your environment or systemd service:
export DATABASE_HOST=localhost
export DATABASE_PORT=3306
export DATABASE_NAME=openeyes
export DATABASE_USER=openeyes
export DATABASE_PASS=STRONG_PASSWORD_HERE
Option 2: Configuration File (Traditional deployment)Create /etc/openeyes/db.conf:
host=localhost
port=3306
dbname=openeyes
username=openeyes
password=STRONG_PASSWORD_HERE
Secure the file:
sudo chown www-data:www-data /etc/openeyes/db.conf
sudo chmod 600 /etc/openeyes/db.conf
The configuration is read from protected/config/core/common.php:
if (file_exists('/etc/openeyes/db.conf')) {
    $db = parse_ini_file('/etc/openeyes/db.conf');
} else {
    $db = array(
        'host' => getenv('DATABASE_HOST') ?: 'localhost',
        'port' => getenv('DATABASE_PORT') ?: '3306',
        'dbname' => getenv('DATABASE_NAME') ?: 'openeyes',
        'username' => getenv('DATABASE_USER') ?: 'openeyes',
        'password' => getenv('DATABASE_PASS') ?: 'openeyes',
    );
}
6

Run Database Migrations

Initialize the database schema:
cd /var/www/openeyes
sudo -u www-data php protected/yiic.php migrate --interactive=0
This creates all necessary tables and applies schema migrations.For module-specific migrations:
sudo -u www-data php protected/yiic.php migrate \
  --migrationPath=application.modules.OphCiExamination.migrations
7

Set File Permissions

Configure proper ownership and permissions:
cd /var/www/openeyes

# Set ownership
sudo chown -R www-data:www-data /var/www/openeyes

# Runtime directory needs write access
sudo chmod -R 775 protected/runtime
sudo chmod -R 775 assets

# Protect sensitive files
sudo chmod 640 protected/config/local/*.php
8

Configure Apache Virtual Host

Create /etc/apache2/sites-available/openeyes.conf:
<VirtualHost *:80>
    ServerName openeyes.example.com
    ServerAdmin [email protected]
    
    DocumentRoot /var/www/openeyes
    
    <Directory /var/www/openeyes>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
        
        # Yii framework rewrite rules
        RewriteEngine On
        RewriteBase /
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.php [L]
    </Directory>
    
    # Protect sensitive directories
    <Directory /var/www/openeyes/protected>
        Require all denied
    </Directory>
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/openeyes_error.log
    CustomLog ${APACHE_LOG_DIR}/openeyes_access.log combined
    
    # Security headers
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>
Enable the site:
sudo a2ensite openeyes
sudo systemctl reload apache2
9

Configure SSL/TLS

For production, HTTPS is mandatory. Use Let’s Encrypt:
# Install Certbot
sudo apt install -y certbot python3-certbot-apache

# Obtain certificate
sudo certbot --apache -d openeyes.example.com
Certbot will automatically:
  • Obtain SSL certificate
  • Configure Apache for HTTPS
  • Set up automatic renewal
For manual SSL configuration, create /etc/apache2/sites-available/openeyes-ssl.conf:
<VirtualHost *:443>
    ServerName openeyes.example.com
    
    DocumentRoot /var/www/openeyes
    
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/openeyes.crt
    SSLCertificateKeyFile /etc/ssl/private/openeyes.key
    SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
    
    # Modern SSL configuration
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLHonorCipherOrder on
    
    # HSTS
    Header always set Strict-Transport-Security "max-age=31536000"
    
    # Include directory configuration from HTTP vhost
    Include /etc/apache2/sites-available/openeyes.conf
</VirtualHost>
10

Configure Application Settings

Set production environment variables:
# In Apache envvars or systemd unit
export OE_MODE=LIVE
export OE_INSTITUTION_CODE=YOUR_INSTITUTION_CODE
export AUTH_SOURCE=BASIC  # or LDAP, SAML, OIDC
Key configuration options from protected/config/core/common.php:
VariableDefaultDescription
OE_MODE-Operating mode: LIVE, TEST, or DEV
OE_INSTITUTION_CODENEWYour institution identifier
AUTH_SOURCEBASICAuthentication: BASIC, LDAP, SAML, OIDC
SSO_CLIENT_ID-OIDC client ID (if using SSO)
SSO_CLIENT_SECRET-OIDC client secret (if using SSO)
OE_PASAPI_ENABLEFALSEEnable PAS API integration
OE_PORTAL_ENABLEDFALSEEnable patient portal
For production, always set OE_MODE=LIVE to disable debug features and enforce security.
11

Create Initial Admin User

Access the database and create an administrative user:
mysql -u openeyes -p openeyes
-- Insert admin user (adjust as needed)
INSERT INTO user (username, first_name, last_name, email, 
                  active, password_softlocked, password_status)
VALUES ('admin', 'System', 'Administrator', '[email protected]', 
        1, 0, 0);

-- Set password (will need to be changed on first login)
UPDATE user SET password = MD5('ChangeMe123!') 
WHERE username = 'admin';

-- Grant admin role
INSERT INTO authassignment (itemname, userid)
SELECT 'admin', id FROM user WHERE username = 'admin';
The user will be prompted to change their password on first login.
12

Verify Installation

Test the installation:
  1. Access the application:
    • Navigate to https://openeyes.example.com
    • You should see the OpenEyes login page
  2. Check PHP configuration:
    sudo -u www-data php protected/yiic.php version
    
  3. Verify database connection:
    sudo -u www-data php protected/yiic.php migrate --interactive=0
    
    Should report “No new migrations found.”
  4. Review logs:
    tail -f /var/log/apache2/openeyes_error.log
    

Post-Installation Configuration

Authentication Setup

Configure LDAP integration:
export AUTH_SOURCE=LDAP
export OE_LDAP_SERVER=ldap://ldap.example.com
export OE_LDAP_PORT=389
export OE_LDAP_ADMIN_DN="cn=admin,dc=example,dc=com"
export OE_LDAP_PASSWORD="ldap_password"
export OE_LDAP_BASE_DN="ou=users,dc=example,dc=com"

Cron Jobs

Set up scheduled tasks:
sudo crontab -u www-data -e
Add the following:
# OpenEyes scheduled tasks
*/5 * * * * /usr/bin/php /var/www/openeyes/protected/yiic.php cronrunner

# Database backup (daily at 2 AM)
0 2 * * * /var/www/openeyes/protected/scripts/backupdb.sh

# Log rotation
0 0 * * 0 /usr/sbin/logrotate /etc/logrotate.d/openeyes

Backup Strategy

Implement regular backups:
backup.sh
#!/bin/bash
# OpenEyes Backup Script

BACKUP_DIR="/backup/openeyes"
DATE=$(date +%Y%m%d_%H%M%S)

# Database backup
mysqldump -u openeyes -p$DB_PASSWORD openeyes | \
  gzip > $BACKUP_DIR/db_$DATE.sql.gz

# File backup
tar -czf $BACKUP_DIR/files_$DATE.tar.gz \
  /var/www/openeyes/protected/runtime \
  /var/www/openeyes/protected/files \
  /etc/openeyes/

# Retain last 30 days
find $BACKUP_DIR -mtime +30 -delete

Security Hardening

Configure UFW firewall:
sudo ufw allow 22/tcp   # SSH
sudo ufw allow 80/tcp   # HTTP
sudo ufw allow 443/tcp  # HTTPS
sudo ufw enable
Edit /etc/php/8.1/apache2/php.ini:
expose_php = Off
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log

upload_max_filesize = 128M
post_max_size = 128M
memory_limit = 256M

disable_functions = exec,passthru,shell_exec,system,proc_open
  • Use strong passwords
  • Restrict database user to localhost only
  • Enable binary logging for point-in-time recovery
  • Regular security updates
# Remove anonymous users
mysql -e "DELETE FROM mysql.user WHERE User=''"

# Remove test database
mysql -e "DROP DATABASE IF EXISTS test"

# Flush privileges
mysql -e "FLUSH PRIVILEGES"
Install and configure AIDE:
sudo apt install aide
sudo aideinit
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Run daily checks
echo '0 3 * * * root /usr/bin/aide --check' | sudo tee -a /etc/crontab

Performance Optimization

PHP OpCache

Enable and configure OpCache in /etc/php/8.1/apache2/php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1

MySQL Tuning

Optimize MySQL configuration:
[mysqld]
innodb_buffer_pool_size = 2G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
query_cache_size = 64M
tmp_table_size = 64M
max_heap_table_size = 64M

Apache MPM

Configure Apache MPM prefork:
<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

Monitoring and Maintenance

Application Monitoring

# Monitor Apache processes
sudo systemctl status apache2

# Check PHP-FPM status
sudo systemctl status php8.1-fpm

# Monitor MySQL
sudo systemctl status mysql

# View application logs
tail -f /var/www/openeyes/protected/runtime/application.log

Health Checks

Create a monitoring script:
monitor.sh
#!/bin/bash
# Check if OpenEyes is responding

URL="https://openeyes.example.com"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" $URL)

if [ $HTTP_CODE -eq 200 ]; then
    echo "OpenEyes is healthy"
else
    echo "OpenEyes returned HTTP $HTTP_CODE"
    # Send alert
fi

Troubleshooting

Check PHP error logs:
tail -f /var/log/apache2/openeyes_error.log
tail -f /var/www/openeyes/protected/runtime/application.log
Common causes:
  • Database connection failure
  • File permission issues
  • Missing PHP extensions
Reset migration state:
mysql -u openeyes -p openeyes -e "SELECT * FROM migration_history ORDER BY apply_time DESC LIMIT 10;"
Manually apply failed migration:
sudo -u www-data php protected/yiic.php migrate redo
Clear session data:
sudo rm -rf /var/www/openeyes/protected/runtime/sessions/*
sudo systemctl restart apache2
Enable slow query log:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
Review slow queries:
tail -f /var/log/mysql/mysql-slow.log

Upgrading OpenEyes

Always backup before upgrading!
1

Backup Current Installation

# Database
mysqldump -u openeyes -p openeyes > backup_$(date +%F).sql

# Files
tar -czf openeyes_backup_$(date +%F).tar.gz /var/www/openeyes
2

Pull Latest Code

cd /var/www/openeyes
sudo -u www-data git fetch --tags
sudo -u www-data git checkout tags/v3.1  # Or desired version
3

Update Dependencies

sudo -u www-data composer install --no-dev --optimize-autoloader
4

Run Migrations

sudo -u www-data php protected/yiic.php migrate --interactive=0
5

Clear Cache

sudo rm -rf /var/www/openeyes/protected/runtime/cache/*
sudo rm -rf /var/www/openeyes/assets/*
sudo systemctl restart apache2

Getting Support

GitHub Issues

Community issue tracker

Wiki Documentation

Additional installation guides

Professional Services

Accredited partners for production support

Contact

General inquiries
Production Deployment Checklist
  • SSL/TLS certificate configured
  • Firewall rules applied
  • Database backups automated
  • Cron jobs configured
  • Monitoring enabled
  • Security hardening completed
  • Admin users created
  • Authentication configured (LDAP/SAML/OIDC)
  • Clinical safety assessment performed
  • Support contract in place
  • Disaster recovery plan documented

Build docs developers (and LLMs) love