Setting up Kilonova: an interactive guide

So, you want to set up a kilonova instance? Maybe it's the future, I'm dead and you want to keep the legacy, or you just want to set up a private instance for a contest or something. Well, this guide right here is just for you! I'll show you step by step, explaining everything along the way.

Prerequisites

  • An Ubuntu server (recommended: 24.04 or later, minimum: 22.04). Something else may work, but I can't make sure your packages match up correctly;
  • Some system administration skills;
  • A bit of patience.

Installing the base goods

# mold is a faster linker that is used by the c/c++ compilers on the platform
$ sudo apt install build-essential mold git golang

Setting up the environment

Disclaimer: I generally use the master branch of go for the platform, since I try to make use of bleeding edge features wherever possible. Here is a script that automatically compiles from source for you. Make sure to add $HOME/src/go/bin to $PATH if you do this. Otherwise, you must add $HOME/go/bin, since this is where binaries produced by go build reside in.

However, right now, a normal build of Go 1.22 is good enough to run the platform (may change in the future, though). Assuming you already installed go in the first step, you should have an older toolchain at hand. If, by the time you are reading this, go version returns 1.22, that's great! Otherwise, you will have to install the new version (please note that go 1.21 might be enough, since it should automatically download a newer toolchain from the web when it sees go 1.22 in go.mod):

# The current latest version is 1.22.0, but newer releases might have been released. Check here to see the latest version: https://go.dev/dl/
$ go install golang.org/dl/go1.22.0@latest
$ go1.22.0 download

Now you need to rename go in runkn.sh to the version you downloaded. In this case, the new line in runkn.sh will look like this:

# [...]
go1.22.0 build -v ./cmd/kn || exit 2
# [...]

Setting up postgres

Recent versions of PostgreSQL are recommended since the platform makes heavy use of CTEs and the latest versions optimize them properly.

Here's the setup steps for postgres:

$ sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/trusted.gpg.d/psql.asc
$ sudo apt update && sudo apt install -y postgresql-16

This is the part where things get a bit clunky for me, we need to generate the database and the user. My username is usually alexv, and I found that setting it identical to your usual user helps make things easier when manually connecting to the DB. You may replace alexv in the following snippets with whatever you like.

$ sudo su - postgres
$ createuser alexv -sP
Password: <insert new user password>
$ createdb kilonova -O alexv
$ exit

I usually use password authentication to make sure everything's alright, so we need to enable it in pg_hba.conf.

/etc/postgresql/16/main/pg_hba.conf

# ....
# "local" is for Unix domain socket connections only
local   all             all                                     md5
# ....

At the beginning, it's set to peer, but I always modify to md5.

A sudo systemctl restart postgresql@16-main.service is probably required to actually deploy the changes.

NOTE: In earlier versions, the platform didn't feature a schema migrator and everything had to be done by hand. Now, just running the platform will bring it up to the latest version. This behaviour can be disabled by setting the KN_FLAG_OVERRIDES flag to behavior.db.run_migrations=false or disabling it from the admin interface.

Setting up nodejs and yarn

For better or for worse, we need to set up nodejs and yarn before moving forward, since the next step requires them.

$ curl -fsSL https://deb.nodesource.com/setup_current.x | sudo -E bash - &&\
	sudo apt-get install -y nodejs
$ sudo npm install --global yarn # The npm setup script globally saves node_modules... we need to run as sudo

Building static JS/CSS bundles and solving the chicken-and-egg problem

We want our instance to have both style, and functionality, right? Well, we need to set up the javascript bundles first. Before we get to that, however, there's a few issues we need to resolve:

  • building the platform will automatically regenerate the translation files, but the translations aren't initially included when cloning. As such, we need to run the toml convertor by hand before trying to run the platform for the first time;
  • also, for the server-side rendering of LaTeX math, we use katex, but I don't include it in the repo since it's a large library and isn't worth it. As such, I wrote the ./scripts/init_katex.sh script to copy the latest version from node_modules. If this script isn't run before compiling the platform, it will just error out saying that it doesn't find a file to embed.

I acknowledge that these things are hacks that should be better handled in the future. I'm sorry, it is how it is right now, but please remind me to fix them later.

Assuming we are in the project repository's root directory, we can do:

$ yarn --cwd ./web/assets install # set up node_modules, we will copy the KaTeX JavaScript using ./scripts/init_katex.sh later
$ # Generate the translation files. Otherwise, prodJS will fail because it doesn't know what ./_translations.json is
$ go run ./scripts/toml_gen --target ./_translations.json --target ./web/assets/_translations.json
$ ./scripts/init_katex.sh
$ cd ./web/assets/
$ yarn prodJS # bundle custom functions
$ yarn prodCSS # build styles
$ yarn vendor # bundle libraries used directly from html

Setting up isolate (cg2 branch)

NOTE: If you are running an older Ubuntu version (most likely 22.04 LTS), then you must install the hardware enablement kernel before continuing (minimum supported version for cgroups v2 isolate is 5.19, HWE kernel for 22.04 provides version 6.5, normal kernel package uses version 5.15):

sudo apt install linux-generic-hwe-22.04
sudo reboot # Reboot is required

If uname -r returns a version newer than 5.19, you can proceed with using the newer sandbox version with cgroups v2 support. Firstly, install the required dependencies:

sudo apt install libcap-dev libsystemd-dev

After that, run the script located at scripts/init_isolate_cg2.sh using root permissions. That should be it.

Sample config.toml

[common]
 log_dir = "/home/alexv/src/kninfo/logs"
 data_dir = "/home/alexv/src/kninfo/data"
 debug = false # true if you want more debug output, usually from the grader.
 host_prefix = "http://localhost:8070" # Note that it must be without an ending backslash!
 default_language = "ro"
 db_dsn = "sslmode=disable host=/var/run/postgresql dbname=kilonova user=<YOUR USERNAME> password=<YOUR PSQL PASSWORD> application_name=kilonova"
 test_max_mem_kb = 1048576 # 1gb limit for setting up tests

[eval]
 num_concurrent = 3
 global_max_mem_kb = 1048576 # 1gb global memory limit
 starting_box = 1 # If there are multiple kilonova instances active on the system, change to a multiple of 100, just to be safe

[email]
 enabled = true # set to false if you don't want to setup the mailer service.
 host = "smtp.fastmail.com:587"
 username = "<SMTP USERNAME>"
 password = "<SMTP PASSWORD>"

[frontend]
 banned_hot_problems = [] # This is used to hide some problems from the trending menu on the front page

Finishing touches

Right now, the grader doesn't work when kilonova is not run as root. ./runkn.sh will start the platform with the root user.

You should create the first user now. The first user is automatically granted admin+proposer ranks. I'll also write guides about their respective abilities and how to properly have a nice experience as a kilonova proposer/admin.

Creating a simple sum-type problem with some basic tests and sending a sample solution should help you make sure the grader is fully and correctly running.

Final disclaimer

This may not fully work right now. I'm just noting all the honourable mentions from my last attempts at setting up this platform. The next time I'll set it up, I'll revamp this guide further.

Not included in this guide, but you should also set up a firewall like ufw, a reverse proxy like nginx and something like fail2ban for SSH and nginx.

Don't even think building a docker image for kilonova. You will need to gather a few workarounds to make isolate run properly and it's probably too much of a hassle. In a future in which the grader can be decoupled from the rest of the platform, you could make an argument that the part that is not grading submissions could be dockerized, but that's a hassle for the reader attempting this kind of stuff.

Bonus: setting up Kotlin

Kotlin is a fun case. The repository is pretty old

I found that using sdkman is a pretty easy solution to adding kotlin support. Now, since the compiler must be present in the sandbox for proper compilation, we have to save it somewhere in /usr instead of $HOME. As such, here's a chain of commands to copy-paste and make it just work(tm):

# Create the directory to save sdkman in. Due to their script being pretty bad, we actually need to create the *parent* directory since we want 
$ sudo mkdir -p /usr/local/sdk && sudo chown $USER /usr/local/sdk 
$ export SDKMAN_DIR="/usr/local/sdk/sdkman" && curl -s "https://get.sdkman.io" | bash
$ sdk install kotlin
# The default runkn.sh runs the platform with sudo, but -E does not preserve path. As such, we need to add the sdkman stuff at the end of the root's bashrc
$ sudo tee -a /root/.bashrc <<EOF
export SDKMAN_DIR="/usr/local/sdk/sdkman"
[[ -s "/usr/local/sdk/sdkman/bin/sdkman-init.sh" ]] && source "/usr/local/sdk/sdkman/bin/sdkman-init.sh"
EOF

Bonus: Fedora debugging tips

Kilonova builds a static binary when running C/C++ submissions. On Fedora it seems like the static standard library is not provided by default and must be installed with the following packages:

# glibc-static provides libm.a; libstdc++-static makes c++ work in a static build context
$ sudo dnf install glibc-static libstdc++-static

Old sections, kept for historical purposes

Setting up isolate (LEGACY SETUP)

I created a simple script that automatically sets up the isolate sandbox for you in scripts/init_isolate_cg1_precompiled.sh. You may need to run usermod -a -G kn_sandbox "$USER" a few times then log out and back in for it to truly take effect.

Disabling cgroups v2

Modern linux systems are a bit of a pain in the arse since with the legacy setup they come with cgroups v2 enabled, but isolate currently only supports cgroups v1 on the main branch (this is why the newer setup is recommended; the cg2 branch is experimental but still stable). Thus, we need to disable cgroups v2 from grub. If you don't do this step, you may get a cryptic error status 2 from isolate!

To do this, go to /etc/default/grub and add systemd.unified_cgroup_hierarchy=0 to GRUB_CMDLINE_LINUX. After this, run sudo update-grub and restart your server.

Updated at: 1731923774569 Posted at: 1696668074181