Skip to content

The .htaccess file

Nicholas K. Dionysopoulos edited this page Jul 4, 2026 · 3 revisions

Panopticon ships with a file called htaccess.txt. If you are using Apache 2.2 or later (preferably Apache 2.4) as your web server and you are accessing Panopticon over HTTP you should rename this file to .htaccess.

This .htaccess file enables the following optional, but very welcome, security and performance features:

  • Disables listing the files of arbitrary subdirectories.
  • Blocks access to internal directories with no web-accessible content e.g. cache, tmp, vendor, ViewTemplates and so on.
  • Sets up Content-Security-Policy, X-Frame-Options, X-XSS-Protection, and X-Content-Type HTTP headers to tighten the security of your Panopticon installation.
  • Automatically compresses static media files with Brotli (preferred, if available), or Gzip.
  • Disables the X-Powered-By and X-Content-Powered-By headers.
  • Enables HSTS (the HTTP Strict-Transport-Security header) to force your installation be accessed over HTTPS.
  • Disables the HTTP method TRACE which is not used by Panopticon and could be abused for Cross Site Tracking.
  • Sets the default output character set to UTF-8 so that your browser can display pages correctly, even on misconfigured installations of PHP.

Caveats

The included .htaccess content requires Apache's mod_rewrite module to be enabled. If this is not the case, you will be unable to access your installation. In this case, delete the .htaccess file.

The included .htaccess content is compatible with Apache 2.2, and Apache 2.4. It seems to be working fine with Litespeed. However, it will not work correctly with OpenLitespeed. Unlike Litespeed proper, OpenLitespeed does NOT support the full range of .htaccess directives, leading to problems. If you have a problem using Panopticon with OpenLitespeed delete the .htaccess file, or switch to either Apache (free) or Litespeed (commercial, for a fee).

The included .htaccess content is written with the assumption that your Panopticon installation is accessible over HTTPS. This is the only recommended setup for security reasons. If you have some fringe use case where this is not the case, e.g. you use a standalone SSL/TLS Terminator in front of Apache, you will have to edit the file manually. Please do not ask for assistance; if you have such a use case you should be more than comfortable editing a .htaccess file.

The .htaccess files are NOT supported by NginX and Microsoft Internet Information Services (ISS) web servers. We do not have plans on porting our .htaccess content to NginX and/or IIS. Users of these servers need to be technically adept, or work with such a person, therefore they can configure their server themselves.

JSON API and MCP Server: Authorization header forwarding

The JSON API and the MCP Server both authenticate with Bearer tokens (Authorization: Bearer …) and share the same token-authentication code. For either to work you must ensure the Authorization HTTP header is forwarded to PHP. Many web server / PHP SAPI combinations strip this header by default, which makes every request fail with an HTTP 401 even when the token is correct. This is the single most common cause of "the token is right but I keep getting 401" reports.

  • Apache + PHP-FPM (or CGI/FastCGI). The shipped .htaccess already takes care of this through the SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 directive inside the mod_rewrite block. The alternative is CGIPassAuth On, available in Apache 2.4.13 and later.
  • Apache + mod_php. No action needed; the header is passed through automatically.
  • NginX + PHP-FPM. Add fastcgi_pass_header Authorization; to your location block that handles PHP. Alternatively, explicitly set the FastCGI parameter: fastcgi_param HTTP_AUTHORIZATION $http_authorization;.
  • IIS + PHP (FastCGI). Behaviour varies by version and configuration; some setups forward Authorization and some strip it. If Bearer tokens fail, add a URL Rewrite rule to web.config that copies the header into a server variable PHP can see (you must first list HTTP_AUTHORIZATION under URL Rewrite → View Server Variables to allow setting it):
    <rule name="Forward Authorization header" stopProcessing="false">
        <match url=".*" />
        <serverVariables>
            <set name="HTTP_AUTHORIZATION" value="{HTTP_AUTHORIZATION}" />
        </serverVariables>
        <action type="None" />
    </rule>

Minimal Apache configuration if you manage your own .htaccess

If you do not use the full shipped .htaccess (for example, you maintain your own), the two things Panopticon's API and MCP server need are the Authorization header forwarding and — only if you want the short /api/… and /mcp URLs — the clean-URL rewrites:

<IfModule mod_setenvif.c>
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</IfModule>
## …or, on Apache 2.4.13 and later, use "CGIPassAuth On" instead of the SetEnvIf block above.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^api(/.*)?$ index.php/api$1 [L,QSA]
    RewriteRule ^mcp(/.*)?$ index.php/mcp$1 [L,QSA]
</IfModule>

Note

The clean-URL rewrites (and their Nginx/IIS equivalents) are optional. The https://…/index.php/api/v1/… and https://…/index.php/mcp forms always work, on any server, without any rewrite rule. On Nginx and IIS, using the index.php form is the simplest option — you then only need to sort out Authorization header forwarding, not URL rewriting.

If Bearer tokens unexpectedly return HTTP 401 responses, this header-stripping behaviour is the first thing to check. As a fallback, you can pass the token through the X-Panopticon-Token header or the _panopticon_token query parameter (URL-encode the token in that case — API tokens are Base64 and contain characters such as + that a URL otherwise mangles; note also that the query-parameter form leaks the token into access logs and Referer headers, so prefer Bearer in production).

Getting Started

Installation

Using Panopticon

Administration

How it works

For Experts

Installation and updates

Customisation

CLI Reference

Reference

JSON API

AI integration

Translation

Miscellaneous

Clone this wiki locally