diff --git a/.idea/jsonSchemas.xml b/.idea/jsonSchemas.xml
index eb488a0..e5121b9 100644
--- a/.idea/jsonSchemas.xml
+++ b/.idea/jsonSchemas.xml
@@ -27,6 +27,13 @@
+
diff --git a/contrib/compose_helpers.j2 b/contrib/compose_helpers.j2
index b4f4010..5bb73a3 100644
--- a/contrib/compose_helpers.j2
+++ b/contrib/compose_helpers.j2
@@ -1,4 +1,4 @@
-{% macro traefik_labels(host, service="", port="") %}
+{% macro traefik_labels(host, service="", port="", auth=false) %}
traefik.enable=true
- traefik.http.routers.{{ host }}.rule=Host(`{{ host }}.{{ domain }}`)
- traefik.http.routers.{{ host }}.entrypoints=web
@@ -10,8 +10,11 @@ traefik.enable=true
- traefik.http.routers.{{ host }}-tls.tls.domains.0.sans=*.{{ domain }}
{% if service -%}
- traefik.http.routers.{{ host }}.service={{ service }}
-{%- endif %}
+{% endif %}
{% if port -%}
- traefik.http.services.{{ host }}.loadbalancer.server.port={{ port }}
-{%- endif %}
-{%- endmacro %}
+{% endif %}
+{% if auth -%}
+- traefik.http.routers.{{ host }}-tls.middlewares=authentik@docker
+{% endif %}
+{% endmacro %}
diff --git a/inventories/prod/group_vars/all.yml b/inventories/prod/group_vars/all.yml
index 3c54186..e5ef8ff 100644
--- a/inventories/prod/group_vars/all.yml
+++ b/inventories/prod/group_vars/all.yml
@@ -8,3 +8,13 @@ wg_privkey: !vault |
3831353935663865390a383335333133613039386237653665653663346666626666616439323530
33626333383830383430313765386439323738336336333234303738383837356135353635366365
3066313962653537376430613963316132613663356665316238
+
+github_consumer_key: 32d5cae58d744c56fcc9
+github_consumer_secret: !vault |
+ $ANSIBLE_VAULT;1.2;AES256;alpina
+ 36353230356266303131333732363736383633313038326161346434303061633464393738383433
+ 3933343436316530306439326237353265363333656264620a373036383835313733303561333233
+ 33343834313163613037643734653535306365326536383532366166313261323265616133333865
+ 3362663865666466320a363338303436626532393665663564313937366362326263396431316538
+ 33396237333766666635333039643338333133346636363966326437646334636138353934333834
+ 3139363661653364306231303966346333643166326536383164
diff --git a/inventories/staging/group_vars/all.yml b/inventories/staging/group_vars/all.yml
index 4d14df2..3bf1eb1 100644
--- a/inventories/staging/group_vars/all.yml
+++ b/inventories/staging/group_vars/all.yml
@@ -8,3 +8,13 @@ wg_privkey: !vault |
3662633131636332620a313334396161386230303936646566363162643831393965376563386432
37613538613466353266666566373836663037363139316463313335633335633536613232323062
3765366135356362326138313636646263646235656333386132
+
+github_consumer_key: dbacb8621c37320eb745
+github_consumer_secret: !vault |
+ $ANSIBLE_VAULT;1.2;AES256;alpina
+ 65393439653532323865356337353164666331653438396564613663363865643233323666316537
+ 6365303062326139366139623232366338663831333333610a343035313364383738396635633737
+ 32616366393365643565636337633334363637356435386235373638653139326665353537363939
+ 3936336336663264310a343137653436323831366237376539353231656463663164316133376333
+ 37373937356438373335663234616165663739626663663635316335333534333566326632346437
+ 3539656334346163663635376533376362626235343466303430
diff --git a/roles/arrstack/templates/docker-compose.yml.j2 b/roles/arrstack/templates/docker-compose.yml.j2
index 7400a5b..5d401d9 100644
--- a/roles/arrstack/templates/docker-compose.yml.j2
+++ b/roles/arrstack/templates/docker-compose.yml.j2
@@ -14,7 +14,7 @@ services:
cap_add:
- NET_ADMIN
labels:
- - {{ traefik_labels("qbit", port="8080") | indent(6) }}
+ - {{ traefik_labels("qbit", port="8080", auth=true) | indent(6) }}
restart: unless-stopped
networks:
- default
@@ -31,7 +31,7 @@ services:
image: linuxserver/prowlarr:latest
container_name: prowlarr
labels:
- - {{ traefik_labels("prowlarr", port="9696") | indent(6) }}
+ - {{ traefik_labels("prowlarr", port="9696", auth=true) | indent(6) }}
restart: unless-stopped
depends_on:
- qbittorrent
@@ -45,7 +45,7 @@ services:
image: linuxserver/sonarr:latest
container_name: sonarr
labels:
- - {{ traefik_labels("sonarr", port="8989") | indent(6) }}
+ - {{ traefik_labels("sonarr", port="8989", auth=true) | indent(6) }}
restart: unless-stopped
depends_on:
- qbittorrent
@@ -61,7 +61,7 @@ services:
image: linuxserver/radarr:latest
container_name: radarr
labels:
- - {{ traefik_labels("radarr", port="7878") | indent(6) }}
+ - {{ traefik_labels("radarr", port="7878", auth=true) | indent(6) }}
restart: unless-stopped
depends_on:
- qbittorrent
diff --git a/roles/authentik/templates/.env.authentik.j2 b/roles/authentik/templates/.env.authentik.j2
new file mode 100644
index 0000000..a0446de
--- /dev/null
+++ b/roles/authentik/templates/.env.authentik.j2
@@ -0,0 +1,21 @@
+AUTHENTIK_ERROR_REPORTING__ENABLED=true
+
+AUTHENTIK_REDIS__HOST=redis
+AUTHENTIK_POSTGRESQL__HOST=postgres
+AUTHENTIK_POSTGRESQL__USER=authentik
+AUTHENTIK_POSTGRESQL__NAME=authentik
+AUTHENTIK_POSTGRESQL__PASSWORD={{ db_password }}
+
+AUTHENTIK_SECRET_KEY={{ authentik_secret_key }}
+
+AUTHENTIK_EMAIL__HOST=smtp.sendgrid.net
+AUTHENTIK_EMAIL__PORT=587
+AUTHENTIK_EMAIL__USERNAME=apikey
+AUTHENTIK_EMAIL__PASSWORD={{ sengrid_api_key }}
+
+AUTHENTIK_EMAIL__USE_TLS=true
+AUTHENTIK_EMAIL__TIMEOUT=10
+AUTHENTIK_EMAIL__FROM=auth@cazzzer.com
+
+AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL=false
+AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME=false
diff --git a/roles/authentik/templates/.env.db.j2 b/roles/authentik/templates/.env.db.j2
new file mode 100644
index 0000000..ab2eb10
--- /dev/null
+++ b/roles/authentik/templates/.env.db.j2
@@ -0,0 +1,3 @@
+POSTGRES_USER=authentik
+POSTGRES_DB=authentik
+POSTGRES_PASSWORD={{ db_password }}
diff --git a/roles/authentik/templates/.env.j2 b/roles/authentik/templates/.env.j2
new file mode 100644
index 0000000..32676c3
--- /dev/null
+++ b/roles/authentik/templates/.env.j2
@@ -0,0 +1 @@
+AUTHENTIK_VERSION=2023.3
\ No newline at end of file
diff --git a/roles/authentik/templates/blueprints/apps-oauth2.yaml.j2 b/roles/authentik/templates/blueprints/apps-oauth2.yaml.j2
new file mode 100644
index 0000000..2470cfe
--- /dev/null
+++ b/roles/authentik/templates/blueprints/apps-oauth2.yaml.j2
@@ -0,0 +1,51 @@
+version: 1
+metadata:
+ labels:
+ blueprints.goauthentik.io/instantiate: "true"
+ name: Alpina - OAuth2 Apps
+entries:
+ {% set apps = {
+ "Gitea": {
+ "redirect_uris": "https://gitea."~ domain ~"/user/oauth2/Authentik/callback",
+ "icon": "https://gitea."~ domain ~"/assets/img/logo.svg",
+ },
+ "Nextcloud": {
+ "redirect_uris": "https://nc."~ domain ~"/apps/sociallogin/custom_oidc/authentik",
+ "icon": "https://nc."~ domain ~"/apps/theming/favicon",
+ },
+ } -%}
+ {% for app in apps.keys() -%}
+ - identifiers:
+ name: {{ app }}
+ model: authentik_providers_oauth2.oauth2provider
+ id: {{ app | lower }}
+ attrs:
+ access_code_validity: minutes=1
+ access_token_validity: minutes=5
+ authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
+ client_type: confidential
+ issuer_mode: per_provider
+ sub_mode: hashed_user_id
+ property_mappings:
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
+ redirect_uris: {{ apps[app]["redirect_uris"] }}
+ refresh_token_validity: days=30
+ signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Self-signed Certificate"]]
+
+ - identifiers:
+ slug: {{ app | lower }}
+ model: authentik_core.application
+ id: {{ app | lower }}
+ attrs:
+ name: {{ app }}
+ group: "Apps"
+ meta_description: "Hello, I'm {{ app }}!"
+ meta_publisher: Alpina
+ # This isn't supported yet, https://github.com/goauthentik/authentik/issues/3484
+ # meta_icon: "{{ apps[app]["icon"] }}"
+ open_in_new_tab: true
+ policy_engine_mode: any
+ provider: !KeyOf {{ app | lower }}
+ {% endfor %}
diff --git a/roles/authentik/templates/blueprints/arrstack.yaml.j2 b/roles/authentik/templates/blueprints/arrstack.yaml.j2
new file mode 100644
index 0000000..906e1b5
--- /dev/null
+++ b/roles/authentik/templates/blueprints/arrstack.yaml.j2
@@ -0,0 +1,65 @@
+version: 1
+metadata:
+ labels:
+ blueprints.goauthentik.io/instantiate: "true"
+ name: Alpina - Arrstack Proxy
+entries:
+ - identifiers:
+ name: arrstack
+ model: authentik_core.group
+ id: arrstack
+
+ {% for service in ["qBit", "Prowlarr", "Sonarr", "Radarr"] -%}
+ - identifiers:
+ name: {{ service }}
+ model: authentik_providers_proxy.proxyprovider
+ id: {{ service | lower }}
+ attrs:
+ access_token_validity: hours=24
+ authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
+ certificate: !Find [authentik_crypto.certificatekeypair, [name, "authentik Self-signed Certificate"]]
+ intercept_header_auth: true
+ external_host: https://{{ service | lower }}.{{ domain }}/
+ mode: forward_single
+ property_mappings:
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
+ - !Find [authentik_providers_oauth2.scopemapping, [scope_name, ak_proxy]]
+ refresh_token_validity: days=30
+ skip_path_regex: {{ "/images/qbittorrent-tray.svg" if service == "qBit" else "/Content/Images/logo.svg" }}
+
+ - identifiers:
+ slug: {{ service | lower }}
+ model: authentik_core.application
+ id: {{ service | lower }}
+ attrs:
+ name: {{ service }}
+ group: "Arrstack"
+ meta_description: "Hello, I'm {{ service }}!"
+ meta_publisher: Alpina
+ # This isn't supported yet, https://github.com/goauthentik/authentik/issues/3484
+ # meta_icon: "https://{{ service }}.{{ domain }}/Content/Images/logo.svg"
+ open_in_new_tab: true
+ policy_engine_mode: any
+ provider: !KeyOf {{ service | lower }}
+
+ - identifiers:
+ group: !KeyOf arrstack
+ target: !Find [authentik_core.application, [slug, {{ service | lower }}]]
+ model: authentik_policies.policybinding
+ attrs:
+ enabled: true
+ order: 0
+ timeout: 30
+ {% endfor %}
+
+ - identifiers:
+ managed: goauthentik.io/outposts/embedded
+ name: authentik Embedded Outpost
+ model: authentik_outposts.outpost
+ attrs:
+ providers:
+ {% for service in ["qBit", "Prowlarr", "Sonarr", "Radarr"] -%}
+ - !KeyOf {{ service | lower }}
+ {% endfor %}
diff --git a/roles/authentik/templates/blueprints/default-authentication.yaml.j2 b/roles/authentik/templates/blueprints/default-authentication.yaml.j2
new file mode 100644
index 0000000..701902b
--- /dev/null
+++ b/roles/authentik/templates/blueprints/default-authentication.yaml.j2
@@ -0,0 +1,19 @@
+version: 1
+metadata:
+ labels:
+ blueprints.goauthentik.io/instantiate: "true"
+ name: Alpina - Default Identification Stage
+entries:
+ - identifiers:
+ name: default-authentication-identification
+ model: authentik_stages_identification.identificationstage
+ attrs:
+ sources:
+ - !Find [authentik_core.source, [slug, authentik-built-in]]
+ - !Find [authentik_sources_oauth.oauthsource, [slug, github]]
+
+ - identifiers:
+ slug: default-authentication-flow
+ model: authentik_flows.flow
+ attrs:
+ compatibility_mode: true
diff --git a/roles/authentik/templates/blueprints/github-oauth.yaml.j2 b/roles/authentik/templates/blueprints/github-oauth.yaml.j2
new file mode 100644
index 0000000..93c93b4
--- /dev/null
+++ b/roles/authentik/templates/blueprints/github-oauth.yaml.j2
@@ -0,0 +1,25 @@
+version: 1
+metadata:
+ labels:
+ blueprints.goauthentik.io/instantiate: "true"
+ name: Alpina - GitHub OAuth
+entries:
+ - identifiers:
+ slug: github
+ model: authentik_sources_oauth.oauthsource
+ attrs:
+ name: GitHub
+ slug: github
+ access_token_url: https://github.com/login/oauth/access_token
+ additional_scopes: openid read:org
+ authentication_flow: !Find [authentik_flows.flow, [slug, default-source-authentication]]
+ authorization_url: https://github.com/login/oauth/authorize
+ consumer_key: {{ github_consumer_key }}
+ consumer_secret: {{ github_consumer_secret }}
+ enabled: true
+ enrollment_flow: !Find [authentik_flows.flow, [slug, default-source-enrollment]]
+ policy_engine_mode: any
+ profile_url: https://api.github.com/user
+ provider_type: github
+ user_matching_mode: email_link
+ user_path_template: goauthentik.io/sources/%(slug)s
diff --git a/roles/authentik/templates/docker-compose.yml.j2 b/roles/authentik/templates/docker-compose.yml.j2
new file mode 100644
index 0000000..35978a1
--- /dev/null
+++ b/roles/authentik/templates/docker-compose.yml.j2
@@ -0,0 +1,63 @@
+{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
+{##}
+version: "3.7"
+
+networks:
+ default:
+ traefik_traefik:
+ external: true
+
+services:
+ server:
+ image: ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}
+ container_name: authentik_server
+ labels:
+ - {{ traefik_labels("auth", port="9000") | indent(6) }}
+ - traefik.http.middlewares.authentik.forwardauth.address=http://authentik_server:9000/outpost.goauthentik.io/auth/traefik
+ - traefik.http.middlewares.authentik.forwardauth.trustForwardHeader=true
+ - traefik.http.middlewares.authentik.forwardauth.authResponseHeaders=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
+ restart: unless-stopped
+ command: server
+ env_file:
+ - .env.authentik
+ networks:
+ - default
+ - traefik_traefik
+
+ worker:
+ image: ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}
+ container_name: authentik_worker
+ restart: unless-stopped
+ command: worker
+ env_file:
+ - .env.authentik
+ volumes:
+ - ./blueprints:/blueprints/alpina
+ - {{ base_volume_path }}/authentik/certs:/certs
+
+ postgres:
+ image: postgres:12-alpine
+ container_name: authentik_postgres
+ restart: unless-stopped
+ env_file:
+ - .env.db
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 5s
+ volumes:
+ - {{ base_volume_path }}/authentik/postgres:/var/lib/postgresql/data
+
+ redis:
+ image: redis:alpine
+ container_name: authentik_redis
+ restart: unless-stopped
+ command: --save 60 1 --loglevel warning
+ healthcheck:
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
+ start_period: 20s
+ interval: 30s
+ retries: 5
+ timeout: 3s
diff --git a/roles/authentik/vars/app_config.yml b/roles/authentik/vars/app_config.yml
new file mode 100644
index 0000000..69ad34a
--- /dev/null
+++ b/roles/authentik/vars/app_config.yml
@@ -0,0 +1,18 @@
+$ANSIBLE_VAULT;1.2;AES256;alpina
+38336166363764396232386330336236356663376532323666326237336636626661343963653838
+6362363439383865393864363535613664656565653138360a373066343138633337653536386138
+63373232616430626464303832313966353162626333393032656237313939366538643930613365
+6637373666616538370a353635393731356237316462326437326463636438306134323839323637
+31653333326531663236333862316533346533623761306135393233333730386131666235356663
+62313030323736373837633938646237303966373865353037656339613364386165646534373461
+64343164663533613931613461616166646632353362386638336162303935336466393133356265
+31643366623036356632646338616431663737636637656462316165363231383631353961383663
+35613565316638353361316632376263633866353562303832623562393832326439386230343237
+39386536376530336365336234363134643334303836326130396330626566366663303764313262
+33333333353738623230633139343135613730636161306662636136646361613863363461333462
+64633434323361643034333834643766336466333636616136616563643930636339663462633865
+34343133663737356633633264396433373334393065366130313563393231633932663231616137
+65643739333137393034623362303735643166326132343133643435613936373333333464356638
+32646436373264636161613630366661383265373537646239643562303237636663616638383030
+62363664633332663638396630366134613464363137323562646236383961373239333133323964
+3065