While Kwil hopes that you let us manage your databases for you, we understand that this might not fit the requirements of all users! Therefore, we have made Kwil DB's open-source and free to use!


Kwil Databases are responsible for handling a lot of separate processes. Therefore, in order to run your own, there will be a variety of requirements that are atypical for a centralized database.

Machine Requirements:

  • At least 2 vCPU
  • 4 GB Memory
  • Ubuntu 18.04 or later installed
  • (Recommended) 100 GB Storage
  • Any CLI Text Editor (We will be using Nano)


  • An Arweave private key holding some AR (JWK format).
  • A TLS/SSL certificate (Preferably Wildcard)
  • A Domain Name

Getting started

Once you have all of the required resources, you're ready to set up your node! Open up your terminal to the directory where you want your node files to be stored. We will begin by updating our system:
sudo apt-get update;
Next, we need to install both NGINX and Postgresql:
sudo apt-get install nginx -y;
sudo apt -y install postgresql postgresql-client postgresql-contrib;
Then, we need to install Node Version Manager:
sudo curl -o- | bash;
Next, we need to export Node Version Manager:
export NVM_DIR="$HOME/.nvm";
[ -s "$NVM_DIR/" ] && \. "$NVM_DIR/";
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion";
Now, we need to install NodeJS:
nvm install stable;
Now, we will need to install software to enable our server to run in the background. We will be using an NPM package known as "forever".
npm i -g forever
Finally, we will need to download the synchronizer:
git clone

Configuring TLS and CORS With NGINX

We will now set up our TLS Certificate with NGINX, as well as create our CORS configuration. This will involve us creating four new files, as well as editing a fifth:

Private Key

First, we will need to create a file to hold the actual private key, stored in PEM format:
sudo touch /etc/nginx/sites-available/privkey.pem;
Let's open up the file and paste in our TLS Certificate:
sudo nano /etc/nginx/sites-available/privkey.pem
In the editor:
Exit the file using "^x", and then press "y" to save, and then "return"

Full Chain

Next, we will need a file to hold the full chain PEM:
sudo touch /etc/nginx/sites-available/fullchain.pem;
Opening up the file to paste the full chain:
sudo nano /etc/nginx/sites-available/fullchain.pem;
In the editor:


Then, we will create a file to hold our SSL NGINX configurations:
sudo touch /etc/nginx/sites-available/options-ssl-nginx.conf;
Then, open the file:
sudo nano /etc/nginx/sites-available/options-ssl-nginx.conf;
Then, paste in the following configuration:
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
client_max_body_size 10M;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

Diffie-Hellman Params

Finally, we will create a file to specify how NGINX handles Diffie-Hellman key exchange. This should have been given to you by your SSL CA with the rest of your key:
sudo touch /etc/nginx/sites-available/ssl-dhparams.pem
Open the file:
sudo nano /etc/nginx/sites-available/ssl-dhparams.pem
Then, paste in:

Editing NGINX Configuration:

Once you have set up your TLS/SSL Certificate, you will need to update your NGINX configuration. This example will use a wide-open CORS policy with restricted filesystem access (with the exception of static assets meant to be served):
sudo nano /etc/nginx/sites-available/default
Paste in the following. Make sure to change the server_name as well as the user for the /public location:
server {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
#If you have a wildcard SSL certificate, change server_name to *
location /public {
autoindex on;
alias /home/{user}/Kwil_DB_Synchronizer/public;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header Access-Control-Allow-Origin *;
location / {
proxy_pass http://localhost:1984; #whatever port your app runs on
proxy_http_version 1.1;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header Access-Control-Allow-Origin *;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
listen 80;
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
ssl_certificate /etc/nginx/sites-available/fullchain.pem;
ssl_certificate_key /etc/nginx/sites-available/privkey.pem;
include /etc/nginx/sites-available/options-ssl-nginx.conf;
ssl_dhparam /etc/nginx/sites-available/ssl-dhparams.pem;
Exit by pressing "^x", "y", then "return".
Now, we're done setting up our NGINX configuration! We just need to restart the server:
sudo service nginx restart;
If this fails, run this command to debug:
sudo nginx -t -c /etc/nginx/nginx.conf;
Lastly, you will need to point your domain name to the external IP address of the machine you are running on. To do this, all you need to do is add an A record with your name service provider!

Setting Up The Database

Now that we have set up NGINX, we need to set up Postgresql. Since we installed Postgresql earlier, all we need to do is change our password and restart!
sudo -u postgres psql postgres;
In Postgresql:
\password postgres
(Enter new password)
(Re-enter password)
Now, just restart Postgresql:
sudo service postgresql restart;

Setting Up The Synchronizer

The last thing we need to do is set up the Kwil DB Synchronizer. To begin, lets enter the folder that we downloaded it to:
cd kwil_db_v2
Install necessary NPM packages:
npm i;
Now, it's time to configure the synchronizer. Start by just running the server:
npm start
This should throw an error. Our team recently found a config issue (April 10th), and so as a quick workaround, the first failure should fix the issues.
Once the server has failed to start once, you need to fill out your .env configuration. The application should provide a base template.

.env Configuration

Below is an example of what the base template fully filled out would like:
NODE_PORT = 1984
NODE_ENV = production
SYNC = false
SHOVE = false
KEY_SECRET = mysupersecretcipherkey
PRIVATE_KEY = 2056d52c3fa968e426a3424a21f8020092e5075bcad423805fbd382bcff20a65
ACCEPTED_TOKENS = USDC_ethereum USDC_polygon KRED_polygon

Arweave JWK

Next, you need to paste in an Arweave JWK to key.json:
Now, we're ready to test to see if everything worked! Let's start the server:
npm start
The server will then go through syncing with the network. If your network has lots of data, this can take up to an hour. If your network is new, it should only take a few seconds.
Tip: If you're curious to just see if you set it up correctly, you can set "SYNC" and "SHOVE" to "false" in .env. This will prevent network synchronization and is useful for testing / saving on gas costs.
If everything worked correctly, you should see "Synchronizer is running on port 1984". If so, then all you need to do is stop the server and re-run with "forever":
forever start server.js;
And now you're done! Once the server finishes synchronizing, you should be able to access it via https with the API by using your domain name!