/documents

:star2: documents of justice online judge

MIT LicenseMIT

Introduction

Justice is an online-judge system which supports Java, C and CPP.

Now Justice is composed of three parts:

  • frontend: the website of Justice online judge with an additional admin control panel, powered by yii2;

  • dispatcher: dispatches submissions to a local worker(AKA justice-sandbox) and fetches the results, powered by spring-boot;

  • sandbox: yet another sandbox written in Go, providing kernel-based namespace and cgroup isolation.

Blogs about Justice

Blogs

Deployment Guide

Here is a deployment guide for Justice online judge.

Architecture

The picture above describes the main judging process of Justice:

  • user submits a piece of code, justice-frontend then updates MySQL and puts the judge submission to RabbitMQ;

  • justice-dispatcher fetches the judge submission from RabbitMQ: if the submitted code is written in Java, the dispatcher will judge the code itself, or it will delegate the code to justice-sandbox for judging;

  • justice-sandbox runs the submitted code in a jailed environment, and returns the judge result in a json-encoded string;

  • justice-dispatcher then updates MySQL / Redis with the result decoded from justice-sandbox.

For now Justice is tested on Debian Buster only, migrating the following instructions to any other dist may cause security issues.

Components

IP aliases

Replace the following ip addresses in your hosts file for justice dev environment.

192.168.17.128 justice.mysql
192.168.17.128 justice.rabbitmq
192.168.17.128 justice.redis

MySQL

  • Install MySQL Server:
apt install mariadb-server
mysql_secure_installation
  • Create a database for our app:
CREATE DATABASE www_justice_plus;
CREATE USER 'root'@'%' IDENTIFIED BY '${PASSWORD}';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
  • Update /etc/mysql/mysql.conf.d/mysqld.cnf, and replace ${justice.mysql} with your own IP address:
+ bind-address = ${justice.mysql}
  • Restart MySQL Server:
/etc/init.d/mysql restart

RabbitMQ

  • Install RabbitMQ:
apt install -y rabbitmq-server
  • Enable rabbitmq_management plugin, and replace ${password} with your own password:
rabbitmq-plugins enable rabbitmq_management
rabbitmqctl add_user justice ${password}
rabbitmqctl set_user_tags justice administrator
rabbitmqctl set_permissions -p / justice ".*" ".*" ".*"
  • Update /etc/rabbitmq/rabbitmq-env.conf, and replace ${justice.rabbitmq} with your own IP address:
NODENAME=justice
NODE_IP_ADDRESS=${justice.rabbitmq}
NODE_PORT=5672
  • Restart RabbitMQ:
/etc/init.d/rabbitmq-server restart

Redis

  • Install Redis
apt install -y redis-server
  • Update /etc/redis/redis.conf, and replace ${justice.redis} with your own IP address:
bind ${justice.redis}
  • Restart Redis:
/etc/init.d/redis-server restart

Frontend

PHP

  • Install PHP 7.4:
apt install -y php7.4-xml php7.4-mbstring php7.4-zip php7.4-mysql php7.4 \
php7.4-opcache php7.4-json php7.4-curl php7.4-bz2 php7.4-cgi php7.4-cli \
php7.4-fpm php7.4-gmp php7.4-common php7.4-bcmath php7.4-gd
  • Composer
curl -o /usr/local/bin/composer https://getcomposer.org/composer-stable.phar
chmod +x /usr/local/bin/composer

Init project

mkdir -p /var/www
git clone https://github.com/justice-oj/frontend.git /var/www/justice.plus

cd /var/www/justice.plus
composer global require "fxp/composer-asset-plugin:^1.4.2"
composer install

For Development environment

  • Init yii2 project
cd /var/www/justice.plus
php init --env=Development --overwrite=All
php yii migrate
php yii fixture "*"
php yii serve --docroot="www/web" localhost:8888
php yii serve --docroot="admin/web" localhost:9999

For Production environment

  • Update config justice.plus/environments/prod/common/config/main-local.php for MySQL / Redis and RabbitMQ:
[
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=${justice.mysql};dbname=www_justice_plus',
            'username' => 'root',
            'password' => '${justice.mysql.password}',
            'charset' => 'utf8',
        ],
        'redis' => [
            'class' => 'yii\redis\Connection',
            'hostname' => '${justice.redis}',
            'port' => 6379,
            'database' => 15,
        ],
        'rabbitMQ' => [
            'class' => \common\components\queue\BasicRabbitMQProducer::class,
            'host' => '${justice.rabbitmq}',
            'port' => 5672,
            'user' => 'justice',
            'password' => '${justice.rabbitmq.password}',
            'queueName' => 'justice',
            'exchangeName' => 'justice',
            'exchangeType' => 'topic',
        ],
    ],
];
  • Init yii2 project
cd /var/www/justice.plus
php init --env=Production --overwrite=All
php yii migrate
chown -R www-data:www-data /var/www/justice.plus
  • Install Nginx
apt install -y nginx
  • Edit /etc/php/7.4/fpm/pool.d/www.conf to change PHP-FPM from listening on unix socket to listening on TCP/IP port:
- listen = /run/php/php7.4-fpm.sock
+ listen = 127.0.0.1:9000
  • Sample server block of /etc/nginx/conf.d/justice.plus.conf
server {
    listen 80;
    server_name admin.justice.plus;

    access_log logs/admin_justice_plus.access.log main;
    error_log logs/admin_justice_plus.error.log warn;

    root /var/www/justice.plus/admin/web;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

server {
    listen 80;
    server_name www.justice.plus;

    access_log logs/www_justice_plus.access.log main;
    error_log logs/www_justice_plus.error.log warn;

    root /var/www/justice.plus/www/web;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
  • Start nginx and PHP-fpm
/etc/init.d/nginx start
/etc/init.d/php7.4-fpm start

Dispatcher

  • Install openjdk-11
apt install openjdk-11-jdk
  • Install Tomcat 9
cd /opt
wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.tar.gz
tar zxf apache-tomcat-9.0.37.tar.gz
mv apache-tomcat-9.0.37 dispatcher
  • Update conf/catalina.properties, ${ENV} must be in one of local, test or prod:
+ spring.profiles.active=${ENV}
  • Update application-*.properties for each environment.

  • Deploy .war and start Tomcat

mkdir -p /var/log/justice/code
./bin/startup.sh

Sandbox

cd /opt
git clone https://github.com/justice-oj/sandbox.git
cd /opt/sandbox/
./build.sh
  • C/C++ language support
apt install -y gcc g++