I use supervisord for managing tornado with no issuse wnhile using nginx as a load balancer.
I am having severe issues with supervisor and uWSGI with nginx as a load blancer. I am using bottle as the framework.
when I run the below from the command line and I load a page in FF hitting nginx, all works great.
sudo command = /usr/local/bin/uwsgi --loop gevent --socket 127.0.0.1:8070 --wsgi-file /home/ubuntu/workspace/uwsgiServer.py -b 32768 --master --async 5 --enable-threads --listen 100 --uid root
If I place the command line in supervior then I get page not found.
uWSGI Error
Python application not found
[program:uwsgi]
#autostart=true
#autorestart=true
#process_name = uwsgi-%(process_num)s
command = /usr/local/bin/uwsgi --loop gevent --socket 127.0.0.1:8070 --wsgi-file /home/ubuntu/workspace//uwsgiServer.py -b 32768 --master --async 5 --enable-threads --listen 100 --uid root
#--port=%(process_num)s
#--log_file_prefix=%(here)s/logs/%(program_name)s-%(process_num)s.log
#numprocs = 1
#numprocs_start = 8070
Here are the relevant portions of the nginx.conf file:
upstream uwsgi_b {
server 127.0.0.1:8070;
}
location /u/ {
include uwsgi_params;
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param Host $http_host;
uwsgi_pass uwsgi_b;
}
You might probably add some more params to supervisord config, like --pp (python path) to the uwsgi command, and maybe some environment variables:
[program:uwsgi]
command = /usr/local/bin/uwsgi
--loop gevent
--socket 127.0.0.1:8070
--wsgi-file uwsgiServer.py
--buffer-size 32768 --master --async 5 --enable-threads --listen 100 --uid root
--pp /home/ubuntu/workspace/
autostart=true
autorestart=true
environment=ENV_VAR='var'
user=root # or other
group=root # or other
directory=/home/ubuntu/workspace/
umask=022
EDIT: Removed Django-specific settings
Related
I know this is a common issue, but due to the fact that I've been searching for 3 hours now, and given that there must be a quantum singularity involved, I had to post this.
I keep getting this familiar error:
[uWSGI] getting INI configuration from uwsgi.ini,
*** Starting uWSGI 2.0.18-debian (64bit) on [Mon May 25 15:56:04 2020] ***,
compiled with version: 8.2.0 on 10 February 2019 02:42:46,
os: Linux-5.6.12-1-MANJARO #1 SMP PREEMPT Sun May 10 14:36:43 UTC 2020,
nodename: a43c6a7bbb2c,
machine: x86_64,
clock source: unix,
pcre jit disabled,
detected number of CPU cores: 8,
current working directory: /srv/myapp,
detected binary path: /usr/bin/uwsgi-core,
setgid() to 33,
setuid() to 33,
your memory page size is 4096 bytes,
detected max file descriptor number: 1048576,
lock engine: pthread robust mutexes,
thunder lock: disabled (you can enable it with --thunder-lock),
uwsgi socket 0 bound to UNIX address /tmp/uwsgi.socket fd 3,
your server socket listen backlog is limited to 100 connections,
your mercy for graceful operations on workers is 60 seconds,
mapped 437520 bytes (427 KB) for 5 cores,
*** Operational MODE: preforking ***,
*** no app loaded. going in full dynamic mode ***,
*** uWSGI is running in multiple interpreter mode ***,
!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!,
no request plugin is loaded, you will not be able to manage requests.,
you may need to install the package for your language of choice, or simply load it with --plugin.,
!!!!!!!!!!! END OF WARNING !!!!!!!!!!,
spawned uWSGI master process (pid: 25),
spawned uWSGI worker 1 (pid: 28, cores: 1),
spawned uWSGI worker 2 (pid: 29, cores: 1),
spawned uWSGI worker 3 (pid: 30, cores: 1),
spawned uWSGI worker 4 (pid: 31, cores: 1),
spawned uWSGI worker 5 (pid: 32, cores: 1),
However, I don't see anything wrong with this very simple setup. My setup:
core/__init__.py
from flask import Flask
def create_app():
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
return app
app.py
from core import create_app
app = create_app()
if __name__ == '__main__':
app.run()
Dockerfile
FROM python:3.6-slim
RUN apt-get clean \
&& apt-get -y update
RUN apt-get -y install uwsgi nginx
COPY . /srv/myapp
COPY nginx.conf /etc/nginx
WORKDIR /srv/myapp
RUN pip install -r requirements.txt
RUN chmod +r uwsgi.ini
RUN chmod +x ./start.sh
CMD ["./start.sh"]
start.sh
#!/usr/bin/env bash
service nginx start
uwsgi --ini uwsgi.ini
uwsgi.ini
[uwsgi]
module = app:app
uid = www-data
gid = www-data
master = true
processes = 5
socket = /tmp/uwsgi.socket
chmod-sock = 664
vacuum = true
die-on-term = true
nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;events
{
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
access_log /dev/stdout;
error_log /dev/stdout;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
index index.html index.htm;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
root /var/www/html;
location /
{
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.socket;
}
}
}
If I add the python3 plugin RUN apt-get -y install uwsgi nginx uwsgi-plugin-python3 in DOCKERFILE and run uwsgi via uwsgi --ini uwsgi.ini --plugin python3 I get:
Traceback (most recent call last):
File "./app.py", line 1, in <module>
from core import create_app
File "./core/__init__.py", line 1, in <module>
from flask import Flask
ModuleNotFoundError: No module named 'flask'
I don't know if this may be a hint.
Any help is appreciated!
Thanx!
After 8 hours of sleep I found my mistake:
Installing uwsgi via apt-get will not work. It is required to install uwsgi via pip install. (My guess is, that these are two different uwsgi instances / services)
Centos7,when I connect to my website, shows 502 Bad Gateway,
I test my website with command
uwsgi --ini
systemctl start nginx
And I cant figure out what's happened,please help me!
here's nginx.conf
upstream django {
server 127.0.0.1:8000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
charset utf-8;
include /etc/nginx/default.d/*.conf;
location / {
include uwsgi_params;
uwsgi_pass django;
}
location /static/ {
alias /usr/local/etc/dmp/static/;
}
}
and uwsgi setting
[uwsgi]
chdir = /usr/local/etc/dmp
module = DMP_python.wsgi
plugins = python3
socket = :8000
chmod-socket = 666
master = true
processes = 2
vacuum = true
You're using the wrong setting to tell uwsgi to use an HTTP port. You need http-socket rather than socket.
There can be multiple reasons for which an upstream might return invalid or even do not return any response
Verify if upstream uwsgi is actually running locally in the centos instance and can handle incoming requests
for this to verify run it as http-socket = :8000 in uwsgi.ini and then run uwsgi --ini uwsgi.ini
if uwsgi running fine on localhost, then change config back to socket = :8000
On centos 7.x SELinux package is enabled and runs in enforcing mode. So it won't allow nginx to write/connect to a socket.
verify if SELinux has the policy for nginx to write to sockets
check if read/connect/write to socket is allowed grep nginx /var/log/audit/audit.log | audit2allow -m nginx
do so by grep nginx /var/log/audit/audit.log | audit2allow -M nginx
and finally semodule -i nginx.pp
permission to connect to socket issue should be resolved by now
verify if nginx can do network connection with upstream. Check nginx error.log or getsebool -a | grep httpd
to allow it run setsebool httpd_can_network_connect on -P
I am doing multi-application nginx+uwsgi setup in django. I am following this documentation
to set up emperor mode for my project.
It works fine when I run "uwsgi --ini myproject_uwsgi.ini" but I am not able to deploy emperor mode following this documentation.
I have researched many docs but not able to find relevant information related to emperor mode setup.
My nginx.conf file:(angularJS frontend)
server {
listen 80;
server_name 192.168.xx.xx;
root /home/user/Myspace/workspace/Myproject_frontend/dist;
}
My "etc/uwsgi/vassals/uwsgi.ini" file looks like:
[uwsgi]
#Django-related settings
#Django's wsgi file
wsgi-file = /home/user/Myspace/workspace/myproject/myproject/wsgi.py
http = 192.168.xx.xx:8080
virtualenv = /home/user/Myspace/VENV_MYPROD
Also, i have created a uwsgi.service file in "/etc/systemd/system/uwsgi.service" to start emperor mode service and it looks like:
[Unit]
Description=uWSGI Emperor service
After=syslog.target
[Service]
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals/
RuntimeDirectory= uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target
Please provide help on setting up uwsgi emperor mode.
I am trying to setup uwsgi and Django on Nginx but showing page not found error and error logs are empty.
I cannot identify the error because the error logs are empty.
Error log /var/log/nginx/error.log:
-rw-r--r-- 1 www-data root 0 Feb 26 12:31 error.log
uswgi is running properly because I tested this on following method:
uwsgi --http :8080 --home /home/flybegins/python/django/venv/ --chdir
/home/flybegins/python/django/sample -w sample.wsgi
virtual host
server {
listen 80;
server_name test.aaaaaaa.com;
error_log /var/log/nginx/error.log
location /static/ {
root /home/flybegins/python/django/sample/
}
location / {
include uwsgi_params;
uwsgi_pass unix:/home/flybegins/python/django/sample/sample.sock;
} }
Virtual host permission:
-rw-r--r-- 1 root root 333 Feb 27 08:54 test.aaaa.com
Thanks in advance!
You need to install python plugin for uwsgi
sudo apt-get install uwsgi-plugin-python
or for python 3
sudo apt-get install uwsgi-plugin-python3
You are running your project using port 8080 with this code:
uwsgi --http :8080 --home /home/flybegins/python/django/venv/ --chdir /home/flybegins/python/django/sample -w sample.wsgi
And you are trying to bind NGINX to a socket file that doesn't exist using this configuration:
location / {
include uwsgi_params;
uwsgi_pass unix:/home/flybegins/python/django/sample/sample.sock;
}
That why it doesn't work.
I did two mistakes One is nginx virtual host configuration and another one is socket permission error
uWSGI Configuration
[uwsgi]
project = prd
base = /home/flybegins/python/django
chdir = %(base)/%(project)
home = %(base)/venv
module = %(project).wsgi:application
master = true
processes = 5
gid = www-data
uid = www-data
socket = /var/uwsgi/%(project).sock
chmod-socket = 664
vacuum = true
To create the space for the socket to exist, you just have to pick a persistent directory (e.g. not /run or /tmp) and make www-data (the user nginx runs as) the owner of it, as such:
$ sudo mkdir /var/uwsgi
$ sudo chown www-data:www-data /var/uwsgi
My nginx virtual host configuration
server {
listen 80;
server_name testserver1.com;
access_log /home/flybegins/log/python/testserver1.com/access.log;
error_log /home/flybegins/log/python/testserver1.com/error.log error;
location /static {
alias /home/flybegins/python/django/prd/static_files/;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/var/uwsgi/prd.sock;
}
}
I have a basic django rest application in my digital ocean server (Ubuntu 16.04) with a local virtual environment.
The basic wsgi.py is:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "workout_rest.settings")
# This application object is used by any WSGI server configured to use this
# file. This includes Django's development server, if the WSGI_APPLICATION
# setting points here.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
# Apply WSGI middleware here.
# from helloworld.wsgi import HelloWorldApplication
# application = HelloWorldApplication(application)
I have followed step by step this tutorial:
https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04
When I test Gunicorn's ability to serve the project with this command:
gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application
All works well.
So I've tried to setup Gunicorn to use systemd service file.
My /etc/systemd/system/gunicorn.service file is:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ben
Group=www-data
WorkingDirectory=/home/ben/myproject
ExecStart=/home/ben/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:/home/ben/myproject/myproject.sock myproject.wsgi:application
[Install]
WantedBy=multi-user.target
My Nginx configuration is:
server {
listen 8000;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ben/myproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ben/myproject/myproject.sock;
}
}
I've changed listen port from 80 to 8000 because 80 give me a err_connection_refused error.
After starting the server with this command:
sudo systemctl restart nginx
When I try to run my website, I get an 502 Bad Gateway error.
I've tried these commands (found on the tutorial comments):
sudo systemctl daemon-reload
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl restart nginx
but nothing changes.
When I take a look at the Nginix logs with this command:
sudo tail -f /var/log/nginx/error.log
I can read that sock file doesn't exists:
2016/10/07 09:00:18 [crit] 24974#24974: *1 connect() to unix:/home/ben/myproject/myproject.sock failed (2: No such file or directory) while connecting to upstream, client: 86.197.20.27, server: 139.59.150.116, request: "GET / HTTP/1.1", upstream: "http://unix:/home/ben/myproject/myproject.sock:/", host: "server_ip_adress:8000"
Why this sock file isn't created? How can I configure django/gunicorn to create this file?
I have added gunicorn in my INSTALLED_APP in my Django project but it doesn't change anything.
EDIT:
When I test the nginx config file with nginx -t I get an error: open() "/run/nginx.pid" failed (13: Permission denied).
But if I run the command with sudo: sudo nginx -t, the test is successful. Does that mean that I have to allow 'ben' user to run Ngnix?
About gunicorn logfile, I cannot find a way to read them. Where are they stored?
When I check whether gunicorn is running by using ps aux | grep gunicorn:
ben 26543 0.0 0.2 14512 1016 pts/0 S+ 14:52 0:00 grep --color=auto gunicorn
Here is hat happens when you run the systemctl enable and start commands for gunicorn:
sudo systemctl enable gunicorn
Synchronizing state of gunicorn.service with SysV init with /lib/systemd/systemd-sysv-install...
Executing /lib/systemd/systemd-sysv-install enable gunicorn
sudo systemctl start gunicorn
I get no output with this command
sudo systemctl is-active gunicorn
active
sudo systemctl status gunicorn
● gunicorn.service - gunicorn daemon
Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: enabled)
Active: active (exited) since Thu 2016-10-06 15:40:29 UTC; 23h ago
Oct 06 15:40:29 DevUsine systemd[1]: Started gunicorn.service.
Oct 06 18:52:56 DevUsine systemd[1]: Started gunicorn.service.
Oct 06 20:55:05 DevUsine systemd[1]: Started gunicorn daemon.
Oct 06 20:55:17 DevUsine systemd[1]: Started gunicorn daemon.
Oct 06 21:07:36 DevUsine systemd[1]: Started gunicorn daemon.
Oct 06 21:16:42 DevUsine systemd[1]: Started gunicorn daemon.
Oct 06 21:21:38 DevUsine systemd[1]: Started gunicorn daemon.
Oct 06 21:25:28 DevUsine systemd[1]: Started gunicorn daemon.
Oct 07 08:58:43 DevUsine systemd[1]: Started gunicorn daemon.
Oct 07 15:01:22 DevUsine systemd[1]: Started gunicorn daemon.
I had to change the permissions of my sock folder:
sudo chown ben:www-data /home/ben/myproject/
Another thing is that I have changed the sock location after reading in many post that it's not a good pratice to keep the sock file in the django project.
My new location is:
/home/ben/run/
Don't forget to change permissions:
sudo chown ben:www-data /home/ben/run/
To be sure that gunicorn is refreshed, run these commands:
pkill gunicorn
sudo systemctl daemon-reload
sudo systemctl start gunicorn
That will kill the gunicorn processes and start new ones.
You can run this command to make the process start at server boot:
sudo systemctl enable gunicorn
All works well now.
While the accepted answer works, there is one (imo major) issue with it, which is that the gunicorn web server is (probably) running as root, which is not recommended. The reason you end up needing to chown the socket is because it is owned by root:root, because that is the user/group your init job assumes by default. There are multiple ways to get your job to assume another role. As of this time (with gunicorn 19.9.0), in my opinion, the simplest solution to this is to use the --user and --group flags provided as part of the gunicorn command. This means your server can start with the user/group you specify. In your case:
exec gunicorn --user ben --group www-data --bind unix:/home/ben/myproject/myproject.sock -m 007 wsgi
will start gunicorn under ben:www-data user and create a socket owned by ben:www-data with the permissions 770, or read/write/execute privilege for the user ben and group www-data on the socket, which is exactly what you ned in this case.
I have given path to the sock file outside my project. I needed to just create the directory so that the gunicorn can create the file inside that directory as I had had mentioned that path in the .services file. Basically, I made sure that I had all directories existing according to the path in the .services file. No need to change permissions or ownership
Try run
sudo systemctl daemon-reload
sudo systemctl start gunicorn
sudo systemctl status gunicorn.service
The last line helped me to re-create .scok file