unifi-utilities / unifios-utilities

A collection of enhancements for UnifiOS based devices
GNU General Public License v3.0
3.84k stars 415 forks source link

Authelia Setup for 2FA behind NGINX Proxy Manager #228

Open MRobi1 opened 2 years ago

MRobi1 commented 2 years ago

@boostchicken feel free to add this to your list of utilities if others may be able to use it.

After successfully getting NGINX Proxy Manager running on the UDM-P following the instructions here I figured I would tackle Authelia to compliment NGINX since they go hand in hand. I opted for the Authelia-lite deployment since it uses a small sqlite db and yml files for user configuration.

Here's how I got it running.

/mnt/data/on_boot.d/10-authelia.sh

#!/bin/sh

## configuration variables:
VLAN=5
IPV4_IP_AUTHELIA="10.0.5.5"

# This is the IP address of the container. You may want to set it to match
# your own network structure such as 192.168.5.3 or similar.
IPV4_GW="10.0.5.1/24"
# As above, this should match the gateway of the VLAN for the container
# network as above which is usually the .1/24 range of the IPV4_IP

# container name; e.g. nextdns, pihole, adguardhome, etc.
CONTAINER_AUTHELIA=authelia

## network configuration and startup:
CNI_PATH=/mnt/data/podman/cni
if [ ! -f "$CNI_PATH"/macvlan ]; then
    mkdir -p $CNI_PATH
    curl -L https://github.com/containernetworking/plugins/releases/download/v1.0.0/cni-plugins-linux-arm64-v1.0.0.tgz | tar -xz -C $CNI_PATH
fi

mkdir -p /opt/cni
rm -f /opt/cni/bin
ln -s $CNI_PATH /opt/cni/bin

for file in "$CNI_PATH"/*.conflist
do
    if [ -f "$file" ]; then
        ln -fs "$file" "/etc/cni/net.d/$(basename "$file")"
    fi
done

# set VLAN bridge promiscuous
ip link set br${VLAN} promisc on

# create macvlan bridge and add IPv4 IP
ip link add br${VLAN}.mac link br${VLAN} type macvlan mode bridge
ip addr add ${IPV4_GW} dev br${VLAN}.mac noprefixroute

# set macvlan bridge promiscuous and bring it up
ip link set br${VLAN}.mac promisc on
ip link set br${VLAN}.mac up

#######################################################################################
# add IPv4 route to DNS container
ip route add ${IPV4_IP_AUTHELIA}/32 dev br${VLAN}.mac
#######################################################################################

#######################################################################################
if podman container exists ${CONTAINER_AUTHELIA}; then
  podman start ${CONTAINER_AUTHELIA}
else
  logger -s -t podman-dns -p ERROR Container $CONTAINER_AUTHELIA not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up
fi
#######################################################################################

/mnt/data/podman/cni/20-authelia.conflist

{
  "cniVersion": "0.4.0",
  "name": "authelia",
  "plugins": [
    {
      "type": "macvlan",
      "mode": "bridge",
      "master": "br5",
      "mac": "00-15-6D-XX-XX-XX",
      "ipam": {
        "type": "static",
        "addresses": [
          {
            "address": "10.0.5.5/24",
            "gateway": "10.0.5.1"
          }
        ],
        "routes": [
          {"dst": "0.0.0.0/0"}
        ]
      }
    }
  ]
}

podman command

mkdir /mnt/data/authelia

podman run -d \
 --network authelia \
 --restart always \
 --name authelia \
 -e TZ=America/Moncton \
 -v "/mnt/data/authelia:/config" \
 authelia/authelia

In /mnt/data/authelia you'll need to create 2 yml files. configuration.yml and user_database.yml. See authelia's documentation for how to configure these files.

This is where things got a little complicated. In NGINX proxy manager you'll need a minimum of 2 proxy hosts setup. 1 for your authelia instance, and 1 for any service you want behind a reverse proxy (ie: sonarr, radarr, etc...)

Authelia proxy host configuration (Be sure to change YOURDOMAIN):

Details tab:
domain name: auth.YOURDOMAIN.com
Scheme: http
Forward Hostname/IP: 10.0.5.5
Forward Port: 9091
Cache Assets: ON
Block Common Exploits: ON

SSL:
Request a new SSL certificate
Force SSL: ON
HTTP/2 Support: ON

Advanced:
location / {
set $upstream_authelia http://10.0.5.5:9091;  
proxy_pass $upstream_authelia;
client_body_buffer_size 128k;

#Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

# Advanced Proxy Config
send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;

# Basic Proxy Config
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;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_redirect  http://  $scheme://;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;

# If behind reverse proxy, forwards the correct IP, assumes you're using Cloudflare. Adjust IP for your Docker network.
set_real_ip_from 192.168.0.0/24;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
} 

All other proxy hosts configurations. Setup hosts like normal, but add the following to the advanced tab. Be sure to change YOURDOMAIN to whatever your proper domain is.

location /authelia {
internal;
set $upstream_authelia http://10.0.5.5:9091/api/verify;
proxy_pass_request_body off;
proxy_pass $upstream_authelia;    
proxy_set_header Content-Length "";

# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
client_body_buffer_size 128k;
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr; 
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_redirect  http://  $scheme://;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 4 32k;

send_timeout 5m;
proxy_read_timeout 240;
proxy_send_timeout 240;
proxy_connect_timeout 240;
}

location / {
set $upstream_CONTAINERNAME $forward_scheme://$server:$port;
proxy_pass $upstream_CONTAINERNAME;

auth_request /authelia;
auth_request_set $target_url https://$http_host$request_uri;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $email $upstream_http_remote_email;
auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Email $email;
proxy_set_header Remote-Groups $groups;

error_page 401 =302 https://auth.YOURDOMAIN.com/?rd=$target_url;

client_body_buffer_size 128k;

proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;

proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
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;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_redirect  http://  $scheme://;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;

set_real_ip_from 192.168.0.0/24;
set_real_ip_from 10.0.0.0/24;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;

}

There you have it, a fully functional authelia deployment on the UDM-P giving 2FA capabilities to your proxy hosts through NGINX Proxy Manager also running on the UDM-P

boostchicken commented 2 years ago

Hey can you make a pull request for this in the actual repo?