The all-in-one dashboard built from the legacy of Heliactyl. A high performance user interface, full built-in panel for managing servers, coins system, resources store and more.
Before deploying Heliactyl Next, you must configure each node's Wings configuration!
- On each node, edit the Wings configuration file (usually at
/etc/pterodactyl/config.yml) - Locate the
allowed-originssection - Change:
to either:
allowed-origins: []
or:allowed-origins: ['*'] # recommended for simplicity
allowed-origins: ['https://your-dashboard-domain.com'] # more restrictive option
If you don't do this, Heliactyl Next can't communicate with your nodes.
- Modern, responsive user interface
- Built-in panel, goodbye Pterodactyl
- Integrated coins/credits system
- User/password authentication
- Resource allocation system
- Real-time stats and charts
- Support tickets (pending reimplementation)
- Admin area with users, nodes and more
- Node.js v18+ (Required for both frontend and backend)
- Redis
- Nginx
- SSL certificate (recommended)
- Optional: Bun v1.1.42+ (You can use Bun instead of Node.js for the backend if preferred)
- Install Redis:
# For Ubuntu/Debian
sudo apt update
sudo apt install redis-server
# For CentOS/RHEL
sudo dnf install epel-release
sudo dnf install redis
# Start and enable Redis
sudo systemctl start redis
sudo systemctl enable redis- Install Node.js & NPM: Find how to install Node.js via https://nodejs.org or via NVM.
(Optional) Install Bun if you prefer it for the backend:
curl -fsSL https://bun.sh/install | bash
bun upgrade --canary
source ~/.bashrc- Clone the repository:
git clone https://github.com/re-heliactyl/Toledo
cd Toledo- Install backend dependencies:
cd server
npm install
# Or use 'bun install' or 'pnpm install'- Create configuration file:
cp example_config.toml config.toml- Create or update your
server/.envfile for Prisma.
For the default SQLite setup, use:
DB_PROVIDER="sqlite"
SQLITE_DATABASE_URL="file:./prisma/heliactyl.db"
DATABASE_URL="file:./prisma/heliactyl.db"For a MySQL setup, use:
DB_PROVIDER="mysql"
MYSQL_DATABASE_URL="mysql://USER:PASSWORD@127.0.0.1:3306/heliactyl"
DATABASE_URL="mysql://USER:PASSWORD@127.0.0.1:3306/heliactyl"Notes:
- SQLite URLs must use the
file:prefix. - Keep
DATABASE_URLaligned with the provider-specific URL you are using. - Do not leave
DATABASE_URLempty, or Prisma commands such asdb pushwill fail. - The intended SQLite file for the default setup is
server/prisma/heliactyl.db. - Use
DB_PROVIDER="mysql"if you want Prisma to useprisma/schema.mysql.prismaand the generated MySQL client.
-
Configure your
config.tomlfile with your website, database and Pterodactyl details. -
Initialize the Prisma database schema.
For SQLite:
npm run prisma:validate:sqlite
npm run prisma:push:sqliteFor MySQL:
npm run prisma:validate:mysql
npm run prisma:push:mysqlnpm install and npm start already run Prisma client generation automatically. Use the commands above to validate the datasource and create/update the schema explicitly for the provider you selected.
- Build Frontend & Start Heliactyl Next:
# Optional: If you haven't installed frontend dependencies yet
# cd ../frontend && pnpm install && cd ../server
# Build the frontend using the server's mono script
npm run mono:build
# Start the app
npm start
# Or manually: node --no-deprecation app.js (or bun run app.js)This is required to host Heliactyl Next on a public URL.
server {
listen 80;
listen [::]:80;
server_name dashboard.yourdomain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name dashboard.yourdomain.com;
client_max_body_size 100M;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS (uncomment if you're using HTTPS)
# add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Cache static assets (filenames contain hashes, so immutable is safe)
location /assets/ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
expires 30d;
add_header Cache-Control "public, immutable";
}
# WebSocket support
location /ws {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket specific settings
proxy_read_timeout 86400; # Prevents timeout for long-lived connections
proxy_send_timeout 86400; # Prevents timeout for long-lived connections
proxy_buffering off; # Disable buffering for real-time communication
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}Route users to the nearest Heliactyl instance using NGINX GeoIP2 + CockroachDB for cross-region data replication.
Stack: NGINX + GeoIP2 module, MaxMind GeoLite2 DB, CockroachDB cluster, 2+ regional servers.
1. Install GeoIP2 on the entry-point server:
apt install libnginx-mod-http-geoip2 geoipupdate
# Add your MaxMind license to /etc/GeoIP.conf, then run: geoipupdate2. Add to nginx.conf inside http {}:
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
$geoip2_continent_code continent code;
}
map $geoip2_continent_code $backend {
default usa_backend;
EU europe_backend;
AS asia_backend;
NA usa_backend;
SA usa_backend;
OC asia_backend;
AF europe_backend;
}
upstream europe_backend { server 127.0.0.1:3000; keepalive 32; }
upstream asia_backend { server <ASIA_IP>:3000; keepalive 32; }
upstream usa_backend { server <USA_IP>:3000; keepalive 32; }Use
127.0.0.1for the local server to avoid hairpin NAT issues on cloud providers.
3. In your site config, use the dynamic backend:
location / {
proxy_pass http://$backend;
}4. If behind Cloudflare, add to nginx.conf so GeoIP sees real visitor IPs:
set_real_ip_from 103.21.244.0/22; # ... add all Cloudflare ranges
set_real_ip_from 173.245.48.0/20; # Full list: https://cloudflare.com/ips
real_ip_header CF-Connecting-IP;5. Database — use CockroachDB for automatic replication:
[settings]
database = { url = "postgresql://root@localhost:26257/heliactyl?sslmode=disable" }Each instance connects to its local CockroachDB node; replication is handled automatically.
This project is licensed under the Heliactyl Next Public Use License - see the LICENSE file for details.
For support, please open an issue on the GitHub repository or join our Discord community.
To report security vulnerabilities, please email toledo@overnode.fr