Complete Knowledge Base & Setup Guide
Version 2.0 · Updated July 2026| Component | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 2 GB | 4 GB |
| Storage | 20 GB SSD | 50 GB SSD |
| Bandwidth | 1 TB/month | Unlimited |
| OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| Component | Specification |
|---|---|
| CPU | 4+ vCPU |
| RAM | 8 GB (16 GB recommended) |
| Storage | 100 GB NVMe SSD |
| Database | PostgreSQL 15+ (NOT SQLite) |
| Cache | Redis 7+ (recommended) |
| OS | Ubuntu 22.04/24.04 LTS or Debian 12 |
| Software | Version | Purpose |
|---|---|---|
| Node.js | 20 LTS or 22 LTS | JavaScript runtime |
| Bun | 1.1+ | Package manager & runtime (faster than npm) |
| PostgreSQL | 15+ (or MySQL 8+) | Database (production) |
| Redis | 7+ (optional) | Caching & session store |
| Nginx | 1.18+ | Reverse proxy & SSL |
| PM2 | 5+ | Process manager (keeps app running) |
| Certbot | 2+ | SSL certificates (Let's Encrypt) |
ssh root@YOUR_SERVER_IP
# Update system packages
apt update && apt upgrade -y
# Install essential packages
apt install -y curl git nginx ufw
# Install Node.js 20 LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
# Install Bun (package manager)
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
# Install PM2 (process manager)
npm install -g pm2
# Install PostgreSQL
apt install -y postgresql postgresql-contrib
# Start and enable PostgreSQL
systemctl enable postgresql
systemctl start postgresql
# Create database and user
su - postgres
psql
CREATE DATABASE smarttech;
CREATE USER smarttech_user WITH ENCRYPTED PASSWORD 'YourStrongPassword123';
GRANT ALL PRIVILEGES ON DATABASE smarttech TO smarttech_user;
ALTER USER smarttech_user WITH SUPERUSER;
\q
exit
# Create directory
mkdir -p /var/www/smarttech
cd /var/www/smarttech
# Option A: Upload the zip file from your computer
scp smarttech-hosting-panel.zip root@YOUR_SERVER_IP:/var/www/smarttech/
unzip smarttech-hosting-panel.zip
mv smarttech-package/* .
rm -rf smarttech-package smarttech-hosting-panel.zip
# Option B: Clone from Git (if you have a repo)
git clone https://github.com/yourusername/smarttech-hosting.git .
# Install dependencies
bun install
# Copy example env file
cp .env.example .env
# Edit the .env file
nano .env
Update these values in .env:
# Database — PostgreSQL connection
DATABASE_URL="postgresql://smarttech_user:YourStrongPassword123@localhost:5432/smarttech?schema=public"
# Security secrets (generate with: openssl rand -hex 32)
SESSION_SECRET="your-generated-secret-here"
NEXTAUTH_SECRET="your-generated-secret-here"
NEXTAUTH_URL="https://yourdomain.com"
# Email (optional — for notifications)
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="your-email@gmail.com"
SMTP_PASS="your-app-password"
FROM_EMAIL="noreply@yourdomain.com"
# Monitoring cron secret
CRON_SECRET="your-cron-secret"
# Edit the schema
nano prisma/schema.prisma
Change the datasource provider from sqlite to postgresql:
datasource db {
provider = "postgresql" // Change from "sqlite"
url = env("DATABASE_URL")
}
# Push schema to PostgreSQL
bun run db:push
# Run all seed scripts
bun run scripts/seed.ts
bun run scripts/seed-integrations.ts
bun run scripts/seed-settings-payments.ts
bun run scripts/seed-content-monitors.ts
bun run scripts/seed-admin.ts
bun run scripts/seed-licenses.ts
bun run scripts/seed-domain-tlds.ts
# Build for production
bun run build
# Start with PM2
pm2 start "bun run start" --name smarttech
# Save PM2 config (auto-restart on reboot)
pm2 save
pm2 startup
# Follow the instructions PM2 prints
nano /etc/nginx/sites-available/smarttech
Paste this configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
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_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;
proxy_cache_bypass $http_upgrade;
}
location /_next/static/ {
proxy_pass http://localhost:3000;
expires 365d;
add_header Cache-Control "public, immutable";
}
client_max_body_size 10M;
}
# Enable the site
ln -s /etc/nginx/sites-available/smarttech /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
# Test config
nginx -t
# Restart Nginx
systemctl restart nginx
# Install Certbot
apt install -y certbot python3-certbot-nginx
# Generate SSL certificate
certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Follow the prompts — it auto-configures Nginx for HTTPS
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw allow 5432/tcp # PostgreSQL (only if remote access needed)
ufw enable
crontab -e
Add these lines:
# Server monitoring — check every minute
* * * * * curl -s "https://yourdomain.com/api/monitors/cron?key=your-cron-secret" > /dev/null
# Email notifications — daily at 9 AM
0 9 * * * curl -s -X POST "https://yourdomain.com/api/notifications" -H "Content-Type: application/json" -d '{"trigger":"domain-expiry"}' > /dev/null
0 9 * * * curl -s -X POST "https://yourdomain.com/api/notifications" -H "Content-Type: application/json" -d '{"trigger":"invoice-reminders"}' > /dev/null
# Database backup — daily at 2 AM
0 2 * * * pg_dump -U smarttech_user smarttech > /var/backups/smarttech_$(date +\%Y\%m\%d).sql
https://yourdomain.com. Access the admin panel at https://yourdomain.com/?admin=true.
smarttech.yourdomain.com)smarttechsmarttech_user with a strong passwordusername_smarttech) and user name (username_smarttech_user)smarttechsmarttech-hosting-panel.zip filesmarttech foldercd ~/smarttech
# Install Node.js dependencies
npm install
# If npm is not available, use the Node.js Selector:
# 1. Go to cPanel → Software → Setup Node.js App
# 2. Click "Create Application"
# 3. Set Node.js version to 20.x
# 4. Set Application Mode to "Production"
# 5. Set Application Root to /smarttech
# 6. Set Application URL to your domain
# 7. Click Create
# Create .env file
cp .env.example .env
nano .env
Set these values:
# MySQL connection (cPanel format: username_dbname)
DATABASE_URL="mysql://username_smarttech_user:YourPassword@localhost:3306/username_smarttech"
# Update prisma/schema.prisma to use mysql:
# datasource db {
# provider = "mysql"
# url = env("DATABASE_URL")
# }
SESSION_SECRET="generate-with-openssl-rand-hex-32"
NEXTAUTH_SECRET="generate-another-one"
NEXTAUTH_URL="https://yourdomain.com"
CRON_SECRET="your-cron-secret"
# Update Prisma schema to MySQL
sed -i 's/provider = "sqlite"/provider = "mysql"/' prisma/schema.prisma
# Push schema
npx prisma db push
# Run seed scripts
node scripts/seed.js
node scripts/seed-integrations.js
node scripts/seed-settings-payments.js
node scripts/seed-content-monitors.js
node scripts/seed-admin.js
node scripts/seed-licenses.js
node scripts/seed-domain-tlds.js
# Build for production
npm run build
npm run startSQLite is a file-based database that only allows one write operation at a time. With 1000+ clients, you'll experience:
apt install -y postgresql postgresql-contrib
systemctl enable postgresql
systemctl start postgresql
su - postgres
psql
CREATE DATABASE smarttech;
CREATE USER smarttech_user WITH ENCRYPTED PASSWORD 'YourStrongPassword123';
GRANT ALL PRIVILEGES ON DATABASE smarttech TO smarttech_user;
ALTER USER smarttech_user WITH SUPERUSER;
\q
exit
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
DATABASE_URL="postgresql://username:password@localhost:5432/databasename?schema=public"
apt install -y mysql-server
systemctl enable mysql
systemctl start mysql
# Secure installation
mysql_secure_installation
mysql -u root -p
CREATE DATABASE smarttech CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'smarttech_user'@'localhost' IDENTIFIED BY 'YourStrongPassword123';
GRANT ALL PRIVILEGES ON smarttech.* TO 'smarttech_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
// prisma/schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
DATABASE_URL="mysql://username:password@localhost:3306/databasename"
bun run db:push to create all tables in the new database, then re-run all seed scripts.
The SmartTech Hosting Panel includes 14 admin modules and a full client portal:
Real-time KPIs showing total revenue, active clients, domains, hosting services, open tickets, and outstanding amounts. Includes a 30-day revenue chart, server capacity bars, and recent activity feeds for clients, invoices, tickets, and domains.
Full client management with searchable, paginated table. Click any client to open a detail sheet showing profile, contact info, credit balance, and cross-module counts (hosting, domains, invoices, tickets).
All provisioned hosting accounts with plan, server, billing cycle, and next due date. Click any service to see full details and perform actions.
Domain registrations with expiry tracking, auto-renew toggles, and WHOIS privacy indicators. Click any domain for full details and management actions.
Set your own prices for every TLD. Configure registration, transfer, and renewal prices separately. Mark TLDs as "popular" to show them on the storefront.
Order history with itemized products, billing cycles, and totals. Click any order to see full details and take action.
Billing summary with collected, outstanding, paid, and unpaid counts. Click any invoice for full details including line items and payment actions.
Full ticket pipeline with conversation thread. Reply to customers and update ticket status from the detail sheet.
Hosting plan catalog with full CRUD. Add, edit, or delete any product. Set prices, features, setup fees, and stock control.
Server infrastructure dashboard with capacity bars and full uptime monitoring.
Configure API credentials for all hosting providers, domain registrars, and payment gateways.
Generate and manage license keys for reselling the app. Create admin and reseller keys with time durations.
Edit the storefront page content without touching code. All changes go live immediately.
Configure branding, currency, contact info, and system settings.
Clients log in via the "Client Login" button on the storefront. They can:
shared01.yourcompany.comroot or reseller usernamelivesite_XXXXXXXXhttps://api.20i.comSpaceship uses HMAC-signed requests. The integration code handles signing automatically.
https://easypaisa.com.pk/easypaisa-service/api/v1https://yourdomain.com/api/payments/easypaisa/callbackMC12345https://sandbox.jazzcash.com.pk/CustomerApp/Api/Payment/Requesthttps://api.jazzcash.com.pk/jazzcash/payment/Requesthttps://yourdomain.com/api/payments/jazzcash/callbackNo API credentials needed — just enter your bank account details:
PK36SCBL0000001123456702Supported banks: HBL, Meezan Bank, Bank Alfalah, UBL, MCB, Standard Chartered Pakistan, Faysal Bank, BankIslami, HabibMetro, Askari Bank.
pk_live_... or pk_test_...sk_live_... or sk_test_...whsec_... for payment verificationSet webhook URL to: https://yourdomain.com/api/webhooks/stripe
Set webhook URL to: https://yourdomain.com/api/webhooks/paypal
The licensing system lets you resell the SmartTech Hosting Panel to other hosting companies.
theirdomain.com/?admin=true| Type | Access | Use Case |
|---|---|---|
| Admin | Full admin panel access | For your own staff or single-customer deployments |
| Reseller | Full admin panel + max client limit | For reselling to other hosting companies |
| Duration | Code | Use Case |
|---|---|---|
| 30 days | 30 | Trial / Demo |
| 90 days | 90 | Quarterly |
| 180 days | 180 | Semi-annual |
| 365 days | 365 | Annual (most common) |
| 730 days | 730 | 2-year |
| Lifetime | null | Never expires (enterprise) |
All keys follow the format: ST-XXXX-XXXX-XXXX-XXXX (ST = SmartTech)
Example: ST-ZFX8-AWWY-H0N0-7LO6
| Key | Duration | Note |
|---|---|---|
ST-ZFX8-AWWY-H0N0-7LO6 | Lifetime | Master key |
ST-4BKN-NSAM-VXDY-BA4T | 365 days | 1-year admin |
ST-CAYH-9E7J-XJZS-DC6J | 365 days | 1-year admin |
ST-843W-P4EK-VLZH-QC1F | 90 days | Trial |
ST-9IRJ-AR6E-N9H3-ROB0 | 30 days | Demo |
The monitoring system checks your servers at regular intervals and logs uptime/downtime data.
The monitoring cron job runs the actual checks. Set it up on your server:
# Edit crontab
crontab -e
# Add this line (runs every minute):
* * * * * curl -s "https://yourdomain.com/api/monitors/cron?key=YOUR_CRON_SECRET" > /dev/null
Replace YOUR_CRON_SECRET with the value from your .env file's CRON_SECRET setting.
If you don't have server access for cron, use an external service:
Set the URL to: https://yourdomain.com/api/monitors/cron?key=YOUR_CRON_SECRET
The system sends these automated emails:
| Template | When Sent | Recipient |
|---|---|---|
| Welcome | New client signup | Client |
| Invoice Created | New invoice generated | Client |
| Invoice Paid | Payment received | Client |
| Ticket Reply | Staff replies to ticket | Client |
| Domain Expiry | 60, 30, 7 days before expiry | Client |
| Invoice Reminder | 7, 3, 1 days before due | Client |
Configure SMTP in your .env file:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-gmail-app-password
FROM_EMAIL=noreply@yourdomain.com
SMTP_PASS| Provider | SMTP Host | Port |
|---|---|---|
| Gmail | smtp.gmail.com | 587 |
| Outlook/Hotmail | smtp-mail.outlook.com | 587 |
| Yahoo | smtp.mail.yahoo.com | 587 |
| SendGrid | smtp.sendgrid.net | 587 |
| Mailgun | smtp.mailgun.org | 587 |
| Amazon SES | email-smtp.us-east-1.amazonaws.com | 587 |
# Daily at 9 AM — check domain expiry warnings
0 9 * * * curl -s -X POST "https://yourdomain.com/api/notifications" -H "Content-Type: application/json" -d '{"trigger":"domain-expiry"}' > /dev/null
# Daily at 9 AM — send invoice due reminders
0 9 * * * curl -s -X POST "https://yourdomain.com/api/notifications" -H "Content-Type: application/json" -d '{"trigger":"invoice-reminders"}' > /dev/null
# Manual backup
pg_dump -U smarttech_user smarttech > backup_$(date +%Y%m%d).sql
# Restore from backup
psql -U smarttech_user smarttech < backup_20260710.sql
# Create backup script
cat > /var/backups/pg-backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/var/backups/postgresql"
mkdir -p $BACKUP_DIR
DATE=$(date +%Y%m%d_%H%M%S)
pg_dump -U smarttech_user smarttech > $BACKUP_DIR/smarttech_$DATE.sql
# Keep only last 7 days
find $BACKUP_DIR -name "smarttech_*.sql" -mtime +7 -delete
EOF
chmod +x /var/backups/pg-backup.sh
# Schedule daily backup at 2 AM
crontab -e
# Add:
0 2 * * * /var/backups/pg-backup.sh
# Manual backup
mysqldump -u smarttech_user -p smarttech > backup_$(date +%Y%m%d).sql
# Restore from backup
mysql -u smarttech_user -p smarttech < backup_20260710.sql
# Backup the entire application directory
tar -czf /var/backups/smarttech_files_$(date +%Y%m%d).tar.gz /var/www/smarttech
# Backup the .env file separately (contains secrets)
cp /var/www/smarttech/.env /var/backups/.env.backup
#!/bin/bash
# /var/backups/full-backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/smarttech"
mkdir -p $BACKUP_DIR
# Database backup
pg_dump -U smarttech_user smarttech > $BACKUP_DIR/db_$DATE.sql
# Files backup
tar -czf $BACKUP_DIR/files_$DATE.tar.gz /var/www/smarttech --exclude=node_modules --exclude=.next
# Keep only last 7 days
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
echo "Backup completed: $DATE"
Cause: Wrong DATABASE_URL or database not running.
Fix:
systemctl status postgresqlpsql -U smarttech_user -d smarttech -h localhost.env file has correct DATABASE_URLtail -f /var/log/postgresql/postgresql-15-main.logCause: Another process is using port 3000.
Fix:
# Find the process
lsof -i :3000
# Kill it
kill -9 PID
# Or change the port in package.json:
# "dev": "next dev -p 3001"
Cause: Prisma client not built after schema change.
Fix:
bun run db:generate
# or
npx prisma generate
Cause: DNS not pointing to server, or Certbot failed.
Fix:
dig yourdomain.com — should show your server IPcertbot --nginx -d yourdomain.comnginx -tcat /var/log/letsencrypt/letsencrypt.logCause: Missing environment variables or database not initialized.
Fix:
.env file exists and has all required variablesbun run db:push to create database tablespm2 logs smarttechbun run buildCause: SMTP not configured or wrong credentials.
Fix:
.env has SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS setnode -e "require('nodemailer').createTransport({host:'smtp.gmail.com',port:587,auth:{user:'you@gmail.com',pass:'app-password'}}).verify().then(()=>console.log('OK')).catch(e=>console.error(e))"Cause: Callback URL not set correctly in payment gateway dashboard.
Fix:
curl https://yourdomain.com/api/payments/easypaisa/callbacktail -f /var/log/nginx/error.logCause: Cron job not set up or wrong secret key.
Fix:
systemctl status croncrontab -lcurl "https://yourdomain.com/api/monitors/cron?key=YOUR_SECRET".env matches the cron URL# Check app status
pm2 status
pm2 logs smarttech
# Restart app
pm2 restart smarttech
# Check Nginx status
systemctl status nginx
nginx -t
# Check PostgreSQL status
systemctl status postgresql
# Check disk space
df -h
# Check memory usage
free -h
# Check running processes
htop
# View app logs
pm2 logs smarttech --lines 100
# Clear Next.js cache
rm -rf .next
bun run build
# Reset database (DESTRUCTIVE!)
bun run db:push --force-reset
pm2 logs smarttech/var/log/nginx/error.log/var/log/postgresql/journalctl -u smarttech