Troubles with Apache reverse proxy while trying to run CMS in a subdirectory

# CMS Version
2.3.10

# Installation Method
Docker

# Operating System
Oracle Linux 8 (Red Hat 8)
Apache 2.4.37
Docker 20.10.7

# Issue
Hello,
I apologize up front as I am going to make an assumption that this will be a rather long post. I would also like to right away give my thanks for all that the Xibo team, and any person who responds to my post.

- What we are trying to do:
The development team I supervise is working towards using Xibo within our establishment. We have the Xibo CMS in docker behind an Apache reverse proxy and everything is working as intended, or at least as far as we can tell.

Due to the nature of our establishment we have also created two different web based apps that directly access the Xibo CMS API.

The first app, known as the submission system (SS), allows for certain people, without any access to Xibo, to be able to upload an advertisement, provide a start and end date, and then SS will contact the Xibo API and upload the image when the advertisement is suppose to start displaying on the units.

The second app, known as the Xibo alerts system (XAS), monitors an emergency alert system that is used on the campus in which we work. XAS will contact the Xibo CMS API when the Alert system indicates there is a message to be displayed. XAS will then checkout a specific layout, update the widgets within the layout, publish the layout, and then execute a schedule now for that lay out on a specific display group. This causes the Xibo CMS to display the emergency alert system on our digital signs.

- Where we are having issues:
What we would really like to do is to be able to host the SS and XAS apps within the same server as the CMS. Such as in the image below.

So in the end we would like to have the Xibo CMS be active only on the /cms URL of the server and the root of the server to be SS and the /alerts URL to be XAS.

We have tried to follow all of the instructions we could find but for some reason we keep running into weird issues and we are at a lost here.

Just for clarity the XAS and SS applications have been Dockerized and we know they work in the Docker setup when each app is the only Docker container running.

- What we have tried to do:
We have followed the steps to have the CMS be located at the /cms URL and that sort of works.

The docker container does spin up and we can access the CMS but at the exact same time we can still access the CMS at the root of the server URL. In addition, when we do set the CMS_ALIAS directive in the config.env and restart the Docker containers and Apache the CMS API stops working.

The CMS API will return a 404 not found when the CMS Docker container is not running on the root of the server.

- Here is our configuration files and other info for the server.


Apache Configuration File:

# Virtual Hosts # Required modules: mod_log_config

# If you want to maintain multiple domains/hostnames on your # machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about # IP addresses. This is indicated by the asterisks in the directives below.
# # Please see the documentation at
# <URL: Removed for post> # for further details before you try to setup virtual hosts.
# # You may use the command line option β€˜-S’ to verify your virtual host
` # configuration.

# VirtualHost example: # Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not # match a ServerName or ServerAlias in any block.

<VirtualHost *:80>

DocumentRoot "/var/www/html/"
ServerName <server url>

<Directory "/var/www/html/">
	Redirect permanent "/" "<server url>"
    Options FollowSymLinks MultiViews
    AllowOverride All
    Require all granted
</Directory>

NameVirtualHost *:443

<VirtualHost *:443>
DocumentRoot β€œ/var/www/html/”
ServerName

 SSLEngine on

 SSLProtocol +TLSv1.2

 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
# --- END New settings ---

 SSLHonorCipherOrder on

SSLCertificateFile "/etc/pki/tls/certs/cert.pem"
SSLCertificateKeyFile "/etc/pki/tls/private/key.pem"
SSLCertificateChainFile "/etc/pki/tls/certs/Global_Chain.pem"

# ErrorDocument 404 /server_error_pages/404.php

ErrorLog "/var/log/httpd/error_log"
CustomLog "/var/log/httpd/access_log" common
CustomLog logs/ssl_request_log \
     "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

ProxyPreserveHost On
ProxyRequests Off

RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"


# Submission system
<Location />
   ProxyPass http://127.0.0.1:9000/
   ProxyPassReverse http://127.0.0.1:9000/
</Location>

# Xibo CMS
<Location /cms>   
   ProxyPass http://127.0.0.1:9001/cms
   ProxyPassReverse http://127.0.0.1:9001/cms
</Location>
  
# Alerts system
<Location /alerts> 
   ProxyPass http://127.0.0.1:9002/
   ProxyPassReverse http://127.0.0.1:9002/
</Location>

# Prevents git directory, and files from being served.
<DirectoryMatch "^/.*/\.git/">
  Require all denied
</DirectoryMatch>

# Prevent sensitive application files from being served.
<FilesMatch "\.(env|md|gitignore|gitattributes)">
  Require all denied
</FilesMatch>

<FilesMatch "(package.json|composer.json)">
  Require all denied
</FilesMatch>

#    Header set Content-Security-Policy "frame-ancestors none;"

config.env

` ## CMS Configuration

## Please make a copy of this file as config.env, and then ## edit it to suit your environment

## The CMS brings its own MySQL server to store your ## data.
## On a new installation, we need to create a user account for the CMS to ## connect to that database with. What password should
## that account use? Enter a random password here. ## We recommend using a 16 character random upper/lower case
## and digits. ## You could for example use the random.org password generator
## here: ## IMPORTANT: DO NOT USE SPECIAL CHARACTERS, SPACES etc. Please use only
## alpha-numeric (ie A-Z a-z 0-9) passwords of around 16 characters. The ## random generator linked above will give you something suitable.
## ## If you’re upgrading an existing installation, be sure to use the correct
## password for the cms user account in the MySQL database (ie what you had in ## this variable previously).

MYSQL_PASSWORD=

## SMTP Server Configuration ## The CMS needs to be able to send email to you
## Please enter credentials for a suitable SMTP server ## Defaults will work for GMail - replacing your GMail username
## and password as appropriate. You will also need to enable access ## for less secure applications on your GMail account for this to
` ## work.

` ## SMTP Server Hostname
CMS_SMTP_SERVER=

` ## SMTP Username

CMS_SMTP_USERNAME=youraccount@gmail.com

## SMTP Password # CMS_SMTP_PASSWORD=yourpassword

## Use a TLS Connection YES/NO # CMS_SMTP_USE_TLS=YES
CMS_SMTP_USE_TLS=NO

## Use a STARTTLS Connection YES/NO # CMS_SMTP_USE_STARTTLS=YES
` # CMS_SMTP_USE_STARTTLS=NO
CMS_SMTP_USE_STARTTLS=NO

` ## Rewrite domain (the domain your email will appear to come from)
CMS_SMTP_REWRITE_DOMAIN=

` ## Hostname that we should identify ourself to the remote server as
CMS_SMTP_HOSTNAME=

## Can the From line be overridden in the outbound email ## NB GMail will rewrite the From address anyway so it’s not important
` ## for GMail - YES/NO
CMS_SMTP_FROM_LINE_OVERRIDE=YES

## It is sometimes necessary to configure the webserver running inside ## the container to know the DNS name by which you will normally
## access the CMS. For most installations this is unnecessary and can ## be left as default, however, if you know this, it won’t hurt to
` ## set it
CMS_SERVER_NAME=

## Sometimes you want Xibo to run in a sub directory of the webserver ## rather than at the root. If so, specify it here. Comment it out to
## use the web root. # CMS_ALIAS=/xibo
CMS_ALIAS=/cms

## Xibo comes with a 2GB limit for individual file uploads ## If you require larger files, uncomment the following and adjust as
## required # CMS_PHP_POST_MAX_SIZE=4G
# CMS_PHP_UPLOAD_MAX_FILESIZE=4G CMS_PHP_UPLOAD_MAX_FILESIZE=75M # CMS_PHP_MAX_EXECUTION_TIME=600


CMS Docker Compose

version: β€œ2.1”

services:
cms-db:
image: mysql:5.7
volumes:
- β€œ./shared/db:/var/lib/mysql:Z”
environment:
- MYSQL_DATABASE=cms
- MYSQL_USER=cms
- MYSQL_RANDOM_ROOT_PASSWORD=yes
mem_limit: 1g
env_file: config.env
restart: always
cms-xmr:
image: xibosignage/xibo-xmr:release-0.8
ports:
- β€œ9505:9505”
restart: always
mem_limit: 256m
env_file: config.env
cms-web:
image: xibosignage/xibo-cms:release-2.3.10
volumes:
- β€œ./shared/cms/custom:/var/www/cms/custom:Z”
- β€œ./shared/backup:/var/www/backup:Z”
- β€œ./shared/cms/web/theme/custom:/var/www/cms/web/theme/custom:Z”
- β€œ./shared/cms/library:/var/www/cms/library:Z”
- β€œ./shared/cms/web/userscripts:/var/www/cms/web/userscripts:Z”
- β€œ./shared/cms/ca-certs:/var/www/cms/ca-certs:Z”
restart: always
links:
- cms-db:mysql
- cms-xmr:50001
environment:
- XMR_HOST=cms-xmr
env_file: config.env
ports:
- β€œ127.0.0.1:9001:80”
mem_limit: 1g
cms-quickchart:
image: ianw/quickchart
restart: always

Again, I apologize for the length of this post. I am really hoping that someone has a solution to our issue.

Thank you,

1 Like

Hello,

Thank you for those who viewed this posting. We have figured the issue with attempting to move the CMS down a directory, off of the web root, using an Apache reverse proxy.

I am submitting my solution here as I know that other people look at the posts here for support.

- What was wrong

The issue with attempting to move the CMS down a directory is that the entrypoint.sh file within the CMS Docker container does handle using the CMS_ALIAS from the config.env file to modify the .htaccess file within the /var/www/cms/web/ directory. However, the entrypoint.sh file does not complete all of the actions that would be needed to be done on the .htaccess file if a person has set the CMS_ALIAS configuration within the config.env file.

The entrypoint.sh file will uncomment and update the RewriteBase directive in the .htaccess file with the value of the CMS_ALIAS set within the config.env file but it does not modify the rewrite conditions for the API end points which it would have to do so if the CMS has moved down a directory.

Here is what the .htaccess file will look like in the Docker container once the container is spun up and a value is set on the CMS_ALIAS variable. The below example is with the assumption that the CMS_ALIAS was set to /cms.

RewriteEngine On
RewriteBase /cms

RewriteCond %{HTTP:Authorization} .+
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/api/authorize/.*$
RewriteRule ^ api/authorize/index.php [QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/api/.*$
RewriteRule ^ api/index.php [QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/maint/.*$
RewriteRule ^ maint/index.php [QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !.(css|js|png|jpg)$
RewriteCond %{REQUEST_URI} !^/dist/.$
RewriteCond %{REQUEST_URI} !^/theme/.
$
RewriteRule ^ index.php [QSA,L]

As you can see in the rewrite conditions for the API access points that the rewrite condition is never matched due to the assertion of the start of the line in the regex condition for the API endpoints.
The rewrite conditions will match only when the rewrite base is not used.

- How to fix the issue

What needs to happen is to remove the ^ symbols in the rewrite conditions for the API end points so they look below.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /api/authorize/.*$
RewriteRule ^ api/authorize/index.php [QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /api/.*$
RewriteRule ^ api/index.php [QSA,L]

The issue is that the .htaccess file needs to be in the spun up CMS Docker container.

This is how we solved the issue. I have no idea if this would be the correct method or not so if you know a better way to solve this issue please contact me.

  1. First we obtained a copy of the .htaccess file from the spun up Docker container. We pulled a copy of the file when the CMS_ALIAS in the config.env was active.
  2. We updated the .htaccess file to correct for the issue.
  3. We placed the modified .htaccess file in our persistent volume for the CMS, /shared/cms/web/.
  4. We modified the docker-compose.yml file and added a specific file for the /var/www/cms/web/ directory within the container. What we added was the reference to the modified .htaccess file. See example below.

cms-web:
image: xibosignage/xibo-cms:release-2.3.10
volumes:
- β€œ./shared/cms/custom:/var/www/cms/custom:Z”
- β€œ./shared/backup:/var/www/backup:Z”
- β€œ./shared/cms/web/theme/custom:/var/www/cms/web/theme/custom:Z”
- β€œ./shared/cms/library:/var/www/cms/library:Z”
- β€œ./shared/cms/web/userscripts:/var/www/cms/web/userscripts:Z”
- β€œ./shared/cms/ca-certs:/var/www/cms/ca-certs:Z”
- β€œ./shared/cms/web/.htaccess:/var/www/cms/web/.htaccess:Z”

  1. Spin down and up the containers and everything should work after that.

I hope this helps someone someday.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.