Debian setup notes - kawajanagi/mwa2 GitHub Wiki
Following are some notes on installing MWA2 on Debian 12 (Bookworm). Other Linux distros should be similar. There are a few additional notes for other related distros.
apt install python3-venv
On Debian 12, virtualenv can be installed by apt
apt install python3-venv
. You will also need to install Python version 3 so that you can later use use it for your virtual environmentapt install python3
. If you do not install python3 so you can use it for your virtual environment, you will have syntax errors later when you try to run mwa2/manage.py
# cd /some/path/you/want/to/use
# virtualenv mwa2_env
New python executable in mwa2_env/bin/python
Installing setuptools, pip, wheel...done.
On Debian 12, you will need to have virtualenv create an environment running python 3
python3 -m venv mwa2_env
. Without this step, you will have syntax errors later when you try to run mwa2/manage.py
# cd mwa2_env
If you aren't using bash as your interactive shell, type bash
and hit return
# source bin/activate
(mwa2_env)#
(mwa2_env)# pip install Django==4.2.11
(mwa2_env)# pip install gunicorn==20.1.0
(optional, if you plan to setup LDAP authentication)
(mwa2_env)# pip install django-auth-ldap
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: Enumerating objects: 1444, done.
remote: Counting objects: 100% (59/59), done.
remote: Compressing objects: 100% (46/46), done.
remote: Total 1444 (delta 15), reused 28 (delta 8), pack-reused 1385 (from 1)
Receiving objects: 100% (1444/1444), 2.00 MiB | 3.99 MiB/s, done.
Resolving deltas: 100% (704/704), done.
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: Enumerating objects: 35375, done.
remote: Counting objects: 100% (1697/1697), done.
remote: Compressing objects: 100% (538/538), done.
remote: Total 35375 (delta 1418), reused 1239 (delta 1157), pack-reused 33678 (from 3)
Receiving objects: 100% (35375/35375), 20.88 MiB | 4.73 MiB/s, done.
Resolving deltas: 100% (25164/25164), done.
(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 = '/mnt/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'
Add the following line at the end of the file to refer to the FQDN of the main Apache2 website that will be allowed to talk to the Gunicorn server so that it's the only site that can do unsecure requests to Gunicorn. This is especially true if leveraging HTTPS.
# URL to the main Apache2
CSRF_TRUSTED_ORIGINS = ['https://hostname.company.com:443']
#### 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)# cd mwa2 (mwa2_env)# gunicorn -c gunicorn.py munkiwebadmin.wsgi:application Starting gunicorn 20.1.0 Listening at: http://0.0.0.0:8000 (349470) Using worker: sync Booting worker with pid: 349471 Booting worker with pid: 349472 Booting worker with pid: 349473
#### 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`.
USE_LDAP = True
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/'
site.addsitedir(os.path.join(MUNKIWEBADMIN_ENV_DIR, 'lib/python2.7/site-packages'))
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 and hostnames to suite your needs.
I use a Gunicorn process that gets proxied from the Apache server for the WSGI elements displayed on the MWA2 pages.
###### Debian 12 using Apache 2.4
#MWA2 PART <VirtualHost *:80> ServerName hostname.domain.com
ProxyPass /catalogs/static/ !
ProxyPass /manifests/static/ !
ProxyPass /munkiwebadmin/static/ !
ProxyPass /pkgsinfo/static/ !
ProxyPass / http://localhost:8000/
<Directory /usr/local/mwa2-env>
Require all granted
Options -Indexes
</Directory>