Installation Guide
This guide covers production installation of Sakai LMS. For development and quick testing, see the Quick Start Guide .
Production deployments require careful planning for security, performance, backup, and high availability. This guide provides the foundation, but consult with your IT security and infrastructure teams.
Installation Methods
Sakai can be installed using several approaches:
Source Build Build from source for maximum control and customization. Recommended for institutions with development teams.
Docker Deployment Container-based deployment for easier management and scaling. Ideal for modern infrastructure.
Binary Release Pre-built releases available from the Sakai project. Fastest deployment but limited customization.
Cloud Deployment Deploy on AWS, Azure, or GCP using containers or VMs. Provides scalability and redundancy.
System Requirements
Hardware Requirements
Minimum (Small Installation - up to 1,000 users):
4 CPU cores
8 GB RAM
100 GB storage (SSD recommended)
100 Mbps network
Recommended (Medium Installation - 1,000-10,000 users):
8-16 CPU cores
16-32 GB RAM
500 GB storage (SSD)
1 Gbps network
Enterprise (Large Installation - 10,000+ users):
16+ CPU cores per application server
32+ GB RAM per application server
Multiple application servers behind load balancer
Dedicated database server(s) with replication
1+ TB storage (SSD/NVMe)
Multiple network interfaces, bonded if possible
Software Requirements
Core Dependencies Operating System:
Linux (Ubuntu 20.04+, RHEL/CentOS 8+, Debian 11+)
Required packages: Java 17, build tools, database client
Java Runtime:
Java 17 (OpenJDK 17, Eclipse Temurin recommended)
NOT compatible with Java 18+ or Java 11
Application Server:
Apache Tomcat 9.x (latest stable)
Must be manual installation (not from package manager)
Database:
MariaDB 10.5+ (recommended)
MySQL 8.0+
Oracle 19c+
Microsoft SQL Server 2019+
MariaDB is the recommended database for new installations due to better performance with Sakai and active development.
Installation from Source
This is the most flexible installation method, allowing customization and local tool development.
Step 1: Prepare the Server
Update System
# Ubuntu/Debian
sudo apt-get update && sudo apt-get upgrade -y
# RHEL/CentOS
sudo yum update -y
Install Java 17
# Ubuntu/Debian
sudo apt-get install -y openjdk-17-jdk
# RHEL/CentOS
sudo yum install -y java-17-openjdk-devel
# Verify installation
java -version
javac -version
# Set JAVA_HOME
export JAVA_HOME = / usr / lib / jvm / java-17-openjdk-amd64
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> ~/.bashrc
Install Maven
# Download and install Maven 3.9+
cd /opt
sudo wget https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
sudo tar -xzf apache-maven-3.9.6-bin.tar.gz
sudo ln -s /opt/apache-maven-3.9.6 /opt/maven
# Add to PATH
echo 'export PATH=/opt/maven/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
# Verify
mvn -version
Install Git
sudo apt-get install -y git # Ubuntu/Debian
sudo yum install -y git # RHEL/CentOS
# Install MariaDB 10.5+
sudo apt-get install -y mariadb-server mariadb-client
# Secure installation
sudo mysql_secure_installation
Configure MariaDB for Sakai: sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
Add these settings under [mysqld]: [mysqld]
# Character set and collation
character-set-server =utf8mb4
collation-server =utf8mb4_unicode_ci
# InnoDB settings
innodb_buffer_pool_size =2G
innodb_log_file_size =256M
innodb_flush_log_at_trx_commit =2
# Performance
max_connections =200
max_allowed_packet =64M
# Required for Sakai
lower_case_table_names =1
Create Sakai database: sudo mysql - u root - p
CREATE DATABASE sakai CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER ' sakai '@ 'localhost' IDENTIFIED BY 'your_secure_password' ;
GRANT ALL PRIVILEGES ON sakai. * TO 'sakai' @ 'localhost' ;
FLUSH PRIVILEGES;
EXIT;
Restart MariaDB: sudo systemctl restart mariadb
sudo systemctl enable mariadb
# Install MySQL 8.0
sudo apt-get install -y mysql-server
# Secure installation
sudo mysql_secure_installation
Configure MySQL: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Add under [mysqld]: [mysqld]
character-set-server =utf8mb4
collation-server =utf8mb4_unicode_ci
innodb_buffer_pool_size =2G
innodb_log_file_size =256M
max_connections =200
max_allowed_packet =64M
lower_case_table_names =1
# MySQL 8 compatibility
default_authentication_plugin =mysql_native_password
Create database and user: sudo mysql - u root - p
CREATE DATABASE sakai CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER ' sakai '@ 'localhost' IDENTIFIED WITH mysql_native_password BY 'your_secure_password' ;
GRANT ALL PRIVILEGES ON sakai. * TO 'sakai' @ 'localhost' ;
FLUSH PRIVILEGES;
EXIT;
Step 3: Install Tomcat
Download and Extract Tomcat
# Create sakai user
sudo useradd -r -m -U -d /opt/sakai -s /bin/bash sakai
# Download Tomcat 9
cd /opt
sudo wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.85/bin/apache-tomcat-9.0.85.tar.gz
sudo tar -xzf apache-tomcat-9.0.85.tar.gz
sudo mv apache-tomcat-9.0.85 /opt/sakai/tomcat
sudo chown -R sakai:sakai /opt/sakai
Configure Tomcat Environment
Create /opt/sakai/tomcat/bin/setenv.sh: #!/bin/sh
# Java options
export JAVA_OPTS = "-server"
export JAVA_OPTS = " $JAVA_OPTS -Xms2g -Xmx4g"
export JAVA_OPTS = " $JAVA_OPTS -XX:+UseG1GC"
export JAVA_OPTS = " $JAVA_OPTS -XX:+UseStringDeduplication"
export JAVA_OPTS = " $JAVA_OPTS -Djava.awt.headless=true"
# Sakai properties
export JAVA_OPTS = " $JAVA_OPTS -Dsakai.home=/opt/sakai/sakai-home"
export JAVA_OPTS = " $JAVA_OPTS -Dsakai.security=/opt/sakai/sakai-home/security"
# Logging
export JAVA_OPTS = " $JAVA_OPTS -Dlog4j2.formatMsgNoLookups=true"
# Timezone
export JAVA_OPTS = " $JAVA_OPTS -Duser.timezone=America/New_York"
Make executable: sudo chmod +x /opt/sakai/tomcat/bin/setenv.sh
sudo chown sakai:sakai /opt/sakai/tomcat/bin/setenv.sh
Configure Tomcat Server
Edit /opt/sakai/tomcat/conf/server.xml: Update the Connector: < Connector port = "8080" protocol = "HTTP/1.1"
maxThreads = "150"
minSpareThreads = "25"
connectionTimeout = "20000"
maxParameterCount = "100000"
URIEncoding = "UTF-8"
compression = "on"
compressibleMimeType = "text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json" />
The maxParameterCount="100000" setting is critical for Sakai to function properly.
Step 4: Build Sakai
Clone Source
sudo -u sakai bash
cd /opt/sakai
git clone https://github.com/sakaiproject/sakai.git sakai-source
cd sakai-source
# Checkout stable release
git checkout 25.1
Build from Source
cd /opt/sakai/sakai-source
# Full build with tests
mvn clean install
# Or skip tests for faster build
mvn clean install -Dmaven.test.skip=true
This process takes 15-30 minutes depending on hardware.
Deploy to Tomcat
mvn clean install sakai:deploy -Dmaven.tomcat.home=/opt/sakai/tomcat
This copies:
WAR files to /opt/sakai/tomcat/webapps/
Components to /opt/sakai/tomcat/components/
Libraries to /opt/sakai/tomcat/lib/
Create Sakai Home Directory
sudo mkdir -p /opt/sakai/sakai-home
sudo mkdir -p /opt/sakai/sakai-home/security
sudo chown -R sakai:sakai /opt/sakai/sakai-home
Create sakai.properties
Create /opt/sakai/sakai-home/sakai.properties: # Database configuration
vendor@ org.sakaiproject.db.api.SqlService =mysql
driverClassName@ javax.sql.BaseDataSource =org.mariadb.jdbc.Driver
url@ javax.sql.BaseDataSource =jdbc:mariadb://localhost:3306/sakai? useUnicode =true& characterEncoding =UTF-8
username@ javax.sql.BaseDataSource =sakai
password@ javax.sql.BaseDataSource =your_secure_password
hibernate.dialect =org.hibernate.dialect.MySQL5InnoDBDialect
validationQuery@ javax.sql.BaseDataSource =select 1 from DUAL
defaultTransactionIsolationString@ javax.sql.BaseDataSource =TRANSACTION_READ_COMMITTED
# Server identification
serverName =your.institution.edu
serverId =prod-sakai-01
serverInstance =production
# Email configuration
smtp.enabled =true
smtp.server =smtp.your.edu
smtp.port =25
# System email addresses
setup.request [email protected]
mail.support [email protected]
# Portal
portal.error.showdetail =false
# Security
skin.repo =/opt/sakai/sakai-home/skins
# Performance
search.enable =true
portal.cdn.version =25.1
# Session timeout (minutes)
inactiveInterval@ org.sakaiproject.tool.api.SessionManager =60
Reference: This configuration mirrors the structure in docker/tomcat/sakai/sakai.properties:1-64
Set File Permissions
sudo chown -R sakai:sakai /opt/sakai/sakai-home
sudo chmod 600 /opt/sakai/sakai-home/sakai.properties
Step 6: Start Sakai
Initial Startup
sudo -u sakai /opt/sakai/tomcat/bin/startup.sh
# Monitor logs
tail -f /opt/sakai/tomcat/logs/catalina.out
First startup takes 2-5 minutes as Sakai initializes the database schema. Look for: INFO: Server startup in [xxxxx] milliseconds
ComponentManagerImpl.init() - ComponentManager ready
Verify Installation
Access Sakai: http://your-server:8080/portal
Login with default credentials:
Username: admin
Password: admin
Change the admin password immediately!
Docker Installation
Docker provides a faster, more portable installation method.
Prerequisites
# Install Docker Engine
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group
sudo usermod -aG docker $USER
# Install Docker Compose
sudo apt-get install -y docker-compose
Build Sakai Docker Image
The multi-stage Dockerfile builds Sakai from source:
From Master Branch
From Specific Release
From Custom Repository
cd /opt/sakai
git clone https://github.com/sakaiproject/sakai.git
cd sakai/docker
docker build \
--build-arg GIT_CACHEBUST= $( date +%s ) \
--build-arg release=master \
-t sakai:latest \
-f ./Dockerfile.source .
The Dockerfile.source uses a two-stage build as seen in docker/Dockerfile.source:1-38
Docker Compose Deployment
Create docker-compose.yml:
version : '3.8'
services :
database :
image : mariadb:10
container_name : sakai-db
environment :
MARIADB_ROOT_PASSWORD : rootpassword
MARIADB_DATABASE : sakai
MARIADB_USER : sakai
MARIADB_PASSWORD : sakaipassword
volumes :
- sakai-db-data:/var/lib/mysql
command : --lower-case-table-names=1
networks :
- sakai-network
sakai :
image : sakai:25.1
container_name : sakai-app
ports :
- "8080:8080"
depends_on :
- database
volumes :
- sakai-home:/usr/local/tomcat/sakai
- sakai-components:/usr/local/tomcat/components
networks :
- sakai-network
environment :
- JAVA_OPTS=-Xmx4g -Xms2g
volumes :
sakai-db-data :
sakai-home :
sakai-components :
networks :
sakai-network :
driver : bridge
Start services:
docker-compose up -d
# View logs
docker-compose logs -f sakai
# Stop services
docker-compose down
Production Hardening
SSL/TLS Configuration
Install Nginx as Reverse Proxy
sudo apt-get install -y nginx
Configure Nginx
Create /etc/nginx/sites-available/sakai: upstream sakai_backend {
server localhost:8080;
}
server {
listen 80 ;
server_name sakai.your.edu;
return 301 https://$ server_name $ request_uri ;
}
server {
listen 443 ssl http2;
server_name sakai.your.edu;
ssl_certificate /etc/ssl/certs/sakai.crt;
ssl_certificate_key /etc/ssl/private/sakai.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 100M ;
location / {
proxy_pass http://sakai_backend;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $ scheme ;
}
}
Enable site: sudo ln -s /etc/nginx/sites-available/sakai /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Security Best Practices
Immediately change the admin password and database credentials. In Sakai:
Login as admin
Navigate to Account → Password
Set a strong password (minimum 12 characters)
# Only allow localhost connections
REVOKE ALL PRIVILEGES ON sakai. * FROM 'sakai' @ '%' ;
GRANT ALL PRIVILEGES ON sakai. * TO 'sakai' @ 'localhost' ;
FLUSH PRIVILEGES;
Add to sakai.properties: # Require strong passwords
password.policy =true
password.minLength =12
password.requireMixedCase =true
password.requireNumbers =true
password.requireSpecialChars =true
# Session security
session.cookie.secure =true
session.cookie.httpOnly =true
# Disable autocomplete on login
login.autocomplete =false
Database Tuning
Tomcat Tuning
Sakai Configuration
Optimize MariaDB for Sakai workload: [mysqld]
# InnoDB tuning
innodb_buffer_pool_size =4G # 50-75% of available RAM
innodb_log_file_size =512M
innodb_flush_method =O_DIRECT
innodb_file_per_table =1
# Query cache (disable for MySQL 8)
query_cache_type =1
query_cache_size =128M
# Connection pooling
max_connections =300
thread_cache_size =50
Update setenv.sh: # Memory allocation
export JAVA_OPTS = " $JAVA_OPTS -Xms4g -Xmx8g"
# G1GC tuning
export JAVA_OPTS = " $JAVA_OPTS -XX:+UseG1GC"
export JAVA_OPTS = " $JAVA_OPTS -XX:MaxGCPauseMillis=200"
export JAVA_OPTS = " $JAVA_OPTS -XX:ParallelGCThreads=8"
export JAVA_OPTS = " $JAVA_OPTS -XX:ConcGCThreads=2"
# Native memory optimization
export JAVA_OPTS = " $JAVA_OPTS -XX:+UseStringDeduplication"
export JAVA_OPTS = " $JAVA_OPTS -XX:MaxMetaspaceSize=512m"
Performance settings in sakai.properties: # Enable caching
memory.db.cache =true
# Connection pooling
connection.pool.maxActive =100
connection.pool.maxIdle =25
connection.pool.minIdle =10
# Search indexing
search.enable =true
search.indexDelay =60
# Content hosting
bodyPath@ org.sakaiproject.content.api.ContentHostingService =/opt/sakai/content
bodyVolumes@ org.sakaiproject.content.api.ContentHostingService =vol1,vol2
Backup and Recovery
Database Backup
#!/bin/bash
# Daily backup script
BACKUP_DIR = /opt/backups/sakai
DATE = $( date +%Y%m%d_%H%M%S )
mkdir -p $BACKUP_DIR
# Dump database
mysqldump -u sakai -p 'password' sakai | gzip > $BACKUP_DIR /sakai-db- $DATE .sql.gz
# Backup sakai-home
tar -czf $BACKUP_DIR /sakai-home- $DATE .tar.gz /opt/sakai/sakai-home
# Keep only last 30 days
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete
Schedule with cron:
0 2 * * * /opt/scripts/backup-sakai.sh
Recovery Procedure
# Stop Sakai
sudo systemctl stop tomcat
# Restore database
zcat /opt/backups/sakai/sakai-db-20260304.sql.gz | mysql -u sakai -p sakai
# Restore sakai-home
tar -xzf /opt/backups/sakai/sakai-home-20260304.tar.gz -C /
# Start Sakai
sudo systemctl start tomcat
Monitoring and Maintenance
Health Checks
# Check if Sakai is responding
curl -I http://localhost:8080/portal
# Monitor Tomcat memory
jps -v | grep Bootstrap
# Database connections
mysql -u root -p -e "SHOW PROCESSLIST;"
Log Management
Configure log rotation in /etc/logrotate.d/sakai:
/opt/sakai/tomcat/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
copytruncate
}
Troubleshooting
Check logs: tail -f /opt/sakai/tomcat/logs/catalina.out
Common issues:
Database connection failures (check credentials)
Port 8080 already in use
Insufficient memory (increase in setenv.sh)
Database connection errors
Verify database is running: sudo systemctl status mariadb
Test connection:
Next Steps
Configuration Guide Customize Sakai for your institution
User Management Set up authentication, roles, and permissions
Customization Brand Sakai with your institution’s theme
Integration Connect with SIS, SSO, and external tools
Additional Resources
Official Documentation : Sakai Install Guide
Community Support : [email protected]
Commercial Support : Available from Apereo partners
Training : Sakai project offers training programs