diff --git a/ansible/cluster.yml b/ansible/cluster.yml
index 9664bf9e22996377bec93b4d4eb4155830a1d0d7..d940e1b41809b0d8eab20b738157e4f2d3ca64c6 100644
--- a/ansible/cluster.yml
+++ b/ansible/cluster.yml
@@ -14,3 +14,5 @@
     - { name: 'rewrite_map', tags: 'rewrite_map', when: enable_rewrite_map }
     - { name: 'fail2ban', tags: 'fail2ban', when: enable_fail2ban }
     - { name: 'install_node_exporter', tags: 'install_node_exporter', when: enable_node_exporter }
+    - { name: 'ood_config', tags: 'ood_config', when: enable_ood_config }
+
diff --git a/ansible/group_vars/all b/ansible/group_vars/all
index 46267cd8eb7d645ece328c8f74f82fb3d536fa77..1fd150ee38d6fca531845519b3f5cabd9a7b3f83 100644
--- a/ansible/group_vars/all
+++ b/ansible/group_vars/all
@@ -89,3 +89,10 @@
   node_exporter_user: node_exporter
   node_exporter_group: node_exporter
   node_exporter_port: 9100
+
+# ood_config
+  enable_ood_config: false
+  ood_internal_ip: 10.141.0.133
+  ood_hostname: ood-gpfs5-01
+  ood_domain: https://rc.uab.edu
+  login_hostname: login-gpfs5-01
diff --git a/ansible/roles/ood_config/tasks/main.yml b/ansible/roles/ood_config/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..75d140eee911d30218c4450cc515d11da8a92beb
--- /dev/null
+++ b/ansible/roles/ood_config/tasks/main.yml
@@ -0,0 +1,33 @@
+---
+- name: Add apache config to accept connections only from proxy
+  ansible.builtin.template:
+    src: ood_proxy.conf.j2
+    dest: /opt/rh/httpd24/root/etc/httpd/conf.d/ood-proxy.conf
+
+- name: Download patched shell app with shell timeout fix
+  ansible.builtin.get_url:
+    url: https://s3.lts.rc.uab.edu/ood-proxy-file/ood-proxy.conf
+    dest: /var/www/ood/apps/sys/shell/app.js
+
+- name: Create a directory if it does not exist
+  ansible.builtin.file:
+    path: /etc/ood/config/apps/shell
+    state: directory
+    mode: "0755"
+
+- name: Shell app configuration env
+  ansible.builtin.template:
+    src: shell_app.env.j2
+    dest: /etc/ood/config/apps/shell/env
+
+- name: Point shell app to login node
+  ansible.builtin.replace:
+    path: /etc/ood/config/clusters.d/SLURM_CLUSTER.yml
+    regexp: '^(\s+host:).*'
+    replace: '\1 "{{ login_hostname }}"'
+    backup: yes
+
+- name: Restart httpd24-httpd
+  ansible.builtin.service:
+    name: httpd24-httpd
+    state: restarted
diff --git a/ansible/roles/ood_config/templates/ood_proxy.conf.j2 b/ansible/roles/ood_config/templates/ood_proxy.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d6ef3adcdaa14042fb6536c722c88b1e3e6e3f71
--- /dev/null
+++ b/ansible/roles/ood_config/templates/ood_proxy.conf.j2
@@ -0,0 +1,206 @@
+#
+# Open OnDemand Portal
+#
+# Generated using ood-portal-generator version 0.8.0
+#
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# !!                                    !!
+# !!     DO NOT EDIT THIS FILE          !!
+# !!                                    !!
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#
+# This file is auto-generated by ood-portal-generator and will be over-written
+# in future updates.
+#
+# 1. To modify this file, first update the global configuration file:
+#
+#      /etc/ood/config/ood_portal.yml
+#
+#    You can find more information about the ood-portal-generator configuration
+#    at:
+#
+#      https://osc.github.io/ood-documentation/master/infrastructure/ood-portal-generator.html
+#
+# 2. Then build/install the updated Apache config with:
+#
+#      sudo /opt/ood/ood-portal-generator/sbin/update_ood_portal
+#
+# 3. Finally, restart Apache to have the changes take effect:
+#
+#      # For CentOS 6
+#      sudo service httpd24-httpd condrestart
+#      sudo service httpd24-htcacheclean condrestart
+#
+#      # For CentOS 7
+#      sudo systemctl try-restart httpd24-httpd.service httpd24-htcacheclean.service
+#
+
+
+
+# The Open OnDemand portal VirtualHost
+#
+<VirtualHost {{ ood_internal_ip }}:80>
+  ServerName {{ ood_hostname }}
+
+  ErrorLog  "logs/SERVER_HOSTNAME_error.log"
+  CustomLog "logs/SERVER_HOSTNAME_access.log" combined
+
+  RewriteEngine On
+  RewriteCond %{HTTP_HOST} !^(rc.uab.edu(:80)?)?$ [NC]
+  RewriteRule ^(.*) http://rc.uab.edu:80$1 [R=301,NE,L]
+
+
+  # Lua configuration
+  #
+  LuaRoot "/opt/ood/mod_ood_proxy/lib"
+  LogLevel lua_module:info
+
+  # Log authenticated user requests (requires min log level: info)
+  LuaHookLog logger.lua logger
+
+  # Authenticated-user to system-user mapping configuration
+  #
+  SetEnv OOD_USER_MAP_CMD "/opt/ood/ood_auth_map/bin/user_auth.py"
+  SetEnv OOD_USER_ENV "REMOTE_USER"
+  SetEnv OOD_MAP_FAIL_URI "/account"
+
+  # Per-user Nginx (PUN) configuration
+  # NB: Apache will need sudo privs to control the PUNs
+  #
+  SetEnv OOD_PUN_STAGE_CMD "sudo /opt/ood/nginx_stage/sbin/nginx_stage"
+
+  #
+  # Below is used for sub-uri's this Open OnDemand portal supports
+  #
+
+  # Serve up publicly available assets from local file system:
+  #
+  #     http://SERVER_HOSTNAME:80/public/favicon.ico
+  #     #=> /var/www/ood/public/favicon.ico
+  #
+  Alias "/public" "/var/www/ood/public"
+  <Directory "/var/www/ood/public">
+    Options Indexes FollowSymLinks
+    AllowOverride None
+    Require all granted
+  </Directory>
+
+  # Reverse proxy traffic to backend webserver through IP sockets:
+  #
+  #     http://SERVER_HOSTNAME:80/node/HOST/PORT/index.html
+  #     #=> http://HOST:PORT/node/HOST/PORT/index.html
+  #
+  <LocationMatch "^/node/(?<host>c\d+)/(?<port>\d+)">
+    RewriteCond %{IS_SUBREQ} ^false$
+    RewriteCond %{HTTP:Proxy-user} "([^!]+?)(@uab.edu)?$"
+    RewriteRule . - [E=REMOTE_USER:%1]
+
+    # ProxyPassReverse implementation
+    Header edit Location "^[^/]+//[^/]+" ""
+
+    # ProxyPassReverseCookieDomain implemenation
+    Header edit* Set-Cookie ";\s*(?i)Domain[^;]*" ""
+
+    # ProxyPassReverseCookiePath implementation
+    Header edit* Set-Cookie ";\s*(?i)Path[^;]*" ""
+    Header edit  Set-Cookie "^([^;]+)" "$1; Path=/node/%{MATCH_HOST}e/%{MATCH_PORT}e"
+
+    LuaHookFixups node_proxy.lua node_proxy_handler
+  </LocationMatch>
+
+  # Reverse "relative" proxy traffic to backend webserver through IP sockets:
+  #
+  #     http://SERVER_HOSTNAME:80/rnode/HOST/PORT/index.html
+  #     #=> http://HOST:PORT/index.html
+  #
+  <LocationMatch "^/rnode/(?<host>c\d+)/(?<port>\d+)(?<uri>/.*|)">
+    RewriteCond %{IS_SUBREQ} ^false$
+    RewriteCond %{HTTP:Proxy-user} "([^!]+?)(@uab.edu)?$"
+    RewriteRule . - [E=REMOTE_USER:%1]
+
+    # ProxyPassReverse implementation
+    Header edit Location "^([^/]+//[^/]+)|(?=/)" "/rnode/%{MATCH_HOST}e/%{MATCH_PORT}e"
+
+    # ProxyPassReverseCookieDomain implemenation
+    Header edit* Set-Cookie ";\s*(?i)Domain[^;]*" ""
+
+    # ProxyPassReverseCookiePath implementation
+    Header edit* Set-Cookie ";\s*(?i)Path[^;]*" ""
+    Header edit  Set-Cookie "^([^;]+)" "$1; Path=/rnode/%{MATCH_HOST}e/%{MATCH_PORT}e"
+
+    LuaHookFixups node_proxy.lua node_proxy_handler
+  </LocationMatch>
+
+  # Reverse proxy traffic to backend PUNs through Unix domain sockets:
+  #
+  #     http://SERVER_HOSTNAME:80/pun/dev/app/simulations/1
+  #     #=> unix:/path/to/socket|http://localhost/pun/dev/app/simulations/1
+  #
+  SetEnv OOD_PUN_URI "/pun"
+  <Location "/pun">
+    RewriteCond %{IS_SUBREQ} ^false$
+    RewriteCond %{HTTP:Proxy-user} "([^!]+?)(@uab.edu)?$"
+    RewriteRule . - [E=REMOTE_USER:%1]
+
+    ProxyPassReverse "http://localhost/pun"
+
+    # ProxyPassReverseCookieDomain implementation (strip domain)
+    Header edit* Set-Cookie ";\s*(?i)Domain[^;]*" ""
+
+    # ProxyPassReverseCookiePath implementation (less restrictive)
+    Header edit* Set-Cookie ";\s*(?i)Path\s*=(?-i)(?!\s*/pun)[^;]*" "; Path=/pun"
+
+    SetEnv OOD_PUN_SOCKET_ROOT "/var/run/ondemand-nginx"
+    SetEnv OOD_PUN_MAX_RETRIES "5"
+    LuaHookFixups pun_proxy.lua pun_proxy_handler
+
+  </Location>
+
+  # Control backend PUN for authenticated user:
+  # NB: See mod_ood_proxy for more details.
+  #
+  #    http://SERVER_HOSTNAME:80/nginx/stop
+  #    #=> stops the authenticated user's PUN
+  #
+  SetEnv OOD_NGINX_URI "/nginx"
+  <Location "/nginx">
+    RewriteCond %{IS_SUBREQ} ^false$
+    RewriteCond %{HTTP:Proxy-user} "([^!]+?)(@uab.edu)?$"
+    RewriteRule . - [E=REMOTE_USER:%1]
+
+    LuaHookFixups nginx.lua nginx_handler
+  </Location>
+
+  # Redirect root URI to specified URI
+  #
+  #     http://SERVER_HOSTNAME:80/
+  #     #=> http://SERVER_HOSTNAME:80/pun/sys/dashboard
+  #
+  RedirectMatch ^/$ "/pun/sys/dashboard"
+
+  # Redirect logout URI to specified redirect URI
+  #
+  #     http://SERVER_HOSTNAME:80/logout
+  #     #=> http://SERVER_HOSTNAME:80/pun/sys/dashboard/logout
+  #
+  Redirect "/logout" "/pun/sys/dashboard/logout"
+
+
+
+
+  # Register and/or unregister the mapping of an authenticated-user to a system-user
+  # NB: This is not needed for regular expression mapping
+  #
+  #     http://SERVER_HOSTNAME:80/account
+  #     #=> /var/www/ood/register/
+  #
+  Alias "/account" "/var/www/ood/register"
+  <Directory "/var/www/ood/register">
+    Options Indexes FollowSymLinks
+    AllowOverride None
+
+    RewriteCond %{IS_SUBREQ} ^false$
+    RewriteCond %{HTTP:Proxy-user} "([^!]+?)(@uab.edu)?$"
+    RewriteRule . - [E=REMOTE_USER:%1]
+  </Directory>
+</VirtualHost>
diff --git a/ansible/roles/ood_config/templates/shell_app.env.j2 b/ansible/roles/ood_config/templates/shell_app.env.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b078fe82172cc83a38a5bbef882fa7c73fb5b3b3
--- /dev/null
+++ b/ansible/roles/ood_config/templates/shell_app.env.j2
@@ -0,0 +1 @@
+OOD_SHELL_ORIGIN_CHECK='{{ ood_domain }}'
diff --git a/openstack-ood/nodeimage.pkr.hcl b/openstack-ood/nodeimage.pkr.hcl
index 1a1374419cd8ed985a4cde57378154a5cf07ff3f..6ade3c0bfd08dfcc8e56552b039f56fd5c6f35f9 100644
--- a/openstack-ood/nodeimage.pkr.hcl
+++ b/openstack-ood/nodeimage.pkr.hcl
@@ -60,7 +60,7 @@ build {
 
   provisioner "shell" {
     inline = [
-      "sudo yum install -y libselinux-python3 python3 python3-pip tmux vim git bash-completion curl wget unzip",
+      "sudo yum install -y libselinux-python3 python3 python3-pip tmux vim git bash-completion curl wget unzip NetworkManager",
       "sudo python3 -m pip install --upgrade pip",
       "sudo pip3 install s3cmd==2.3.0 ansible==4.10.0 python-openstackclient==5.8.0"
     ]