Skip to content
Greg Neagle edited this page Feb 27, 2020 · 16 revisions

Following are some notes on installing MWA2 on RHEL7. Other Linux distros should be similar. There are a few additional notes for other related distros.

Install virtualenv

easy_install virtualenv or pip install virtualenv

On CentOS 8, virtualenv can be installed by yum yum install virtualenv. You will also need to install Python version 2 so that you can later use use it for your virtual environment yum install python2. If you do not install python2 so you can use it for your virtual environment, you will have syntax errors later when you try to run mwa2/manage.py

Create a virtual environment for MWA2

# cd /some/path/you/want/to/use
# virtualenv mwa2_env
New python executable in mwa2_env/bin/python
Installing setuptools, pip, wheel...done.

On CentOS 8, you will need to have virtualenv create an environment running python 2.7 virtualenv --python=python2.7 mwa2_env. Without this step, you will have syntax errors later when you try to run mwa2/manage.py

Activate the virtual environment

# cd mwa2_env

If you aren't using bash as your interactive shell, type bash and hit return

# source bin/activate
(mwa2_env)#

Install the Python dependencies

(mwa2_env)# pip install Django==1.9.1
(mwa2_env)# pip install django-wsgiserver==0.8.0rc1

(optional, if you plan to setup LDAP authentication)

(mwa2_env)# pip install django-auth-ldap

Fix django-webserver to work with Django 1.9.x

Edit mwa2_env/lib/python2.7/site-packages/django_wsgiserver/management/commands/runwsgiserver.py.
Change line 326 from:

        self.validate(display_num_errors=True)

to

        self.check(display_num_errors=True)

Clone the MWA2 code into the mwa2 virtual environment

If you changed directories at any point, make sure you are in the mwa2_env directory:

(mwa2_env)# cd /path/to/mwa2_env

Clone the mwa2 code from GitHub:

(mwa2_env)# git clone https://github.com/munki/mwa2.git
Cloning into 'mwa2'...
remote: Counting objects: 1138, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 1138 (delta 0), reused 0 (delta 0), pack-reused 1134
Receiving objects: 100% (1138/1138), 1.93 MiB | 463.00 KiB/s, done.
Resolving deltas: 100% (544/544), done.
Checking connectivity... done.
Checking out files: 100% (452/452), done.

Clone the munkitools into the virtual environment

MWA2 makes use of makecatalogs from Munki. You can just copy it locally into the virtual environment, or you can do what we do here, which is to clone the entire Munki project here, which allows us to update makecatalogs easily with a future git pull.

(mwa2_env)# git clone https://github.com/munki/munki.git
Cloning into 'munki'...
remote: Counting objects: 15612, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 15612 (delta 4), reused 0 (delta 0), pack-reused 15600
Receiving objects: 100% (15612/15612), 36.39 MiB | 2.41 MiB/s, done.
Resolving deltas: 100% (11208/11208), done.
Checking connectivity... done.

Duplicate and edit settings.py

(mwa2_env)# cp mwa2/munkiwebadmin/settings_template.py mwa2/munkiwebadmin/settings.py

Edit line 224 of mwa2/munkiwebadmin/settings.py, pointing MUNKI_REPO_DIR to the filesystem path to your repo

###########################################################################
# munkiwebadmin-specific
###########################################################################

# APPNAME is user-visible web app name
APPNAME = 'MunkiWebAdmin2'
# MUNKI_REPO_DIR holds the local filesystem path to the Munki repo
MUNKI_REPO_DIR = '/automounted/nfs/path/munki_repo'
#MUNKI_REPO_DIR = '/Volumes/repo

Edit line 242 of mwa2/munkiwebadmin/settings.py to point MAKECATALOGS_PATH to a copy of the makecatalogs tool. If you used git clone to get a copy of the Munki tools as suggested above, it will be in the munki/code/client/ directory.

# path to the makecatalogs binary
MAKECATALOGS_PATH = '/path/to/mwa2_env/munki/code/client/makecatalogs'

Initialize the app database

(mwa2_env)# python mwa2/manage.py migrate
Operations to perform:
  Apply all migrations: sessions, admin, auth, manifests, process, contenttypes, pkgsinfo
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying manifests.0001_initial... OK
  Applying pkgsinfo.0001_initial... OK
  Applying process.0001_initial... OK
  Applying sessions.0001_initial... OK

Create the superuser

(mwa2_env)# python mwa2/manage.py createsuperuser
Username (leave blank to use 'root'): root (or whatever you'd like)
Email address: [email protected]
Password: 
Password (again):
Superuser created successfully.

Start the development web server

(mwa2_env)# python mwa2/manage.py runwsgiserver host=0.0.0.0 port=8080
Validating models..
System check identified no issues (0 silenced).
May 04, 2016 - 22:49:41
Django version 1.9.1, using settings 'munkiwebadmin.settings'
cherrypy django_wsgiserver is running at http://0.0.0.0:8080/
Quit the server with CONTROL-C.

Test the server

In a web browser, navigate to http://[hostname_or_ip_of_the_rhel7_box]:8080

Optional/advanced

Configure LDAP authentication

Edit lines 167-191 of mwa2/munkiwebadmin/settings.py.
See https://pythonhosted.org/django-auth-ldap/authentication.html#server-config for detailed documentation.
Be sure to set USE_LDAP to True.

# django ldap auth
USE_LDAP = True
# LDAP authentication support
if USE_LDAP:
    import ldap
    from django_auth_ldap.config import LDAPSearch, PosixGroupType
    
    # LDAP settings
    AUTH_LDAP_SERVER_URI = "ldap://foo.example.com"
    AUTH_LDAP_BIND_DN = ""
    AUTH_LDAP_BIND_PASSWORD = ""
    AUTH_LDAP_USER_SEARCH = LDAPSearch(
        "ou=People,o=ExampleCorp,c=US",
        ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
    AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
        "ou=Groups,o=ExampleCorp,c=US",
        ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)")
    AUTH_LDAP_GROUP_TYPE = PosixGroupType()
    AUTH_LDAP_FIND_GROUP_PERMS = True
    AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", 
                               "last_name": "sn",
                               "email": "mail"}
    # Cache group memberships for an hour to minimize LDAP traffic
    AUTH_LDAP_CACHE_GROUPS = True
    AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600

Configuring MWA2 to start at boot (systemd-style)

This is not a guide to systemd or systemctl, and I am no systemctl expert, so there may be "better" approaches here:

Create a run script in the mwa2 directory
[root@vmmunki]# vi run_mwa2.sh

Be sure to replace the paths with the correct paths to your mwa2_env directory. Change the port number as desired/required:

#!/bin/sh

/path/to/mwa2_env/bin/python /path/to/mwa2_env/mwa2/manage.py runwsgiserver port=8080 host=0.0.0.0

Make sure it's executable:

[root@vmmunki]# chmod a+x run_mwa2.sh
Create a systemd service file
[root@vmmunki]# vi /etc/systemd/system/mwa2.service

Again, alter the path to the mwa2_env match your specific path:

[Unit]
Description=MunkiWebAdmin2
Requires=httpd.service
After=httpd.service

[Service]
ExecStart=/path/to/mwa2_env/run_mwa2.sh
Restart=always

[Install]
WantedBy=multi-user.target
Tell systemd to load and run the mwa2.service
[root@vmmunki]# systemctl enable mwa2
Created symlink from /etc/systemd/system/multi-user.target.wants/mwa2.service to /etc/systemd/system/mwa2.service.
[root@vmmunki]# systemctl start mwa2

MWA2 should be running shortly; you can check its status:

[root@vmmunki]# systemctl status mwa2
● mwa2.service - MunkiWebAdmin2
   Loaded: loaded (/etc/systemd/system/mwa2.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2016-05-06 09:52:02 PDT; 33s ago
 Main PID: 11070 (run_mwa2.sh)
   CGroup: /system.slice/mwa2.service
           ├─11070 /path/to/mwa2_env/run_mwa2.sh
           └─11071 /path/to/mwa2_env/bin/python /path/to/mwa2_env/mwa2/manage.py runwsgiserver port=8080...

May 06 09:52:02 vmmunki systemd[1]: Started MunkiWebAdmin2.
May 06 09:52:02 vmmunki systemd[1]: Starting MunkiWebAdmin2...

Configure Apache and mod_wsgi to serve the app

(notes by @dimaui)

I will just be covering the mwa2 specific content and not the complete Apache setup.
This can probably be solved a lot nicer then the way I did it I am no python or apache expert.

Copy the content here to your mwa2/munkiwebadmin/wsgi.py file and edit the paths.
import os
import sys
import site

MUNKIWEBADMIN_ENV_DIR = '/usr/local/mwa2_env/'
MY_ENV_DIR2 = '/usr/local/mwa2_env/mwa2/'
# Use site to load the site-packages directory of our virtualenv
site.addsitedir(os.path.join(MUNKIWEBADMIN_ENV_DIR, 'lib/python2.7/site-packages'))

# Make sure we have the virtualenv and the Django app itself added to our path
sys.path.append(MUNKIWEBADMIN_ENV_DIR)
sys.path.append(MY_ENV_DIR2)
sys.path.append(os.path.join(MY_ENV_DIR2, 'munkiwebadmin'))

os.environ['DJANGO_SETTINGS_MODULE'] = 'munkiwebadmin.settings'

import django
django.setup()
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Create your apache config.

Make sure to edit the paths, users and wsgi process to suite your needs. I run an environment with multipe mwa instances and a growing number of mwa2 instances as well as some other webapps. I need the WSGIDaemonProcess and WSGIProcessGroup for my setup to work proplerly without these i have no write access to the sqlite database within mwa2.

RHEL / CentOS 6 using Apache 2.2
#MWA2 PART
<VirtualHost *:80>
   ServerName xxxxxxxx1337.company.com
   WSGIScriptAlias / /usr/local/mwa2_env/mwa2/munkiwebadmin/wsgi.py
   WSGIDaemonProcess companymwa user=munkiwebadmin group=munki
   <Directory /usr/local/mwa2_env/mwa2/munkiwebadmin>
        WSGIProcessGroup companymwa
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
   </Directory>
</VirtualHost>
RHEL / CentOS 7 using Apache 2.4
#MWA2 PART
<VirtualHost *:80>
   ServerName xxxxxxxx1337.company.com
   WSGIScriptAlias / /usr/local/mwa2_env/mwa2/munkiwebadmin/wsgi.py
   WSGIDaemonProcess companymwa user=munkiwebadmin group=munki
   <Directory /usr/local/mwa2_env/mwa2/munkiwebadmin>
        WSGIProcessGroup companymwa
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
   </Directory>
</VirtualHost>