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 guide you step by step, explaining everything along the way.

Prerequisites

  • An Ubuntu server (22.04 or later, 23.10 makes life a bit easier with the grader, though). 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

# python is required only for scripts/data_cleanup.py, which will be removed soon.
# mold is a faster linker that is used by the c/c++ compilers on the platform
$ sudo apt install build-essential mold git golang python3-dev python-is-python3

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]
 isolatePath = "/usr/local/bin/isolate" # for cg2 isolate, for cg1 use: "/usr/local/etc/isolate_bin"
 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
 
[donations]
 buy_coffee_name = "" # Name to buymeacoffee campaign
 bmac_webhook_secret = "" # Secret for BuyMeACoffee webhook, used to forward donations to updates webhook
 paypal_button_id = "" # Button ID for paypal donations

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.

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: 1714065433402 Posted at: 1696668074181