Deployment on aaPanel
This guide deploys SocialMine on aaPanel (Linux web hosting panel): Node.js, MySQL, Nginx, PM2, and SSL. It aligns with the repository’s root .env layout and the Production deployment overview.
Replace
yourdomain.com,api.yourdomain.com, and paths like/www/wwwroot/socialminewith your real domain and install location.
Prerequisites
- A server with aaPanel installed (root or sudo access)
- A domain (optional but recommended for SSL and OAuth)
1. Install software in aaPanel
- Log in to aaPanel (often
http://your-server-ip:7800). - App Store → Node.js Version Manager → install Node.js 18+ (or 20.x) and set as default.
- App Store → MySQL 8 — set a strong root password.
- App Store → PM2 Manager — install.
- App Store → Nginx — install.
2. Upload the project
cd /www/wwwroot
mkdir -p socialmine
cd socialmine
git clone <your-repository-url> .
Or use Files in aaPanel to upload and extract a ZIP into /www/wwwroot/socialmine.
Ensure uploads can be written by the web user (often www):
cd /www/wwwroot/socialmine/server
mkdir -p uploads/avatars uploads/products uploads/posts uploads/tickets uploads/branding
chown -R www:www uploads
chmod -R 755 uploads
3. Database
Database → MySQL → Add Database: create socialmine and a dedicated user, or use SQL:
CREATE DATABASE socialmine CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'socialmine_user'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON socialmine.* TO 'socialmine_user'@'localhost';
FLUSH PRIVILEGES;
4. Environment file (project root)
Create /www/wwwroot/socialmine/.env from .env.example at the repository root (not only inside server/). SocialMine’s server loads this file from the project root.
Example production values (adjust domains and secrets):
NODE_ENV=production
PORT=3000
DEMO_MODE=false
DATABASE_URL="mysql://socialmine_user:your_password@localhost:3306/socialmine?schema=public"
JWT_SECRET=your-long-random-secret-minimum-32-characters
JWT_EXPIRES_IN=7d
ENCRYPTION_KEY=generate-with-openssl-rand-base64-32
CORS_ORIGIN=https://yourdomain.com
FRONTEND_URL=https://yourdomain.com
API_PUBLIC_URL=https://api.yourdomain.com
VITE_API_URL=https://api.yourdomain.com/api
VITE_APP_NAME=SocialMine
VITE_APP_VERSION=1.0.0
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=
SMTP_PASSWORD=
SMTP_FROM_EMAIL=noreply@yourdomain.com
SMTP_FROM_NAME=SocialMine
If the web app is served on the same origin as the API (unified server/index.js or Nginx proxying /api on the same host), set VITE_API_URL, CORS_ORIGIN, FRONTEND_URL, and API_PUBLIC_URL to match that single public URL.
Rebuild the client after any change to VITE_* variables:
cd /www/wwwroot/socialmine/client && npm run build
5. Backend: install, Prisma, build
cd /www/wwwroot/socialmine/server
npm install --production
npm run prisma:generate
npx dotenv-cli -e ../.env -- prisma migrate deploy
npm run build
6. Frontend build
cd /www/wwwroot/socialmine/client
npm install
npm run build
Output: client/dist/.
7. PM2 — backend process
Option A — Use the repo ecosystem.config.js (from project root)
cd /www/wwwroot/socialmine
pm2 start ecosystem.config.js
pm2 save
pm2 startup
The default app name is socialmine. It runs server/dist/main.js with cwd set to server.
Option B — PM2 Manager UI
- Project path:
/www/wwwroot/socialmine/server - Startup file:
dist/main.js - Node version: match your installed version
Verify:
pm2 status
pm2 logs socialmine
curl -s http://127.0.0.1:3000/api/health
8. Nginx
Typical split setup:
- API —
api.yourdomain.com→ proxy tohttp://127.0.0.1:3000 - Frontend —
yourdomain.com→root=/www/wwwroot/socialmine/client/distandtry_filesfor SPA
API site (api.yourdomain.com)
server {
listen 80;
server_name api.yourdomain.com;
location / {
proxy_pass http://127.0.0.1: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;
}
location /uploads {
alias /www/wwwroot/socialmine/server/uploads;
expires 30d;
}
}
Frontend site (yourdomain.com)
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
root /www/wwwroot/socialmine/client/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:3000;
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_set_header X-Forwarded-Proto $scheme;
}
}
Test and reload:
nginx -t && systemctl reload nginx
In aaPanel you can create sites via Website → Add Site, then paste the relevant server { ... } under Configuration.
9. SSL
Website → your site → SSL → Let’s Encrypt → apply for yourdomain.com and api.yourdomain.com → enable Force HTTPS.
10. Firewall
Open 80 and 443 (aaPanel Security → Firewall or firewalld / ufw).
Updates (deploy new code)
cd /www/wwwroot/socialmine
git pull origin main
cd server
npm install --production
npm run prisma:generate
npx dotenv-cli -e ../.env -- prisma migrate deploy
npm run build
pm2 restart socialmine
cd ../client
npm install
npm run build
Troubleshooting
| Issue | What to check |
|---|---|
| 502 Bad Gateway | pm2 status, pm2 logs socialmine, Nest listening on port 3000 |
| DB errors | DATABASE_URL, MySQL running, migrations applied |
| OAuth redirect mismatch | API_PUBLIC_URL and provider consoles — see Social platform configuration |
| Blank SPA / 404 on refresh | Nginx try_files and correct root to client/dist |
| Wrong API URL in browser | Rebuild client after changing VITE_API_URL |
For command shortcuts and paths, see aaPanel quick reference. The repository also ships AAPANEL_DEPLOYMENT.md and AAPANEL_QUICK_REFERENCE.md at the project root for the same workflow with minor wording differences.