Skip to main content

Apache httpd.conf settings

Modifying the Bitnami instance httpd.conf files

bitnami.conf (/opt/bitnami/apache/conf/bitnami/bitnami.conf)

Make sure to add these modifications to the server's bitnami.conf file (on Bitnami instances, this is in /opt/bitnami/apache/conf/bitnami/bitnami.conf), and also to modify the DocumentRoot and other applicable parts of the bitnami-ssl.conf file. Additionally make the DocumentRoot and Directory changes to the main httpd.conf and httpd-ssl.conf files.

# The root folder for files that Apache will serve.
# The default is the htdocs folder; for Deserted Chateau,
# it is /opt/bitnami/apache/htdocs/public .
DocumentRoot "/opt/bitnami/apache/htdocs/public"

<Directory "/opt/bitnami/apache/htdocs/public">

# Do not allow .htaccess files to override these settings.
AllowOverride None
# Do not show the contents of folders for URLs ending in /.
Options -Indexes
httpd.conf (/opt/bitnami/apache/conf/httpd.conf)

Modify the main section (i.e. outside any <Directory> or other tags) by modifying the ErrorLog directive:

# Where Apache will write error logs.
# It is best practice for the logs folder not to be
# inside the DocumentRoot to avoid accidental internet exposure.
ErrorLog "/opt/bitnami/apache/htdocs/logs/apache_error_log"

Modify the area within the <IfModule log_config_module> section:

# For logging non-error messages.
# Again, for best practices, put this folder outside the DocumentRoot.
CustomLog "/opt/bitnami/apache/htdocs/logs/apache_access_log" common

Insert the following at the end of the <Directory=/opt/bitnami/apache/htdocs/public> section. This is for Deserted Chateau only - you can read the comments to get an idea of what this does to help understand how to use the rewrite module on your own website.

# Stops unexpected behaviour when requesting an existing folder without a slash, e.g. https://desertedchateau.com/admin .
DirectorySlash Off

# Enable the mod_rewrite engine.
RewriteEngine on

# If the client connected via HTTP, rewrite the URL to HTTPS.
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=permanent,L]

# It is necessary to comment the BELOW lines when a LIGHTSAIL load balancer IS in use,
# as Lightsail load balancers only forward traffic on port 80 (HTTP).
# Otherwise we end up in an infinite HTTP => HTTPS loop.

RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

# Remove www from the URL.
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]

# Uncomment the below lines to enable maintenance mode.
# This will redirect ALL site requests to the maintenance page.

#RewriteCond %{REQUEST_URI} !/maintenance(.php)?$ [NC]
#RewriteRule ^ /maintenance [R=302,L]

# Rewrite any request containing ".php" to remove the .php extension.
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\ (.*)\.php [NC]
RewriteRule ^ %1 [R=301,L]

# Redirect requests to /reports/ to the correct index page for that directory.
RewriteCond %{REQUEST_URI} ^/reports/$ [NC]
RewriteRule ^(.*)$ /reports/reportshome [L]

# Redirect requests to /moderation/ to the correct index page for that directory.
RewriteCond %{REQUEST_URI} ^/moderation/$ [NC]
RewriteRule ^(.*)$ /moderation/moderationhome [L]

# Redirect requests to /admin/ to the correct index page for that directory.
RewriteCond %{REQUEST_URI} ^/admin/$ [NC]
RewriteRule ^(.*)$ /admin/adminhome [L]

# Redirect requests to /settings/ to the correct index page for that directory.
RewriteCond %{REQUEST_URI} ^/settings/$ [NC]
RewriteRule ^(.*)$ /settings/account [L]

# Redirect requests to /subscribe/ to the correct index page for that directory.
RewriteCond %{REQUEST_URI} ^/subscribe/$ [NC]
RewriteRule ^(.*)$ /subscribe/subscribehome [L]

RewriteCond %{REQUEST_URI} ^/submit/comic(/)?$ [NC]
RewriteRule ^(.*)$ /submit/comic/comic.php [L]

RewriteCond %{REQUEST_URI} ^/support(/)?$ [NC]
RewriteRule ^(.*)$ /support/supporthome.php [L]

# -- start changes for user profiles --
# First of all, redirect all "userprofile.php?username=whoever" requests to the pretty URL.
RewriteCond %{THE_REQUEST} profile/userprofile.php [NC]
RewriteCond %{QUERY_STRING} username=(.*)
RewriteRule ^.*$ /%1? [R=301,L]

# If the URL contains one slash, point the query string to the correct starting tab.
# The first condition ensures the top-level folders do not get inadvertently caught by this.
RewriteCond %{REQUEST_URI} !^/(admin|moderation|ajax|forms|css|js|profile|settings|about|account|nav|submit|search|errors|messages|notifications|articles|rules|browse|webhooks|reports|artwork|support)/(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/maintenance(.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/robots(.txt)?$ [NC]
# The extra '-' is in the second part of this rule so that links like "commission-info" work correctly.
RewriteRule ^([A-Za-z0-9]+)/([A-Za-z0-9-]+)$ /profile/userprofile.php?username=$1&startingtab=$2 [L]

# Now, rewrite the pretty URL to the actual URL that will process the request.
# Since we don't have a / in the RewriteRule's pattern, "https://website.com/username/ will NOT work, but "https://website.com/username" will.
RewriteCond %{REQUEST_URI} !^/(admin|moderation|ajax|forms|css|js|profile|settings|about|account|nav|submit|search|errors|messages|notifications|articles|rules|browse|webhooks|reports|artwork|support)/(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/maintenance(.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/robots(.txt)?$ [NC]
RewriteRule ^([A-Za-z0-9]+)$ /profile/userprofile.php?username=$1 [L]

# -- end changes for user profiles --

# Rewrite requests to a particular artwork page to the pretty URL.
RewriteCond %{THE_REQUEST} ^/artwork/displayartwork(.php)? [NC]
RewriteCond %{QUERY_STRING} artworkid=(.*)
RewriteRule ^.*$ /artwork/%1? [R=301,L]

# Redirect the pretty URL to the actual page to serve the request.
RewriteCond %{THE_REQUEST} /artwork/([A-Za-z0-9-]*) [NC]
RewriteRule ^artwork/(.*)$ /profile/displayartwork.php?artworkid=$1 [L]

# If the request isn't for a file, send it to the php page for the request URL.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

# Set the error documents for the different error response codes.
ErrorDocument 400 /errors/errorpage.php
ErrorDocument 401 /errors/errorpage.php
ErrorDocument 403 /errors/errorpage.php
ErrorDocument 404 /errors/errorpage.php
ErrorDocument 405 /errors/errorpage.php
ErrorDocument 406 /errors/errorpage.php
ErrorDocument 407 /errors/errorpage.php
ErrorDocument 408 /errors/errorpage.php
ErrorDocument 412 /errors/errorpage.php
ErrorDocument 413 /errors/errorpage.php
ErrorDocument 414 /errors/errorpage.php
ErrorDocument 415 /errors/errorpage.php
ErrorDocument 416 /errors/errorpage.php
ErrorDocument 429 /errors/errorpage.php
ErrorDocument 500 /errors/errorpage.php
ErrorDocument 501 /errors/errorpage.php
ErrorDocument 502 /errors/errorpage.php
ErrorDocument 503 /errors/errorpage.php
ErrorDocument 504 /errors/errorpage.php

# Set the default landing page for the website.
DirectoryIndex /browse/index.php

<IfModule headers_module>
    #
    # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
    # backend servers which have lingering "httpoxy" defects.
    # 'Proxy' request header is undefined by the IETF, not listed by IANA
    #
    RequestHeader unset Proxy early
    # Do not allow any part of the site to be embedded in an iFrame.
    Header always set X-Frame-Options "DENY"
    # Set the content security policy, which defines what content can be displayed on the website.
    # This is a critical security measure against XSS attacks, by blocking inline scripts and other
    # potential attack vectors.
    # Unsafe-inline style-src is required for TinyMCE to function.
	Header always set Content-Security-Policy "default-src 'self' localhost:* *.desertedchateau.com https://challenges.cloudflare.com *.stripe.com; style-src *.desertedchateau.com localhost:* 'unsafe-inline'; connect-src *.desertedchateau.com *.stripe.com; img-src localhost:* *.desertedchateau.com *.stripe.com https://challenges.cloudflare.com data: blob:; media-src blob: *.desertedchateau.com; worker-src blob: *.desertedchateau.com;"
    # Force HTTPs, and tell the browser to cache that instruction for two years.
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin"
    # Prevent the site using specific functions in a user's browser for security reasons.
    Header always set Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()"
</IfModule>

Add the following to the end of the httpd.conf file root area (outside of any tags):

# An additional measure to make sure anything we didn't intend to
# make publicly viewable is not viewable.
<FilesMatch "\.(zip|rar|log|pem|crt|key)$">
    Require all denied
</FilesMatch>
# Disallow access to Git version control files.
<Files ".gitignore">
    Require all denied
</Files>
<Files ".gitattributes">
    Require all denied
</Files>
# Disallow access to any Apache logs in case they're in the DocumentRoot
# for some reason.
<FilesMatch "(error_log|access_log|apache_error_log|apache_access_logs)$">
    Require all denied
</FilesMatch>