Intro:
Hello guys 👋🏾, coming with another story, today on how I solved deployment issues while deploying a Flask app using gunicorn and Nginx 🙂
So, here I had built the backend for the project, just an API connecting to the frontend client. I had built the API and tested it locally successfully but when it came to deploying on a physical server, the problems came raining down 😮💨
Now what's the use of an API if it isn't available for consumption? 🤔
It doesn't serve a use I guess So I had to fix it 🥲
Strategy for Deployment:
Now to understand the problem, we must talk about the strategy for the deployment. The Plan: The Flask app is to be run with the gunicorn HTTP Server(as a service), with this running on the server, we would use Nginx as a reverse proxy to accept HTTP requests and redirect them to the sockets running the app and to send the response to the client. That was the plan.
Now this plan was selected because these choices are popular choices 🫣 and they integrate well with each other, they are easily configured which makes it easier 🙂
The Production Environment:
When it came to setting up the environment, I used an Azure server(running Ubuntu 22.04), Python 3.12, gunicorn 22.0
The Genesis of the Problem:
After cloning the project from GitHub, I tested it locally with the Python runtime and it worked! 🧑🏾💻
I tried it with the gunicorn command and it worked too.
I wrote a config file for the service to run the gunicorn server and checked the status of the service and it was up and running perfectly with the socket 🙂
Now was the time for the problematic part, I went on to install the Nginx server which was successful, and then I went into the config to set up the server for the project... I created the config file for the sit which set up the server to redirect the requests to the socket.
I created the symlink to the appropriate folder and tested the config for any issues... Successfully, the check went through 🫠
The Puzzle:
Now I thought that part was done, so I used my domain to make the machine accessible through it.
Now for the test of faith, I entered the API endpoint into my Postman client, and it failed(actually it timed out), I was wondering why that was.
Initially, I realised that the firewall for the server on the Azure dashboard was blocking all HTTP requests so I quickly fixed that... Still no progress 😮💨
Then I deep-dived into the NGINX log files where I found that there was an error in the log file.
A summary of the error was a permission issue, I checked the permission of the project folder, the nginx config files, the nginx service and the gunicorn service file, with the help of ChatGPT, I tweaked the permission as advised but still, the same error 😢
I tried many other things over 3 days but all to no avail 😢
As Dan Salomon once said
"Sometimes it pays to stay in bed on Monday, rather than spending the rest of the week debugging Monday's code" - Dan Salomon
The Way Out:
Finally, I checked an appealing YouTube video to alleviate this pain... As I consumed its content, by a stroke of luck, the YouTuber ran into the same issue and gave the fix which I implemented(setting the permission of the home directory to 775 🥲).
I:
- Recloned the repo
- Rewrote the config for the service(with my_username as the user and www-data as the group)
- Reconfigured the Nginx server
- Changed the permission on the home directory(to 775) to enable the service access to it
- Restarted the services(Nginx and gunicorn) And tested again... IT WORKED!!! 🎉🎉
Conclusion:
Well, after it was deployed, the pain did go away 🥲 In the end, the API was up and functional and I was a happy dev 🙂 This blog was inspired by the HNG 11 Program.
About Me 🫣:
My name is Ukeme Edet, I'm a Software Engineer, but I'm currently exploring Backend Systems. I recently started the HNG Program. I heard it's going to be a very interesting and challenging journey, but I look forward to becoming a Finalist 😊
As a Backend Engineer, I decided to gain real-world experience in the software development lifecycle. Looking ahead, it will be worth it. :)
Top comments (0)