uwsgi http is ambiguous - python

Im trying to run Django application on uwsgi but get the below error.
uwsgi --http :8000 --home /home/cuser/.virtualenvs/vq --chdir /var/www/sid/sid -w wsgi.py
uwsgi: option '--http' is ambiguous
getopt_long() error
When I change from -http to --socket it works but again it says --home is ambiguous

This is most likely because you have uwsgi installed from your distributions packaged binaries, which are more minimal in their build and lack some of the plugins.
You can fix this by either pip install uwsgi and replace uwsgi with path/to/uwsgi/binary/installed/using/pip. You can find that using pip show uwsgi.
[Please note: use pip3 if you're using python3]
Another method would be to download the respective http/python3 plugins and running the following command:
uwsgi --plugins http,python --http :8000 --home /home/cuser/.virtualenvs/vq --chdir /var/www/sid/sid -w wsgi.py

You may want to take into account when using this with distro-supplied packages, is that very probably your distribution has built uWSGI in modular way (every feature is a different plugin that must be loaded).
You have to prepend --plugin python,http to the command, and --plugin python when the HTTP router is removed
Example
Appended --plugin python
uwsgi --http :8000 --plugin python --home /home/cuser/.virtualenvs/vq --chdir /var/www/sid/sid -w wsgi.py

try:
uwsgi --http=:8000 --home=/home/cuser/.virtualenvs/vq --chdir=/var/www/sid/sid -w wsgi.py
For some versions of getopt this should work. If not, try to put your parameters in config file or update getopt library in your system and recompile uWSGI.

Related

How to add the heroku nginx buildpack to a python django app with gunicorn?

I am trying to deploy a python with django on heroku and configure an nginx reverse proxy to have like a filter which won't let the requests pass to my django backend until the token is checked to an third party IDP.
**
STEP 1
**
I am following this tutorial to add the nginx buildpack : https://elements.heroku.com/buildpacks/hq-mobile/v3-nginx-buildpack
After I've added the buildpack and start the app, I get the following message: bin/start-nginx: line 37: bundle: command not found
After some digging I noticed some paths need to be added to the config vars for the heroku app in order for bundler to get the needed dependencies :
So I've added this paths:
heroku config:add GEM_PATH=vendor/bundle/1.9.3
heroku config:set PATH=bin:vendor/bundle/ruby/1.9.3/bin:/usr/local/bin:/usr/bin:/bin
Then the config/unicorn.rb file:
require 'fileutils'
listen '/tmp/nginx.socket'
before_fork do |server,worker|
FileUtils.touch('/tmp/app-initialized')
end
Procfile:
web: bin/start-nginx bundle exec unicorn -c config/unicorn.rb gunicorn -c gunicorn.conf.py MyApp.wsgi
gunicorn.conf.py
# gunicorn.conf
def when_ready(server):
# touch app-initialized when ready
open('/tmp/app-initialized', 'w').close()
bind = 'unix:///tmp/nginx.socket'
workers = 4
Even after adding this, the error still persists.
**
STEP 2
**
Once the normal buildpack will be in place I want to follow this tutorial to configure nginx how I want:
https://www.nginx.com/blog/validating-oauth-2-0-access-tokens-nginx/
What configuration is needed to be able to have this buildpack working in my situation?
To fix this problem, you remove the bundle exec part from the Procfile. In other words, your Procfile becomes:
web: bin/start-nginx unicorn -c config/unicorn.rb gunicorn -c gunicorn.conf.py MyApp.wsgi
(sidenote: there might be an error with just using MyApp.wsgi since you might need to change it to something like MyApp.wsgi:application to expose the environment variable for your application)

Why does uWSGI fail to start in Docker?

I am relatively new to using uWSGI to serve Python applications and I am attempting to start a uWSGI process in emperor mode with a vassal, but every time I try to start uWSGI inside of Docker with the following command (as root):
# /usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini
What I get as a response is:
[uWSGI] getting INI configuration from /etc/uwsgi/emperor.ini
2.0.13.1
The emperor.ini configuration file looks like:
# files/etc/uwsgi/emperor.ini
[uwsgi]
emperor = /etc/uwsgi/apps-enabled
die-on-term = true
log-date = true
While the only vassal's configuration looks like:
# files/etc/uwsgi/apps-enabled/application.ini
[uwsgi]
app_dir = /var/www/server
plugin = python
master = true
callable = app
chdir = %(app_dir)
mount = /=%(app_dir)/start.py
protocol = uwsgi
socket = :8079
uid = www-data
gid = www-data
buffer-size = 32768
enable-threads = true
single-interpreter = true
processes = 1
stats = 127.0.0.1:1717
(NB: The filenames above are given in terms of where they live relative to the Dockerfile which will then copy them to the correct locations, basically removing the prefix files)
Currently the uWSGI Docker image I'm using is built off of an ubuntu:trusty base image (though I've tried ubuntu:latest and alpine:latest and encountered the same problem), and although I am attempting to launch the uWSGI process with supervisor, as stated previously, it also fails when run directly from the command line. In the Docker image I'm installing uWSGI using pip but have also tried using apt-get with the same result.
I should also mention that I've tried different versions of uWSGI 2.0.13.1 and 1.9.something with the same result, if that helps.
# Dockerfile
FROM ubuntu:trusty
MAINTAINER Sean Quinn "me#mail.com"
RUN apt-get update \
&& apt-get install -y \
ack-grep git nano \
supervisor \
build-essential gcc python python-dev python-pip
RUN sed -i 's/^\(\[supervisord\]\)$/\1\nnodaemon=true/' /etc/supervisor/supervisord.conf \
&& sed -i 's/^\(\[supervisord\]\)$/\1\nloglevel=debug/' /etc/supervisor/supervisord.conf \
&& sed -i 's/^\(files = .*\)$/;\1/' /etc/supervisor/supervisord.conf \
&& sed -i 's/^\(\[include\]\)$/\1\nfiles = \/etc\/supervisor\/conf.d\/*.conf/' /etc/supervisor/supervisord.conf
ENV UWSGI_VERSION 2.0.13.1
RUN pip install uwsgi==${UWSGI_VERSION}
RUN mkdir -p /etc/uwsgi \
&& mkdir -p /etc/uwsgi/apps-available \
&& mkdir -p /etc/uwsgi/apps-enabled \
&& mkdir -p /var/log/uwsgi
COPY files/etc/supervisor/conf.d/uwsgi.conf /etc/supervisor/conf.d/uwsgi.conf
COPY files/etc/uwsgi/emperor.ini /etc/uwsgi/emperor.ini
VOLUME /etc/uwsgi/apps-enabled
VOLUME /var/www
ENTRYPOINT ["/usr/bin/supervisord"]
CMD ["-c", "/etc/supervisor/supervisord.conf"]
As mentioned, the supervisord process attempts to launch the uWSGI process using the following supervisor configuration.
# files/etc/supervisor/conf.d/uwsgi.conf
[program:uwsgi]
command=/usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini
user=root
The application Python files are mounted in a subdirectory of /var/www and the application uWSGI configuration is mounted into /etc/uwsgi/apps-enabled.
The bizarre thing is, if I install supervisor and uWSGI on a new Ubuntu VM (outside of Docker) with all of the configuration and files in place I can see uWSGI properly process the emperor.ini and read the vassal .ini files. I haven't yet attempted to add nginx into the equation because I want to make sure uWSGI is starting and reading configuration files correctly first and foremost.
Is there any way to increase the logging or ascertain why I'm only seeing what appears to be the version number of the uWSGI binary? It's like the uWSGI process is completely ignoring command line options. I feel like I'm missing something that should be obvious.
Thanks in advance for any help anyone can give!
tl;dr don't use UWSGI_VERSION as an environment variable, apparently it forces uWSGI to only print the version number instead of start?
I believe I solved my own issue!
After experimenting with other uWSGI images on Docker's hub, I found that they were also running into the same issue so I began to look further into possible configuration issues. I tried changing permissions among other things.
I noticed however that when I used jpetazzo/nsenter to enter the running container that I saw uWSGI start (rather than simply output the uWSGI version information as highlighted above). When entering using docker exec, uWSGI would only print the version information. After playing around a bit more, I discovered that issuing the command su - from within the container launched using docker exec I again saw uWSGI start.
After some inspection, I discovered several differences in the environment variables between the root user in one shell vs. another. It led me to the UWSGI_VERSION environment variable, which appears to have been the culprit because removing UWSGI_VERSION allowed uWSGI to start.
I modified my Dockerfile to use UWSGI_PIP_VERSION instead as the environment variable to indicate the version of uWSGI to install, which seems to be a safe alternative to UWSGI_VERSION. YMMV.

How to integrate a --worker-class of gunicorn in supervisor config setting?

I have configured a supervisor on the server like this:
[program:myproject]
command = /home/mydir/myproj/venv/bin/python /home/mydir/myproj/venv/bin/gunicorn manage:app -b <ip_address>:8000
directory = /home/mydir
I have installed gevent on my virtual environment but I don't know how can I implement it on the supervisor command variable, I can run it manually through terminal like this:
gunicorn manage:app -b <ip_address>:8000 --worker-class gevent
I tried to include a path when I call gevent in supervisor command just like python and gunicorn, but it's not working, honestly, I don't know what's the correct directory/file to execute gevent and I am also not sure if this is the correct way to execute a worker class in supervisor. I am running on Ubuntu v14.04
Anyone?Thanks
Already made a solution for this. But I am not 100% sure if it is correct, after searching a hundred times, I finally came up with a working solution :)
Got this from here, I've created a gunicorn.conf.py file on my project directory containing:
worker_class = 'gevent'
And integrated this file on supervisor config setting:
[program:myproject]
command = /home/mydir/myproj/venv/bin/python /home/mydir/myproj/venv/bin/gunicorn -c /home/mydir/myproj/gunicorn.conf.py manage:app -b <ip_address>:8000
directory = /home/mydir
And start running the supervisor:
sudo supervisorctl start <my_project>
And poof! It's already working!

Running multiple uwsgi python versions

I'm trying to deploy django with uwsgi, and I think I lack understanding of how it all works. I have uwsgi running in emperor mode, and I'm trying to get the vassals to run in their own virtualenvs, with a different python version.
The emperor configuration:
[uwsgi]
socket = /run/uwsgi/uwsgi.socket
pidfile = /run/uwsgi/uwsgi.pid
emperor = /etc/uwsgi.d
emperor-tyrant = true
master = true
autoload = true
log-date = true
logto = /var/log/uwsgi/uwsgi-emperor.log
And the vassal:
uid=django
gid=django
virtualenv=/home/django/sites/mysite/venv/bin
chdir=/home/django/sites/mysite/site
module=mysite.uwsgi:application
socket=/tmp/uwsgi_mysite.sock
master=True
I'm seeing the following error in the emperor log:
Traceback (most recent call last):
File "./mysite/uwsgi.py", line 11, in <module>
import site
ImportError: No module named site
The virtualenv for my site is created as a python 3.4 pyvenv. The uwsgi is the system uwsgi (python2.6). I was under the impression that the emperor could be any python version, as the vassal would be launched with its own python and environment, launched by the master process. I now think this is wrong.
What I'd like to be doing is running the uwsgi master process with the system python, but the various vassals (applications) with their own python and their own libraries. Is this possible? Or am I going to have to run multiple emperors if I want to run multiple pythons? Kinda defeats the purpose of having virtual environments.
The "elegant" way is building the uWSGI python support as a plugin, and having a plugin for each python version:
(from uWSGI sources)
make PROFILE=nolang
(will build a uWSGI binary without language support)
PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27"
will build the python27_plugin.so that you can load in vassals
PYTHON=python3 ./uwsgi --build-plugin "plugins/python python3"
will build the plugin for python3 and so on.
There are various way to build uWSGI plugins, the one i am reporting is the safest one (it ensure the #ifdef are honoured).
Having said that, having a uWSGI Emperor for each python version is viable too. Remember Emperor are stackable, so you can have a generic emperor spawning one emperor (as its vassal) for each python version.
Pip install uWSGI
One option would be to simply install uWSGI with pip in your virtualenvs and start your services separately:
pip install uwsgi
~/.virtualenvs/venv-name/lib/pythonX.X/site-packages/uwsgi --ini path/to/ini-file
Install uWSGI from source and build python plugins
If you want a system-wide uWSGI build, you can build it from source and install plugins for multiple python versions. You'll need root privileges for this.
First you may want to install multiple system-wide python versions.
Make sure you have any dependencies installed. For pcre, on a Debian-based distribution use:
apt install libpcre3 libpcre3-dev
Download and build the latest uWSGI source into /usr/local/src, replacing X.X.X.X below with the package version (e.g. 2.0.19.1):
wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar vzxf uwsgi-latest.tar.gz
cd uwsgi-X.X.X.X/
make PROFILE=nolang
Symlink the versioned folder uwsgi-X.X.X.X to give it the generic name, uwsgi:
ln -s /usr/local/src/uwsgi-X.X.X.X /usr/local/src/uwsgi
Create a symlink to the build so it's on your PATH:
ln -s /usr/local/src/uwsgi/uwsgi /usr/local/bin
Build python plugins for the versions you need:
PYTHON=pythonX.X ./uwsgi --build-plugin "plugins/python pythonXX"
For example, for python3.8:
PYTHON=python3.8 ./uwsgi --build-plugin "plugins/python python38"
Create a plugin directory in an appropriate location:
mkdir -p /usr/local/lib/uwsgi/plugins/
Symlink the created plugins to this directory. For example, for python3.8:
ln -s /usr/local/src/uwsgi/python38_plugin.so /usr/local/lib/uwsgi/plugins
Then in your uWSGI configuration (project.ini) files, specify the plugin directory and the plugin:
plugin-dir = /usr/local/lib/uwsgi/plugins
plugin = python38
Make sure to create your virtualenvs with the same python version that you created the plugin with. For example if you created python38_plugin.so with python3.8 and you have plugin = python38 in your project.ini file, then an easy way to create a virtualenv with python3.8 is with:
python3.8 -m virtualenv path/to/project/virtualenv

Installing uwsgi with plugins using 'pip'

I installed uwsgi using pip install uwsgi.
When I run uwsgi, I get a couple of errors. The command I'm running is uwsgi --master --emperor /etc/uwsgi/apps-enabled --die-on-term --uid www-data --gid www-data.
It appears that I'm missing the http and python plugins:
[uWSGI] getting INI configuration from component_tracking_test.ini
open("./http_plugin.so"): No such file or directory [core/utils.c line 3347]
!!! UNABLE to load uWSGI plugin: ./http_plugin.so: cannot open shared object file: No such file or directory !!!
open("./python_plugin.so"): No such file or directory [core/utils.c line 3347]
!!! UNABLE to load uWSGI plugin: ./python_plugin.so: cannot open shared object file: No such file or directory !!!
[emperor] removed uwsgi instance component_tracking_test.ini
How do I install the required plugins given that I have installed uwsgi via pip?
When I add "--binary-path /usr/local/bin/uwsgi" (change path to your wsgi bin) to the command, the error went away.
from the docu
binary-path
Argument: string
Force binary path.
If you do not have uWSGI in the system path you can force its path with this option to
permit the reloading system and the Emperor to easily find the binary to execute.
I just had a similar problem and the reason was that I was running sudo uwsgi, not realizing that sudo won't respect the PATH and will launch the system-wide uwsgi. See this answer.

Categories