Follow us

Python & React Hosting On Ubuntu/Linux Machine

On React and Python related hosting, I had multiple questions in my mind which I wanted to find like:

  • How I can host on Linux/Ubuntu machine as production build code?
  • How I can configure domain url for my Python service and React application?
  • How I can configure SSL certificate for the same?
  • How I can run Python service on custom port instead of 80 or 443 like 5001, 5002 etc.?
  • How I can use SSL certificate for my custom port domain url like 5001, 5002 port?, so that service still should work on https url but with custom port.
  • How auto start my Python service and React app when system/server reboot via creating systemctl command for my Services/Apps?
  • How to automate running Services/Apps via single bash script(.ssh) file.

 

So below are the answers of all above questions.

 

## I have created one ec2 ubuntu machine.

## Login to ec2 via SSH

 

#Install/update required ubuntu system packages

sudo apt update

 

##install python3 to work with python

sudo apt-get install python3

 

##install python3-pip to work wit python packages

sudo apt-get install python3-pip

 

##install python flask using pip to work with flak api

pip3 install flask

 

##install nginx to host python api

sudo apt install nginx

 

##create folder to store python code base for your first service

mkdir python-service1

 

##move to directory you created above

cd python-service1

 

##create python default run file name as "__init__.py"

sudo nano __init__.py

 

##copy and paste below content into file and save and exit.

from flask import Flask, jsonify

 

app = Flask(__name__)  ##note - this "app" instance used below with gunicorn command to run it

 

@app.route("/")  # this sets the route to this page

def home():

return jsonify({'Message': "Testing"})

 

if __name__ == "__main__":

app.run()

 

 

-------creating/setting nginx configuration start-------------

##This all steps for "creating/setting nginx configuration" is only required, when you are suppose to run with 80 port using below given run command in trial like "gunicorn -w 3 python-service1:app". So it will actually forward your request of 80 port into nginx default proxy and your service will be accessible on 80 or mapped port in config file.

##So if you are running your service with providing port with gunicorn command like to run using given below run command in trial like "gunicorn --bind 0.0.0.0:5000 python-service1:app", then you do not required all these steps and you can skip this.

##create/setup nginx configuration name as "python-service1" (NOTE - NAME COULD BE ANYTHING) to run listen port of your server/machine, so with below, it will be accessible on 80 port with your public server ip.

##below "proxy_pass" – This directive specifies the proxied server’s address. It tells NGINX to pass every request to the proxied application on http://127.0.0.1:8000.

 

##create nginx configuration file

sudo nano /etc/nginx/sites-enabled/python-service1

 

##copy and paste below content and save and exit

server {

listen 80;

server_name 13.233.38.236; ##note - here ip "13.233.38.236" is your server machine ip where this code is being run

 

location / {

proxy_pass http://127.0.0.1:8000##this is default proxy url of nginx, so all public request redirect through this. even you change port, it will still use 8000

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

}

 

##unlink default nginx configuration, so that it will use new configuration you created above.

sudo unlink /etc/nginx/sites-enabled/default

 

##reload nginx, so that it will refresh setup and use new configuration you created above.

sudo nginx -s reload

 

##restart nginx server

sudo systemctl restart nginx

 

-------creating/setting nginx configuration end-------------

 

##install gunicorn to run flak service via nginx server instead of using "run python __init__.py", becuase it does not work well on prod environment to handle load/traffic

sudo apt-get install gunicorn

 

##Run the flask web app with gunicorn by providing your service folder name. The name of your flask instance must be app, so you can see same above with __init__.py file.

##run below command from location where your service folder you created above i.e. "python-service1" exists as you are using same into below command.

##where "-w 3" means worker count is 3, and in general count we provide as [((no. of your machine core cpu) * 2) + 1].

##with below command "python-service1:app", where "python-service1" is your python service code base folder and "app" is the instance you are using inside your python file to run.

##And also with below command, I am not giving name of any python file, as my run file name is "__init__.py", which is default python run file.

gunicorn -w 3 python-service1:app

 

##Now navigate to your servers public ip from a web browser to test your service:

http://13.233.38.236/

 

##WITH ABOVE EXAMPLE, IT WILL RUN IN PUBLIC IP AND 80 PORT, NOW IF YOU WANT TO RUN YOUR APPLICATION ON DIFFERENT PORT THEN YOU CAN USE COMMAND LIKE BELOW

##SO NOW, YOU WILL BE ABLE TO ACCESS YOUR SERVICE ON 5000 PORT

##SO EVEN SAME SERVICE/APPLICATION YOU CAN RUN ON MULTIPLE PORTS

gunicorn --bind 0.0.0.0:5000 python-service1:app

 

##NOTE - HERE WITH THIS DEMO, AFTER YOU CLOSE Linux TERMINAL WINDOW, WEBSITE WILL STOP AND TO FIX THAT, YOU NEED TO USE "SCREEN" COMMAND WITH "JUNICORN" COMMAND AS PREFIX AND RUN SAME LIKE BELOW:

screen gunicorn -w 3 python-service1:app

 

##To kill/stop all the running gunicorn instances

pkill gunicorn

or

pkill -f gunicorn

 

 

******************************************************************

**************************other demo******************************

##with above example, I am using "__init__.py" file to run, but if I have different naming of file. so to run that, check the below demo.

##can i run multiple service on different port on same server? and the answer is yes and for that, you simply open new terminal and do below steps.

******************************************************************

 

##from user home directory, create new code repository service folder

mkdir python-service2

 

##move to above created new service folder

cd python-service2

 

##create app.py file where having initialization of your python code base and endpoints

sudo nano app.py

 

##copy and paste below code and save and exit

from flask import Flask

 

app = Flask(__name__)  ##this app instance will be used with gunicorn to run

 

@app.route('/')

def hello_world():

return jsonify({'Message': "Testing service 2"})

 

if __name__ == '__main__':

app.run(debug=True,host='0.0.0.0')

 

##create run.py file where I am running above app.py file

sudo nano run.py

 

from app import app

 

if __name__ == "__main__":

app.run()

 

##now use below command to run my python file i.e. "run.py"

##make sure you run below command from inside the service repository polder you created above and your both above python file exists inside i.e. "python-service2", becuase with below command you are using it.

##here "run:app" used like, "run" is your run.py file naving you created above and "app" is the instance you created with first file to run.

gunicorn --bind 0.0.0.0:5001 run:app

 

##Now navigate to browser and access url with 5001 port with your server public ip like:

http://13.233.38.236:5001/

 

 

******************************************************************

**************************other demo******************************

##with above both examples, I am using "gunicorn" to run python service/app. Now if you want to run simple you run on your local system like "python run.py" and it start with port you have set with your run.py file.

##Althought, this you should not do it for production, as even you run this, it will give you warning as well, because it does not handle load/traffic.

##Also, when you do this demo, then you do not need gunicorn at all on your system, so you can do this programming without gunicorn.

##Now, let see, how we can do this, with below steps.

******************************************************************

 

##from user home directory, create new code repository service folder

mkdir PythonService3

 

##move to above created new service folder

cd PythonService3

 

##create app.py file where having initializatoin of your python code base and endpoints

sudo nano app.py

 

##copy and paste below code and save and exit

from flask import Flask

 

app = Flask(__name__)

 

@app.route('/')

def hello_world():

return jsonify({'Message': "Testing service 3"})

 

if __name__ == '__main__':

app.run(debug=True,host='0.0.0.0')

 

##create run.py file where I am running above app.py file

sudo nano run.py

 

from app import app

 

if __name__ == "__main__":

app.run(host="0.0.0.0",port=5003)

 

##now use below command to run my python file i.e. "run.py"

##make sure you run below command from inside the service repository polder you created above and your both above python file exists inside i.e. "PythonService3", becuase with below command you are using it run.py file.

python3 run.py

 

##Now navigate to browser and access url with 5003 port with your server public ip like: http://13.233.38.236:5003/

 

 

******************************************************************************************************************

##NOW: How we can run above service via bash .sh file:

##below bash script taking above PythonService3 where, service is running with port given with run.py file in code base itself.

##tmux details, used with below example, able to run multiple session/window: https://www.redhat.com/sysadmin/introduction-tmux-linux

*******************************************************************************************************************

 

##create ssh file

sudo nano scripts/python_run.sh

 

#####save below content into file and save and exit

#!/bin/bash

 

echo

go_to_PythonService3(){

cd /home/ubuntu/PythonService3

}

 

echo "Killing tmux sessions..."

tmux kill-session -t PythonService3

 

go_to_PythonService3

 

echo "Start PythonService3"

tmux new-session -d -s PythonService32 \; send-keys 'python3 run.py' Enter

 

##to run .sh file on linux

bash script-name-here.sh

 

###navigate to browser and use same above example url to test

 

 

*****************************************************************************************

##Now how we can automate this to run through "systemctl service", so that whenever system reboot, then still your service is running. AND

## similarly, or you want to start, stop service, by "systemctl service" command.

##below bash script taking above PythonService3 where, service is running with port given with run.py file in code base itself.

*****************************************************************************************

 

##create systemctl service file

sudo nano /lib/systemd/system/python_run2.service

 

##copy and paste below content and save and exit

[Unit]

Description=Python 3 service

After=multi-user.target

 

[Service]

Type=simple

#WorkingDirectory=/home/ubuntu/PythonService3

ExecStart=/usr/bin/python3 /home/ubuntu/PythonService3/run.py -k start -DFOREGROUND

ExecStop=/usr/bin/python3 /home/ubuntu/PythonService3/run.py -k graceful-stop

Restart=Always

User=ubuntu

#PrivateTmp=true

#LimitNOFILE=infinity

#KillMode=mixed

 

[Install]

WantedBy=multi-user.target

 

 

##run this command to reload systemctl. You need this when you are making change to existing file, so first you stop that service and then reload. Note - first time you do not need this command.

sudo systemctl stop python_run2

sudo systemctl daemon-reload

 

##now enable systemctl for your service, so that it will auto run on server/system reboot/restart

sudo systemctl enable python_run2

 

##now to start service

sudo systemctl start python_run2

 

##to check status of your service

sudo systemctl status python_run2

 

##or to get more detailed status of your service

journalctl -xeu python_run2.service

 

##to stop your service

sudo systemctl stop python_run2

 

##NOTE - WHILE YOU RUN YOUR SERVICE VIA SYSTEMCTL AND CHECKING STATUS, IF YOU GET SESSION OUT RELATED ERROR, THEN USE BELOW COMMAND

 

##OPEN FILE

sudo nano /etc/pam.d/sudo

 

##ADD BELOW LINE FOR YOUR USER, like with below command user is "ubuntu"

session [success=1 default=ignore] pam_succeed_if.so quiet uid = 0 ruser = ubuntu

 

 

*****************************************************************************************

##Now how we can configure domain url to the application hosted on machine and running with IP.

##With all above example, you able to run/test your application with server ip like "http://13.233.38.236:5003/"

##To configure domain, I have considered above "PythonService3" application which is already running with machine ip and on port 5003.

*****************************************************************************************

 

##create hosting config file or even you can modify existing default file as well, but you can create multiple files and then link those files. So here I am creating new file:

sudo nano /etc/nginx/sites-available/custom_hosting

 

##copy and paste below content and save and exist. With below, I am actually pointing url on 80 port which will run local host running application on port 5003.

##So part of this example, you need to make sure, your application is already running with machine ip and on port "5003". This I have taken example from above demo "PythonService3" which is already running on same port.

##Also with below I am mapping my domain url "linuxhosttest-a.test.com", so make sure this url is mapped with your machine public ip into domain provider like godaddy.

server {

listen 80;

server_name linuxhosttest-a.test.com; ##here domain url is mapped and IP of this server should map with domain provider like godaddy

location / {

proxy_set_header Host $host;

proxy_pass http://127.0.0.1:5003##this is the actual application which is running on this server on given port

proxy_redirect off;

}

}

 

##Now link above created file into ngnix sites-enabled.

sudo ln -s /etc/nginx/sites-available/custom_hosting /etc/nginx/sites-enabled

 

 

##Reaload ngnix server, so that it able to pick/user new hosting configuration

sudo nginx -s reload

 

##now you should be able to use your domain url

 

 

 

*****************************************************************************************

##Now how we can configure ssl-certificate for your above hosted domain url, so that you able to use https url like "https://linuxhosttest-a.test.com".

##To configure domain, I have considered above "PythonService3" application with domain hosted already.

##So make sure, before going through below steps, you are alrea able to access your application via http domain url like "http://linuxhosttest-a.test.com".

*****************************************************************************************

 

###NOTE - Doc ref having below steps: https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal

 

##SSH into the your Ubuntu server

 

##Install snapd

sudo apt update

sudo apt install snapd

 

##To test your system, install the hello-world snap and make sure it runs correctly:

 

$ sudo snap install hello-world

##NOTE - with above command, it will result like - hello-world 6.4 from Canonical installed

$ hello-world

##NOTE - with above command, it will result like - Hello World!

 

##Ensure that your version of snapd is up to date

sudo snap install core; sudo snap refresh core

 

##Remove certbot-auto and any Certbot OS packages

##If you have any Certbot packages installed using an OS package manager like apt, dnf, or yum, you should remove them before installing the Certbot snap to ensure that when you run the command certbot the snap is used rather than the installation from your OS package manager.

sudo apt-get remove certbot, sudo dnf remove certbot, or sudo yum remove certbot.

 

##Install Certbot

sudo snap install --classic certbot

 

##Prepare the Certbot command

##Execute the following instruction on the command line on the machine to ensure that the certbot command can be run

sudo ln -s /snap/bin/certbot /usr/bin/certbot

 

##Run this command to get a certificate and have Certbot edit your nginx configuration automatically to serve it, turning on HTTPS access in a single step.

##Here when you run below command, it will ask you few questions like email id for notification, which hosted url you want to create certificate etc.

sudo certbot --nginx

 

##After this step, your url should be avaialble on https. FYI - next time to configure https/ssl-certificate on for new url on same server, you just need to run above last step i.e. "sudo certbot --nginx".

 

##with above command i.e. "sudo certbot --nginx", when you run, it automatically generate certificate for your url and also update your nginx ssl configuration, so that your application is accessible via https and you do not need to do any manual steps. Although if you have own own private certificate, then you will have to do this manual. 

 

*****************************************************************************************

##As per above example, you are able to run your python service on https url with ssl certifiate, but let say if you want to run same service on https with certifiate but with custom port, so that if you want to whitelist public IPs to have access that port, then, how we can do it? - so let say, I want to run same above service with port 5002, i.e. "https://linuxhosttest-a.test.com:5002".

##To do this, I have considered just above same application with domain https/ssl hosted, so your domain url is already accessible with https i.e. "https://linuxhosttest-a.test.com" and now I want to configure another url with 5002 port but with https.

##We just simply need to add one more configuraiton and will copy/paste same ssl certificate config details as per above example.

*****************************************************************************************

 

##run below command to open and modify nginx hosting config we created earlier for above demo.

sudo nano /etc/nginx/sites-avaialble/custom_hosting

 

##copy and paste below code and save and exit

server {

listen 5002 ssl; ##this is port number on which I want to access my python service on browser.

listen [::]:5002 ssl;

 

server_name linuxhosttest-b.test.com; ##here domain url is mapped and IP of this server should map with domain provider like godaddy

location / {

proxy_set_header Host $host;

proxy_pass http://127.0.0.1:5003##this is the actual application which is running on server

proxy_redirect off;

}

 

##below all four lines I used/copied from save above example where I geneated ssl certificate for domain url

##all these lines of codes you will find in same file, which got added automatically by letsencrypt

ssl_certificate /etc/letsencrypt/live/linuxhosttest-b.test.com/fullchain.pem; # managed by Certbot

ssl_certificate_key /etc/letsencrypt/live/linuxhosttest-b.test.com/privkey.pem; # managed by Certbot

include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

 

##run below command to unlink.

sudo unlink /etc/nginx/sites-enabled/custom_hosting

 

##reload nginx, so that it will refresh setup and use new configuration you created above.

sudo nginx -s reload

 

##run below command to link again

sudo ln -s /etc/nginx/sites-available/custom_hosting /etc/nginx/sites-enabled

 

##reload nginx, so that it will refresh setup and use new configuration you created above.

sudo nginx -s reload

 

##restart nginx server

sudo systemctl restart nginx

 

##check the nginx config, if nginx is wokring fine on your server and config files are correct.

sudo nginx -t

 

************************************

***********Reeact  Hosting************

*********************** ************

 

##login to Ubuntu machine via ssh connection and login as "ubuntu" user

 

##make sure you have nginx installed on your machine

sudo apt install nginx

 

##reate your site’s web root directory. Most of the time, it will be located in the /var/www directory, but you can create anywhere, but you need to make sure, it have required permission to that directory to run/access by nginx server, because it will run via referring to location, not like with port number.

sudo mkdir -p /var/www/ReactApp1

 

##Set permissions for the new directory to allow your regular user account to write to it:

sudo chmod 755 -R /var/www/ReactApp1

 

##The Rsync program will execute its commands as the user you designate in your deployment script. This user must be the owner of your site’s web root. Replace example_user with your own user’s name and /var/www/example.com with the location of your site’s web root.

##comand - sudo chown -R <user-name-of-server>:www-data <your-application-folder-path>

sudo chown -R ubuntu:www-data /var/www/ReactApp1

 

##Create hosting config

sudo nano /etc/nginx/sites-available/ReactApp1

 

##Copy and paste below content and save and exit. NOTE - If you already have config file like other apps/serice already running, then

##Pleaes update below config with existing file and probably you can use different port.

server {

      listen 80;

 

  ##if you want to use domain name for your app, then use below code and update correct domain, else you can access via IP or even you can put IP here.

  server_name linuxhosttest-a.test.com;

 

      root /var/www/ReactApp1; ## this is your project location

      index index.html index.htm; ##this is default file to open on url

}

 

##check the nginx config, if nginx is wokring fine on your server and config files are correct.

sudo nginx -t

 

##unlink earlier config file, so that you able to link your new file or updated file from sites-available/ to sites-enabled/

sudo unlink /etc/nginx/sites-enabled/default

 

##link new file or updated file from sites-available/ to sites-enabled/

sudo ln -s /etc/nginx/sites-available/ReactApp1 /etc/nginx/sites-enabled/

 

##check the nginx config, if nginx is wokring fine on your server and config files are correct.

sudo nginx -t

 

##restart nginx server

sudo systemctl restart nginx

 

##check the nginx config, if nginx is wokring fine on your server and config files are correct.

sudo nginx -t

 

##Use the Node Package Manager to create your React app.

##NOTE - below all steps creating react app and running deployment script, all I have done on window machine, open cmd and run.

npm init react-app react-test-app1

 

cd react-test-app1

 

code . ##this will open you code into VS code editor

 

##Now open terminal window and build, start and check, it should work on you local

npm run build

npm run start ##it should start localhost url to use into browser to run your sample react test app

 

##Deploy manually build folder codes base to your ubuntu server project folder location i.e. /var/www/ReactApp1/

 

##Run url into your browser as per config you have done above either by public ip or domain url.

 

Categories/Tags:

Recent Articles

1

AWS Saving Plan - Cost optimization tips

2
3

AWS RDS Key Concepts & Why you should use it?

4
5

Open-Search/Kibana - Multi Tenancy Setup

See All Articles