Merge pull request #1415 from luckylinux/add-caddy-and-authentik-sso-documentation
Add caddy and authentik sso documentation
@@ -513,4 +513,887 @@ Mapping the updated file (on the local filesystem at `/appl/docker/netalertx/def
|
||||
...
|
||||
```
|
||||
|
||||
## Caddy + Authentik Outpost Proxy SSO
|
||||
> Submitted by [luckylinux](https://github.com/luckylinux) 🙏.
|
||||
|
||||
### Introduction
|
||||
This Setup assumes:
|
||||
1. Authentik Installation running on a separate Host at `https://authentik.MYDOMAIN.TLD`
|
||||
2. Container Management is done on Baremetal OR in a Virtual Machine (KVM/Xen/ESXi/..., no LXC Containers !):
|
||||
|
||||
i. Docker and Docker Compose configured locally running as Root (needed for `network_mode: host`) OR
|
||||
|
||||
ii. Podman (optionally `podman-compose`) configured locally running as Root (needed for `network_mode: host`)
|
||||
3. TLS Certificates are already pre-obtained and located at `/var/lib/containers/certificates/letsencrypt/MYDOMAIN.TLD`.
|
||||
|
||||
I use the `certbot/dns-cloudflare` Podman Container on a separate Host to obtain the Certificates which I then distribute internally.
|
||||
This Container uses the Wildcard Top-Level Domain Certificate which is valid for `MYDOMAIN.TLD` and `*.MYDOMAIN.TLD`.
|
||||
4. Proxied Access
|
||||
|
||||
i. NetAlertX Web Interface is accessible via Caddy Reverse Proxy at `https://netalertx.MYDOMAIN.TLD` (default HTTPS Port 443: `https://netalertx.MYDOMAIN.TLD:443`) with `REPORT_DASHBOARD_URL=https://netalertx.MYDOMAIN.TLD`
|
||||
|
||||
ii. NetAlertX GraphQL Interface is accessible via Caddy Reverse Proxy at `https://netalertx.MYDOMAIN.TLD:20212` with `BACKEND_API_URL=https://netalertx.MYDOMAIN.TLD:20212`
|
||||
|
||||
iii. Authentik Proxy Outpost is accessible via Caddy Reverse Proxy at `https://netalertx.MYDOMAIN.TLD:9443`
|
||||
5. Internal Ports
|
||||
|
||||
i. NGINX Web Server is set to listen on internal Port 20211 set via `PORT=20211`
|
||||
|
||||
ii. Python Web Server is set to listen on internal Port `GRAPHQL_PORT=20219`
|
||||
|
||||
iii. Authentik Proxy Outpost is listening on internal Port `AUTHENTIK_LISTEN__HTTP=[::1]:6000` (unencrypted) and Port `AUTHENTIK_LISTEN__HTTPS=[::1]:6443` (encrypted)
|
||||
8. Some further Configuration for Caddy is performed in Terms of Logging, SSL Certificates, etc
|
||||
|
||||
It's also possible to [let Caddy automatically request & keep TLS Certificates up-to-date](https://caddyserver.com/docs/automatic-https), although please keep in mind that:
|
||||
1. You risk enumerating your LAN. Every Domain/Subdomain for which Caddy requests a TLS Certificate for you will result in that Host to be listed on [List of Letsencrypt Certificates issued](https://crt.sh/).
|
||||
2. You need to either:
|
||||
|
||||
i. Open Port 80 for external Access ([HTTP challenge](https://caddyserver.com/docs/automatic-https#http-challenge)) in order for Letsencrypt to verify the Ownership of the Domain/Subdomain
|
||||
|
||||
ii. Open Port 443 for external Access ([TLS-ALPN challenge](https://caddyserver.com/docs/automatic-https#tls-alpn-challenge)) in order for Letsencrypt to verify the Ownership of the Domain/Subdomain
|
||||
|
||||
iii. Give Caddy the Credentials to update the DNS Records at your DNS Provider ([DNS challenge](https://caddyserver.com/docs/automatic-https#dns-challenge))
|
||||
|
||||
You can also decide to deploy your own Certificates & Certification Authority, either manually with OpenSSL, or by using something like [mkcert](https://github.com/FiloSottile/mkcert).
|
||||
|
||||
In Terms of IP Stack Used:
|
||||
- External: Caddy listens on both IPv4 and IPv6.
|
||||
- Internal:
|
||||
- Authentik Outpost Proxy listens on IPv6 `[::1]`
|
||||
- NetAlertX listens on IPv4 `0.0.0.0`
|
||||
|
||||
### Flow
|
||||
The Traffic Flow will therefore be as follows:
|
||||
- Web GUI:
|
||||
|
||||
i. Client accesses `http://authentik.MYDOMAIN.TLD:80`: default (built-in Caddy) Redirect to `https://authentik.MYDOMAIN.TLD:443`
|
||||
|
||||
ii. Client accesses `https://authentik.MYDOMAIN.TLD:443` -> reverse Proxy to internal Port 20211 (NetAlertX Web GUI / NGINX - unencrypted)
|
||||
- GraphQL: Client accesses `https://authentik.MYDOMAIN.TLD:20212` -> reverse Proxy to internal Port 20219 (NetAlertX GraphQL - unencrypted)
|
||||
- Authentik Outpost: Client accesses `https://authentik.MYDOMAIN.TLD:9443` -> reverse Proxy to internal Port 6000 (Authentik Outpost Proxy - unencrypted)
|
||||
|
||||
An Overview of the Flow is provided in the Picture below:
|
||||
|
||||

|
||||
|
||||
### Security Considerations
|
||||
#### Caddy should be run rootless
|
||||
> [!WARNING]
|
||||
> By default Caddy runs as `root` which is a Security Risk.
|
||||
> In order to solve this, it's recommended to create an unprivileged User `caddy` and Group `caddy` on the Host:
|
||||
> ```
|
||||
> groupadd --gid 980 caddy
|
||||
> useradd --shell /usr/sbin/nologin --gid 980 --uid 980 -c "Caddy web server" --base-dir /var/lib/caddy
|
||||
> ```
|
||||
|
||||
At least using Quadlets with Usernames (NOT required with UID/GID), but possibly using Compose in certain Cases as well, a custom `/etc/passwd` and `/etc/group` might need to be bind-mounted inside the Container.
|
||||
`passwd`:
|
||||
```
|
||||
root:x:0:0:root:/root:/bin/sh
|
||||
bin:x:1:1:bin:/bin:/sbin/nologin
|
||||
daemon:x:2:2:daemon:/sbin:/sbin/nologin
|
||||
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
|
||||
sync:x:5:0:sync:/sbin:/bin/sync
|
||||
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
|
||||
halt:x:7:0:halt:/sbin:/sbin/halt
|
||||
mail:x:8:12:mail:/var/mail:/sbin/nologin
|
||||
news:x:9:13:news:/usr/lib/news:/sbin/nologin
|
||||
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
|
||||
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
|
||||
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
|
||||
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
|
||||
games:x:35:35:games:/usr/games:/sbin/nologin
|
||||
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
|
||||
guest:x:405:100:guest:/dev/null:/sbin/nologin
|
||||
nobody:x:65534:65534:nobody:/:/sbin/nologin
|
||||
caddy:x:980:980:caddy:/var/lib/caddy:/bin/sh
|
||||
```
|
||||
|
||||
`group`:
|
||||
```
|
||||
root:x:0:root
|
||||
bin:x:1:root,bin,daemon
|
||||
daemon:x:2:root,bin,daemon
|
||||
sys:x:3:root,bin
|
||||
adm:x:4:root,daemon
|
||||
tty:x:5:
|
||||
disk:x:6:root
|
||||
lp:x:7:lp
|
||||
kmem:x:9:
|
||||
wheel:x:10:root
|
||||
floppy:x:11:root
|
||||
mail:x:12:mail
|
||||
news:x:13:news
|
||||
uucp:x:14:uucp
|
||||
cron:x:16:cron
|
||||
audio:x:18:
|
||||
cdrom:x:19:
|
||||
dialout:x:20:root
|
||||
ftp:x:21:
|
||||
sshd:x:22:
|
||||
input:x:23:
|
||||
tape:x:26:root
|
||||
video:x:27:root
|
||||
netdev:x:28:
|
||||
kvm:x:34:kvm
|
||||
games:x:35:
|
||||
shadow:x:42:
|
||||
www-data:x:82:
|
||||
users:x:100:games
|
||||
ntp:x:123:
|
||||
abuild:x:300:
|
||||
utmp:x:406:
|
||||
ping:x:999:
|
||||
nogroup:x:65533:
|
||||
nobody:x:65534:
|
||||
caddy:x:980:
|
||||
```
|
||||
|
||||
#### Authentication of GraphQL Endpoint
|
||||
> [!WARNING]
|
||||
> Currently the GraphQL Endpoint is NOT authenticated !
|
||||
|
||||
### Environment Files
|
||||
Depending on the Preference of the User (Environment Variables defined in Compose/Quadlet or in external `.env` File[s]), it might be prefereable to place at least some Environment Variables in external `.env` and `.env.<application>` Files.
|
||||
|
||||
The following is proposed:
|
||||
- `.env`: common Settings (empty by Default)
|
||||
- `.env.caddy`: Caddy Settings
|
||||
- `.env.server`: NetAlertX Server/Application Settings
|
||||
- `.env.outpost.proxy`: Authentik Proxy Outpost Settings
|
||||
|
||||
The following Contents is assumed.
|
||||
|
||||
`.env.caddy`:
|
||||
```
|
||||
# Define Application Hostname
|
||||
APPLICATION_HOSTNAME=netalertx.MYDOMAIN.TLD
|
||||
|
||||
# Define Certificate Domain
|
||||
# In this case: use Wildcard Certificate
|
||||
APPLICATION_CERTIFICATE_DOMAIN=MYDOMAIN.TLD
|
||||
APPLICATION_CERTIFICATE_CERT_FILE=fullchain.pem
|
||||
APPLICATION_CERTIFICATE_KEY_FILE=privkey.pem
|
||||
|
||||
# Define Outpost Hostname
|
||||
OUTPOST_HOSTNAME=netalertx.MYDOMAIN.TLD
|
||||
|
||||
# Define Outpost External Port (TLS)
|
||||
OUTPOST_EXTERNAL_PORT=9443
|
||||
```
|
||||
|
||||
`.env.server`:
|
||||
```
|
||||
PORT=20211
|
||||
PORT_SSL=443
|
||||
NETALERTX_NETWORK_MODE=host
|
||||
LISTEN_ADDR=0.0.0.0
|
||||
GRAPHQL_PORT=20219
|
||||
NETALERTX_DEBUG=1
|
||||
BACKEND_API_URL=https://netalertx.MYDOMAIN.TLD:20212
|
||||
```
|
||||
|
||||
`.env.outpost.proxy`:
|
||||
```
|
||||
AUTHENTIK_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
AUTHENTIK_LISTEN__HTTP=[::1]:6000
|
||||
AUTHENTIK_LISTEN__HTTPS=[::1]:6443
|
||||
```
|
||||
|
||||
### Compose Setup
|
||||
```
|
||||
version: "3.8"
|
||||
services:
|
||||
netalertx-caddy:
|
||||
container_name: netalertx-caddy
|
||||
|
||||
network_mode: host
|
||||
image: docker.io/library/caddy:latest
|
||||
pull: missing
|
||||
|
||||
env_file:
|
||||
- .env
|
||||
- .env.caddy
|
||||
|
||||
environment:
|
||||
CADDY_DOCKER_CADDYFILE_PATH: "/etc/caddy/Caddyfile"
|
||||
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro,z
|
||||
- /var/lib/containers/data/netalertx/caddy:/data/caddy:rw,z
|
||||
- /var/lib/containers/log/netalertx/caddy:/var/log:rw,z
|
||||
- /var/lib/containers/config/netalertx/caddy:/config/caddy:rw,z
|
||||
- /var/lib/containers/certificates/letsencrypt:/certificates:ro,z
|
||||
|
||||
# Set User
|
||||
user: "caddy:caddy"
|
||||
|
||||
# Automatically restart Container
|
||||
restart: unless-stopped
|
||||
|
||||
netalertx-server:
|
||||
container_name: netalertx-server # The name when you docker contiainer ls
|
||||
|
||||
network_mode: host # Use host networking for ARP scanning and other services
|
||||
|
||||
depends_on:
|
||||
netalertx-caddy:
|
||||
condition: service_started
|
||||
restart: true
|
||||
netalertx-outpost-proxy:
|
||||
condition: service_started
|
||||
restart: true
|
||||
|
||||
# Local built Image including latest Changes
|
||||
image: localhost/netalertx-dev:dev-20260109-232454
|
||||
|
||||
read_only: true # Make the container filesystem read-only
|
||||
|
||||
# It is most secure to start with user 20211, but then we lose provisioning capabilities.
|
||||
# user: "${NETALERTX_UID:-20211}:${NETALERTX_GID:-20211}"
|
||||
cap_drop: # Drop all capabilities for enhanced security
|
||||
- ALL
|
||||
cap_add: # Add only the necessary capabilities
|
||||
- NET_ADMIN # Required for scanning with arp-scan, nmap, nbtscan, traceroute, and zero-conf
|
||||
- NET_RAW # Required for raw socket operations with arp-scan, nmap, nbtscan, traceroute and zero-conf
|
||||
- NET_BIND_SERVICE # Required to bind to privileged ports with nbtscan
|
||||
- CHOWN # Required for root-entrypoint to chown /data + /tmp before dropping privileges
|
||||
- SETUID # Required for root-entrypoint to switch to non-root user
|
||||
- SETGID # Required for root-entrypoint to switch to non-root group
|
||||
volumes:
|
||||
|
||||
# Override NGINX Configuration Template
|
||||
- type: bind
|
||||
source: /var/lib/containers/config/netalertx/server/nginx/netalertx.conf.template
|
||||
target: /services/config/nginx/netalertx.conf.template
|
||||
read_only: true
|
||||
bind:
|
||||
selinux: Z
|
||||
|
||||
# Letsencrypt Certificates
|
||||
- type: bind
|
||||
source: /var/lib/containers/certificates/letsencrypt/MYDOMAIN.TLD
|
||||
target: /certificates
|
||||
read_only: true
|
||||
bind:
|
||||
selinux: Z
|
||||
|
||||
# Data Storage for NetAlertX
|
||||
- type: bind # Persistent Docker-managed Named Volume for storage
|
||||
source: /var/lib/containers/data/netalertx/server
|
||||
target: /data # consolidated configuration and database storage
|
||||
read_only: false # writable volume
|
||||
bind:
|
||||
selinux: Z
|
||||
|
||||
# Set the Timezone
|
||||
- type: bind # Bind mount for timezone consistency
|
||||
source: /etc/localtime
|
||||
target: /etc/localtime
|
||||
read_only: true
|
||||
bind:
|
||||
selinux: Z
|
||||
|
||||
# tmpfs mounts for writable directories in a read-only container and improve system performance
|
||||
# All writes now live under /tmp/* subdirectories which are created dynamically by entrypoint.d scripts
|
||||
# mode=1700 gives rwx------ permissions; ownership is set by /root-entrypoint.sh
|
||||
- type: tmpfs
|
||||
target: /tmp
|
||||
tmpfs-mode: 1700
|
||||
uid: 0
|
||||
gid: 0
|
||||
rw: true
|
||||
noexec: true
|
||||
nosuid: true
|
||||
nodev: true
|
||||
async: true
|
||||
noatime: true
|
||||
nodiratime: true
|
||||
bind:
|
||||
selinux: Z
|
||||
|
||||
env_file:
|
||||
- .env
|
||||
- .env.server
|
||||
|
||||
environment:
|
||||
PUID: ${NETALERTX_UID:-20211} # Runtime UID after priming (Synology/no-copy-up safe)
|
||||
PGID: ${NETALERTX_GID:-20211} # Runtime GID after priming (Synology/no-copy-up safe)
|
||||
LISTEN_ADDR: ${LISTEN_ADDR:-0.0.0.0} # Listen for connections on all interfaces
|
||||
PORT: ${PORT:-20211} # Application port
|
||||
PORT_SSL: ${PORT_SSL:-443}
|
||||
GRAPHQL_PORT: ${GRAPHQL_PORT:-20212} # GraphQL API port
|
||||
ALWAYS_FRESH_INSTALL: ${ALWAYS_FRESH_INSTALL:-false} # Set to true to reset your config and database on each container start
|
||||
NETALERTX_DEBUG: ${NETALERTX_DEBUG:-0} # 0=kill all services and restart if any dies. 1 keeps running dead services.
|
||||
BACKEND_API_URL: ${BACKEND_API_URL-"https://netalertx.MYDOMAIN.TLD:20212"}
|
||||
|
||||
# Resource limits to prevent resource exhaustion
|
||||
mem_limit: 4096m # Maximum memory usage
|
||||
mem_reservation: 2048m # Soft memory limit
|
||||
cpu_shares: 512 # Relative CPU weight for CPU contention scenarios
|
||||
pids_limit: 512 # Limit the number of processes/threads to prevent fork bombs
|
||||
logging:
|
||||
driver: "json-file" # Use JSON file logging driver
|
||||
options:
|
||||
max-size: "10m" # Rotate log files after they reach 10MB
|
||||
max-file: "3" # Keep a maximum of 3 log files
|
||||
|
||||
# Always restart the container unless explicitly stopped
|
||||
restart: unless-stopped
|
||||
|
||||
# To sign Out, you need to visit
|
||||
# {$OUTPOST_HOSTNAME}:{$OUTPOST_EXTERNAL_PORT}/outpost.goauthentik.io/sign_out
|
||||
netalertx-outpost-proxy:
|
||||
container_name: netalertx-outpost-proxy
|
||||
|
||||
network_mode: host
|
||||
|
||||
depends_on:
|
||||
netalertx-caddy:
|
||||
condition: service_started
|
||||
restart: true
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
image: ghcr.io/goauthentik/proxy:2025.10
|
||||
pull: missing
|
||||
|
||||
env_file:
|
||||
- .env
|
||||
- .env.outpost.proxy
|
||||
|
||||
environment:
|
||||
AUTHENTIK_HOST: "https://authentik.MYDOMAIN.TLD"
|
||||
AUTHENTIK_INSECURE: false
|
||||
AUTHENTIK_LISTEN__HTTP: "[::1]:6000"
|
||||
AUTHENTIK_LISTEN__HTTPS: "[::1]:6443"
|
||||
```
|
||||
|
||||
### Quadlet Setup
|
||||
`netalertx.pod`:
|
||||
```
|
||||
[Pod]
|
||||
# Name of the Pod
|
||||
PodName=netalertx
|
||||
|
||||
# Network Mode Host is required for ARP to work
|
||||
Network=host
|
||||
|
||||
# Automatically start Pod at Boot Time
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
`netalertx-caddy.container`:
|
||||
```
|
||||
[Unit]
|
||||
Description=NetAlertX Caddy Container
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Container]
|
||||
ContainerName=netalertx-caddy
|
||||
|
||||
Pod=netalertx.pod
|
||||
StartWithPod=true
|
||||
|
||||
# Generic Environment Configuration
|
||||
EnvironmentFile=.env
|
||||
|
||||
# Caddy Specific Environment Configuration
|
||||
EnvironmentFile=.env.caddy
|
||||
|
||||
Environment=CADDY_DOCKER_CADDYFILE_PATH=/etc/caddy/Caddyfile
|
||||
|
||||
Image=docker.io/library/caddy:latest
|
||||
Pull=missing
|
||||
|
||||
# Run as rootless
|
||||
# Specifying User & Group by Name requires to mount a custom passwd & group File inside the Container
|
||||
# Otherwise an Error like the following will result: netalertx-caddy[593191]: Error: unable to find user caddy: no matching entries in passwd file
|
||||
# User=caddy
|
||||
# Group=caddy
|
||||
# Volume=/var/lib/containers/config/netalertx/caddy-rootless/passwd:/etc/passwd:ro,z
|
||||
# Volume=/var/lib/containers/config/netalertx/caddy-rootless/group:/etc/group:ro,z
|
||||
|
||||
# Run as rootless
|
||||
# Specifying User & Group by UID/GID will NOT require a custom passwd / group File to be bind-mounted inside the Container
|
||||
User=980
|
||||
Group=980
|
||||
|
||||
Volume=./Caddyfile:/etc/caddy/Caddyfile:ro,z
|
||||
Volume=/var/lib/containers/data/netalertx/caddy:/data/caddy:z
|
||||
Volume=/var/lib/containers/log/netalertx/caddy:/var/log:z
|
||||
Volume=/var/lib/containers/config/netalertx/caddy:/config/caddy:z
|
||||
Volume=/var/lib/containers/certificates/letsencrypt:/certificates:ro,z
|
||||
```
|
||||
|
||||
`netalertx-server.container`:
|
||||
```
|
||||
[Unit]
|
||||
Description=NetAlertX Server Container
|
||||
Requires=netalertx-caddy.service netalertx-outpost-proxy.service
|
||||
After=netalertx-caddy.service netalertx-outpost-proxy.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Container]
|
||||
ContainerName=netalertx-server
|
||||
|
||||
Pod=netalertx.pod
|
||||
StartWithPod=true
|
||||
|
||||
# Local built Image including latest Changes
|
||||
Image=localhost/netalertx-dev:dev-20260109-232454
|
||||
Pull=missing
|
||||
|
||||
# Make the container filesystem read-only
|
||||
ReadOnly=true
|
||||
|
||||
# Drop all capabilities for enhanced security
|
||||
DropCapability=ALL
|
||||
|
||||
# It is most secure to start with user 20211, but then we lose provisioning capabilities.
|
||||
# User=20211:20211
|
||||
|
||||
# Required for scanning with arp-scan, nmap, nbtscan, traceroute, and zero-conf
|
||||
AddCapability=NET_ADMIN
|
||||
|
||||
# Required for raw socket operations with arp-scan, nmap, nbtscan, traceroute and zero-conf
|
||||
AddCapability=NET_RAW
|
||||
|
||||
# Required to bind to privileged ports with nbtscan
|
||||
AddCapability=NET_BIND_SERVICE
|
||||
|
||||
# Required for root-entrypoint to chown /data + /tmp before dropping privileges
|
||||
AddCapability=CHOWN
|
||||
|
||||
# Required for root-entrypoint to switch to non-root user
|
||||
AddCapability=SETUID
|
||||
|
||||
# Required for root-entrypoint to switch to non-root group
|
||||
AddCapability=SETGID
|
||||
|
||||
# Override the Configuration Template
|
||||
Volume=/var/lib/containers/config/netalertx/server/nginx/netalertx.conf.template:/services/config/nginx/netalertx.conf.template:ro,Z
|
||||
|
||||
# Letsencrypt Certificates
|
||||
Volume=/var/lib/containers/certificates/letsencrypt/MYDOMAIN.TLD:/certificates:ro,Z
|
||||
|
||||
# Data Storage for NetAlertX
|
||||
Volume=/var/lib/containers/data/netalertx/server:/data:rw,Z
|
||||
|
||||
# Set the Timezone
|
||||
Volume=/etc/localtime:/etc/localtime:ro,Z
|
||||
|
||||
# tmpfs mounts for writable directories in a read-only container and improve system performance
|
||||
# All writes now live under /tmp/* subdirectories which are created dynamically by entrypoint.d scripts
|
||||
# mode=1700 gives rwx------ permissions; ownership is set by /root-entrypoint.sh
|
||||
# Mount=type=tmpfs,destination=/tmp,tmpfs-mode=1700,uid=0,gid=0,rw=true,noexec=true,nosuid=true,nodev=true,async=true,noatime=true,nodiratime=true,relabel=private
|
||||
Mount=type=tmpfs,destination=/tmp,tmpfs-mode=1700,rw=true,noexec=true,nosuid=true,nodev=true
|
||||
|
||||
# Environment Configuration
|
||||
EnvironmentFile=.env
|
||||
EnvironmentFile=.env.server
|
||||
|
||||
# Runtime UID after priming (Synology/no-copy-up safe)
|
||||
Environment=PUID=20211
|
||||
|
||||
# Runtime GID after priming (Synology/no-copy-up safe)
|
||||
Environment=PGID=20211
|
||||
|
||||
# Listen for connections on all interfaces (IPv4)
|
||||
Environment=LISTEN_ADDR=0.0.0.0
|
||||
|
||||
# Application port
|
||||
Environment=PORT=20211
|
||||
|
||||
# SSL Port
|
||||
Environment=PORT_SSL=443
|
||||
|
||||
# GraphQL API port
|
||||
Environment=GRAPHQL_PORT=20212
|
||||
|
||||
# Set to true to reset your config and database on each container start
|
||||
Environment=ALWAYS_FRESH_INSTALL=false
|
||||
|
||||
# 0=kill all services and restart if any dies. 1 keeps running dead services.
|
||||
Environment=NETALERTX_DEBUG=0
|
||||
|
||||
# Set the GraphQL URL for external Access (via Caddy Reverse Proxy)
|
||||
Environment=BACKEND_API_URL=https://netalertx-fedora.MYDOMAIN.TLD:20212
|
||||
|
||||
# Resource limits to prevent resource exhaustion
|
||||
# Maximum memory usage
|
||||
Memory=4g
|
||||
|
||||
# Limit the number of processes/threads to prevent fork bombs
|
||||
PidsLimit=512
|
||||
|
||||
# Relative CPU weight for CPU contention scenarios
|
||||
PodmanArgs=--cpus=2
|
||||
PodmanArgs=--cpu-shares=512
|
||||
|
||||
# Soft memory limit
|
||||
PodmanArgs=--memory-reservation=2g
|
||||
|
||||
# !! The following Keys are unfortunately not [yet] supported !!
|
||||
|
||||
# Relative CPU weight for CPU contention scenarios
|
||||
#CpuShares=512
|
||||
|
||||
# Soft memory limit
|
||||
#MemoryReservation=2g
|
||||
```
|
||||
|
||||
`netalertx-outpost-proxy.container`:
|
||||
```
|
||||
[Unit]
|
||||
Description=NetAlertX Authentik Proxy Outpost Container
|
||||
Requires=netalertx-caddy.service
|
||||
After=netalertx-caddy.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Container]
|
||||
ContainerName=netalertx-outpost-proxy
|
||||
|
||||
Pod=netalertx.pod
|
||||
StartWithPod=true
|
||||
|
||||
# General Configuration
|
||||
EnvironmentFile=.env
|
||||
|
||||
# Authentik Outpost Proxy Specific Configuration
|
||||
EnvironmentFile=.env.outpost.proxy
|
||||
|
||||
Environment=AUTHENTIK_HOST=https://authentik.MYDOMAIN.TLD
|
||||
Environment=AUTHENTIK_INSECURE=false
|
||||
|
||||
# Overrides Value from .env.outpost.rac
|
||||
# Environment=AUTHENTIK_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
# Optional setting to be used when `authentik_host` for internal communication doesn't match the public URL
|
||||
# Environment=AUTHENTIK_HOST_BROWSER=https://authentik.MYDOMAIN.TLD
|
||||
|
||||
# Container Image
|
||||
Image=ghcr.io/goauthentik/proxy:2025.10
|
||||
Pull=missing
|
||||
|
||||
# Network Configuration
|
||||
Network=container:supermicro-ikvm-pve031-caddy
|
||||
|
||||
# Security Configuration
|
||||
NoNewPrivileges=true
|
||||
```
|
||||
|
||||
### Firewall Setup
|
||||
Depending on which GNU/Linux Distribution you are running, it might be required to open up some Firewall Ports in order to be able to access the Endpoints from outside the Host itself.
|
||||
|
||||
This is for instance the Case for Fedora Linux, where I had to open:
|
||||
- Port 20212 for external GraphQL Access (both TCP & UDP are open, unsure if UDP is required)
|
||||
- Port 9443 for external Authentik Outpost Proxy Access (both TCP & UDP are open, unsure if UDP is required)
|
||||
|
||||

|
||||
|
||||
### Authentik Setup
|
||||
In order to enable Single Sign On (SSO) with Authentik, you will need to create a Provider, an Application and an Outpost.
|
||||
|
||||

|
||||
|
||||
First of all, using the Left Sidebar, navigate to `Applications` → `Providers`, click on `Create` (Blue Button at the Top of the Screen), select `Proxy Provider`, then click `Next`:
|
||||

|
||||
|
||||
Fill in the required Fields:
|
||||
- Name: choose a Name for the Provider (e.g. `netalertx`)
|
||||
- Authorization Flow: choose the Authorization Flow. I typically use `default-provider-authorization-implicit-consent (Authorize Application)`. If you select the `default-provider-authorization-explicit-consent (Authorize Application)` you will need to authorize Authentik every Time you want to log in NetAlertX, which can make the Experience less User-friendly
|
||||
- Type: Click on `Forward Auth (single application)`
|
||||
- External Host: set to `https://netalertx.MYDOMAIN.TLD`
|
||||
|
||||
Click `Finish`.
|
||||
|
||||

|
||||
|
||||
Now, using the Left Sidebar, navigate to `Applications` → `Applications`, click on `Create` (Blue Button at the Top of the Screen) and fill in the required Fields:
|
||||
- Name: choose a Name for the Application (e.g. `netalertx`)
|
||||
- Slug: choose a Slug for the Application (e.g. `netalertx`)
|
||||
- Group: optionally you can assign this Application to a Group of Applications of your Choosing (for grouping Purposes within Authentik User Interface)
|
||||
- Provider: select the Provider you created the the `Providers` Section previosly (e.g. `netalertx`)
|
||||
|
||||
Then click `Create`.
|
||||
|
||||

|
||||
|
||||
Now, using the Left Sidebar, navigate to `Applications` → `Outposts`, click on `Create` (Blue Button at the Top of the Screen) and fill in the required Fields:
|
||||
- Name: choose a Name for the Outpost (e.g. `netalertx`)
|
||||
- Type: `Proxy`
|
||||
- Integration: open the Dropdown and click on `---------`. Make sure it is NOT set to `Local Docker connection` !
|
||||
|
||||
In the `Available Applications` Section, select the Application you created in the Previous Step, then click the right Arrow (approx. located in the Center of the Screen), so that it gets copied in the `Selected Applications` Section.
|
||||
|
||||
Then click `Create`.
|
||||
|
||||

|
||||
|
||||
Wait a few Seconds for the Outpost to be created. Once it appears in the List, click on `Deployment Info` on the Right Side of the relevant Line.
|
||||
|
||||

|
||||
|
||||
Take note of that Token. You will need it for the Authentik Outpost Proxy Container, which will read it as the `AUTHENTIK_TOKEN` Environment Variable.
|
||||
|
||||
### NGINX Configuration inside NetAlertX Container
|
||||
> [!NOTE]
|
||||
> This is something that was implemented based on the previous Content of this Reverse Proxy Document.
|
||||
> Due to some Buffer Warnings/Errors in the Logs as well as some other Issues I was experiencing, I increased a lot the client_body_buffer_size and large_client_header_buffers Parameters, although these might not be required anymore.
|
||||
> Further Testing might be required.
|
||||
|
||||
```
|
||||
# Set number of worker processes automatically based on number of CPU cores.
|
||||
worker_processes auto;
|
||||
|
||||
# Enables the use of JIT for regular expressions to speed-up their processing.
|
||||
pcre_jit on;
|
||||
|
||||
# Configures default error logger.
|
||||
error_log /tmp/log/nginx-error.log warn;
|
||||
|
||||
pid /tmp/run/nginx.pid;
|
||||
|
||||
events {
|
||||
# The maximum number of simultaneous connections that can be opened by
|
||||
# a worker process.
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
|
||||
# Mapping of temp paths for various nginx modules.
|
||||
client_body_temp_path /tmp/nginx/client_body;
|
||||
proxy_temp_path /tmp/nginx/proxy;
|
||||
fastcgi_temp_path /tmp/nginx/fastcgi;
|
||||
uwsgi_temp_path /tmp/nginx/uwsgi;
|
||||
scgi_temp_path /tmp/nginx/scgi;
|
||||
|
||||
# Includes mapping of file name extensions to MIME types of responses
|
||||
# and defines the default type.
|
||||
include /services/config/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# Name servers used to resolve names of upstream servers into addresses.
|
||||
# It's also needed when using tcpsocket and udpsocket in Lua modules.
|
||||
#resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001];
|
||||
|
||||
# Don't tell nginx version to the clients. Default is 'on'.
|
||||
server_tokens off;
|
||||
|
||||
# Specifies the maximum accepted body size of a client request, as
|
||||
# indicated by the request header Content-Length. If the stated content
|
||||
# length is greater than this size, then the client receives the HTTP
|
||||
# error code 413. Set to 0 to disable. Default is '1m'.
|
||||
client_max_body_size 1m;
|
||||
|
||||
# Sendfile copies data between one FD and other from within the kernel,
|
||||
# which is more efficient than read() + write(). Default is off.
|
||||
sendfile on;
|
||||
|
||||
# Causes nginx to attempt to send its HTTP response head in one packet,
|
||||
# instead of using partial frames. Default is 'off'.
|
||||
tcp_nopush on;
|
||||
|
||||
|
||||
# Enables the specified protocols. Default is TLSv1 TLSv1.1 TLSv1.2.
|
||||
# TIP: If you're not obligated to support ancient clients, remove TLSv1.1.
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
# Path of the file with Diffie-Hellman parameters for EDH ciphers.
|
||||
# TIP: Generate with: `openssl dhparam -out /etc/ssl/nginx/dh2048.pem 2048`
|
||||
#ssl_dhparam /etc/ssl/nginx/dh2048.pem;
|
||||
|
||||
# Specifies that our cipher suits should be preferred over client ciphers.
|
||||
# Default is 'off'.
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# Enables a shared SSL cache with size that can hold around 8000 sessions.
|
||||
# Default is 'none'.
|
||||
ssl_session_cache shared:SSL:2m;
|
||||
|
||||
# Specifies a time during which a client may reuse the session parameters.
|
||||
# Default is '5m'.
|
||||
ssl_session_timeout 1h;
|
||||
|
||||
# Disable TLS session tickets (they are insecure). Default is 'on'.
|
||||
ssl_session_tickets off;
|
||||
|
||||
|
||||
# Enable gzipping of responses.
|
||||
gzip on;
|
||||
|
||||
# Set the Vary HTTP header as defined in the RFC 2616. Default is 'off'.
|
||||
gzip_vary on;
|
||||
|
||||
|
||||
# Specifies the main log format.
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
# Sets the path, format, and configuration for a buffered log write.
|
||||
access_log /tmp/log/nginx-access.log main;
|
||||
|
||||
|
||||
# Virtual host config (unencrypted)
|
||||
server {
|
||||
listen ${LISTEN_ADDR}:${PORT} default_server;
|
||||
root /app/front;
|
||||
index index.php;
|
||||
add_header X-Forwarded-Prefix "/app" always;
|
||||
|
||||
server_name netalertx-server;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
client_body_buffer_size 512k;
|
||||
large_client_header_buffers 64 128k;
|
||||
|
||||
location ~* \.php$ {
|
||||
# Set Cache-Control header to prevent caching on the first load
|
||||
add_header Cache-Control "no-store";
|
||||
fastcgi_pass unix:/tmp/run/php.sock;
|
||||
include /services/config/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_connect_timeout 75;
|
||||
fastcgi_send_timeout 600;
|
||||
fastcgi_read_timeout 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Caddyfile
|
||||
```
|
||||
# Example and Guide
|
||||
# https://caddyserver.com/docs/caddyfile/options
|
||||
|
||||
# General Options
|
||||
{
|
||||
# (Optional) Debug Mode
|
||||
# debug
|
||||
|
||||
# (Optional ) Enable / Disable Admin API
|
||||
admin off
|
||||
|
||||
# TLS Options
|
||||
# (Optional) Disable Certificates Management (only if SSL/TLS Certificates are managed by certbot or other external Tools)
|
||||
auto_https disable_certs
|
||||
}
|
||||
|
||||
# (Optional Enable Admin API)
|
||||
# localhost {
|
||||
# reverse_proxy /api/* localhost:9001
|
||||
# }
|
||||
|
||||
# NetAlertX Web GUI (HTTPS Port 443)
|
||||
# (Optional) Only if SSL/TLS Certificates are managed by certbot or other external Tools and Custom Logging is required
|
||||
{$APPLICATION_HOSTNAME}:443 {
|
||||
tls /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_CERT_FILE:fullchain.pem} /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_KEY_FILE:privkey.pem}
|
||||
|
||||
log {
|
||||
output file /var/log/{$APPLICATION_HOSTNAME}/access_web.json {
|
||||
roll_size 100MiB
|
||||
roll_keep 5000
|
||||
roll_keep_for 720h
|
||||
roll_uncompressed
|
||||
}
|
||||
|
||||
format json
|
||||
}
|
||||
|
||||
route {
|
||||
# Always forward outpost path to actual outpost
|
||||
reverse_proxy /outpost.goauthentik.io/* https://{$OUTPOST_HOSTNAME}:{$OUTPOST_EXTERNAL_PORT} {
|
||||
header_up Host {http.reverse_proxy.upstream.hostport}
|
||||
}
|
||||
|
||||
# Forward authentication to outpost
|
||||
forward_auth https://{$OUTPOST_HOSTNAME}:{$OUTPOST_EXTERNAL_PORT} {
|
||||
uri /outpost.goauthentik.io/auth/caddy
|
||||
|
||||
# Capitalization of the headers is important, otherwise they will be empty
|
||||
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
|
||||
|
||||
# (Optional)
|
||||
# If not set, trust all private ranges, but for Security Reasons, this should be set to the outposts IP
|
||||
trusted_proxies private_ranges
|
||||
}
|
||||
}
|
||||
|
||||
# IPv4 Reverse Proxy to NetAlertX Web GUI (internal unencrypted Host)
|
||||
reverse_proxy http://0.0.0.0:20211
|
||||
|
||||
# IPv6 Reverse Proxy to NetAlertX Web GUI (internal unencrypted Host)
|
||||
# reverse_proxy http://[::1]:20211
|
||||
}
|
||||
|
||||
# NetAlertX GraphQL Endpoint (HTTPS Port 20212)
|
||||
# (Optional) Only if SSL/TLS Certificates are managed by certbot or other external Tools and Custom Logging is required
|
||||
{$APPLICATION_HOSTNAME}:20212 {
|
||||
tls /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_CERT_FILE:fullchain.pem} /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_KEY_FILE:privkey.pem}
|
||||
|
||||
log {
|
||||
output file /var/log/{$APPLICATION_HOSTNAME}/access_graphql.json {
|
||||
roll_size 100MiB
|
||||
roll_keep 5000
|
||||
roll_keep_for 720h
|
||||
roll_uncompressed
|
||||
}
|
||||
|
||||
format json
|
||||
}
|
||||
|
||||
# IPv4 Reverse Proxy to NetAlertX GraphQL Endpoint (internal unencrypted Host)
|
||||
reverse_proxy http://0.0.0.0:20219
|
||||
|
||||
# IPv6 Reverse Proxy to NetAlertX GraphQL Endpoint (internal unencrypted Host)
|
||||
# reverse_proxy http://[::1]:6000
|
||||
}
|
||||
|
||||
# Authentik Outpost
|
||||
# (Optional) Only if SSL/TLS Certificates are managed by certbot or other external Tools and Custom Logging is required
|
||||
{$OUTPOST_HOSTNAME}:{$OUTPOST_EXTERNAL_PORT} {
|
||||
tls /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_CERT_FILE:fullchain.pem} /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_KEY_FILE:privkey.pem}
|
||||
|
||||
log {
|
||||
output file /var/log/outpost/{$OUTPOST_HOSTNAME}/access.json {
|
||||
roll_size 100MiB
|
||||
roll_keep 5000
|
||||
roll_keep_for 720h
|
||||
roll_uncompressed
|
||||
}
|
||||
|
||||
format json
|
||||
}
|
||||
|
||||
# IPv4 Reverse Proxy to internal unencrypted Host
|
||||
# reverse_proxy http://0.0.0.0:6000
|
||||
|
||||
# IPv6 Reverse Proxy to internal unencrypted Host
|
||||
reverse_proxy http://[::1]:6000
|
||||
}
|
||||
```
|
||||
|
||||
### Login
|
||||
Now try to login by visiting `https://netalertx.MYDOMAIN.TLD`.
|
||||
|
||||
You should be greeted with a Login Screen by Authentik.
|
||||
|
||||
If you are already logged in Authentik, log out first. You can do that by visiting `https://netalertx.MYDOMAIN.TLD/outpost.goauthentik.io/sign_out`, then click on `Log out of authentik` (2nd Button). Or you can just sign out from your Authentik Admin Panel at `https://authentik.MYDOMAIN.TLD`.
|
||||
|
||||
If everything works as expected, then you can now set `SETPWD_enable_password=false` to disable double Authentication.
|
||||
|
||||

|
||||
|
||||
BIN
docs/img/REVERSE_PROXY/authentik-application-setup-01.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/img/REVERSE_PROXY/authentik-login.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/img/REVERSE_PROXY/authentik-outpost-setup-01.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
docs/img/REVERSE_PROXY/authentik-outpost-setup-02.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
docs/img/REVERSE_PROXY/authentik-provider-setup-01.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
docs/img/REVERSE_PROXY/authentik-provider-setup-02.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
docs/img/REVERSE_PROXY/authentik-sidebar.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/REVERSE_PROXY/fedora-firewall.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
202
docs/img/REVERSE_PROXY/reverse_proxy_flow.drawio
Normal file
@@ -0,0 +1,202 @@
|
||||
<mxfile host="Electron" modified="2026-01-15T05:36:26.645Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.1.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="OpSjRPjeNeyudFLZJ2fD" version="24.1.0" type="device">
|
||||
<diagram name="Page-1" id="mulIpG3YQAhf4Klf7Njm">
|
||||
<mxGraphModel dx="6733" dy="1168" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="4681" pageHeight="3300" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="850" y="160" width="920" height="810" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-2" value="NetAlertX Pod" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=32;" vertex="1" parent="1">
|
||||
<mxGeometry x="850" y="130" width="670" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-3" value="" style="image;html=1;image=img/lib/clip_art/computers/Laptop_128x128.png" vertex="1" parent="1">
|
||||
<mxGeometry x="-50" y="395" width="140" height="140" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-4" value="" style="image;html=1;image=img/lib/clip_art/networking/Firewall_02_128x128.png" vertex="1" parent="1">
|
||||
<mxGeometry x="488" y="344" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-5" value="" style="image;html=1;image=img/lib/clip_art/networking/Firewall_02_128x128.png" vertex="1" parent="1">
|
||||
<mxGeometry x="488" y="555" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-8" value="Web UI<br>(NGINX + PHP)" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="230" y="320" width="200" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-9" value="API GraphQL<br>(Python)" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="230" y="555" width="200" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-10" value="" style="endArrow=classic;html=1;rounded=0;dashed=1;dashPattern=8 8;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="240" y="390" as="sourcePoint" />
|
||||
<mxPoint x="240" y="600" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-12" value="<div>443</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="581" y="335" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-13" value="20212" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="581" y="554" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-14" value="" style="image;html=1;image=img/lib/clip_art/networking/Firewall_02_128x128.png" vertex="1" parent="1">
|
||||
<mxGeometry x="488" y="813" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-16" value="Authentik SSO for Web UI" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="230" y="793" width="200" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-17" value="9443" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="580" y="803" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-18" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="1470" y="250" width="288" height="440" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-19" value="NetAlertX" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="1470" y="210" width="288" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-21" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="1260" y="751" width="500" height="199" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-22" value="Authentik Outpost Proxy" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="1280" y="711" width="480" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-23" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="860" y="250" width="380" height="700" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-24" value="Caddy" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="860" y="210" width="390" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-25" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="1498" y="319" width="220" height="130" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-26" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="1498" y="530" width="220" height="150" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-27" value="Web UI<div>(NGINX + PHP)</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="1498" y="264" width="220" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-28" value="API GraphQL<div>(Python)</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="1498" y="475" width="220" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-6" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wwqsnaxs0Bt7SYwqQu8i-53" target="wwqsnaxs0Bt7SYwqQu8i-58">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="130" y="390" as="sourcePoint" />
|
||||
<mxPoint x="1129" y="389.9999999999998" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-30" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="wwqsnaxs0Bt7SYwqQu8i-59" target="wwqsnaxs0Bt7SYwqQu8i-31">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1214" y="483" as="sourcePoint" />
|
||||
<mxPoint x="1209" y="823" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-31" value="Authenticated &amp; Authorized ?" style="rhombus;whiteSpace=wrap;html=1;fontSize=18;" vertex="1" parent="1">
|
||||
<mxGeometry x="1294" y="773.5" width="170" height="160" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-35" value="20211" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="1488" y="335" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-36" value="" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1688" y="369" as="sourcePoint" />
|
||||
<mxPoint x="1688" y="649" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-37" value="20219" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="1498" y="535" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-38" value="HTTPS" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#66CC00;" vertex="1" parent="1">
|
||||
<mxGeometry x="730" y="340" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-39" value="HTTPS" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#66CC00;" vertex="1" parent="1">
|
||||
<mxGeometry x="730" y="803" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-40" value="HTTPS" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#66CC00;" vertex="1" parent="1">
|
||||
<mxGeometry x="730" y="554" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-42" value="" style="endArrow=none;html=1;rounded=0;endFill=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1381" y="1071" as="sourcePoint" />
|
||||
<mxPoint x="130" y="1071" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-43" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="130.5" y="1070" as="sourcePoint" />
|
||||
<mxPoint x="130" y="860" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-44" value="NO" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="1364" y="1000" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-45" value="YES" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;" vertex="1" parent="1">
|
||||
<mxGeometry x="1294" y="680" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-47" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1156.5" y="450" as="sourcePoint" />
|
||||
<mxPoint x="1157" y="1070" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-48" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wwqsnaxs0Bt7SYwqQu8i-56" target="wwqsnaxs0Bt7SYwqQu8i-26">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1299" y="600" as="sourcePoint" />
|
||||
<mxPoint x="1499" y="600" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-49" value="HTTP" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="1379" y="340" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-50" value="HTTP" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=24;fontColor=#FF0000;" vertex="1" parent="1">
|
||||
<mxGeometry x="1379" y="554" width="100" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-54" value="" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1" target="wwqsnaxs0Bt7SYwqQu8i-53">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="130" y="390" as="sourcePoint" />
|
||||
<mxPoint x="1129" y="390" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-53" value="TLS Termination" style="whiteSpace=wrap;html=1;aspect=fixed;fontSize=18;" vertex="1" parent="1">
|
||||
<mxGeometry x="905" y="340" width="100" height="100" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-56" value="TLS Termination" style="whiteSpace=wrap;html=1;aspect=fixed;fontSize=18;" vertex="1" parent="1">
|
||||
<mxGeometry x="902" y="554" width="100" height="100" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-7" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" target="wwqsnaxs0Bt7SYwqQu8i-56">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="130" y="601" as="sourcePoint" />
|
||||
<mxPoint x="850" y="601" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-58" value="Check Authentication" style="whiteSpace=wrap;html=1;aspect=fixed;fontSize=18;" vertex="1" parent="1">
|
||||
<mxGeometry x="1097" y="330" width="120" height="120" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-59" value="TLS Termination" style="whiteSpace=wrap;html=1;aspect=fixed;fontSize=18;" vertex="1" parent="1">
|
||||
<mxGeometry x="899" y="803" width="100" height="100" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-15" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" target="wwqsnaxs0Bt7SYwqQu8i-59">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="30" y="853" as="sourcePoint" />
|
||||
<mxPoint x="850" y="853" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-60" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1379" y="390" as="sourcePoint" />
|
||||
<mxPoint x="1500" y="389.58" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-61" value="" style="endArrow=none;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endFill=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1379" y="773" as="sourcePoint" />
|
||||
<mxPoint x="1379" y="390" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wwqsnaxs0Bt7SYwqQu8i-62" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="1380" y="933.5" as="sourcePoint" />
|
||||
<mxPoint x="1379" y="1069" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
BIN
docs/img/REVERSE_PROXY/reverse_proxy_flow.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
3
docs/img/REVERSE_PROXY/reverse_proxy_flow.svg
Normal file
|
After Width: | Height: | Size: 31 KiB |