A self-contained database engine with REST API, API key auth, rate limiting, admin dashboard, and terminal UI. Runs as a single binary — no dependencies, no runtime, no Docker required.
- Build
- Run
- Environment Variables
- Terminal UI Menu
- SQL Shell
- REST API
- Admin API
- Connect from Your Project
- Deploy on Custom Hardware
- Deploy on a VPS
- Running as a System Service
- Reverse Proxy with Nginx
- TLS / HTTPS
- Data Persistence
- Supported SQL
Windows (MSYS2 / MinGW):
build.batOr manually:
set PATH=C:\msys64\ucrt64\bin;%PATH%
g++ -std=c++17 -O2 -o skilldb.exe main.cpp -lws2_32 -lcrypt32Linux / macOS:
g++ -std=c++17 -O2 -o skilldb main.cpp -lpthreadRequires GCC 9+ or Clang 10+ with C++17 support.
skilldb.exeStarts the HTTP server on http://0.0.0.0:8080 and opens the terminal UI.
Server-only mode (no interactive UI — ideal for VPS / headless):
./skilldb --server| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP port to listen on |
DATA_DIR |
data |
Directory for data.json and users.json |
# Example
PORT=3000 DATA_DIR=/var/lib/skilldb ./skilldb --server| Option | Action |
|---|---|
| 1 | Create a new database |
| 2 | Create user + generate API key & URL |
| 3 | List all users and their keys |
| 4 | Revoke an API key |
| 5 | Show all databases |
| 6 | Show tables in current database |
| 7 | Interactive SQL shell |
| 8 | Server status & endpoints |
| 9 | Export database to .sql file |
CREATE DATABASE myapp
USE myapp
CREATE TABLE users (name TEXT, email TEXT, age INT)
INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 30)
SELECT * FROM users
SELECT name, email FROM users WHERE age > 25
UPDATE users SET age = 31 WHERE name = 'Alice'
DELETE FROM users WHERE name = 'Alice'
DESCRIBE users
SHOW TABLES
SHOW DATABASESPass your API key via header or query param:
X-API-Key: sdb_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or
?apiKey=sdb_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GET /health
POST /register
Content-Type: application/json
{"username": "alice", "dbName": "myapp"}
Returns apiKey, dbName, connectionUrl.
GET /validate
X-API-Key: YOUR_KEY
GET /db/:dbname?apiKey=YOUR_KEY
POST /db/:dbname/query
Content-Type: application/json
X-API-Key: YOUR_KEY
{"sql": "SELECT * FROM users"}
GET /db/:dbname/tables
X-API-Key: YOUR_KEY
GET /db/:dbname/tables/:table
X-API-Key: YOUR_KEY
GET /db/:dbname/tables/:table/rows
X-API-Key: YOUR_KEY
GET /db/:dbname/export/sql
X-API-Key: YOUR_KEY
Change the default credentials in
server.hppbefore deploying:static const std::string ADMIN_EMAIL = "your@email.com"; static const std::string ADMIN_PASSWORD = "your_password"; static const std::string ADMIN_TOKEN = "your_secret_token";
const API_KEY = "sdb_your_key_here";
const BASE = "http://localhost:8080/db/myapp";
async function query(sql) {
const res = await fetch(`${BASE}/query`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": API_KEY },
body: JSON.stringify({ sql })
});
return res.json();
}
const rows = await query("SELECT * FROM users");
console.log(rows);import requests
API_KEY = "sdb_your_key_here"
BASE = "http://localhost:8080/db/myapp"
def query(sql):
r = requests.post(f"{BASE}/query",
json={"sql": sql},
headers={"X-API-Key": API_KEY})
return r.json()
rows = query("SELECT * FROM users")
print(rows)curl -X POST http://localhost:8080/db/myapp/query \
-H "Content-Type: application/json" \
-H "X-API-Key: sdb_your_key_here" \
-d '{"sql":"SELECT * FROM users"}'This covers bare-metal servers, Raspberry Pi, old PCs repurposed as servers, or any Linux box you physically control.
If you build on Windows but your server runs Linux (e.g. a Raspberry Pi):
# On a Linux machine or WSL:
g++ -std=c++17 -O2 -o skilldb main.cpp -lpthread
scp skilldb user@192.168.1.100:/opt/skilldb/# SSH into the machine
ssh user@192.168.1.100
# Install GCC if not present
sudo apt update && sudo apt install -y g++
# Clone or copy source
mkdir -p /opt/skilldb && cd /opt/skilldb
# (copy your source files here)
# Build
g++ -std=c++17 -O2 -o skilldb main.cpp -lpthread
# Create data directory
mkdir -p /opt/skilldb/datacd /opt/skilldb
PORT=8080 DATA_DIR=/opt/skilldb/data ./skilldb --serverOpen the port you're using:
# ufw
sudo ufw allow 8080/tcp
# iptables
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPTFor production, expose only port 80/443 via a reverse proxy (see Nginx section) and keep skilldb on a private port.
Once running, any device on the same network can access it:
http://192.168.1.100:8080/health
Works with any provider: DigitalOcean, Linode/Akamai, Vultr, Hetzner, AWS EC2, etc.
Minimum specs:
- 1 vCPU, 512 MB RAM (it runs fine on the cheapest tier)
- Ubuntu 22.04 LTS (or any modern Linux)
ssh root@YOUR_SERVER_IP
# Install build tools
apt update && apt install -y g++ build-essential
# Set up app directory
mkdir -p /opt/skilldb/data
cd /opt/skilldb
# Upload your source files (from local machine):
# scp -r ./dbf/* root@YOUR_SERVER_IP:/opt/skilldb/
# Build
g++ -std=c++17 -O2 -o skilldb main.cpp -lpthreadPORT=8080 DATA_DIR=/opt/skilldb/data ./skilldb --serverTest from your local machine:
curl http://YOUR_SERVER_IP:8080/healthufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enableskilldb itself runs on an internal port (e.g. 8080) and is exposed via Nginx.
Set up skilldb to auto-start and auto-restart on crash using systemd.
sudo nano /etc/systemd/system/skilldb.service[Unit]
Description=skilldb Database Engine
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/skilldb
ExecStart=/opt/skilldb/skilldb --server
Environment=PORT=8080
Environment=DATA_DIR=/opt/skilldb/data
Restart=on-failure
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=skilldb
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable skilldb
sudo systemctl start skilldb
sudo systemctl status skilldbjournalctl -u skilldb -fProxying through Nginx lets you run skilldb on a private port while exposing it publicly on port 80/443, and handles TLS termination.
sudo apt install -y nginxsudo nano /etc/nginx/sites-available/skilldbserver {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 30s;
}
}sudo ln -s /etc/nginx/sites-available/skilldb/etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxNow skilldb is accessible at http://yourdomain.com.
Use Certbot for a free Let's Encrypt certificate.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.comCertbot automatically updates your Nginx config to serve HTTPS and redirect HTTP → HTTPS.
After this, your connection URLs look like:
https://yourdomain.com/db/myapp?apiKey=sdb_xxx
Update your API key connection URLs by changing the host in auth.hpp or by re-creating users pointing to the new domain. The setEndpoint call in DBServer controls the host used in generated connectionUrl values:
// server.hpp — constructor calls:
auth.setEndpoint("yourdomain.com", 443);Or you can set the host dynamically via the HOST environment variable — add this to main.cpp:
const char* hostEnv = std::getenv("HOST");
server.auth.setEndpoint(hostEnv ? hostEnv : "localhost", SERVER_PORT);| File | Contents |
|---|---|
data/data.json |
All databases and tables (auto-saved on every write) |
data/users.json |
API keys and user credentials (auto-saved) |
Both files are plain JSON — human-readable and easy to back up.
# Simple cron backup (daily at 2am)
crontab -e
# Add:
0 2 * * * cp -r /opt/skilldb/data /opt/skilldb/backups/$(date +\%F)Copy data.json and users.json back to DATA_DIR and restart the service.
Use menu option 9 in the UI, or via the API:
curl http://localhost:8080/db/myapp/export/sql \
-H "X-API-Key: sdb_your_key" | jq -r '.sql' > myapp_export.sqlImport into PostgreSQL / MySQL:
psql -U user -d dbname -f myapp_export.sql
mysql -u user -p dbname < myapp_export.sql| Statement | Syntax |
|---|---|
| CREATE DATABASE | CREATE DATABASE name |
| USE | USE name |
| CREATE TABLE | CREATE TABLE t (col TYPE, ...) |
| DROP TABLE | DROP TABLE t |
| INSERT | INSERT INTO t (col1, col2) VALUES (v1, v2) |
| SELECT | SELECT */cols FROM t [WHERE col op val] |
| UPDATE | UPDATE t SET col=val [WHERE col op val] |
| DELETE | DELETE FROM t [WHERE col op val] |
| DESCRIBE | DESCRIBE t |
| SHOW TABLES | SHOW TABLES |
| SHOW DATABASES | SHOW DATABASES |
WHERE operators: =, !=, >, <, >=, <=, AND
Column types: TEXT, INT, FLOAT
An
id INTprimary key column is automatically added to every table.