Computer Science

Building a programming contest system with Domjudge on LAMP & AWS

Due to growing interests and industrial demands for problem-solving skills, programming contests are on fire these days. There have emerged a number of services to provide contest system along with computing resources. However, one may find that such proprietary systems are not suitable as the problem set cannot be shared with a third-party due to copyright or security issues. Thus, here I share my experience with building an open-source contest system with a spotboard module, on LAMP stack and Amazon AWS.

Domjudge

Domjudge is an automated judging system to run programming contests. It provides interfaces for participants (called teams in the system) to submit their solution and recieve the verdict, for administrator to coordinate logistics for contests, for juries to review the verdicts of the internal judging system.[1] It supports an ACM-ICPC format and is widely adopted by ICPC regional directors and university contests. It is an open-source project, and, as such, there may be some instability with recent releases. It is advised to pick a stable version for serious contests.

Environment

  • AWS Ubuntu Server 16. 04 LTS (HVM)
  • Domjudge 5.3.0

Installation

You may refer to the official documentation, but it is outdated; thus some customization is needed as per your environment.

Pre-requisites

  • An instance for main server (Domserver)
  • An instance for Database
  • A few instances for Judgehosts (2+ recommended)

You could put all of the above in a single instance but it is highly discouraged for two main reasons. First, the Judgehosts require an exclusive usage of CPU during execution. Even though they consider the user execution time, instead of the real execution time, the execution time of a submission might considerably differ due to cache misses or I/O interaction. It makes jury difficult to set a tight time limit. Also, it is recommended to use isolated databases for security issues, especially when you can’t rule out malicious submissions from untrusted users. For brevity, we will put the database into the main server in this post.

1. Install the Main Server

Dependencies

$ sudo apt update
$ sudo apt install -y gcc g++ make zip unzip php-fpm php-cli php-gd php-curl php-mbstring php-mysql php-json php-xml php-mcrypt php-zip bsdmainutils ntp linuxdoc-tools linuxdoc-tools-text groff texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended apache2 mysql-client mysql-server libapache2-mod-php libcgroup-dev

It will take several minutes. You may not install mysql-server if you decided to use the external database server. Remember the password of mysql for later.

Download & Build

$ wget https://domjudge.org/releases/domjudge-5.3.0.tar.gz
$ tar -xzf domjudge-5.3.0.tar.gz
$ cd domjudge-5.3.0
$ ./configure --disable-submitclient
$ make domserver && make docs
$ sudo make install-domserver && sudo make install-docs

Now you have domserver installed at /opt/domjudge/domserver.

Configure Database Setting

$ sudo vi /opt/domjudge/domserver/etc/dbpasswords.secret
# Randomly generated on host ip-*-*-*-*, Thu Oct 26 12:03:44 UTC 2017
# Format: 'dummy:<db_host>:<db_name>:<user>:<password>'
dummy:localhost:domjudge:domjudge:YourPasswordHere

Setup Database

$ cd /opt/domjudge/domserver/bin

/* You need to change the host if you have decided to use external DB server. Otherwise, skip this. */
$ vi ./dj_setup_database
/* Replace 'localhost' to your designated server. */
 
$ ./dj_setup_database -u root -r bare-install
Database credentials read from '/opt/domjudge/domserver/etc/dbpasswords.secret'.
Enter password: [Your Database User password]
DOMjudge database and user(s) created.
Enter password: [Your Database User password]
SQL structure and defaults installed (no sample data).

Apache2 Configuration

Domjudge provides .conf file for apache2, which is located at etc/apache.conf.

$ sudo ln -s ~/domjudge-5.3.0/etc/apache.conf /etc/apache2/conf-available/domjudge.conf
$ sudo a2enconf domjudge
$ sudo service apache2 reload

Now you can use the web interface in the URL, your.server.address/domjudge/.

Login as an administrator with admin/admin. In the user tab, you will see the judgehost in the list. Set the password and remember it. This will be used for setting up the judgehosts.

Config Checker

In the home tab, click the “Config checker” below ‘Administrator’ section.
The following is the screenshot if you’ve come through. As clicking each tab, it will show you how to fix the issue. Do as it suggests. “Active contests” is okay for this moment.

2. Install Judgehosts

Install Dependencies

$ sudo apt install gcc g++ make cmake zip unzip debootstrap php-cli php-zip php-curl php-json procps openjdk-8-jre-headless openjdk-8-jdk libcgroup-dev -y
It will take a moment.

Enable cgroups

$ sudo vi /etc/default/grub.d/50-cloudimg-settings.cfg 

/* In line 11 (probably), append the following */
GRUB_CMDLINE_LINUX_DEFAULT="~~~~ quiet cgroup_enable=memory swapaccount=1”

$ sudo update-grub
$ sudo reboot

This will allow domjudge to use cgroups library. If you’re using your own machines (not AWS), modify /etc/default/grub instead of `/etc/default/grub.d/50-cloudimg-settings.cfg`.

After the reboot, check if you can see a message like this:

$ cat /proc/cmdline 
BOOT_IMAGE=/boot/vmlinuz-4.4.0-1022-aws root=UUID=*-*-*-* ro console=tty1 console=ttyS0 quiet cgroup_enable=memory swapaccount=1

Download & Build

$ wget https://www.domjudge.org/releases/domjudge-5.3.0.tar.gz
$ tar -xzf domjudge-5.3.0.tar.gz
$ sudo ./configure --enable-cgroups --disable-submitclient --with-domjudge-user=root
$ sudo make domserver && sudo make judgehost
$ sudo make install-judgehost

Now we have judgehost at /opt/domjudge/judgehost.
If you want to use multiple judgehosts for reliability, repeat above for each judgehost.

Connect with Main Server

$ sudo vi /opt/domjudge/judgehost/etc/restapi.secret

# Randomly generated on host ip-*-*-*-*, Thu Oct 26 12:59:58 UTC 2017
# Format: '<ID> <API url> <user> <password>'
default http://[Your Main Server}/domjudge/api judgehost [Your judgehost Password]

For the security issues, the domjudge highly recommends to use chroot. You may skip this part if you trust users.

$ sudo vi /opt/domjudge/judgehost/bin/dj_make_chroot

/* Line 30-31 */
DISTRO="Ubuntu"
RELEASE="xenial"

/* Line 103 */
INSTALLDEBS="openjdk-8-jre-headless locales"

/* Line 132 */
INSTALLDEBS="openjdk-8-jre-headless locales"

$ sudo /opt/domjudge/judgehost/bin/dj_make_chroot

It will take several minutes depending on the server’s status. After completing, add a user and start the daemon:

$ sudo useradd -d /nonexistent -g nogroup -s /bin/false domjudge-run
$ cd /opt/domjudge/judgehost
$ sudo bin/judgedaemon

If you can see the judgehost list in the web interface, everything is done! Be sure to keep your session not closed during the judging. You may use tmux or the like to keep the judgedaemon alive even after disconnecting a SSH session.

3. Stress Test

You may want to check how much judging requests the hosts can handle in advance. For that, please see https://github.com/ubergeek42/domjudge-gatling.

4. Spotboard

Spotboard is a modern-style, web-based scoreboard application for programming contests, especially ACM-ICPC. [2] It has been officially used in the ACM-ICPC Regional of South Korea since 2015. Please follow the link to couple it with Domjudge.

References

1. Domjudge Documentation
2. Spotboard Github