xModel Lite Installation

xModel Lite Installation

I. Server Requirements

1. Web Server

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

II. Software Requirements

xModels architecture needs these softwares

Ensure all softwares above are running before setup source code

Install nodejs with nvm Install nodejs on Ubuntu Install Yarn Install mongoDB on Ubuntu Install FFMPEG on Ubuntu Install NGINX on Ubuntu

Testing

From command line / terminal please run these commands to check

1. NodeJS

$ node -v v12.16.2

2. MongoDB

$ mongo --version MongoDB shell version v4.0.7 git version: 1b82c812a9c0bbf6dc79d5400de9ea99e6ffa025 allocator: system modules: none build environment: distarch: x86_64 target_arch: x86_64

3. Redis Server

$ redis-server --version Redis server v=5.0.4 sha=00000000:0 malloc=libc bits=64 build=d4ba11298acbb366

4. FFMPEG

$ 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

5. NGINX

$ nginx -v nginx version: nginx/1.10.3

6. Pm2

$ pm2 -v [PM2] Spawning PM2 daemon with pm2_home=/Users/xxx/.pm2 [PM2] PM2 Successfully daemonized 4.4.0

7. Yarn

$ yarn -v 1.16.0

III. Setup and Test it Locally

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

1. API

  • 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. You should change with your key TOKEN_SECRET=qG4EjJ9xJzbfnvUKieJT # mongo connection string. check here https://docs.mongodb.com/manual/reference/connection-string/ MONGO_URI=mongodb://localhost/xmodels # redis server config # Redis connection string. Pattern redis[s]://[[username][:password]@][host][:port][/db-number] # DB-number is a integer number REDIS_URI=redis://127.0.0.1:6379/0 # redis prefix for queue service QUEUE_PREFIX=xmodels_queue_ # queue event service prefix QUEUE_EVENT_PREFIX=xmodels_queue_event_ MAILER_CONCURRENCY=2 TEMPLATE_DIR=templates # domain will be used to generate some data DOMAIN=example.com # public API URL BASE_URL=https://api.example.com # public front office URL USER_URL=https://example.com # redirect email after user clicks to verificaiton email link EMAIL_VERIFIED_SUCCESS_URL=https://example.com/auth/email-verified-success
  • Check Migration point to seed default

  • Run yarn start to start application

  • Open browsers and run http://localhost:8080 it should show success message or Hello World!

2. Frontend

  • Ensure nodejs and yarn are running

  • From frontend root directory run yarn insall --production=false to install nodeJS dependencies and dev 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

# API endpoint for server call. It can be public API or internal API API_SERVER_ENDPOINT=http://localhost:8080 # Public API endpoint, all API in client side will use this endpoint API_ENDPOINT=https://api.example.com # Socket endpoint, usually it is API public endpoint SOCKET_ENDPOINT=https://api.example.com
  • Run yarn start to start application

  • Then you can open browser http://localhost:8081 to see the web

  • Note: Do not run yarn dev because this minified version doesn't support

3. Admin 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

# API endpoint for server call. It can be public API or internal API API_SERVER_ENDPOINT=http://localhost:8080 # Public API endpoint, all API in client side will use this endpoint API_ENDPOINT=https://api.example.com # Socket endpoint, usually it is API public endpoint SOCKET_ENDPOINT=https://api.example.com # Public site (front office site). Use to generate URL SITE_URL=https://example.com # max size upload validate in client side MAX_SIZE_IMAGE=5 MAX_SIZE_FILE=100 MAX_SIZE_TEASER=200 MAX_SIZE_VIDEO=2000
  • Run yarn start to start application

  • Then you can open browser http://localhost:8082 to see the web

  • Note: Do not run yarn dev because this minified version doesn't support

IV. Setup and setup production environment with nginx and pm2

1. API

  • Make sure you have installed nodeJS dependencies by yarn install command. Configure it like local setup, pm2 was installed

  • In API root directory run pm2 start yarn --interpreter bash --name api.example.com -- start to run application under port 8080

Note: If have error when starting with Pm2, please try to start without interpreter

pm2 start yarn --name api.example.com -- start

2. Frontend Web

  • cd user web folder

  • Make sure you have installed nodeJS dependencies by yarn install command. Configure it like local setup, pm2 was installed

  • Run pm2 start yarn --interpreter bash --name api.example.com -- start to run application under port 8081. You can change port in package.json in start script

Note: If have error when starting with Pm2, please try to start without interpreter

pm2 start yarn --name example.com -- start

3. Admin Web

  • cd user admin folder

  • Make sure you have installed nodeJS dependencies by yarn install command. Configure it like local setup, pm2 was installed

  • Run pm2 start yarn --interpreter bash --name admin.example.com -- start to run application under port 8082. You can change port in package.json in start script

Note: If have error when starting with Pm2, please try to start without interpreter

pm2 start yarn --name admin.example.com -- start

4. Setup Nginx

a. API

  • Let say our frontend code is in /var/www/api.example.com folder and api is running under port 8080, add new file in /etc/nginx/sites-enabled/api.example.com and content as bellow

  • You have to change with our server name and source code path

server { listen 80; root /var/www/api.example.com/public; index index.html; server_name api.example.com; gzip on; gzip_proxied any; gzip_comp_level 4; gzip_types text/css application/javascript image/svg+xml; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; sendfile_max_chunk 512k; client_max_body_size 5000M; access_log off; error_log off; location / { try_files $uri @app; } location @app { proxy_set_header proxy_set_header proxy_pass proxy_set_header proxy_set_header proxy_cache_bypass $http_upgrade; # WebSocket support proxy_connect_timeout 1d; proxy_send_timeout 1d; proxy_read_timeout 1d; } location /.well-known { alias /var/www/api.example.com/public/.well-known; } location /videos/protected/ { auth_request /authvideo; root /var/www/api.example.com/public/; } location = /authvideo { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/assets/videos/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header range ""; } location /photos/protected/ { auth_request /authphoto; root /var/www/api.example.com/public/; } location = /authphoto { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/assets/photos/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header range ""; } location /digital-products/protected { auth_request /authproduct; root /var/www/api.example.com/public/; } location = /authproduct { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/assets/products/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header range ""; } location /stories/protected/ { auth_request /authstory; root /var/www/api.example.com/public/; } location = /authstory { internal; set $query ''; if ($request_uri ~* "[^\?]+\?(.*)$") { set $query $1; } proxy_pass http://localhost:8080/stories/auth/check?$query; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header range ""; } }

b. Frontend

  • Let say our frontend code is in /var/www/example.com folder and Frontend app is running under port 8081, add new file in /etc/nginx/sites-enabled/example.com and content as bellow

  • You have to change with our server name and source code path

server { listen 80; server_name example.com; root /var/www/example.com/public; 6 gzip on; gzip_proxied any; gzip_comp_level 4; gzip_types text/css application/javascript image/svg+xml; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; sendfile_max_chunk 512k; # tuning performance for log request access_log off; error_log off; 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 proxy_set_header proxy_set_header proxy_set_header proxy_set_header } location /.well-known { alias /var/www/example.com/public/.well-known; } location /_next/static/ { alias /var/www/example.com/dist/.next/static/$1; access_log off; expires max; } }

c. Admin

  • Let say our frontend code is in /var/www/admin.example.com folder and Frontend app is running under port 8082, add new file in /etc/nginx/sites-enabled/admin.example.com and content as bellow

  • You have to change with our server name and source code path

server { listen 80; server_name admin.example.com; root /var/www/admin.example.com/public; gzip on; gzip_proxied any; gzip_comp_level 4; gzip_types text/css application/javascript image/svg+xml; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; sendfile_max_chunk 512k; access_log off; error_log off; location / { try_files $uri @app; } location @app { proxy_set_header proxy_set_header proxy_pass proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; } location /.well-known { alias /var/www/admin.example.com/public/.well-known; } location /_next/static/ { alias /var/www/admin.example.com/dist/.next/static/$1; access_log off; expires max; } }

d. Testing

  • Open browser and access: http://yourdomain.com to access web frontend

  • Open browser and access: http://admin.yourdomain.com to access web admin

5. Check applications are running under pm2

  • 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

6. Set up nginx with https

7. Migration

  • 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