Django apps in HestiaCP? Django apps in HestiaCP!

Hello everyone.

I have an Ubuntu 18.04 with HestiaCP 1.1.1, and I’m trying to serve some Django apps.

In VestaCP it is more or less tricky to do, but it’s something that is possible to be done using mod_wsgi. However I’m having difficulties to make it work in HestiaCP.

I forked Anton Bozhina’s templates and I did some modifications at https://github.com/realjumy/hestiacp-python-templates/tree/testing

Does anyone have any idea of why this could be failing? I can’t manage to see the Apache2 templates, to start with. All the steps are indicated in the README.md file.

I think being able to run Django and Flask apps will be a real asset for HestiaCP.

Thanks in advance!

2 Likes

with the change to multi-php / php-fpm for apache and no prefork anymore in the newest hestia version you need to add your templates into /usr/local/hestia/data/templates/apache2/php-fpm to have them selectable. the folder level above only contains the old templates for compatibility reason with systems that don’t use multiphp.

maybe look at the new default template and compare to the old wsgi/django stuff, to see what’s obvious to be changed already…

interesting topic and nice to see someone developing stuff like this. keep us updated, while I don’t have a use case for django/flask, I am happy to help with the development. if you encounter further errors, please be as descriptive about it as possible, logentries or journaltctl messages often help a lot to narrow down on the issues :wink: best of luck!

2 Likes

Thanks for your answer.

I’m going to continue working on it tonight. I will be sharing my results :smiley:

I have some advances already.

The new templates can be chosen now, and the .sh script should do everything all right. However, it gives an “Error, apache2 restart failed” once the installation is completed. So I guess there’s something wrong with the tpl and stpl files.

If someone want to give it a try, you can check my progress at the testing branch . At the moment, only the Django template should do something, hence ignore the Flask template for now.

Screenshot 2020-04-22 at 17.45.09

I have been checking the logs at /var/log/apache2/ and /var/log/apache2/domains, but I can’t see anything that can point me in the right direction. If any of you have more experience than me with the templates, please feel free to give it a try.

apachectl -t,

systemctl status apache2.service and journalctl -xe can be used for debugging

How ever when I try it on a test sever. I got this:

root@test:/usr/local/hestia# apachectl -t
AH00526: Syntax error on line 22 of /etc/apache2/conf.d/domains/test.nl.conf:
Name duplicates previous WSGI daemon definition.
Action ‘-t’ failed.
The Apache error log may have more information.

1 Like

this usually is the most helpful for me, simply try to restart apache2 manually and run that command after the restart fails, the error message most likely points you into the right direction.

apachectl -t seems to show the same info as well, so now someone simply has to look at line 22 of the mentioned config file and figure what exactly is the duplicate there, right?

as said earlier the templates will need some adjustment to work with the newer configs used in hestia for apache anyway :wink: I am confident you’ll manage that…

2 Likes

Mmmm… Maybe any of you have any idea of how to sort this.

I believe that the problem in particular is located in the tpl/stpl files, in particular at:

    <IfModule mod_wsgi.c>
        WSGIScriptReloading On
        WSGIScriptAlias / %sdocroot%/app/app.wsgi
        WSGIDaemonProcess %domain%-django-ssl user=%user% group=%user% processes=1 threads=5 display-name=%{GROUP} python-path=%docroot%/venv/lib/python3.7/site-packages
        WSGIProcessGroup %domain%-django-ssl
        WSGIApplicationGroup %{GLOBAL}
    </IfModule>

And all is caused because of the WSGIDaemonProcess %domain%-django-ssl line, which is giving an Name duplicates previous WSGI daemon definition error.

I tried giving different names to the daemon, but I’m still unsuccessful.

Any suggestion?

afaik it uses the %domain%-django-ssl to have different names for the service per domain already and exactly avoid that duplicate error. so maybe it doesn’t fill in that placeholder correctly? what does the vhost conf-file say after it is actually created from the templates?

could it also be, that it even isn’t the vhost file you are looking at, but you already have some WSGI definitions in the general files somewhere or load a custom config you forgot about, that accidentically contains the same line and name? (just guessing around)

To be honest… No idea. But at least you just game me some ideas of where to look. Thanks!

This is how it looks after being created from the templates:

<VirtualHost IP.IP.IP.IP:8080>

    ServerName mysite.web
    ServerAlias www.mysite.web
    ServerAdmin [email protected]
    DocumentRoot /home/admin/web/mysite.web/public_html
    ScriptAlias /cgi-bin/ /home/admin/web/mysite.web/cgi-bin/
    Alias /vstats/ /home/admin/web/mysite.web/stats/
    Alias /error/ /home/admin/web/mysite.web/document_errors/
    SuexecUserGroup admin admin
    CustomLog /var/log/apache2/domains/mysite.web.bytes bytes
    CustomLog /var/log/apache2/domains/mysite.web.log combined
    ErrorLog /var/log/apache2/domains/mysite.web.error.log
    
    IncludeOptional /home/admin/conf/web/mysite.web/apache2.forcessl.conf*

    <Directory /home/admin/web/mysite.web/stats>
        AllowOverride All
    </Directory>

    <Directory /home/admin/web/mysite.web/public_html>
        AllowOverride All
        Options +Includes -Indexes +ExecCGI
    </Directory>

    <IfModule mod_ruid2.c>
        RMode config
        RUidGid admin admin
        RGroups www-data
    </IfModule>
    <IfModule itk.c>
        AssignUserID admin admin
    </IfModule>

    <IfModule mod_wsgi.c>
        WSGIScriptReloading On
        WSGIScriptAlias /app /home/admin/web/mysite.web/public_html/app/app.wsgi
        WSGIDaemonProcess admin-django user=admin group=admin processes=1 threads=5 display-name=%{GROUP} python-home=docroot%/venv/ python-path=/home/admin/web/mysite.web/public_html/venv/lib/python3.6/site-packages socket-user=admin
        WSGIApplicationGroup %{GLOBAL}
    </IfModule>

    <Directory /home/admin/web/mysite.web/public_html>
        AllowOverride FileInfo
        Options ExecCGI Indexes
        MultiviewsMatch Handlers
        Options +FollowSymLinks
        Order allow,deny
        Allow from all
    </Directory>

    IncludeOptional /home/admin/conf/web/apache2.mysite.web.conf*

</VirtualHost>

(IP and domain anonymised)

The problem is located always in the same line:

        WSGIDaemonProcess admin-django user=admin group=admin processes=1 threads=5 display-name=%{GROUP} python-home=docroot%/venv/ python-path=/home/admin/web/mysite.web/public_html/venv/lib/python3.6/site-packages socket-user=admin

yes that seems wrong, as the name for the process, which is the 2nd part ‘admin-django’ in your example has to be different for each vhost. if you run multiple vhost and they have the same name there you’ll see that ‘duplicate’ message.

from the template this should be put together from the web-domain plus the -django… part, hence

%domain%-django-ssl

or

%domain%-django

depending on the template… in your example it seem to more likely use %user%-django instead - maybe you can check your .tpl file again, if you just accidentically put the wrong var in there?

having %domain% there makes much more sense, as exactly that would be the key differantiator and not the user name :wink:

1 Like

That makes sense. Thanks for the tip. I’m going to try right away. Hopefully that will fix it. Thanks!

Mmmm… It seems that that’s not the solution, but it’s probably pointing in the right direction. I will continue working on it. Thanks @falzo!

1 Like

might sound like a bit of a poor mans approach, but you could run something like

find /etc /home -type f -exec grep 'WSGIDaemonProcess' {} \; -print

and check the ouput… according to the error you should see a name for that procces at least twice and the files which contain these lines :wink:
maybe that helps to narrow it down. I have a feeling that you are quite close already…

Yeah, I tried that, but it was appearing only once…

I really have interest in making this work because I see PHP too limited… And definitely more insecure than Python. But I’m running out of ideas on how to fix this…

This is what I find so far:

root@host1:/home# find /etc /home -type f -exec grep 'WSGIDaemonProcess' {} \; -print
    #WSGIDaemonProcess directive instead. 
/etc/apache2/mods-available/wsgi.conf
        WSGIDaemonProcess myweb.site-django user=admin group=admin processes=1 threads=5 display-name=%{GROUP} python-home=/home/admin/web/myweb.site/public_html/venv/ python-path=/home/admin/web/myweb.site/public_html/venv/lib/python3.6/site-packages socket-user=admin
/home/admin/conf/web/myweb.site/apache2.conf
        WSGIDaemonProcess myweb.site-django-ssl user=admin group=admin processes=1 threads=5 display-name=%{GROUP} python-home=docroot%/venv/ python-path=/home/admin/web/myweb.site/public_html/venv/lib/python3.6/site-packages
/home/admin/conf/web/myweb.site/apache2.ssl.conf

Everything at /etc/apache2/mods-available/wsgi.conf is commented out, so that leaves the other 2 files, which have different names for the process…

UPDATE:
I also found this tutorial, but it’s not working for me. And at this point I don’t know if it’s because I messed something with my server… https://danieldevine.dev/creating-a-vesta-control-panel-template-for-django-projects-python-3-with-apache-nginx-virtualenv-and-mod_wsgi-on-ubuntu-server-16-04/

weird, I googled around a bit more and came across this: https://stackoverflow.com/questions/39317200/name-duplicates-previous-wsgi-daemon-definition

which also mentions

WSGIProcessGroup

from the snippet of your tpl/stpl you posted first it seems to be in there… from the quote of the ready made config later it seems to be missing. maybe run the same find for the processgroup again and check if it’s there at all and differs for ssl vs non-ssl.

I know it’s grasping at straws though… I am simply also running out of ideas, but I strongly believe that the error message is usually very close to the real problem :wink:

1 Like

All ideas are welcomed, even if they are just wild thoughts or random guessing.

I tried with WSGIProcessGroup and also adding process-group=%domain% to WSGIScriptAlias as suggested in another StackOverflow posts… Still the same.

At the moment I managed to have a WSGI process group not yet configured error with this wsgi_django.tpl template:

<VirtualHost %ip%:%web_port%>

    ServerName %domain_idn%
    %alias_string%
    Server%user% %email%
    DocumentRoot %docroot%
    ScriptAlias /cgi-bin/ %home%/%user%/web/%domain%/cgi-bin/
    Alias /vstats/ %home%/%user%/web/%domain%/stats/
    Alias /error/ %home%/%user%/web/%domain%/document_errors/
    SuexecUserGroup %user% %group%
    CustomLog /var/log/%web_system%/domains/%domain%.bytes bytes
    CustomLog /var/log/%web_system%/domains/%domain%.log combined
    ErrorLog /var/log/%web_system%/domains/%domain%.error.log
        
    IncludeOptional %home%/%user%/conf/web/%domain%/apache2.forcessl.conf*
    
    <Directory %home%/%user%/web/%domain%/stats>
        AllowOverride All
    </Directory>
    <Directory %sdocroot%>
        AllowOverride All
    </Directory>

    Alias /static /home/%user%/web/%domain%/private/django/app/static

    <Directory /home/%user%/web/%domain%/private/django/app/static>
        Require all granted
    </Directory>

    Alias /static /home/%user%/web/%domain%/private/django/app/static
    <Directory /home/%user%/web/%domain%/private/django/app/static>
        Require all granted
    </Directory>

    Alias /static /home/%user%/web/%domain%/private/django/app/media
    <Directory /home/%user%/web/%domain%/private/django/app/media>
        Require all granted
    </Directory>
    
    <Directory /home/%user%/web/%domain%/private/django/app/app>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>

    SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0

    IncludeOptional %home%/%user%/conf/web/%domain%/%web_system%.conf_*

    <IfModule mod_wsgi.c>
        WSGIDaemonProcess %domain%-ssdsd socket-user=%user% python-home=/home/%user%/web/%domain%/private/venv python-path=/home/%user%/web/%domain%/private/django/app
        WSGIProcessGroup %domain%-ppp
        WSGIScriptAlias / /home/%user%/web/%domain%/private/django/app/app/wsgi.py process-group=%domain%-ppp application-group=%{GLOBAL} 
    </IfModule>


</VirtualHost>

I’m using journalctl -xef to see the errors in real time. If anyone wants to give it a try, please be my guest.

With the error that I’m having, the conflicting line is:

WSGIScriptAlias / /home/%user%/web/%domain%/private/django/app/app/wsgi.py process-group=%domain%-ppp application-group=%{GLOBAL} 

Oddly enough, I found that other people also managed to have this running in VestaCP and a template like the one I’m writing. You can take a look at https://gitlab.com/neyder/vestacp-wsgi/-/tree/master/

I simply can’t understand why mine is not working.

OK, I think I’m giving up on WSGI for doing this… I will look for a different approach instead. :persevere: