From cf0673c43bb744bf1cca481651f4bed738c06dce Mon Sep 17 00:00:00 2001 From: DrMxrcy <58747968+DrMxrcy@users.noreply.github.com> Date: Tue, 14 Nov 2023 19:50:53 -0500 Subject: [PATCH] Add Authentik (#1595) * Add Authentik * Update Missing Items From Tests * Update docker-compose.yml * Update config.json * Update docker-compose.yml * Update Envs * Update docker-compose.yml --- apps/authentik/config.json | 30 +++++++ apps/authentik/docker-compose.yml | 115 +++++++++++++++++++++++++ apps/authentik/metadata/description.md | 22 +++++ apps/authentik/metadata/logo.jpg | Bin 0 -> 8864 bytes 4 files changed, 167 insertions(+) create mode 100644 apps/authentik/config.json create mode 100644 apps/authentik/docker-compose.yml create mode 100644 apps/authentik/metadata/description.md create mode 100644 apps/authentik/metadata/logo.jpg diff --git a/apps/authentik/config.json b/apps/authentik/config.json new file mode 100644 index 00000000..16eb6d7b --- /dev/null +++ b/apps/authentik/config.json @@ -0,0 +1,30 @@ +{ + "$schema": "../schema.json", + "name": "Authentik", + "port": 8770, + "available": true, + "exposable": true, + "id": "authentik", + "tipi_version": 1, + "version": "2023.10.3", + "categories": ["development"], + "description": "The authentication glue you need.", + "short_desc": "The authentication glue you need.", + "author": "goauthentik", + "source": "https://github.com/goauthentik/authentik", + "form_fields": [ + { + "type": "random", + "label": "AUTHENTIK_DB_PASSWORD", + "min": 40, + "env_variable": "AUTHENTIK_DB_PASSWORD" + }, + { + "type": "random", + "label": "AUTHENTIK_SECRET_KEY", + "min": 50, + "env_variable": "AUTHENTIK_SECRET_KEY" + } + ], + "supported_architectures": ["arm64", "amd64"] +} diff --git a/apps/authentik/docker-compose.yml b/apps/authentik/docker-compose.yml new file mode 100644 index 00000000..ef7e8fb4 --- /dev/null +++ b/apps/authentik/docker-compose.yml @@ -0,0 +1,115 @@ +version: "3.7" + +services: + authentik: + image: ghcr.io/goauthentik/server:2023.10.3 + restart: unless-stopped + command: server + container_name: authentik + environment: + AUTHENTIK_REDIS__HOST: authentik-redis + AUTHENTIK_POSTGRESQL__HOST: authentik-db + AUTHENTIK_POSTGRESQL__USER: authentik + AUTHENTIK_POSTGRESQL__NAME: authentik + AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD} + AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} + volumes: + - ${APP_DATA_DIR}/data/authentik-media:/media + - ${APP_DATA_DIR}/data/authentik-custom-templates:/templates + ports: + - "8769:9000" + - "${APP_PORT}:9443" + depends_on: + - authentik-db + - authentik-redis + networks: + - tipi_main_network + labels: + # Main + traefik.enable: true + traefik.http.middlewares.authentik-web-redirect.redirectscheme.scheme: https + traefik.http.services.authentik.loadbalancer.server.port: 9000 + # Web + traefik.http.routers.authentik-insecure.rule: Host(`${APP_DOMAIN}`) + traefik.http.routers.authentik-insecure.entrypoints: web + traefik.http.routers.authentik-insecure.service: authentik + traefik.http.routers.authentik-insecure.middlewares: authentik-web-redirect + # Websecure + traefik.http.routers.authentik.rule: Host(`${APP_DOMAIN}`) + traefik.http.routers.authentik.entrypoints: websecure + traefik.http.routers.authentik.service: authentik + traefik.http.routers.authentik.tls.certresolver: myresolver + # Local domain + traefik.http.routers.authentik-local-insecure.rule: Host(`authentik.${LOCAL_DOMAIN}`) + traefik.http.routers.authentik-local-insecure.entrypoints: web + traefik.http.routers.authentik-local-insecure.service: authentik + traefik.http.routers.authentik-local-insecure.middlewares: authentik-web-redirect + # Local domain secure + traefik.http.routers.authentik-local.rule: Host(`authentik.${LOCAL_DOMAIN}`) + traefik.http.routers.authentik-local.entrypoints: websecure + traefik.http.routers.authentik-local.service: authentik + traefik.http.routers.authentik-local.tls: true + authentik-worker: + image: ghcr.io/goauthentik/server:2023.10.3 + restart: unless-stopped + command: worker + container_name: authentik-worker + environment: + AUTHENTIK_REDIS__HOST: authentik-redis + AUTHENTIK_POSTGRESQL__HOST: authentik-db + AUTHENTIK_POSTGRESQL__USER: authentik + AUTHENTIK_POSTGRESQL__NAME: authentik + AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD} + AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} + # `user: root` and the docker socket volume are optional. + # See more for the docker socket integration here: + # https://goauthentik.io/docs/outposts/integrations/docker + # Removing `user: root` also prevents the worker from fixing the permissions + # on the mounted folders, so when removing this make sure the folders have the correct UID/GID + # (1000:1000 by default) + user: root + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ${APP_DATA_DIR}/data/authentik-media:/media + - ${APP_DATA_DIR}/data/authentik-certs:/certs + - ${APP_DATA_DIR}/data/authentik-custom-templates:/templates + depends_on: + - authentik-db + - authentik-redis + networks: + - tipi_main_network + + authentik-db: + container_name: authentik-db + image: docker.io/library/postgres:12-alpine + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + volumes: + - ${APP_DATA_DIR}/data/postgres:/var/lib/postgresql/data + environment: + POSTGRES_PASSWORD: ${AUTHENTIK_DB_PASSWORD} + POSTGRES_USER: authentik + POSTGRES_DB: authentik + networks: + - tipi_main_network + + authentik-redis: + image: docker.io/library/redis:alpine + command: --save 60 1 --loglevel warning + container_name: authentik-redis + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "redis-cli ping | grep PONG"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 3s + volumes: + - ${APP_DATA_DIR}/data/redis:/data + networks: + - tipi_main_network diff --git a/apps/authentik/metadata/description.md b/apps/authentik/metadata/description.md new file mode 100644 index 00000000..4098474a --- /dev/null +++ b/apps/authentik/metadata/description.md @@ -0,0 +1,22 @@ +## Install Information + +*Initial Install May take a bit to start up!* + +To start the initial setup, navigate to http://:9000/if/flow/initial-setup/. + +There you are prompted to set a password for the akadmin user (the default user). + +## What is authentik? + +authentik is an open-source Identity Provider that emphasizes flexibility and versatility. It can be seamlessly integrated into existing environments to support new protocols. authentik is also a great solution for implementing sign-up, recovery, and other similar features in your application, saving you the hassle of dealing with them. + +## Docs + +Visit the [documentation](https://goauthentik.io/docs/) for more information + +## Screenshots + +| Light | Dark | +| --- | --- | +| [![](https://camo.githubusercontent.com/49bdfe06ba218e307e6eb171bf5c88e96b1302be81cdb9f9e33a39ba1e269479/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f617070735f6c696768742e6a7067)](https://camo.githubusercontent.com/49bdfe06ba218e307e6eb171bf5c88e96b1302be81cdb9f9e33a39ba1e269479/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f617070735f6c696768742e6a7067) | [![](https://camo.githubusercontent.com/32ed9376350e9bb727396ec149de406b2d7b150ea6770343d5ecb405aa0b51fe/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f617070735f6461726b2e6a7067)](https://camo.githubusercontent.com/32ed9376350e9bb727396ec149de406b2d7b150ea6770343d5ecb405aa0b51fe/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f617070735f6461726b2e6a7067) | +| [![](https://camo.githubusercontent.com/52bf3c54e399ecffcdde04089f1939c23c21acf4f53beeb1fa3893573359fbae/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f61646d696e5f6c696768742e6a7067)](https://camo.githubusercontent.com/52bf3c54e399ecffcdde04089f1939c23c21acf4f53beeb1fa3893573359fbae/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f61646d696e5f6c696768742e6a7067) | [![](https://camo.githubusercontent.com/09a804e359f3950b2b8e2fcf59374de6669cad1aeb39efc064dfec880327024f/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f61646d696e5f6461726b2e6a7067)](https://camo.githubusercontent.com/09a804e359f3950b2b8e2fcf59374de6669cad1aeb39efc064dfec880327024f/68747470733a2f2f676f61757468656e74696b2e696f2f696d672f73637265656e5f61646d696e5f6461726b2e6a7067) | \ No newline at end of file diff --git a/apps/authentik/metadata/logo.jpg b/apps/authentik/metadata/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..78d8be1f65b167f7b6d369292359efd7066090c6 GIT binary patch literal 8864 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 U)0orvXRyEfHUAMg-&V(e0n{nhmH+?% literal 0 HcmV?d00001