- OJS 3.5 needs PHP 8.2+, OJS 3.4 needs PHP 8.0+, plus MySQL/MariaDB or PostgreSQL and the mbstring, xml and intl extensions.
- Apache needs mod_rewrite for clean URLs; Nginx needs PATH_INFO support via
fastcgi_split_path_info. - A production journal also needs HTTPS, authenticated SMTP, cron and backups, and a files directory outside the web root.
OJS system requirements at a glance
Open Journal Systems is a PHP application backed by a database, so the OJS requirements are modest compared with many web platforms. A working, secure installation needs:
- Operating system: Linux is standard. PKP also lists BSD, Solaris, macOS and Windows.
- Web server: Apache (or LiteSpeed, common on cPanel hosts) or Nginx with PHP-FPM.
- PHP: a version supported by your OJS release, with the extensions listed below.
- Database: MySQL, MariaDB or PostgreSQL.
- A files directory outside the web root, writable by PHP, for manuscripts and review files.
- HTTPS, SMTP email and cron for a production journal.
To see what an existing server offers before you install, check three things: the PHP version and loaded extensions (php -v and php -m over SSH, or the PHP selector in cPanel), the database type and version (shown in phpMyAdmin or by your host), and whether you can create a folder outside the web root and add cron jobs. If any of these is missing, ask the host before you upload OJS.
If you are about to install, read this page together with our step-by-step OJS installation guide.
OJS server requirements by version (3.3, 3.4, 3.5)
The table below summarises PKP's published requirements. Minimums change between point releases, so always check the README in the package you download and the PKP Administrator's Guide.
| OJS version | PHP | Database (PKP minimums) | Status |
|---|---|---|---|
| OJS 3.5 | 8.2 or newer | MySQL 5.7.22+, MariaDB, or PostgreSQL 9.5+ | Newest long-term support release; best for new journals |
| OJS 3.4 | 8.0 or newer | MySQL 5.7.22+, MariaDB, or PostgreSQL 9.5+ | Current generation; check release notes for the newest PHP it supports |
| OJS 3.3 | 7.3 to 8.2 (latest 3.3.0-x releases) | MySQL or PostgreSQL 9.5+ | Older long-term support release with critical fixes for a limited period |
| OJS 2.x | PHP 5.x / 7.x | MySQL | End of life. Do not deploy; migrate to 3.x |
Use maintained versions, not just minimums
PKP's minimums are the oldest versions OJS can run on, not what you should deploy. MySQL 5.7 and older PostgreSQL releases are already end-of-life upstream. For a new server, use a currently supported PHP 8.x, a maintained MySQL 8.x or MariaDB LTS release (such as 10.11 or 11.4), or a supported PostgreSQL release, and test before going live.
Early OJS 3.3 releases supported fewer PHP 8 versions than the latest ones, so if you run an old 3.3 point release, update OJS before upgrading PHP.
Required and recommended PHP extensions
PKP's documentation names mbstring, xml and intl as required. The OJS 3.5 dependency check also lists several others that most hosts enable by default. Make sure these are available:
| Extension | Why OJS needs it |
|---|---|
mbstring | Multibyte text handling for every language OJS supports (required) |
xml, dom, simplexml, xmlwriter | XML import/export, OAI-PMH, Crossref deposits (xml is required) |
intl | Locale-aware formatting of dates, numbers and languages (required) |
mysqli and pdo_mysql, or pgsql and pdo_pgsql | Database connection. Enabling both the classic and PDO driver avoids surprises across versions. |
gd | Image processing for cover images, logos and thumbnails |
curl, openssl | Secure outbound connections: Plugin Gallery, Crossref, ORCID and other APIs |
zip, zlib | Installing plugins and themes, handling compressed files |
fileinfo | Detecting the real type of uploaded files |
bcmath, ftp | Listed in the OJS 3.5 dependency check |
json, ctype, tokenizer, session, filter, hash | Core PHP features, normally built in |
opcache (recommended) | Caches compiled PHP and noticeably speeds up page loads |
On a VPS, run php -m to list loaded extensions. On cPanel, use Select PHP Version or MultiPHP INI Editor (the exact tool depends on your host). Remember that the command-line PHP used by cron can differ from the web PHP, so check both.
Recommended php.ini settings for OJS
PHP's defaults are too low for a journal that receives manuscripts with figures and supplementary files. These values are sensible starting points, not official PKP figures:
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 72M
max_execution_time = 300
max_input_time = 300
file_uploads = On
display_errors = Off
log_errors = On
date.timezone = UTC
| Setting | Why |
|---|---|
memory_limit | Upgrades, statistics processing, XML imports and large exports need more memory. Use 512M for big multi-journal sites or heavy imports. |
upload_max_filesize | The largest single file an author or editor can upload. Match it to the largest file your journal accepts. |
post_max_size | Must be larger than upload_max_filesize, because the upload travels with form data. |
max_execution_time | Gives long operations (upgrades, imports, report generation) time to finish instead of failing halfway. |
display_errors | Never show PHP errors to visitors on a live site; log them instead. |
The web server has its own upload limit too: client_max_body_size in Nginx, and sometimes LimitRequestBody or a ModSecurity rule in Apache. If uploads fail at a certain size, check all of them. See common OJS errors for upload troubleshooting.
Database: MySQL, MariaDB or PostgreSQL
OJS supports MySQL, MariaDB and PostgreSQL. In practice:
- MySQL / MariaDB is the most common choice, is available on virtually every cPanel host, and matches most answers on the PKP forum.
- PostgreSQL is fully supported and a good fit for institutions that already run it.
Good practice for either database:
- Create a dedicated database and user for OJS, as PKP's security checklist recommends. Do not share it with other applications.
- Use UTF-8 (
utf8mb4on MySQL/MariaDB) for new databases so all languages and special characters are stored correctly. - Give the OJS user full privileges on its own database only, because installs and upgrades create and alter tables.
- Back up the database daily, together with the files directory.
Database size depends mostly on usage statistics and the number of submissions. A small journal's database is often well under 1 GB; large, long-running multi-journal sites can grow far beyond that.
Web server requirements: Apache and Nginx for OJS
OJS builds URLs using PATH_INFO, for example /index.php/journal/article/view/12. Whatever web server you use, it must pass that path to PHP. With clean URLs enabled (restful_urls = On in config.inc.php), the index.php part disappears and the web server rewrites requests to it.
Apache (and LiteSpeed)
Apache works with OJS out of the box. For clean URLs, enable mod_rewrite, allow overrides for the OJS directory (AllowOverride All in the virtual host) and place this .htaccess in the OJS root:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
</IfModule>
# Deny direct web access to configuration files
<FilesMatch "^config\.(inc|TEMPLATE\.inc)\.php$">
Require all denied
</FilesMatch>
Then set restful_urls = On under [general]. If /index.php/... URLs return 404 even without rewriting, make sure AcceptPathInfo is not switched off for the site. Most cPanel servers run LiteSpeed or Apache and read .htaccess the same way.
As extra hardening, stop PHP from running inside the public/ folder, which holds uploaded journal images and files. Uploaded PHP scripts in writable folders are a common route in hacked OJS sites:
<Directory /var/www/ojs/public>
<FilesMatch "\.(php|phtml|phar)$">
Require all denied
</FilesMatch>
</Directory>
Nginx with PHP-FPM
Nginx does not read .htaccess, so everything goes in the server block. The critical part is fastcgi_split_path_info, which separates /index.php from the rest of the path and passes it as PATH_INFO. Without it, the homepage may load but article pages, the dashboard and the API return 404 errors.
server {
listen 80;
server_name journal.example.org;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name journal.example.org;
root /var/www/ojs;
index index.php;
ssl_certificate /etc/letsencrypt/live/journal.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/journal.example.org/privkey.pem;
# Keep in line with upload_max_filesize / post_max_size in php.ini
client_max_body_size 72M;
# Block hidden files (.git, .env, .htaccess) but allow Let's Encrypt checks
location ~ /\.(?!well-known/) {
deny all;
}
# Block configuration files and folders that are never requested by browsers
location ~* ^/config\..*\.php$ {
deny all;
}
location ~* ^/(classes|dbscripts|tools)/ {
deny all;
}
# Never execute PHP from writable folders
location ~* ^/(public|cache)/.*\.(php|phtml|phar)$ {
deny all;
}
# Clean (restful) URLs: anything that is not a real file goes to index.php
location / {
try_files $uri $uri/ /index.php$uri$is_args$args;
}
# PHP with PATH_INFO support
location ~ ^.+?\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
try_files $fastcgi_script_name =404;
# try_files resets $fastcgi_path_info, so keep a copy
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_read_timeout 300;
}
}
Adjust the PHP-FPM socket to your PHP version, test with sudo nginx -t and reload. Nginx evaluates regex locations in order, which is why the deny blocks come before the PHP block. On newer Nginx releases you can write http2 on; as a separate directive instead of adding http2 to listen.
The files directory is not covered by these rules
Blocking rules are a second line of defence. Your OJS files_dir must still live outside the web root (for example /var/www/ojs-files), so no web server rule can ever expose manuscripts.
OJS also has a disable_path_info option in config.inc.php that switches to query-string URLs on servers that cannot provide PATH_INFO. It is marked as deprecated and produces less readable URLs, so fix the server configuration instead.
CPU, RAM and disk sizing for OJS
OJS is light, but traffic, statistics processing and the number of journals add up. Use this as guidance, not a guarantee; real needs depend on traffic, bots, file sizes and other software on the server.
| Profile | Example | CPU | RAM | Disk (SSD) |
|---|---|---|---|---|
| Small | 1–2 journals, a few hundred submissions a year | 1–2 vCPU | 2–4 GB | 20–40 GB |
| Medium | 3–10 journals, or one busy journal | 2–4 vCPU | 4–8 GB | 50–150 GB |
| Large | 10+ journals, high traffic, large data files | 4–8+ vCPU | 8–16 GB+ | 200 GB+, database optionally on its own server |
Plan disk space for the files directory (every manuscript version, review file and galley is kept), the database, logs and at least a week of local backups. Aggressive crawlers are a frequent cause of slow OJS sites, so rate limiting or a web application firewall can matter as much as raw CPU.
HTTPS and SSL for OJS
Every journal should run entirely on HTTPS. It protects logins and unpublished manuscripts, and browsers warn visitors about plain HTTP forms. Free Let's Encrypt certificates work well (cPanel AutoSSL or certbot on a VPS). After installing the certificate, set in config.inc.php:
[general]
base_url = "https://journal.example.org"
[security]
force_ssl = On
Recent OJS releases also include an allowed_hosts setting; add your journal's domain there as described in the comments in config.inc.php.
Email (SMTP) requirements
OJS sends registration emails, review invitations, reminders and editorial decisions. Relying on PHP's built-in mail function is the most common cause of missing emails. A production journal needs:
- An authenticated SMTP mailbox on the journal's domain, using port 587 (STARTTLS) or 465 (SSL).
- SPF, DKIM and DMARC DNS records so messages are not marked as spam.
- Outbound SMTP allowed by the host. Some cloud providers block outbound port 25 by default, so use 587 or a transactional email service.
SMTP settings live in the [email] section of config.inc.php; the switch differs between OJS 3.3 and 3.4+, as shown in our installation guide. For delivery problems, see fixing OJS email errors.
Scheduled tasks and background jobs (cron)
OJS runs regular tasks such as review reminders, usage statistics processing and DOI deposits. How they run depends on the version:
| Version | Scheduled tasks | Background jobs |
|---|---|---|
| OJS 3.3 | Set scheduled_tasks = On and run tools/runScheduledTasks.php from cron (hourly is common; at least daily) | Not applicable |
| OJS 3.4 | Same approach as 3.3 | Job queue introduced; a built-in runner processes jobs during web requests, or you can run workers |
| OJS 3.5 | Built-in task runner (task_runner), or cron running lib/pkp/tools/scheduler.php run every minute | Built-in job runner, cron, or a worker managed by Supervisor |
# OJS 3.3 / 3.4: hourly scheduled tasks
0 * * * * php /var/www/ojs/tools/runScheduledTasks.php
# OJS 3.5: scheduler every minute (then set task_runner = Off)
* * * * * php /var/www/ojs/lib/pkp/tools/scheduler.php run >> /dev/null 2>&1
Busy sites should process jobs with a worker (php lib/pkp/tools/jobs.php work, kept running by Supervisor) instead of relying on visitor traffic. Confirm the commands in the PKP guide to scheduled tasks for your exact version, and use the full path to the PHP binary your host provides.
Pre-install server checklist
- PHP version matches the OJS release you plan to install, for both web and command line.
- mbstring, xml, intl, gd, curl, zip, fileinfo and the database drivers are enabled.
- php.ini limits raised for memory, uploads and execution time.
- MySQL/MariaDB or PostgreSQL database and a dedicated user created, using UTF-8.
- Apache with mod_rewrite and
AllowOverride, or Nginx with PATH_INFO support. - A writable files directory outside the web root.
- SSL certificate installed and HTTPS working.
- SMTP mailbox ready, with SPF, DKIM and DMARC records.
- Cron access (and SSH, ideally) available.
- Automated backups of the database, files directory and
public/folder.
Not sure your current host qualifies? Our OJS hosting guide compares shared, VPS and managed options. If you would rather not configure servers at all, our OJS installation service sets everything up on your server, and our OJS hosting service provides a server already tuned for OJS.
Frequently Asked Questions
What PHP version does OJS need?
It depends on the OJS version. PKP's documentation lists PHP 8.2 or newer for OJS 3.5 and PHP 8.0 or newer for OJS 3.4. The latest OJS 3.3 releases list PHP 7.3 to 8.2. Always confirm in the README of the exact release you download.
Does OJS work with Nginx?
Yes. OJS runs well on Nginx with PHP-FPM, but your PHP location block must pass PATH_INFO using fastcgi_split_path_info, otherwise article and admin URLs return 404 errors. A complete example is in the web server section above.
Can I run OJS on Windows?
PKP lists Windows among the supported operating systems, and it is fine for local testing. For a live journal, Linux with Apache or Nginx is the most common and best-documented setup, and it is what most OJS community answers assume.
Is MySQL or PostgreSQL better for OJS?
Both are supported. MySQL or MariaDB is the most common choice, is available on almost every cPanel host and matches most community troubleshooting advice. Choose PostgreSQL if your institution already runs and supports it.
How much disk space does an OJS journal need?
The application itself is small. Space is used by the files directory, which stores every manuscript version, review file and galley, plus the database and backups. Start with at least 20 GB for a small journal and monitor growth every few months.
Can OJS run on shared hosting?
Yes, if the host offers a supported PHP version, the required extensions, cron jobs and a folder outside the web root. Compare options in our OJS hosting guide, or let our OJS hosting service handle it.