As mentioned in the previous article, Dashy is a perfect fit for people who have purchased dozens of SaaS apps / self-hosting services like me.
However, it seems there is a minor bug that you have to enable guest mode in order to use the basic auth. It may lead to security issues.
Instead of using the basic auth provided by Dashy, using Authelia seems to be a more secure option.
This article will teach you how to set up Authelia for authentication.
Step 1: Move to your home directory and clone the Authelia project from GitHub.
cd ~
git clone https://github.com/authelia/authelia.git
Step 2: Move to the Authelia folder and modify the docker-compose.yml
cd authelia/examples/compose/lite
sudo nano docker-compose.yml
---
version: '3.3'
services:
authelia:
image: authelia/authelia
container_name: authelia
hostname: authelia
restart: unless-stopped
volumes:
- ./authelia:/config
ports:
- 9091:9091
networks:
- npm
redis:
image: redis:alpine
container_name: redis
volumes:
- ./redis:/data
ports:
- 6379:6379
restart: unless-stopped
networks:
- npm
networks:
npm:
name: npm_network
---
Step 3: Generate a hash for your password. Replace your_password with your password.
sudo docker run authelia/authelia:latest authelia crypto hash generate argon2 --password 'your_password'
In my case, it will output
Digest: $argon2id$v=19$m=65536,t=3,p=4$oNNZOjKz6opLBgE30INXJQ$2suPPCr+4icbELbF9KqF9keagAAWlF3YkMSi6uwfVmk
Jot your digest down.
Step 4: Edit your user database.
cd authelia
sudo nano users_database.yml
Replace your_username with your username.
Substitute password with your previously generated digest.
Alter your_email to your email.
---
###############################################################
# Users Database #
###############################################################
# This file can be used if you do not have an LDAP set up.
# List of users
users:
your_username:
disabled: false
displayname: "Authelia User"
# Password is authelia
password: "$6$rounds=50000$BpLnfgDsc2WD8F2q$Zis.ixdg9s/UOJYrs56b5QEZFiZECu0qZVNsIYxBaNJ7ucIL.nlxVCT5tqh8KHG8X4KHG8X4tlwCFm5r6NTOZZ5qRFN/" # yamllint disable-line rule:line-length
email: [email protected]
groups:
- admins
- dev
...
In my case, it is
---
###############################################################
# Users Database #
###############################################################
# This file can be used if you do not have an LDAP set up.
# List of users
users:
silicon:
disabled: false
displayname: "Authelia User"
# Password is your_password
password: "$argon2id$v=19$m=65536,t=3,p=4$oNNZOjKz6opLBgE30INXJQ$2suPPCr+4icbELbF9KqF9keagAAWlF3YkMSi6uwfVmk" # yamllint disable-line rule:line-length
email: [email protected]
groups:
- admins
- dev
...
Press Ctrl + X to save the file.
Step 5: Generate a 64-word password for jwt_secret, authelia_session, and encryption_key. You may generate a 64-word password here.
Avoid using any Symbols.
Edit configuration.yml
sudo nano configuration.yml
Replace your_jwt_secret with the generated jwt_secret.
Substitute your_session_secret with the generated authelia_session.
Alter your_encryption_key to the generated encryption_key.
Modify your_domain with your subdomain.
Change your_root_domain with your domain.
If you want to use the notifier, you need to enter your email & password for authentication.
Check out my article on how to generate a Google App password if you are using Gmail.
Replace your_email with your email.
Replace your_google_app_password with your Google app password.
---
###############################################################
# Authelia configuration #
###############################################################
jwt_secret: your_jwt_secret
#a_very_important_secret
default_redirection_url: https://your_domain
server:
host: 0.0.0.0
port: 9091
log:
level: debug
# This secret can also be set using the env variables AUTHELIA_JWT_SECRET_FILE
totp:
issuer: your_root_domain
authentication_backend:
file:
path: /config/users_database.yml
## Password Reset Options.
password_reset:
## Disable both the HTML element and the API for reset password functionality.
disable: false
access_control:
default_policy: deny
rules:
# Rules applied to everyone
- domain: your_domain
policy: one_factor
session:
name: authelia_session
# This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE
secret: your_session_secret
#unsecure_session_secret
expiration: 3600 # 1 hour
inactivity: 300 # 5 minutes
domain: your_root_domain # Should match whatever your root protected domain is
redis:
host: redis
port: 6379
# This secret can also be set using the env variables AUTHELIA_SESSION_REDIS_PASSWORD_FILE
# password: authelia
regulation:
max_retries: 3
find_time: 120
ban_time: 300
storage:
encryption_key: your_encryption_key
local:
path: /config/db.sqlite3
notifier:
smtp:
username: your_email
# This secret can also be set using the env variables AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE
password: your_google_app_password
host: smtp.gmail.com
port: 587
sender: your_email
...
In my case, it is
---
###############################################################
# Authelia configuration #
###############################################################
jwt_secret: WcZ7uwXXhMH8vjA5asICh6HALuB5sEQy9sVy2DSFyXm5JGBwcXXvW2a7Dy632EjE
#a_very_important_secret
default_redirection_url: https://auth.silicon.blog
server:
host: 0.0.0.0
port: 9091
log:
level: debug
# This secret can also be set using the env variables AUTHELIA_JWT_SECRET_FILE
totp:
issuer: silicon.blog
authentication_backend:
file:
path: /config/users_database.yml
## Password Reset Options.
password_reset:
## Disable both the HTML element and the API for reset password functionality.
disable: false
access_control:
default_policy: deny
rules:
# Rules applied to everyone
- domain: dashy.silicon.blog
policy: one_factor
session:
name: authelia_session
# This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE
secret: ICZeSdKQkHHsCQ24cIdaAugGuq5eDUDQKZPeqePUQcgxczscmNWWpWPs4QYUqXzv
#unsecure_session_secret
expiration: 3600 # 1 hour
inactivity: 300 # 5 minutes
domain: silicon.blog # Should match whatever your root protected domain is
redis:
host: redis
port: 6379
# This secret can also be set using the env variables AUTHELIA_SESSION_REDIS_PASSWORD_FILE
# password: authelia
regulation:
max_retries: 3
find_time: 120
ban_time: 300
storage:
encryption_key: LpJJDcjvcjX9KJnw9utrVFsYQgRwaakK9WIRSXDS93ayaFt4UnVf4555EjXDwEQr
local:
path: /config/db.sqlite3
notifier:
smtp:
username: [email protected]
# This secret can also be set using the env variables AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE
password: itsasecretXD
host: smtp.gmail.com
port: 587
sender: [email protected]
...
Press Ctrl + X to save the file.
Step 6: Execute the container in the background.
cd ..
sudo docker compose up -d
Step 7: Log in to your Nginx Proxy Manager. Read my previous article about how to set up Nginx Proxy Manager using Docker Compose if you have not set it up.
Step 8: Bind authelia to your domain name.
Add this to your Advance section to allow Control Allow Origin (CORS).
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
set $upstream_authelia http://authelia: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 $http_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 $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 172.0.0.0/8;
set_real_ip_from 10.0.0.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}
Press Save button to take effect.
Step 9: Bind Dashy to your domain name.
Add this to your Advance section to add an authentication function to Dashy.
Moreover, this can avoid a minor bug triggered by Dashy. That is, whenever you switch to another page, it will add a /home/ to your directory. If you refresh the page, it will show a 404 error.
I will introduce a method redirecting you to the Dashy homepage when a 404 error occurs.
Replace your_authelia_subdomain with your Authelia subdomain.
Replace your_dashy_subdomain with your Dashy subdomain.
location /authelia {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
internal;
set $upstream_authelia http://authelia: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 $http_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 / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
set $upstream_d http://dashy;
proxy_pass $upstream_d;
auth_request /authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
error_page 401 =302 https://your_authelia_subdomain;
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 $http_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;
set_real_ip_from 172.0.0.0/8;
set_real_ip_from 10.0.0.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}
location ~ ^/home(/?)(.*)$ {
return https://your_dashy_subdomain;
}
In my case, it is
location /authelia {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
internal;
set $upstream_authelia http://authelia: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 $http_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 / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
set $upstream_d http://dashy;
proxy_pass $upstream_d;
auth_request /authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
error_page 401 =302 https://auth.silicon.blog;
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 $http_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;
set_real_ip_from 172.0.0.0/8;
set_real_ip_from 10.0.0.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}
location ~ ^/home(/?)(.*)$ {
return https://dashy.silicon.blog;
}
Step 10: Move to Cloudflare, and add A records to your Dashy & Authelia subdomains if you are using a static IP.
Instead, if you are using a dynamic IP address and you want to use a DDNS. Create a CName record.
Step 11: Ensure you have forwarded port 80/443 to Nginx Proxy Manager on your router/ switch. Since different brands will have different configurations, you may need to Google it and set it up yourself.
If you are using Oracle Cloud, remember to configure your firewall to allow incoming traffic by
sudo iptables -I INPUT -j ACCEPT
sudo su
iptables-save > /etc/iptables/rules.v4
exit
Try to connect to your Dashy subdomain after some time. It may take at most 1 day to update the DNS record.
Troubleshooting
If you cannot connect to Dashy through your Dashy subdomain. Have a look at all of your docker containers
sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f8f41c97315 redis:alpine "docker-entrypoint.s…" 25 minutes ago Up 25 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis
7e3afc21c4cd authelia/authelia "/app/entrypoint.sh …" 25 minutes ago Up 25 minutes (healthy) 0.0.0.0:9091->9091/tcp, :::9091->9091/tcp authelia
d9f30e6bf832 lissy93/dashy:latest "yarn build-and-start" 2 hours ago Up 2 hours (healthy) 0.0.0.0:4000->80/tcp, :::4000->80/tcp Dashy
e44fb1098270 jc21/nginx-proxy-manager:latest "/init" 7 hours ago Up 7 hours 0.0.0.0:80-81->80-81/tcp, :::80-81->80-81/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp nginx-app-1
Check out your container IP
sudo docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx-app-1
172.18.0.2
sudo docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' Dashy
172.19.0.2
If they are not on the same network, change the port number of Dashy to 4000 on Nginx Proxy Manager. If it still does not work, enter the Nginx Proxy Manager terminal.
sudo docker exec -it nginx-app-1 bash
Try to fetch Dashy by
curl http://dashy:4000
If it says it could not resolve the host, you shall add it to the end of each container.
networks:
- npm
Also, add,
networks:
npm:
name: npm_network
to the end of the docker-compose.yml
Step 12: Enter your Dashy subdomain on a browser. It will redirect you to your Authelia subdomain. Log in with the username & password.
Step 13: After authentication, move to your Dashy subdomain again. This time you will be able to access Dashy.
Try to create a new page. Switch between different pages. You will find an additional “home/” path. It is a minor bug on this Dashy version (Commit: 3c5177dd704821286d51830abe2c2840a92b7f54).
Press F5 to refresh the page, and it will redirect you to the homepage of Dashy. We have set up the 404 redirections on the Nginx Proxy Manager before.
If you reach here without any error, congratulation, you have already set up Authelia. It will provide an extra security layer to the Dashy dashboard.