# Установка exchanger-web

{% tabs %}
{% tab title="Docker" %}

#### Prepare dependencies

```bash
apt install -y nano sudo curl wget
apt update
apt upgrade -y
```

#### 1. Install Docker and Docker Compose

```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```

#### 2. Create runner user and add it to sudoers <a href="#user-content-2-create-runner-user-and-add-it-to-sudoers" id="user-content-2-create-runner-user-and-add-it-to-sudoers"></a>

```bash
sudo adduser --disabled-password --gecos "" runner
sudo usermod -aG sudo runner
```

#### 3. Create docker group and add user to it <a href="#user-content-3-create-docker-group-and-add-user-to-it" id="user-content-3-create-docker-group-and-add-user-to-it"></a>

```bash
sudo usermod -aG docker runner
```

#### 4. Switch to a 'runner' user <a href="#user-content-4-switch-to-a-runner-user" id="user-content-4-switch-to-a-runner-user"></a>

```bash
sudo su runner
```

```bash
newgrp docker
```

#### 5. Create docker network <a href="#user-content-10-create-docker-network" id="user-content-10-create-docker-network"></a>

```bash
docker network create --subnet 10.1.0.0/24 exchanger-net
```

#### 6. Docker login

* Create a Personal Access Token in GitLab
* Make sure to tick the `read_registry` permission scope
* Create a reminder to update the PAT after expiration date, as once it expires you lose access for updates.\
  <https://git.boxexchanger.net/-/profile/personal_access_tokens>
* Login to docker read\_registry

  <pre class="language-bash"><code class="lang-bash">docker login rg.boxexchanger.net

  <strong># Username: your_gitlab_username
  </strong># Password: your_gitlab_pat
  </code></pre>

#### 7. Create required folders <a href="#user-content-7-create-required-folders" id="user-content-7-create-required-folders"></a>

```bash
mkdir -p /home/runner/web_server
mkdir -p /home/runner/web_server/config
mkdir -p /home/runner/web_server/public
mkdir -p /home/runner/web_server/nginx
cd /home/runner/web_server
```

#### 8. Place basic nginx config `server_names_hash_bucket_size.conf` <a href="#user-content-8-copy-the-files-to-homerunnerapi_server" id="user-content-8-copy-the-files-to-homerunnerapi_server"></a>

<pre class="language-bash"><code class="lang-bash"><strong>nano /home/runner/web_server/nginx/server_names_hash_bucket_size.conf
</strong></code></pre>

with content:&#x20;

```nginx
server_names_hash_bucket_size 64;
```

#### 9. Place basic nginx config `nginx_default.conf` <a href="#user-content-8-copy-the-files-to-homerunnerapi_server" id="user-content-8-copy-the-files-to-homerunnerapi_server"></a>

<pre class="language-bash"><code class="lang-bash"><strong>nano /home/runner/web_server/nginx/nginx_default.conf 
</strong></code></pre>

with content:&#x20;

```nginx
server {
    listen 80 default_server;
    server_name _;
    return 500;
}
```

#### 10. Place Nginx `nginx_admin.conf` config <a href="#user-content-8-copy-the-files-to-homerunnerapi_server" id="user-content-8-copy-the-files-to-homerunnerapi_server"></a>

{% hint style="info" %}
If you are using separate server for web and api change proxy\_pass <http://nginx-api:3000/service/>  to **<http://ip.your.api.serveri:3000/service/>** and expose port 3000 from your api server
{% endhint %}

```bash
nano /home/runner/web_server/nginx/nginx_admin.conf
```

```nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

server {
    listen 80;
    server_name admin.domain.name;

    location / {
        proxy_pass http://exchanger-admin-web:80;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    
    location /service/ {
        proxy_pass http://nginx-api:3000/service/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    location /ws/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://nginx-api:3000/ws/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_redirect    off;
    }
    
    access_log off;
    error_log  /var/log/nginx-admin-error.log error;
    sendfile off;
    client_max_body_size 100m;
}
```

#### 11.  Place Nginx `nginx_web.conf` config <a href="#user-content-8-copy-the-files-to-homerunnerapi_server" id="user-content-8-copy-the-files-to-homerunnerapi_server"></a>

```bash
nano /home/runner/web_server/nginx/nginx_web.conf
```

```nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}
server {
    listen 80;
    server_name domain.name;
    return 301 https://www.domain.name$request_uri;
}

server {
    listen 80;
    server_name www.domain.name;
    location / {
        proxy_pass http://exchanger-client-web:80;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    location /service/ {
        proxy_pass http://nginx-api:3000/service/;
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    location /ref/ {
        proxy_pass http://nginx-api:3000/service/ref/;
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    location /ws/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://nginx-api:3000/ws/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_redirect    off;
    }
        
    access_log off;
    error_log  /var/log/nginx-error.log error;
    sendfile off;
    client_max_body_size 100m;
}
```

#### 12. Create config file (.env) <a href="#user-content-8-copy-the-files-to-homerunnerapi_server" id="user-content-8-copy-the-files-to-homerunnerapi_server"></a>

```bash
nano /home/runner/web_server/.env
```

```bash
VCS_NAMESPACE=bx4/project-name
```

{% hint style="info" %}
If you would like to setup your branch please add variable to your .env file&#x20;

&#x20;`CLIENT_BRANCH` for client-web and

&#x20;`ADMIN_BRANCH` for admin-web
{% endhint %}

#### 12.  Create your docker-compose.yml <a href="#user-content-8-copy-the-files-to-homerunnerapi_server" id="user-content-8-copy-the-files-to-homerunnerapi_server"></a>

<pre class="language-bash"><code class="lang-bash"><strong>nano /home/runner/web_server/docker-compose.yml
</strong></code></pre>

```yaml
version: '3'
services:
  nginx-web:
    image: nginxinc/nginx-unprivileged:1.27-alpine
    read_only: true
    container_name: nginx-web
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    logging: *default-logging
    networks:
      exchanger-net:
        ipv4_address: 10.1.0.250
    volumes:
      - ./nginx/:/etc/nginx/conf.d:ro
      - type: tmpfs
        target: /docker-entrypoint.d/
        tmpfs:
          size: "100000"
      - type: tmpfs
        target: /tmp/
        tmpfs:
          size: "10000000"
  exchanger-admin-web:
    image: rg.boxexchanger.net/${VCS_NAMESPACE}/exchanger-admin-web:${ADMIN_BRANCH:-master}
    container_name: exchanger-admin-web
    restart: unless-stopped
    networks:
      exchanger-net:
        ipv4_address: 10.1.0.5
  exchanger-client-web:
    image: rg.boxexchanger.net/${VCS_NAMESPACE}/exchanger-client-web:${CLIENT_BRANCH:-box}
    container_name: exchanger-client-web
    restart: unless-stopped
    networks:
      exchanger-net:
        ipv4_address: 10.1.0.4
networks:
    exchanger-net:
        external: true
```

#### 13.  Start WEB server

```bash
docker compose up -d
```

{% hint style="info" %}
All web configuration and request for build project you find in your personal account on our website <https://licence.boxexchanger.net/licenses/>
{% endhint %}

{% hint style="warning" %}
**Server Side Render**:&#x20;

* **Attention!** This mod is not recommended for use; it creates a load on the server to build the project for each client, which greatly increases the delay in loading the site

To enable SSR mode add variable **`SSR = 1`** in your account <https://licence.boxexchanger.net/licenses/> then run pipeline for build project and fetch build on your server.
{% endhint %}
{% endtab %}

{% tab title="Source" %}

## 1. Подготовка окружения

После установки сервера к нему необходимо подключиться по SSH и настроить окружение

#### Установить пакеты сервера (nano git curl)

<pre class="language-bash"><code class="lang-bash">apt update
apt upgrade -y
<strong>apt-get install -y curl git nano wget sudo
</strong></code></pre>

#### Установить  Nginx:&#x20;

```bash
apt-get install -y nginx
```

#### Установить NodeJS:

{% content-ref url="ustanovka-nodejs" %}
[ustanovka-nodejs](https://manual.boxexchanger.net/dlya-razrabotchikov/ustanovka-proekta/ustanovka-po/ustanovka-nodejs)
{% endcontent-ref %}

## 2. Скачать ПО на сервер

#### Создаем SSH-ключ

Документация с github.com [Создание нового ключа SSH](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)

Учебник по Linux

```bash
ssh-keygen -t rsa -b 4096
```

\> Enter x3

```bash
eval "$(ssh-agent -s)"
```

```bash
ssh-add ~/.ssh/id_rsa
```

Получить свой ключ:

```bash
cat ~/.ssh/id_rsa.pub
```

Скопируйте результат и установите данный ключ в своей учётной записи [git.boxexchanger.net](https://git.boxexchanger.net/-/profile/keys)&#x20;

{% content-ref url="../../dostup-k-iskhodnomu-kodu" %}
[dostup-k-iskhodnomu-kodu](https://manual.boxexchanger.net/dlya-razrabotchikov/dostup-k-iskhodnomu-kodu)
{% endcontent-ref %}

#### Клонируем репозитории

```bash
cd /var/www/
```

```bash
git clone git@ssh.boxexchanger.net:bx4/NAME_SPACE/exchanger-client-web.git
```

```bash
git clone git@ssh.boxexchanger.net:bx4/NAME_SPACE/exchanger-admin-web.git
```

## 3. Сборка админ панели

```bash
cd /var/www/exchanger-admin-web/
```

```bash
npm i
```

```bash
npm run configure
```

Сконфигурируйте конфигурацию:&#x20;

```bash
nano .env
```

```bash
ADMIN_BASE_URL="https://admin.domain.name"
EXCHANGE_URL="https://www.domain.name"
PROXY_REST_API="http://localhost:3010/"
```

Сборка проекта:

```bash
npm run generate
```

## 4. Сборка веб-панели

```bash
cd /var/www/exchanger-client-web/
```

```bash
npm i
```

```bash
npm run configure
```

Сконфигурируйте конфигурацию: (при возникновении затруднений обратитесь в техподдержку <support@boxexchanger.net>)

```bash
nano config/app.json
```

Сборка проекта:

```bash
npm run generate
```

## 5. Применяем Nginx конфигурацию

{% hint style="info" %}
Вам необходимо заменить&#x20;

* домен **domain.com**&#x20;
* админ домен: **admin.domain.com**
* IP адрес **API сервера**\
  при аренде он доступен в [личном кабинете](https://licence.boxexchanger.net/) пользователя\
  если у вас API находится на вашем сервере оставьте его `127.0.0.1`
  {% endhint %}

```bash
nano /etc/nginx/sites-enabled/domain.com.conf
```

{% code title="/etc/nginx/sites-enabled/domain.conf" lineNumbers="true" %}

```nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}
server {
    listen 80;
    server_name domain.com;    return 301 https://www.domain.com$request_uri;
}
server {
    listen 80;
    server_name www.domain.com;
    root "/var/www/exchanger-client-web";
    gzip on;
    gzip_comp_level 9;
    gzip_disable "msie6";
    gzip_types application/javascript text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    index index.html;
    charset utf-8;

    add_header "X-Frame-Options" "SAMEORIGIN";
    add_header "X-XSS-Protection" "1; mode=block";
    add_header "X-Content-Type-Options" "nosniff";

    location / {
        root /var/www/exchanger-client-web/dist/client;
        rewrite ^([^.]*[^/])$ $1/ permanent;
        try_files $uri $uri/ /200.html;
        # expires 7d;
    }
    access_log off;
    error_log  /var/www/exchanger-client-web/nginx-error.log error;
    sendfile off;
    client_max_body_size 100m;


    location /service/ {
        proxy_pass http://127.0.0.1:3010/;
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    location /ref/ {
        proxy_pass http://nginx-api:3010/ref/;
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }

    location /service/fs {
        alias /var/www/exchanger-api/public;
    }

    location /tg/ {
        proxy_pass http://127.0.0.1:3003/;
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }
    #location /service/fs {
    #    alias /var/www/exchanger-api/public;
    #}
    location /ws/ {
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://127.0.0.1:3011/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_redirect    off;
    }
}


server {
    listen 80;
    server_name admin.domain.com;
    root "/var/www/exchanger-admin-web";
    gzip on;
    gzip_comp_level 9;
    gzip_disable "msie6";
    gzip_types application/javascript text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    index index.html index.htm index.php;
    charset utf-8;

    add_header "X-Frame-Options" "DENY";
    add_header "X-XSS-Protection" "1; mode=block";
    add_header "X-Content-Type-Options" "nosniff";

    location / {
        root /var/www/exchanger-admin-web/dist/admin;
        try_files $uri $uri/ /index.html;
    }

    access_log off;
    error_log  /var/www/exchanger-admin-web/nginx-error.log error;
    sendfile off;
    client_max_body_size 100m;

    location /service/ {
        proxy_pass http://127.0.0.1:3010/;
        proxy_http_version 1.1;
        add_header CF-IPCountry $http_cf_ipcountry always;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }

    location /service/fs {
        alias /var/www/exchanger-api/public;
    }
}
```

{% endcode %}

Тестируем nginx конфигурацию:

```bash
nginx -t 
```

Применяем изменения:&#x20;

```bash
service nginx restart
```

{% endtab %}
{% endtabs %}
