Compare commits

...

12 Commits

Author SHA1 Message Date
721164a2f2 chore: publish 9.1.0+2025.10.2 release
All checks were successful
continuous-integration/drone/tag Build is passing
2025-12-10 22:03:54 +01:00
f025eda69e add mila blueprint 2025-12-10 21:18:10 +01:00
2d67a8a77e chore: publish 10.0.0+2025.10.2 release
Some checks reported errors
continuous-integration/drone/push Build was killed
2025-11-27 10:25:25 +01:00
4824c7e587 chore: publish 9.0.2+2025.8.1 release
Some checks reported errors
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build was killed
2025-11-25 17:50:44 +01:00
c3065eee54 feat: add set_user_pass function
Some checks reported errors
continuous-integration/drone/push Build was killed
2025-11-25 16:51:29 +01:00
5b5fd5cb2e add get_secrets command
Some checks reported errors
continuous-integration/drone/push Build was killed
2025-11-25 13:10:19 +01:00
35815281b6 style: add nextcloud collectives icon
All checks were successful
continuous-integration/drone/push Build is passing
2025-11-03 13:42:50 +01:00
8c3f3e04b6 fix set_extra_icons for apps with spaces
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-30 16:12:34 +01:00
69e83844af fix removing groups from applications
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-28 15:47:35 +01:00
611fe49295 chore: publish 9.0.1+2025.8.1 release
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2025-09-23 16:04:00 +02:00
fde3efb0d0 add fix_collation_mismatch function for db container 2025-09-23 16:03:59 +02:00
9d1d89ff81 chore: publish 9.0.0+2025.8.1 release
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2025-09-17 08:18:15 +02:00
12 changed files with 232 additions and 120 deletions

View File

@ -156,5 +156,12 @@ COPY_ASSETS="$COPY_ASSETS icon.png|app:/web/dist/assets/icons/"
# APP_ICONS="$APP_ICONS hedgedoc:~/.abra/recipes/authentik/icons/hedgedoc.png"
# HEDGEDOC_APPGROUP="$GROUP_DOCUMENTATION"
# COMPOSE_FILE="$COMPOSE_FILE:compose.mila.yml"
# MILA_DOMAIN=mila.example.com
# SECRET_MILA_ID_VERSION=v1
# SECRET_MILA_SECRET_VERSION=v1
# APP_ICONS="$APP_ICONS mila:~/.abra/recipes/authentik/icons/mila.svg"
# MILA_APPGROUP=""
# APPLICATIONS='{"Calendar": {"url":"https://nextcloud.example.com/apps/calendar/", "group": ""}, "BBB": {"url":"https://nextcloud.example.com/apps/bbb/", "group":""}, "Pretix": {"url":"https://pretix.example.com/control/", "group":""}}'
# EXTRA_ICONS={"Calendar": "~/.abra/recipes/authentik/icons/calendar.svg", "BBB": "~/.abra/recipes/authentik/icons/bbb.png", "Pretix": "~/.abra/recipes/authentik/icons/pretix.svg"}

1
.gitignore vendored
View File

@ -1 +1,2 @@
.envrc
.cursorignore

213
abra.sh
View File

@ -16,48 +16,46 @@ export ZAMMAD_CONFIG_VERSION=v4
export RALLLY_CONFIG_VERSION=v4
export HEDGEDOC_CONFIG_VERSION=v3
export MONITORING_CONFIG_VERSION=v4
export MILA_CONFIG_VERSION=v1
export DB_ENTRYPOINT_VERSION=v1
export PG_BACKUP_VERSION=v2
export ENTRYPOINT_CSS_VERSION=v1
customize() {
if [ -z "$1" ]
then
echo "Usage: ... customize <assets_path>"
exit 1
fi
asset_dir=$1
for asset in $COPY_ASSETS; do
source=$(echo $asset | cut -d "|" -f1)
target=$(echo $asset | cut -d "|" -f2)
echo copy $source to $target
abra app cp $APP_NAME $asset_dir/$source $target
done
if [ -z "$1" ]; then
echo "Usage: ... customize <assets_path>"
exit 1
fi
asset_dir=$1
for asset in $COPY_ASSETS; do
source=$(echo $asset | cut -d "|" -f1)
target=$(echo $asset | cut -d "|" -f2)
echo copy $source to $target
abra app cp $APP_NAME $asset_dir/$source $target
done
}
shell(){
if [ -z "$1" ]
then
echo "Usage: ... shell <python code>"
exit 1
fi
ak shell -c "$1" 2>&1 | quieten
shell() {
if [ -z "$1" ]; then
echo "Usage: ... shell <python code>"
exit 1
fi
ak shell -c "$1" 2>&1 | quieten
}
import_user() {
if [ -z "$1" ]
then
echo "Usage: ... import_user <users.csv>"
exit 1
fi
source_file=$1
filename=$(basename $source_file)
abra app cp $APP_NAME $source_file worker:/tmp/
abra app cmd -T $APP_NAME worker _import_user $filename
if [ -z "$1" ]; then
echo "Usage: ... import_user <users.csv>"
exit 1
fi
source_file=$1
filename=$(basename $source_file)
abra app cp $APP_NAME $source_file worker:/tmp/
abra app cmd -T $APP_NAME worker _import_user $filename
}
_import_user() {
/manage.py shell -c """
/manage.py shell -c """
import csv
new_user = User()
with open('/tmp/$1', newline='') as file:
@ -84,10 +82,22 @@ with open('/tmp/$1', newline='') as file:
""" 2>&1 | quieten
}
set_user_pass() {
username="$1"
password="$2"
/manage.py shell -c """
user = User.objects.get(username='$username')
user.set_password('$password')
user.save()
print('Changed $username password')
""" 2>&1 | quieten
}
set_admin_pass() {
password=$(cat /run/secrets/admin_pass)
token=$(cat /run/secrets/admin_token)
/manage.py shell -c """
password=$(cat /run/secrets/admin_pass)
token=$(cat /run/secrets/admin_token)
/manage.py shell -c """
import time
i = 0
while (not User.objects.filter(username='akadmin')):
@ -122,45 +132,45 @@ else:
}
rotate_db_pass() {
db_password=$(cat /run/secrets/db_password)
psql -U authentik -c """ALTER USER authentik WITH PASSWORD '$db_password';"""
db_password=$(cat /run/secrets/db_password)
psql -U authentik -c """ALTER USER authentik WITH PASSWORD '$db_password';"""
}
# This function is for blueprints that are overwriting custom blueprints
# It deactivates the affected custom blueprints to avoid changes to be reverted
apply_blueprints() {
update_and_disable_blueprint default/flow-password-change.yaml
update_and_disable_blueprint default/flow-default-authentication-flow.yaml
update_and_disable_blueprint default/flow-default-user-settings-flow.yaml
update_and_disable_blueprint default/flow-default-source-enrollment.yaml
apply_blueprint 3_flow_translation.yaml
apply_blueprint 2_flow_authentication.yaml
update_and_disable_blueprint default/flow-password-change.yaml
update_and_disable_blueprint default/flow-default-authentication-flow.yaml
update_and_disable_blueprint default/flow-default-user-settings-flow.yaml
update_and_disable_blueprint default/flow-default-source-enrollment.yaml
apply_blueprint 3_flow_translation.yaml
apply_blueprint 2_flow_authentication.yaml
}
update_and_disable_blueprint() {
enable_blueprint $@ 2>&1 | quieten
sleep 1
apply_blueprint $@
sleep 1
disable_blueprint $@ 2>&1 | quieten
enable_blueprint $@ 2>&1 | quieten
sleep 1
apply_blueprint $@
sleep 1
disable_blueprint $@ 2>&1 | quieten
}
disable_blueprint() {
blueprint_state False $@
blueprint_state False $@
}
enable_blueprint() {
blueprint_state True $@
blueprint_state True $@
}
apply_blueprint() {
echo apply blueprint $@
ak apply_blueprint $@ 2>&1 | quieten
echo apply blueprint $@
ak apply_blueprint $@ 2>&1 | quieten
}
blueprint_state() {
/manage.py shell -c """
/manage.py shell -c """
import time
blueprint_state=$1
blueprint_path='$2'
@ -178,9 +188,9 @@ print(f'{blueprint.name} enabled: {blueprint.enabled}')
}
# This function adds each application with its name, slug and group if passed
add_applications(){
export APPLICATIONS
/manage.py shell -c """
add_applications() {
export APPLICATIONS
/manage.py shell -c """
import json
import os
if os.environ['APPLICATIONS'] == '':
@ -199,6 +209,7 @@ for name, details in applications.items():
app.group = group
print(f'Add {name}: {url} in group: {group}')
else:
app.group = ''
print(f'Add {name}: {url}')
app.open_in_new_tab = True
app.save()
@ -207,69 +218,66 @@ for name, details in applications.items():
## This function is for renaming apps - usage: rename "old name" "new name"
rename() {
/manage.py shell -c """
old_name = '$1'
new_name = '$2' if '$2' else old_name
/manage.py shell -c """
old_name = '$1'
new_name = '$2' if '$2' else old_name
app = Application.objects.filter(name=old_name).first()
if app:
app.name = new_name
app.save()
print(f'Renamed application from {old_name} to {new_name}')
else:
print(f'No application found with name: {old_name}')
""" > /dev/null 2>&1
app = Application.objects.filter(name=old_name).first()
if app:
app.name = new_name
app.save()
print(f'Renamed application from {old_name} to {new_name}')
else:
print(f'No application found with name: {old_name}')
""" 2>&1 | quieten
}
quieten(){
# 'SyntaxWarning|version_regex|"http\['
# is a workaround to get rid of some verbose syntax warnings, this might be fixed with another version
grep -Pv '"level": "(info|debug)"|SyntaxWarning|version_regex|"http\[|RuntimeWarning:'
quieten() {
# 'SyntaxWarning|version_regex|"http\['
# is a workaround to get rid of some verbose syntax warnings, this might be fixed with another version
grep -Pv '"level": "(info|debug)"|SyntaxWarning|version_regex|"http\[|RuntimeWarning:'
}
add_email_templates(){
for file_path in "$@"; do
add_email_templates() {
for file_path in "$@"; do
echo copy template $file_path
abra app cp $APP_NAME $file_path app:/templates/
done
done
}
set_icons(){
if [ -n "$1" ]
then
APP_ICONS="$1"
fi
for icon in $APP_ICONS; do
set_icons() {
if [ -n "$1" ]; then
APP_ICONS="$1"
fi
for icon in $APP_ICONS; do
app=$(echo $icon | cut -d ":" -f1)
file_path=$(eval echo $(echo $icon | cut -d ":" -f2))
file=$(basename $file_path)
echo copy icon $file_path for $app
abra app cp $APP_NAME $file_path app:/media/
abra app cmd -T $APP_NAME app set_app_icon $app /media/$file
done
done
}
set_extra_icons(){
if [ -z "$EXTRA_ICONS" ]
then
echo "Variable EXTRA_ICONS is not set"
exit 1
fi
export EXTRA_ICONS
icon_key_values=$(python3 -c "
set_extra_icons() {
if [ -z "$EXTRA_ICONS" ]; then
echo "Variable EXTRA_ICONS is not set"
exit 1
fi
export EXTRA_ICONS
icon_key_values=$(python3 -c "
import json
import os
for key, value in json.loads(os.environ['EXTRA_ICONS']).items():
print(f'{key}:{value}')
slug = key.replace(' ','-')
print(f'{slug}:{value}')
")
set_icons "$icon_key_values"
set_icons "$icon_key_values"
}
set_app_icon() {
TOKEN=$(cat /run/secrets/admin_token)
python -c """
TOKEN=$(cat /run/secrets/admin_token)
python -c """
import requests
import os
my_token = '$TOKEN'
@ -288,18 +296,18 @@ with open(icon_path, 'rb') as img:
}
blueprint_cleanup() {
/manage.py shell -c """
/manage.py shell -c """
delete_flows = ['default-recovery-flow' , 'custom-authentication-flow' , 'invitation-enrollment-flow' , 'initial-setup']
Flow.objects.filter(slug__in=delete_flows).delete()
Stage.objects.filter(flow=None).delete()
Prompt.objects.filter(promptstage=None).delete()
Brand.objects.filter(default=True).delete()
""" 2>&1 | quieten
apply_blueprints
apply_blueprints
}
get_certificate() {
/manage.py shell -c """
/manage.py shell -c """
provider_name='$1'
if not provider_name:
print('no Provider Name given')
@ -312,7 +320,18 @@ print(''.join(cert.certificate_data.splitlines()[1:-1]))
}
get_user_uid() {
/manage.py shell -c """
/manage.py shell -c """
print(User.objects.filter(username='$1').first().uid)
""" 2>&1 | quieten
}
get_secrets() {
grep "" -r /var/run/secrets
}
fix_collation_mismatch() {
psql -U ${POSTGRES_USER} -d authentik -c "ALTER DATABASE authentik REFRESH COLLATION VERSION;"
psql -U ${POSTGRES_USER} -d authentik -c "REINDEX DATABASE authentik;"
psql -U ${POSTGRES_USER} -d postgres -c "ALTER DATABASE postgres REFRESH COLLATION VERSION;"
psql -U ${POSTGRES_USER} -d postgres -c "REINDEX DATABASE postgres;"
}

View File

@ -87,3 +87,12 @@ hedgedoc:
- hedgedoc.png
secrets:
hedgedoc_id: hedgedoc
mila:
uncomment:
- compose.mila.yml
- MILA_DOMAIN
- SECRET_MILA_ID_VERSION
- SECRET_MILA_SECRET_VERSION
- mila.svg
secrets:
mila_id: mila

27
compose.mila.yml Normal file
View File

@ -0,0 +1,27 @@
version: "3.8"
services:
worker:
secrets:
- mila_id
- mila_secret
environment:
- MILA_DOMAIN
configs:
- source: mila
target: /blueprints/mila.yaml
secrets:
mila_id:
external: true
name: ${STACK_NAME}_mila_id_${SECRET_MILA_ID_VERSION}
mila_secret:
external: true
name: ${STACK_NAME}_mila_secret_${SECRET_MILA_SECRET_VERSION}
configs:
mila:
name: ${STACK_NAME}_mila_${MILA_CONFIG_VERSION}
file: mila.yaml.tmpl
template_driver: golang

View File

@ -1,7 +1,7 @@
version: "3.8"
services:
authentik_ldap:
image: ghcr.io/goauthentik/ldap:2025.8.1
image: ghcr.io/goauthentik/ldap:2025.10.2
# Optionally specify which networks the container should be
# might be needed to reach the core authentik server
networks:

View File

@ -5,7 +5,6 @@ x-env: &env
- AUTHENTIK_POSTGRESQL__USER=authentik
- AUTHENTIK_POSTGRESQL__NAME=authentik
- AUTHENTIK_POSTGRESQL__HOST=db
- AUTHENTIK_REDIS__HOST=redis
- AUTHENTIK_ERROR_REPORTING__ENABLED
- AUTHENTIK_SECRET_KEY=file:///run/secrets/secret_key
- AUTHENTIK_EMAIL__HOST
@ -35,11 +34,10 @@ x-env: &env
version: '3.8'
services:
app:
image: ghcr.io/goauthentik/server:2025.8.1
image: ghcr.io/goauthentik/server:2025.10.2
command: server
depends_on:
- db
- redis
secrets:
- db_password
- admin_pass
@ -71,18 +69,17 @@ services:
- "traefik.http.routers.${STACK_NAME}.middlewares=${STACK_NAME}-redirect,${STACK_NAME}-frameOptions,${STACK_NAME}-redirect"
- "traefik.http.middlewares.${STACK_NAME}-frameOptions.headers.customFrameOptionsValue=SAMEORIGIN"
- "traefik.http.middlewares.${STACK_NAME}-frameOptions.headers.contentSecurityPolicy=frame-ancestors ${X_FRAME_OPTIONS_ALLOW_FROM}"
- "coop-cloud.${STACK_NAME}.version=8.0.0+2025.8.1"
- "coop-cloud.${STACK_NAME}.version=10.1.0+2025.10.2"
- "traefik.http.middlewares.${STACK_NAME}-redirect.redirectregex.regex=^https://(${REDIRECTS})/(.*)"
- "traefik.http.middlewares.${STACK_NAME}-redirect.redirectregex.replacement=https://${DOMAIN}/$${2}"
- "traefik.http.middlewares.${STACK_NAME}-redirect.redirectregex.permanent=true"
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-120}"
worker:
image: ghcr.io/goauthentik/server:2025.8.1
image: ghcr.io/goauthentik/server:2025.10.2
command: worker
depends_on:
- db
- redis
secrets:
- db_password
- admin_pass
@ -119,7 +116,7 @@ services:
start_period: 5m
db:
image: postgres:15.13
image: postgres:15.15
secrets:
- db_password
configs:
@ -150,22 +147,8 @@ services:
backupbot.backup: "${ENABLE_BACKUPS:-true}"
backupbot.backup.pre-hook: "/pg_backup.sh backup"
backupbot.backup.volumes.database.path: "backup.sql"
backupbot.backup.volumes.redis: "false"
backupbot.restore.post-hook: '/pg_backup.sh restore'
redis:
image: redis:8.2.1-alpine
command: --save 60 1 --loglevel warning
networks:
- internal
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
interval: 30s
timeout: 10s
retries: 10
start_period: 1m
volumes:
- redis:/data
secrets:
db_password:
@ -192,7 +175,6 @@ networks:
volumes:
media:
certs:
redis:
templates:
assets:
database:

12
icons/collectives.svg Normal file
View File

@ -0,0 +1,12 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16">
<g>
<path d="M2.9,8.8c0-1.2,0.4-2.4,1.2-3.3L0.3,6c-0.2,0-0.3,0.3-0.1,0.4l2.7,2.6C2.9,9,2.9,8.9,2.9,8.8z" />
<path d="M8,3.7c0.7,0,1.3,0.1,1.9,0.4L8.2,0.6c-0.1-0.2-0.3-0.2-0.4,0L6.1,4C6.7,3.8,7.3,3.7,8,3.7z" />
<path d="M3.7,11.5L3,15.2c0,0.2,0.2,0.4,0.4,0.3l3.3-1.7C5.4,13.4,4.4,12.6,3.7,11.5z" />
<path d="M15.7,6l-3.7-0.5c0.7,0.9,1.2,2,1.2,3.3c0,0.1,0,0.2,0,0.3l2.7-2.6C15.9,6.3,15.9,6.1,15.7,6z" />
<path d="M12.3,11.5c-0.7,1.1-1.8,1.9-3,2.2l3.3,1.7c0.2,0.1,0.4-0.1,0.4-0.3L12.3,11.5z" />
<path d="M9.6,10.1c-0.4,0.5-1,0.8-1.6,0.8c-1.1,0-2-0.9-2.1-2C5.9,7.7,6.8,6.7,8,6.7c0.6,0,1.1,0.3,1.5,0.7
c0.1,0.1,0.1,0.1,0.2,0.1h1.4c0.2,0,0.4-0.2,0.3-0.5c-0.7-1.3-2.1-2.2-3.8-2.1C5.8,5,4.3,6.6,4.1,8.5C4,10.8,5.8,12.7,8,12.7
c1.6,0,2.9-0.9,3.5-2.3c0.1-0.2-0.1-0.4-0.3-0.4H9.9C9.8,10,9.7,10,9.6,10.1z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 917 B

5
icons/mila.svg Normal file
View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<rect width="100" height="100" rx="12" fill="#4f46e5"/>
<text x="50" y="65" font-family="Arial, sans-serif" font-size="48" font-weight="bold" fill="white" text-anchor="middle">M</text>
</svg>

After

Width:  |  Height:  |  Size: 285 B

49
mila.yaml.tmpl Normal file
View File

@ -0,0 +1,49 @@
version: 1
metadata:
labels:
blueprints.goauthentik.io/instantiate: "true"
name: mila
entries:
- attrs:
access_code_validity: minutes=1
authentication_flow: !Find [authentik_flows.flow, [slug, default-authentication-flow]]
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
client_id: {{ secret "mila_id" }}
client_secret: {{ secret "mila_secret" }}
client_type: confidential
include_claims_in_id_token: true
issuer_mode: per_provider
redirect_uris:
- matching_mode: strict
url: https://{{ env "MILA_DOMAIN" }}/auth/user/rauthy/callback
name: Mila
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]]
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
sub_mode: hashed_user_id
token_validity: days=30
conditions: []
id: mila_provider
identifiers:
pk: 9990
model: authentik_providers_oauth2.oauth2provider
state: present
- attrs:
meta_launch_url: https://{{ env "MILA_DOMAIN" }}
open_in_new_tab: true
policy_engine_mode: any
provider: !KeyOf mila_provider
slug: mila
conditions: []
id: mila_application
identifiers:
name: Mila
model: authentik_core.application
state: present

1
release/10.0.0+2025.10.2 Normal file
View File

@ -0,0 +1 @@
2025.10 removes redis. Since 2025.8 all redis tasks have been migrated to postgres.