Commit 5f80f19b authored by Nick Busey's avatar Nick Busey

Merge branch '219-Authelia' into dev

parents e7808260 57f70f38
Pipeline #85189019 passed with stage
in 36 seconds
# 0.7
- Added Apache 2 - Web server
- Added Authelia - Authelia is an open-source full-featured authentication server available on Github
- Added Digikam - Professional Photo Management with the Power of Open Source
- Added HealthChecks - A Cron Monitoring Tool written in Python & Django https://healthchecks.io
- Added HomeBridge - HomeKit support for the impatient
......
......@@ -47,6 +47,7 @@ If you have the latest version of Vagrant and Virtual Box setup you can demo thi
- [Airsonic](https://airsonic.github.io/) - Airsonic is a free, web-based media streamer, providing ubiquitous access to your music.
- [Apache](https://httpd.apache.org/) - Web server
- [Authelia](https://www.authelia.com) - Authelia is an open-source full-featured authentication server available on Github
- [Beets](https://beets.io) - Beets is the media library management system for obsessive-compulsive music geeks.
- [Bitwarden](https://bitwarden.com/) - Password and secrets manager via [bitwarden-rs](https://github.com/dani-garcia/bitwarden_rs)
- [BookStack](https://www.bookstackapp.com/) - Simple & Free Wiki Software
......
# Authelia
[Authelia](https://www.Authelia.com) is an open-source full-featured authentication server.
## What is this?
Authelia is a multi-factor, authentication proxy. Used in conjuction with traefik (which homelabos already uses) it secures your homelabos services behind authentication. By default you must authenticate with username and password, and at least one other 'factor' ie:
- one-time password from, say, google authenticator
- a registered security key, for instance a YubiKey or something similar
- A Push message to your mobile device throuh the Duo service
When enabled, Traefik will forward most requests (more on this later) to Authelia for authentication. Once you login to Authelia, it will redirect you to the service you requested. For instance, if you navigate to firefly.yourdomain.com, traefik will auto-redirect you to auth.yourname.com for authentication. Once you authenticate, it will redirect you back to firefly.yourdomain.com.
On the backend, Authelia authenticates users against a userdb.yml file. The passwords in this file are hashed with sha512. If you need to manually edit the userdb.yml file, you'll need to create new password hashes with this command:
```bash
mkpasswd --rounds 500000 -m sha-512 --salt `head -c 40 /dev/random | base64 | sed -e 's/+/./g' | cut -b 10-25` 'Your new Password Here'
```
## Prerequisites
1. Authelia requires a working SMTP server to authenticate new users and register devices.
## Configuration
Homelabos ships with intelligent defaults for Authelia. However, there are some choices you must make. In config.yml, there is an Authelia section. The configuration options are explained below:
### Authelia configuration options
- log_level: defaults to debug, you can set to 'error' as well
- use_username: Defaults to true. if true, your authellia login name is your config.yml's default username: `{{default_username}}`.
- max:
- retries: this is the maximum number of times someone can _fail_ to authenticate within a given time frame before being locked out. (defaults 5)
- retries_in_time: this is the time frame that a user has to fail X times in before they're banned. (Defaults to 2min.)
- retries_ban_time: How long a user is prohibited from logging in after failing X times in Y mintes, per the first two variables. (defaults to 5 minutes) These three combined (as defaulted), means that a user who fails to authenticate 5 times within 2 minutes is banned for 5 minutes.
- default:
- factor_count: The number of authentication factors required to login. Options are:
1. `bypass` - Authelia will not require authentication.
2. `one_factor` - only a user/pass is required.
3. `two_factor` - (_default_) Username/password as well as a second factor is required.
4. `deny` - Authelia will prevent login and access to the services.
- cookie*expiration: How long the authentication cookie is good for. (\_default: 1hr*)
- cookie*inactivity: How long the cookie can sit, without being refreshed (ie: user is active) before expiring. (\_Defaults to 5min*)
- policy: This is the default policy for any un-named service. This is the policy for everything unless overriten by other service rules.
## Overriding the default policy
`/var/homelabos/Authelia/Authelia_config.yml` file is the source of truth for post-deployment configuration settings. If you wish to override the default policy, stated in config.yml, you'll need to hand edit this configuration file and restart Authelia. You probably only need to do this if there is a service that you want to excempt from two-factor authentication, or excempt from Authelia all together. About 100 lines into the config you'll find a section that looks like this:
```yml
rules:
- domain: portainer.{{ domain }}
policy: one_factor
- domain: auth.{{ domain }}
policy: bypass
- domain: "*.{{ domain }}"
policy: { { Authelia.default.factor_count } }
```
> Right above this section in your config file is a well documented explination of how this works.
Out of the box, the standard config bypasses Authelia for Authelia itself, and drops portainer down to a single-factor. All other subdomains are locked to the default factor-count, with the final rule. Note, the order of rules matters. The first matching rule wins. If you wish to set a subdomain/service to use something other than your configured default, simply add a clause to the rules section containing at least the following:
```yml
- domain: YourExampleSubdomainHere.{{domain}}
policy: Whatever Policy You'd like for this domain.
```
> Note, Authelia does understand the concept of groups, and can limit some services to particular groups, ie: administarators. You might use this to limit say, portainer, to admins.
## Access
It is available at [https://auth.{{ domain }}/](https://auth.{{ domain }}/) or [http://auth.{{ domain }}/](http://auth.{{ domain }}/)
{% if enable_tor %}
It is also available via Tor at [http://auth.{{ tor_domain }}/](http://auth.{{ tor_domain }}/)
{% endif %}
......@@ -6,6 +6,7 @@ enabled_services:
apache2: "{{ enable_apache2 }}"
apple_health_influx: "{{ enable_apple_health_influx }}"
airsonic: "{{ enable_airsonic }}"
authelia: "{{ enable_authelia }}"
beets: "{{ enable_beets }}"
bitwarden: "{{ enable_bitwarden }}"
bookstack: "{{ enable_bookstack }}"
......@@ -89,4 +90,11 @@ gitea:
bastion:
wireguard:
enabled: false
speedtest:
authelia:
duo:
default:
max:
domain:
open_ldap:
seed:
speedtest:
\ No newline at end of file
---
- name: Make authelia directory.
file:
path: "/var/homelabos/authelia"
state: directory
- name: Copy authelia docker-compose.yml file into place.
template:
src: docker-compose.authelia.yml.j2
dest: /var/homelabos/authelia/docker-compose.authelia.yml
- name: Generate new slapd compatible password.
shell: mkpasswd --rounds 500000 -m sha-512 --salt `head -c 40 /dev/random | base64 | sed -e 's/+/./g' | cut -b 10-25` '{{default_password}}'
register: slappasswd_out
become: false
- name: Copy userdb.yml file into place.
template:
src: userdb.yml.j2
dest: /var/homelabos/authelia/userdb.yml
vars:
slapd_password: "{{ slappasswd_out.stdout }}"
- name: Copy authelia_config.yml file into place.
template:
src: authelia_config.yml.j2
dest: /var/homelabos/authelia/authelia_config.yml
vars:
domain_parts: "{{ domain.split('.') }}"
- name: Configure authelia systemd service.
template:
src: service.j2
dest: /etc/systemd/system/authelia.service
- name: Start authelia
systemd:
name: authelia
enabled: "yes"
daemon-reload: "yes"
state: started
###############################################################
# Authelia configuration #
###############################################################
# The port to listen on
port: 9091
# Log level
#
# Level of verbosity for logs
logs_level: {{ authelia.log_level }}
# Default redirection URL
#
# If user tries to authenticate without any referer, Authelia
# does not know where to redirect the user to at the end of the
# authentication process.
# This parameter allows you to specify the default redirection
# URL Authelia will use in such a case.
#
# Note: this parameter is optional. If not provided, user won't
# be redirected upon successful authentication.
default_redirection_url: https://auth.{{ domain }}
# TOTP Issuer Name
#
# This will be the issuer name displayed in Google Authenticator
# See: https://github.com/google/google-authenticator/wiki/Key-Uri-Format for more info on issuer names
totp:
issuer: {{ domain }}
# Duo Push API
#
# Parameters used to contact the Duo API. Those are generated when you protect an application
# of type "Partner Auth API" in the management panel.
{% if authelia.duo.hostname %}
duo_api:
hostname: {{ authelia.duo.hostname }}
integration_key: {{ authelia.duo.integration_key }}
secret_key: {{ authelia.duo.secret_key }}
{% endif %}
# The authentication backend to use for verifying user passwords
# and retrieve information such as email address and groups
# users belong to.
#
# There are two supported backends: `ldap` and `file`.
authentication_backend:
# File backend configuration.
#
# With this backend, the users database is stored in a file
# which is updated when users reset their passwords.
# Therefore, this backend is meant to be used in a dev environment
# and not in production since it prevents Authelia to be scaled to
# more than one instance.
#
file:
path: /etc/authelia/userdb.yml
# Access Control
#
# Access control is a list of rules defining the authorizations applied for one
# resource to users or group of users.
#
# If 'access_control' is not defined, ACL rules are disabled and the `bypass`
# rule is applied, i.e., access is allowed to anyone. Otherwise restrictions follow
# the rules defined.
#
# Note: One can use the wildcard * to match any subdomain.
# It must stand at the beginning of the pattern. (example: *.mydomain.com)
#
# Note: You must put patterns containing wildcards between simple quotes for the YAML
# to be syntaxically correct.
#
# Definition: A `rule` is an object with the following keys: `domain`, `subject`,
# `policy` and `resources`.
#
# - `domain` defines which domain or set of domains the rule applies to.
#
# - `subject` defines the subject to apply authorizations to. This parameter is
# optional and matching any user if not provided. If provided, the parameter
# represents either a user or a group. It should be of the form 'user:<username>'
# or 'group:<groupname>'.
#
# - `policy` is the policy to apply to resources. It must be either `bypass`,
# `one_factor`, `two_factor` or `deny`.
#
# - `resources` is a list of regular expressions that matches a set of resources to
# apply the policy to. This parameter is optional and matches any resource if not
# provided.
#
# Note: the order of the rules is important. The first policy matching
# (domain, resource, subject) applies.
access_control:
# Default policy can either be `bypass`, `one_factor`, `two_factor` or `deny`.
# It is the policy applied to any resource if there is no policy to be applied
# to the user.
default_policy: {{ authelia.default.policy }}
rules:
- domain: portainer.{{ domain }}
policy: one_factor
- domain: auth.{{ domain }}
policy: bypass
- domain: '*.{{ domain }}'
policy: {{ authelia.default.factor_count }}
# Configuration of session cookies
#
# The session cookies identify the user once logged in.
session:
# The name of the session cookie. (default: authelia_session).
name: authelia_session
# The secret to encrypt the session cookie.
secret: {{lookup('password', './settings/passwords/authelia_session_secret')}}
# The time in ms before the cookie expires and session is reset.
expiration: {{ authelia.default.cookie_expiration }} # 1 hour
# The inactivity time in ms before the session is reset.
inactivity: {{ authelia.default.cookie_inactivity }} # 5 minutes
# The domain to protect.
# Note: the authenticator must also be in that domain. If empty, the cookie
# is restricted to the subdomain of the issuer.
domain: {{ domain }}
# The redis connection details
redis:
host: authelia_redis_1
port: 6379
# Configuration of the authentication regulation mechanism.
#
# This mechanism prevents attackers from brute forcing the first factor.
# It bans the user if too many attempts are done in a short period of
# time.
regulation:
# The number of failed login attempts before user is banned.
# Set it to 0 to disable regulation.
max_retries: {{ authelia.max.retries }}
# The time range during which the user can attempt login before being banned.
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: {{ authelia.max.retries_in_time }}
# The length of time before a banned user can login again.
ban_time: {{ authelia.max.retries_ban_time }}
# Configuration of the storage backend used to store data and secrets.
#
# You must use only an available configuration: local, mongo
storage:
# The directory where the DB files will be saved
## local:
## path: /var/lib/authelia/store
# Settings to connect to mongo server
mongo:
url: mongodb://authelia_mongo_1
database: my_authelia
# Configuration of the notification system.
#
# Notifications are sent to users when they require a password reset, a u2f
# registration or a TOTP registration.
# Use only an available configuration: filesystem, gmail
notifier:
# For testing purpose, notifications can be sent in a file
{% if not smtp.user %}
filesystem:
filename: /tmp/authelia/notification.txt
{% endif %}
# Use your email account to send the notifications. You can use an app password.
# List of valid services can be found here: https://nodemailer.com/smtp/well-known/
## email:
## username: user@example.com
## password: yourpassword
## sender: admin@example.com
## service: gmail
# Use a SMTP server for sending notifications
{% if smtp.user %}
smtp:
username: {{ smtp.user }}
password: {{ smtp.pass }}
secure: false
host: {{ smtp.host }}
port: {{ smtp.port }}
sender: {{ smtp.from_email }}
{% endif %}
\ No newline at end of file
version: 1
# Entry 3: ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
dn: ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
objectclass: organizationalUnit
objectclass: top
ou: groups
# Entry 4: cn=admin,ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
dn: cn=admin,ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
cn: admin
gidnumber: 500
objectclass: posixGroup
objectclass: top
# Entry 5: cn=developers,ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
dn: cn=developers,ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
cn: developers
gidnumber: 501
objectclass: posixGroup
objectclass: top
# Entry 6: cn=users,ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
dn: cn=users,ou=groups,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
cn: users
gidnumber: 502
objectclass: posixGroup
objectclass: top
# Entry 7: ou=users,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
dn: ou=users,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
objectclass: organizationalUnit
objectclass: top
ou: users
# Entry 8: cn={{ open_ldap.seed.first_name }} {{ open_ldap.seed.last_name }},ou=users,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
dn: cn={{ open_ldap.seed.first_name }} {{ open_ldap.seed.last_name }},ou=users,dc={{ domain_parts[0] }},dc={{ domain_parts[1] }}
cn: {{ open_ldap.seed.first_name}} {{ open_ldap.seed.last_name }}
gidnumber: 500
givenname: {{ open_ldap.seed.first_name }}
homedirectory: /home/{{ default_username }}
loginshell: /bin/bash
mail: {{ admin_email }}
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: top
sn: {{ open_ldap.seed.last_name }}
uid: {{ default_username }}
uidnumber: 1000
userpassword: {{slapd_password}}
\ No newline at end of file
---
version: '3'
# This networks section required for the pacakge to be visible to Traefik.
# DO NOT Remove
networks:
traefik_network:
external:
name: homelabos_traefik
services:
auth:
image: clems4ever/authelia:v3.15.0
restart: unless-stopped
networks:
- traefik_network
labels:
- "traefik.enable=true"
- "traefik.docker.network=homelabos_traefik"
- "traefik.http.frontend.rule=Host:auth.{{ domain }}"
- "traefik.http.port=9091"
- "traefik.http.frontend.headers.customFrameOptionsValue=ALLOW-FROM http://{{ domain }}"
- "traefik.http.frontend.headers.customFrameOptionsValue=ALLOW-FROM https://{{ domain }}"
{% if enable_tor %}
- "traefik.tor.frontend.rule=Host:auth.{{ tor_domain }}"
- "traefik.tor.protocol=http"
- "traefik.tor.port=9091"
{% endif %}
volumes:
- /var/homelabos/authelia/authelia_config.yml:/etc/authelia/config.yml:ro
- /var/homelabos/authelia/userdb.yml:/etc/authelia/userdb.yml
redis:
networks:
- traefik_network
image: redis:5.0.5-alpine
mongo:
networks:
- traefik_network
image: mongo:latest #3.4.21-xenial
environment:
MONGO_INITDB_DATABASE: my_authelia
volumes:
- /var/homelabos/authelia/mongo_data:/data/db
###############################################################
# Users Database #
###############################################################
# This file can be used if you do not have an LDAP set up.
# List of users
users:
{{default_username}}:
password: "{CRYPT}{{slapd_password}}"
email: {{ authelia.default_user_email }}
groups:
- admins
- dev
......@@ -105,6 +105,7 @@ enable_docs: {{ enable_docs | default(False) }}
enable_apache2: {{ enable_apache2 | default(False) }}
enable_apple_health_influx: {{ enable_apple_health_influx | default(False) }}
enable_airsonic: {{ enable_airsonic | default(False) }}
enable_authelia: {{ enable_authelia | default(False) }}
enable_bitwarden: {{ enable_bitwarden | default(False) }}
enable_beets: {{ enable_beets | default(False) }}
enable_bookstack: {{ enable_bookstack | default(False) }}
......@@ -264,10 +265,37 @@ gitea:
apache2_subdomain: {{ apache2_subdomain | default('apache2') }}
# LDAP Settings
ldap_org_name: {{ ldap_org_name | default() }}
# Speedtest settings
# find your local server here: http://www.speedtestserver.com
# Authelia Settings
authelia:
# Determines how verbose the logs are
log_level: {{ authelia.log_level | default('debug') }}
# Do you want to login with your common name "john doe" or your username "jdoe"?
# defaults to Username
use_username: {{ authelia.use_username | default(True) }}
# This must be an address you can recieve mail at!
default_user_email: {{authelia.default_user_email | default() }}
max:
# max # of retries to authenticate (default 5)
retries: {{ authelia.max.retries | default(5) }}
# max time before the retry count resets (default 2 min)
retries_in_time: {{ authelia.max.retries_in_time | default(120) }}
# if you exceed the max retry count within the time frame, you're banned
# for x seconds. (default 300 seconds /5 min)
retries_ban_time: {{ authelia.max.retries_ban_time | default(300) }}
default:
# the number of authentication factors required by default
factor_count: {{ authelia.default.factor_count | default('one_factor') }}
# how long it takes for the cookie to expire (default, 1hr)
cookie_expiration: {{ authelia.default.cookie_expiration | default(3600000) }}
# inactivity time for the cookie default (5m)
cookie_inactivity: {{ authelia.default.cookie_inactivity | default(300000) }} # 5min
# default policy - deny by default
policy: {{ authelia.default.policy | default('deny') }}
duo:
hostname: {{ authelia.duo.hostname | default() }}
integration_key: {{ authelia.duo.integration_key | default() }}
secret_key: {{ authelia.duo.secret_key | default() }}
# Don't change these unless you know what you're doing
speedtest:
server: {{ speedtest.server | default() }}
\ No newline at end of file
server: {{ speedtest.server | default (11441) }}
\ No newline at end of file
......@@ -13,7 +13,10 @@ defaultEntryPoints = ["http", "https"]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
{% if enable_authelia %}
[entryPoints.https.auth.forward]
address = "http://auth.{{domain}}/api/verify?rd=https://auth.{{domain}}/%23/"
{% endif %}
[retry]
[api]
......
---
# MIGRATION v0.7
- name: Remove tinc
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment