.. contents:: :local: .. _configure-fleio-reseller: =========================================================== How to configure the reseller panel on different subdomains =========================================================== Enable reseller feature ----------------------- First, we will need to enable the reseller feature. To do that please check :ref:`enable-reseller-feature`. Fleio settings.py changes ------------------------- In settings.py we need to allow the reseller's subdomains to connect to the Fleio backend. For this guide, we will use the following setup: Fleio installation URL: * portal.fleio.com Reseller urls: * reseller.fleio.com * reseller2.fleio.com Notice that the cookie domain will be the top level domain (in our case fleio.com). Run the `fleio edit settings.py` command and add the following code at the end of your settings.py file. .. code-block:: python NEW_MIDDLEWARE = list(MIDDLEWARE) NEW_MIDDLEWARE.insert(1, 'corsheaders.middleware.CorsMiddleware') NEW_MIDDLEWARE.insert(1, 'fleio.csrf_reseller_pass.CsrfMid') MIDDLEWARE = tuple(NEW_MIDDLEWARE) RESELLER_DOMAINS = { 'reseller.fleio.com': { 'url': 'http://reseller.fleio.com', 'cookie_domain': 'fleio.com', }, 'portal.fleio.com': { 'url': 'http://reseller.fleio.com', 'cookie_domain': 'fleio.com', }, 'reseller2.fleio.com': { 'url': 'http://reseller2.fleio.com', 'cookie_domain': 'fleio.com', }, 'portal.fleio.com': { 'url': 'http://reseller2.fleio.com', 'cookie_domain': 'fleio.com', }, } CORS_ORIGIN_WHITELIST = ( 'http://portal.fleio.com', 'http://reseller.fleio.com', 'http://reseller2.fleio.com', ) CORS_ALLOW_CREDENTIALS = True CSRF_TRUSTED_ORIGINS = ['http://portal.fleio.com'] for domain in RESELLER_DOMAINS: CORS_ORIGIN_WHITELIST += (RESELLER_DOMAINS[domain]['url'],) CSRF_TRUSTED_ORIGINS.append(domain) ALLOWED_HOSTS.append(domain) For each new domain you will have to add a new entry in the RESELLER_DOMAINS dictionary, with the following syntax: .. code-block:: python ... 'reseller3.fleio.com': { 'url': 'http://reseller3.fleio.com', 'cookie_domain': 'fleio.com', }, 'portal.fleio.com': { 'url': 'http://reseller3.fleio.com', 'cookie_domain': 'fleio.com', }, Additionally, you need to add the reseller domains in the `ALLOWED_HOSTS` list. On exit, when you will be asked to restart Fleio, answer with "N". We will restart later. Fleio web configuration ----------------------- Before digging into adding custom configuration to the fleio_web_1 container, please read the following docs: * :ref:`web-conf` * :ref:`docker_deploy_notes` First we will create a new directory where we will place our updated web.conf.template file. All these needs to be done while using the fleio user: .. code-block:: bash sudo -i -u fleio mkdir /home/fleio/compose/custom-web Create the custom-web Dockerfile and add the updated file .. code-block:: bash touch /home/fleio/compose/custom-web/Dockerfile touch /home/fleio/compose/custom-web/web.conf.template In the Dockerfile add the following: .. code-block:: none ARG FLEIO_DOCKER_HUB ARG FLEIO_RELEASE_SUFFIX FROM ${FLEIO_DOCKER_HUB}/fleio_web${FLEIO_RELEASE_SUFFIX} COPY web.conf.template /etc/nginx/templates/web.conf.template The web.conf.template must be configured different, depending on the FLEIO_SSL_OPTION. Please check the variable in `/home/fleio/compose/.env` and use the proper template: .. important:: Notice that all resellers have different and unused ports. Reseller 1 will use the 9001 port, while reseller 2 will use 9002 port Remember the ports because we will need them in the next step. no_ssl ~~~~~~ .. code-block:: none server { listen 8080; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name ${FLEIO_DOMAIN}; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } location / { proxy_pass http://frontend:9000; proxy_redirect http://$host:9000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } # reseller 1 server { listen 8080; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller.fleio.com; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } location / { proxy_pass http://reseller:9001; proxy_redirect http://$host:9001 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } # reseller 2 server { listen 8080; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller2.fleio.com; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } location / { proxy_pass http://reseller2:9002; proxy_redirect http://$host:9002 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } own_ssl ~~~~~~~ .. code-block:: none server { listen 8080; server_name ${FLEIO_DOMAIN}; location / { return 301 https://$host$request_uri; } } server { listen 4430 ssl; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name ${FLEIO_DOMAIN}; ssl_certificate /var/webapps/fleio/ssl/${FLEIO_DOMAIN}/ssl.crt; ssl_certificate_key /var/webapps/fleio/ssl/${FLEIO_DOMAIN}/ssl.key; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://frontend:9000; proxy_redirect http://$host:9000 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } } # reseller 1 server { listen 4430 ssl; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller.fleio.com; ssl_certificate /var/webapps/fleio/ssl/reseller.fleio.com/ssl.crt; ssl_certificate_key /var/webapps/fleio/ssl/reseller.fleio.com/ssl.key; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://reseller:9001; proxy_redirect http://$host:9001 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } } # reseller 2 server { listen 4430 ssl; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller2.fleio.com; ssl_certificate /var/webapps/fleio/ssl/reseller2.fleio.com/ssl.crt; ssl_certificate_key /var/webapps/fleio/ssl/reseller2.fleio.com/ssl.key; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://reseller2:9002; proxy_redirect http://$host:9002 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } } lets_encrypt ~~~~~~~~~~~~ .. code-block:: none server { listen 8080; server_name ${FLEIO_DOMAIN}; location / { return 301 https://$host$request_uri; } } server { listen 4430 ssl; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name ${FLEIO_DOMAIN}; ssl_certificate /etc/letsencrypt/live/${FLEIO_DOMAIN}/ssl.crt; ssl_certificate_key /etc/letsencrypt/live/${FLEIO_DOMAIN}/ssl.key; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://frontend:9000; proxy_redirect http://$host:9000 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } } # reseller 1 server { listen 4430 ssl; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller.fleio.com; ssl_certificate /var/webapps/fleio/ssl/reseller.fleio.com/ssl.crt; ssl_certificate_key /var/webapps/fleio/ssl/reseller.fleio.com/ssl.key; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://reseller:9001; proxy_redirect http://$host:9001 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } } # reseller 2 server { listen 4430 ssl; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller2.fleio.com; ssl_certificate /var/webapps/fleio/ssl/reseller2.fleio.com/ssl.crt; ssl_certificate_key /var/webapps/fleio/ssl/reseller2.fleio.com/ssl.key; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location /backend { include /etc/nginx/uwsgi_params; proxy_pass http://backend:8000; proxy_redirect http://$host:8000 http://$host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://reseller2:9002; proxy_redirect http://$host:9002 http://$host; 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_buffering off; proxy_request_buffering off; proxy_read_timeout 150s; } } Resellers configuration ----------------------- Now we will need to create a new directory for each reseller, in the /home/fleio/compose directory: .. code-block:: bash # if you're not using the fleio user: sudo -i -u fleio mkdir /home/fleio/compose/reseller.fleio.com mkdir /home/fleio/compose/reseller2.fleio.com In these new directories, we will have to: * create new directories which will contain the enduser and reseller configuration files (these will be mapped as volumes) * define a new reseller image * add the nginx configuration file for the reseller's domain Create the needed directories: .. code-block:: bash #if you're not using the fleio user: sudo -i -u fleio mkdir -p /home/fleio/compose/reseller.fleio.com/enduser/assets/config/ mkdir -p /home/fleio/compose/reseller.fleio.com/reseller/assets/config/ mkdir -p /home/fleio/compose/reseller.fleio.com/site/constants/ Create the Dockerfile and the reseller.fleio.com.conf file: .. code-block:: bash #if you're not using the fleio user: sudo -i -u fleio touch /home/fleio/compose/reseller.fleio.com/Dockerfile touch /home/fleio/compose/reseller.fleio.com/reseller.fleio.com.conf Add the following code in the Dockerfile: .. code-block:: none ARG FLEIO_DOCKER_HUB ARG FLEIO_RELEASE_SUFFIX FROM ${FLEIO_DOCKER_HUB}/fleio_frontend${FLEIO_RELEASE_SUFFIX} COPY reseller.fleio.com.conf "/etc/nginx/conf.d/reseller.fleio.com.conf" Add the following code in the reseller.fleio.com.conf file. Make sure to configure the proper port on the **listen 9001** line: .. code-block:: none server { listen 9001; client_max_body_size 5000m; add_header X-Frame-Options "SAMEORIGIN"; server_name reseller.fleio.com; location /images { alias /var/webapps/fleio/frontend/site/images/; break; } location /js { alias /var/webapps/fleio/frontend/site/js/; expires max; break; } location /vendor { alias /var/webapps/fleio/frontend/site/vendor/; expires max; break; } location /styles { alias /var/webapps/fleio/frontend/site/styles/; expires max; break; } location /reseller { alias /var/webapps/fleio/frontend/reseller/; expires -1; try_files $uri $uri/ /../reseller/index.html; } location /tinymce { alias /var/webapps/fleio/frontend/staff/tinymce/; break; } location /static { alias /var/webapps/fleio/frontend/backendstatic/; break; } location /new { alias /var/webapps/fleio/frontend/enduser/; expires -1; try_files $uri $uri/ /../enduser/index.html; } location / { alias /var/webapps/fleio/frontend/site/; expires -1; try_files $uri $uri/ /index.html; } } Now we need to add the enduser / reseller panel configuration files: .. important:: Notice that the ``backendApiUrl`` is the main Fleio URL. Angular enduser: .. code-block:: bash vi /home/fleio/compose/reseller.fleio.com/enduser/assets/config/enduser.config.json And add the code from bellow. .. code-block:: none { "urls": { "backendApiUrl": "//panel.fleio.com/backend/api/", "homeName": "enduser", "angularJsPanelUrl": "//reseller.fleio.com/", "resellerUrl": "/reseller" }, "settings": { "defaultLanguage": "en", "imagesPath": "assets/img/enduser/", "logoDark": null, "logoLight": null, "defaultTheme": "spring", "availableThemes": [ "spring", "navy", "dusk" ], "instanceForm": { "hideNetworksIfOnlyOneAvailable": true, "preselectPublicNetworks": true, "showUserData": true, "flavorsAsCards": false, "showRootPasswordField": true, "rootPasswordFieldMandatory": false, "hideVolumeSelectionForFlavorsWithDisk": false, "defaultVolumeType": null, "reseller_client_id": null }, "logoutRedirect": null, "usernameInputLabel": null } } Angular JS enduser (will be removed soon, but as of 2021.06.1 this is still needed): .. code-block:: bash vi /home/fleio/compose/reseller.fleio.com/site/constants/constants.js .. code-block:: none // Global end-user panel configuration 'use strict'; var user_config = { api_url: 'http://fleio.reseller.com/backend/api', language: 'en', // default language base_url: '/', home_url: '/', angularPanelUrl: 'http://reseller.fleio.com/new/', // logo_light: 'https://fleio.com/images/logo.png', // logo_dark: 'https://fleio.com/images/logo.png', // shutdown_instance_note: "NOTE: The instance will continue to be charged even if it's shutdown. Delete the instance if you want to no longer be charged.", // toast_hide_delay: 3000, // bottom-left toast message animation delay in milliseconds items_display_mode: 'cardview', //cardview || listview enable_debug: true, // set to true in development to enable angular debug flavors_as_cards: false, // used on instance creation for flavors selector layout local_compute_storage_enabled: true, // used on instance create on boot source selection preselect_public_networks: true, // preselects networks with public tag on instance creation form hide_networks_if_only_one_available: true, // if there is only one network available on the instance creation form, preselect it and hide the input field show_root_password_field_on_new_instance_form: true, root_password_mandatory_on_new_instance_form: false, show_userdata_on_new_instance_form: true, hide_volume_selection_for_flavors_with_disk: false, default_volume_type_on_new_instance_form: null, // dict, with keys as region names and value as volume type names // example default_volume_type_on_new_instance_form // default_volume_type_on_new_instance_form: { // 'RegionOne': 'SSD', // }, customThemesCallback: function(mdThemingProvider) { // read the docs on how to define new themes }, registeredThemes: ['Spring', 'Navy', 'Dusk'], // list of themes that can be used by a user new_object_arrow_img_source: 'images/arrow.png', logout_redirect: null, username_input_label: null, reseller_client_id: null, }; try { angular.module('fleio.config').constant('CONFIG', user_config); } catch (err) { angular.module('fleiostaff.config').constant('USER_CONFIG', user_config); } Reseller panel: .. code-block:: none vi /home/fleio/compose/reseller.fleio.com/reseller/assets/config/reseller.config.json Add the code from bellow: .. code-block:: none { "urls": { "backendApiUrl": "//fleio.reseller.com/backend/resellerapi/", "homeName": "reseller" }, "settings": { "defaultLanguage": "en", "imagesPath": "assets/img/reseller/", "logoDark": null, "logoLight": null, "defaultTheme": "spring", "availableThemes": [ "spring", "navy", "dusk" ], "instanceForm": { "hideNetworksIfOnlyOneAvailable": true, "preselectPublicNetworks": true, "showUserData": true, "flavorsAsCards": false, "showRootPasswordField": true, "rootPasswordFieldMandatory": false, "hideVolumeSelectionForFlavorsWithDisk": false, "defaultVolumeType": null }, "logoutRedirect": null, "usernameInputLabel": null } } Repeat the previous steps for as many resellers as you want. Define docker-compose services and map volumes ---------------------------------------------- Lastly, we need to define the new docker-compose services and we need to map the configuration files in the reseller service: .. code-block:: bash #if you're not using the fleio user: sudo -i -u fleio cd /home/fleio/compose Add this to the docker-compose.override.yml file: .. code-block:: none services: # redefine web service to include the custom web.conf.template file web: build: context: ./custom-web/ dockerfile: Dockerfile args: - FLEIO_DOCKER_HUB - FLEIO_RELEASE_SUFFIX image: fleio_custom_web # define a new reseller service for each of your resellers reseller: build: context: ./reseller.fleio.com/ dockerfile: Dockerfile args: - FLEIO_DOCKER_HUB - FLEIO_RELEASE_SUFFIX image: fleio_reseller_1 restart: always volumes: - /home/fleio/compose/reseller.fleio.com/site/constants:/var/webapps/fleio/frontend/site/constants - /home/fleio/compose/reseller.fleio.com/enduser/assets/config:/var/webapps/fleio/frontend/enduser/assets/config/ - /home/fleio/compose/reseller.fleio.com/reseller/assets/config:/var/webapps/fleio/frontend/reseller/assets/config/ reseller2: build: context: ./reseller2.fleio.com/ dockerfile: Dockerfile args: - FLEIO_DOCKER_HUB - FLEIO_RELEASE_SUFFIX image: fleio_reseller2_1 restart: always volumes: - /home/fleio/compose/reseller2.fleio.com/site/constants:/var/webapps/fleio/frontend/site/constants - /home/fleio/compose/reseller2.fleio.com/enduser/assets/config:/var/webapps/fleio/frontend/enduser/assets/config/ - /home/fleio/compose/reseller2.fleio.com/reseller/assets/config:/var/webapps/fleio/frontend/reseller/assets/config/ Build and publish ----------------- Finally, we will need to build all our changes and to create the new containers based on the changes added in the docker-compose-override file. .. code-block:: none fleio build fleio recreate If you run the ``fleio status`` command you should now see the new reseller services up and running. The reseller panel should also be available at the configured domains.