xModels supports all platforms: Windows, MacOS, Linux.
xModels needs a VPS server with at least:
4GB of RAM - recommend 8GB
40GB of HDD
1 CPU core - recommend 2 cores at least
4 domains / sub domains
api.[your-domain]
and point to server IP address
admin.[your-domain]
and point to server IP address
streaming.[your-domain]
and point to server IP address
[your-domain]
and point to server IP address
xModel use Ant media as a media streaming service for broadcast, private and group chat. Recommend server with at least
Ubuntu 18.04
4GB of RAM
2 CPU core - CPU optimized
Streaming domain like streaming [your-domain]
Note: Ant media is able to be installed on |
xModels architecture needs these softwares
NodeJS v16.x
To install please download NodeJS here
MongoDB v3.6
To install please download mongoDB
Redis server v2.8
To install please download and setup redis
Nginx v1.3
PM2 is a daemon process manager that will help you manage and keep your application online 24/7
Yarn or npm to manage nodeJS package
Ensure all softwares above are running before setup source code
From command line / terminal please run these commands to check
$ node -v v12.16.2 |
$ mongo --version MongoDB shell version v4.0.7 git version: 1b82c812a9c0bbf6dc79d5400de9ea99e6ffa025 allocator: system modules: none build environment: distarch: x86_64 target_arch: x86_64 |
$ redis-server --version Redis server v=5.0.4 sha=00000000:0 malloc=libc bits=64 build=d4ba11298acbb366 |
$ ffmpeg -version fmpeg version 2.8.15-0ubuntu0.16.04.1 Copyright (c) 2000-2018 the FFmpeg developers built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609 configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv libavutil 54. 31.100 / 54. 31.100 libavcodec 56. 60.100 / 56. 60.100 libavformat 56. 40.101 / 56. 40.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 40.101 / 5. 40.101 libavresample 2. 1. 0 / 2. 1. 0 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.101 / 1. 2.101 libpostproc 53. 3.100 / 53. 3.100 |
$ nginx -v nginx version: nginx/1.10.3 |
$ pm2 -v [PM2] Spawning PM2 daemon with pm2_home=/Users/xxx/.pm2 [PM2] PM2 Successfully daemonized 4.4.0 |
$ yarn -v 1.16.0 |
We provide source code with 4 folders, check below and use in the app accordingly
user
web frontend (front office)
admin
backend (back office), admin control panel
api
api of the app
config-example
env
product environment example config
nginx
nginx config example
Ensure node v16.x
, MongoDB
, Redis server
, FFMPEG
and yarn
are running
CD to your API folder
Run yarn
to install nodeJS dependencies
$ yarn yarn install v1.16.0 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... |
Create new .env
from config-example > env > api.env
file in the root dir
Content .env
looks like below
# production or development NODE_ENV=production # http port HTTP_PORT=8080 # secret which is using to generate jwt, password, etc... You should change with your key TOKEN_SECRET=1213456-example.com # mongo connection string. check here https://docs.mongodb.com/manual/reference/connection-string/ MONGO_URI=mongodb://localhost/xmodels # redis server config REDIS_HOST=127.0.0.1 REDIS_PORT=6379 REDIS_DB=xmodels REDIS_PREFIX=xmodels_queue MAILER_CONCURRENCY=2 TEMPLATE_DIR=templates DOMAIN=example.com BASE_URL=https://api.example.com USER_URL=https://example.com EMAIL_VERIFIED_SUCCESS_URL=https://example.com/auth/email-verified-success |
Check Migration point to seed default
Run yarn start:dev
to start development env
$ yarn start:dev :48 PM] Starting compilation in watch mode... [2:49:13 PM] Found 0 errors. Watching for file changes. [Nest] 60068 - 08/03/2020, 2:49:17 PM [NestFactory] Starting Nest application... [Nest] 60068 - 08/03/2020, 2:49:17 PM [InstanceLoader] QueueModule dependencies initialized +134ms [Nest] 60068 - 08/03/2020, 2:49:17 PM [InstanceLoader] RedisModule dependencies initialized +0ms [Nest] 60068 - 08/03/2020, 2:49:17 PM [InstanceLoader] HttpModule dependencies initialized +1ms [Nest] 60068 - 08/03/2020, 2:49:17 PM [InstanceLoader] QueueModule dependencies initialized +0ms [Nest] 60068 - 08/03/2020, 2:49:17 PM [InstanceLoader] ServeStaticModule dependencies initialized +4ms .... |
Open browsers and run http://localhost:8080
it should show success message or Hello World!
Ensure nodejs
and yarn
are running
From frontend root directory run yarn
command to install nodejs dependencies
$ yarn yarn install v1.16.0 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... |
Create .env
file from config-example > env > user.env
. Content looks like below. Change it with your configuration accordingly
# produciton or development NODE_ENV=production # http port PORT=8081 # api endpoint will be called in the server side API_ENDPOINT=http://localhost:8080 # api endpoint will be called in the browser NEXT_PUBLIC_API_ENDPOINT=https://api.example.com NEXT_PUBLIC_SOCKET_ENDPOINT=https://api.example.com NEXT_PUBLIC_MAX_SIZE_IMAGE=5 NEXT_PUBLIC_MAX_STREAM_BITRATE=900 |
Then you can open browser http://localhost:8081
to see the web
Similar Frontend web, same steps.
Create .env
file from config-example > env > user.env
. Content looks like below. Change it with your configuration accordingly
# produciton or development NODE_ENV=production # http port PORT=8082 # api endpoint will be called in the server side API_ENDPOINT=http://localhost:8080 # api endpoint will be called in the browser NEXT_PUBLIC_API_ENDPOINT=https://api.example.com NEXT_PUBLIC_SITE_URL=https://example.com NEXT_PUBLIC_MAX_SIZE_IMAGE=5 NEXT_PUBLIC_MAX_SIZE_FILE=100 NEXT_PUBLIC_MAX_SIZE_TEASER=200 NEXT_PUBLIC_MAX_SIZE_VIDEO=2000 NEXT_PUBLIC_MAX_STREAM_BITRATE=900 NEXT_PUBLIC_BUILD_VERSION=3.0.0 |
Run yarn run dev
to start development env
$ yarn run dev yarn run v1.16.0 $ ts-node --project tsconfig.server.json server/index.ts Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected. See here for more info: https://err.sh/next.js/built-in-css-disabled > Using external babel configuration |
Then you can open browser http://localhost:8082
to see the web
Make sure you have installed nodeJS dependencies by yarn
command
In API root directory, run yarn build
$ yarn build yarn run v1.16.0 $ rimraf dist $ nest build && yarn copy-template $ cp -r ./src/templates ./dist/templates ✨ Done in 22.62s |
Testing by run command yarn start:prod
or node dist/main.js
$ yarn start yarn run v1.16.0 $ node dist/main [Nest] 60205 - 08/03/2020, 2:56:11 PM [NestFactory] Starting Nest application... .... |
Run pm2 start dist/main.js --name=api
to run API under background
Or run pm2 start yarn --interpreter bash --name xmodels-api -- start:prod
to run application under port 8080
Note: If have error when starting with Pm2, please try to start without interpreter
pm2 start yarn --name xmodels-api -- start:prod |
Make sure you have installed nodeJS dependencies by yarn
command
Run yarn build
$ yarn build yarn run v1.16.0 $ next build && tsc && tsc --project tsconfig.server.json Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected. See here for more info: https://err.sh/next.js/built-in-css-disabled > Using external babel configuration > Location: "/Users/tuong/Projects/frontend-base-reactjs/.babelrc" Creating an optimized production build Compiled with warnings. chunk styles [mini-css-extract-plugin] Conflicting order between: * css ./node_modules/css-loader??ref--6-1!./node_modules/less-loader/dist/cjs.js??ref--6-2!./src/components/video/video.less * css ./node_modules/css-loader??ref--6-1!./node_modules/less-loader/dist/cjs.js??ref--6-2!./src/components/common/layout/page.less * css ./node_modules/css-loader??ref--6-1!./node_modules/less-loader/dist/cjs.js??ref--6-2!./src/components/common/base/loader.less .... |
Run pm2 start dist/index.js --name xmodels-web -- start
to run application
Similar Frontend web, same steps.
Run yarn build
Run pm2 start dist/index.js --name xmodels-admin -- start
to run application
Api
Let say our frontend code is in /var/www/api.xmodels.info
folder and api is running under port 8080, add new file in /etc/nginx/sites-enabled/api.xmodels.info
and content as bellow
You have to change with our server name and source code path
server { listen 80 ; root /var/www/api.xmodels.info/public; # Add index.php to the list if you are using PHP index index.html; server_name api.xmodels.info; # reduce the data that needs to be sent over network -- for testing environment gzip on; # gzip_static on; gzip_min_length 10240; gzip_comp_level 1; gzip_vary on; gzip_disable msie6; gzip_proxied expired no-cache no-store private auth; gzip_types # text/html is always compressed by HttpGzipModule text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml application/atom+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; # allow the server to close connection on non responding client, this will free up memory reset_timedout_connection on; # cache informations about FDs, frequently accessed files # can boost performance, but you need to test those values open_file_cache max=200000 inactive=300s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # depend on server, we can change 128k, 256k, 512k... sendfile_max_chunk 1m; client_max_body_size 5000M; # to boost I/O on HDD we can disable access logs access_log off; error_log off; location / { try_files $uri @app; } location @app { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $http_host; proxy_pass http://localhost:8080; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; # WebSocket support proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; } location /.well-known { alias /var/www/api.example.com/public/.well-known; } location /videos/protected/ { auth_request /authvideo; root /var/www/api.xmodels.info/public/; } location = /authvideo { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/user/assets/videos/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; } location /photos/protected/ { auth_request /authphoto; root /var/www/api.xmodels.info/public/; } location = /authphoto { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/user/assets/photos/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; } location /digital-products/protected { auth_request /authproduct; root /var/www/api.xmodels.info/public/; } location = /authproduct { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/user/assets/products/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; } } |
Frontend
Let say our frontend code is in /var/www/xmodels.info
folder and Frontend app is running under port 8081, add new file in /etc/nginx/sites-enabled/xmodels.info
and content as bellow
You have to change with our server name and source code path
server { listen 80; server_name xmodels.info; root /var/www/xmodels.info/public; # cache informations about FDs, frequently accessed files # can boost performance, but you need to test those values open_file_cache max=200000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; # to boost I/O on HDD we can disable access logs access_log off; error_log off; # copies data between one FD and other from within the kernel # faster than read() + write() sendfile on; # send headers in one piece, it is better than sending them one by one tcp_nopush on; # don't buffer data sent, good for small data bursts in real time tcp_nodelay on; # reduce the data that needs to be sent over network -- for testing environment gzip on; # gzip_static on; gzip_min_length 10240; gzip_comp_level 1; gzip_vary on; gzip_disable msie6; gzip_proxied expired no-cache no-store private auth; gzip_types # text/html is always compressed by HttpGzipModule text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml application/atom+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; # allow the server to close connection on non responding client, this will free up memory reset_timedout_connection on; # request timed out -- default 60 client_body_timeout 10; # if client stop responding, free up memory -- default 60 send_timeout 2; # server will close connection after this time -- default 75 keepalive_timeout 30; # number of requests client can make over keep-alive -- for testing environment keepalive_requests 100000; types_hash_max_size 2048; sendfile_max_chunk 512k; client_max_body_size 200M; location / { try_files $uri @app; } location @app { proxy_pass http://localhost:8081; 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_redirect off; 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 Proxy ""; } location /.well-known { alias /var/www/api.example.com/public/.well-known; } location /_next/static/ { alias /var/www/xmodels.info/.next/static/$1; access_log off; expires max; } location /static/ { alias /var/www/xmodels.info/static/$1; expires max; autoindex off; } } |
Admin
Let say our frontend code is in /var/www/admin.xmodels.info
folder and Frontend app is running under port 8082, add new file in /etc/nginx/sites-enabled/admin.xmodels.info
and content as bellow
You have to change with our server name and source code path
server { listen 80; server_name admin.xmodels.info; root /var/www/admin.xmodels.info/public; # cache informations about FDs, frequently accessed files # can boost performance, but you need to test those values open_file_cache max=200000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; # to boost I/O on HDD we can disable access logs access_log off; # copies data between one FD and other from within the kernel # faster than read() + write() sendfile on; # send headers in one piece, it is better than sending them one by one tcp_nopush on; # don't buffer data sent, good for small data bursts in real time tcp_nodelay on; # reduce the data that needs to be sent over network -- for testing environment gzip on; # gzip_static on; gzip_min_length 10240; gzip_comp_level 1; gzip_vary on; gzip_disable msie6; gzip_proxied expired no-cache no-store private auth; gzip_types # text/html is always compressed by HttpGzipModule text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml application/atom+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; # allow the server to close connection on non responding client, this will free up memory reset_timedout_connection on; # request timed out -- default 60 client_body_timeout 10; # if client stop responding, free up memory -- default 60 send_timeout 2; # server will close connection after this time -- default 75 keepalive_timeout 30; # number of requests client can make over keep-alive -- for testing environment keepalive_requests 100000; types_hash_max_size 2048; sendfile_max_chunk 512k; client_max_body_size 200M; location / { try_files $uri @app; } location @app { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $http_host; proxy_pass http://localhost:8082; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; } location /.well-known { alias /var/www/api.example.com/public/.well-known; } location /_next/static/ { alias /var/www/admin.xmodels.info/.next/static/$1; access_log off; expires max; } location /static/ { alias /var/www/admin.xmodels.info/static/$1; expires max; autoindex off; } } |
Testing
Open browser and access: http://yourdomain.com
to access web frontend
Open browser and access: http://admin.yourdomain.com
to access web admin
Run pm2 ls
to see your applications
Run pm2 stop [id]
to stop app or pm2 reload [id]
to reload
Run applications in start up by pm2 startup
then pm2 save
Check here to setup https with nginx
Setup https with Certbot nginx
From API root directory run yarn migrate
to seed default values for settings and users
Default admin: admin@[yourdomain]
with domain is in .env file
Default password: adminadmin
If admin password is wrong, you can run node script reset-admin-pw
to reset it to adminadmin
You can change default values in src > migrations
folder