Reverse Proxy
journex uses WebSockets for live log streaming, so the reverse proxy must
forward WebSocket upgrade requests correctly. The examples below proxy
journex to http://127.0.0.1:8080. Replace the host names and upstream
address to match your environment.
By default, journex expects to run at the root of an HTTP origin, such as
https://journex.example.com. To serve it below a path such as
https://example.com/journex, set JOURNEX_BASE_PATH=/journex and configure
the reverse proxy to forward that same path prefix to journex. Do not strip
the prefix in the proxy when JOURNEX_BASE_PATH is set.
Set JOURNEX_TRUST_PROXY=1 when running behind a proxy. Login attempts are
rate limited per client address, and without this flag every request appears
to come from the proxy itself, so all clients share a single limit: one
scanner can lock out your own logins. With the flag set, journex takes the
client address from the rightmost X-Forwarded-For entry, which your proxy
appends and a client cannot forge. Only enable it if a proxy really is in
front of journex — otherwise clients can spoof the header and evade the
limit.
Apache
Requires mod_proxy, mod_proxy_http, mod_proxy_wstunnel, mod_rewrite,
and an SSL configuration such as Let’s Encrypt.
<VirtualHost *:443>
ServerName journex.example.com
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/journex.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/journex.example.com/privkey.pem
ProxyPreserveHost On
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/(.*) ws://127.0.0.1:8080/$1 [P,L]
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
server_name journex.example.com;
ssl_certificate /etc/letsencrypt/live/journex.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/journex.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Traefik
Traefik handles WebSocket upgrades automatically when proxying the router to journex.
http:
routers:
journex:
rule: Host(`journex.example.com`)
entryPoints:
- websecure
tls:
certResolver: letsencrypt
service: journex
services:
journex:
loadBalancer:
servers:
- url: http://127.0.0.1:8080
Caddy
journex.example.com {
reverse_proxy 127.0.0.1:8080
}
WebSocket Origins
journex only accepts WebSocket connections from a page served on the same
origin it was reached on, so a site you happen to visit cannot open a stream
against a journex on your machine and read your journal. This matters most
with JOURNEX_NO_AUTH, where no token stands in the way.
The check compares the browser’s Origin against the request’s Host, so it
needs your reverse proxy to pass Host through unchanged — Apache needs
ProxyPreserveHost On; Caddy, Traefik and nginx (with
proxy_set_header Host $host) do this by default. To allow other origins,
such as a separate frontend dev server, list them in
JOURNEX_ALLOWED_ORIGINS:
JOURNEX_ALLOWED_ORIGINS=http://localhost:5173,https://logs.example.com ./journex
An explicit list replaces the same-origin default rather than adding to it.
Requests without an Origin header, such as curl or wscat, are always
allowed: only browsers send it, and only browsers can be tricked into sending
someone else’s.