diff --git a/Dockerfile b/Dockerfile index e99499ff2..53de27013 100644 --- a/Dockerfile +++ b/Dockerfile @@ -131,10 +131,10 @@ RUN apt-get update && \ apt-get clean && \ rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \ adduser --system --no-create-home --uid 1000 --group --home /authentik authentik && \ - mkdir -p /certs /media /blueprints && \ + mkdir -p /data/certs /data/media /data/blueprints && \ mkdir -p /authentik/.ssh && \ mkdir -p /ak-root && \ - chown authentik:authentik /certs /media /authentik/.ssh /ak-root + chown authentik:authentik /data/certs /data/media /authentik/.ssh /ak-root COPY ./authentik/ /ak-root/authentik COPY ./pyproject.toml /ak-root @@ -143,7 +143,7 @@ COPY ./schemas /ak-root/schemas COPY ./locale /ak-root/locale COPY ./tests /ak-root/tests COPY ./manage.py /ak-root/ -COPY ./blueprints /blueprints +COPY ./blueprints /data/blueprints COPY ./lifecycle/ /ak-root/lifecycle COPY --from=go-builder /go/authentik /bin/authentik COPY --from=python-deps /ak-root/venv /ak-root/venv @@ -151,7 +151,7 @@ COPY --from=python-deps /work/venv /ak-root/venv COPY --from=web-builder /work/web/dist/ /ak-root/web/dist/ COPY --from=web-builder /work/web/authentik/ /ak-root/web/authentik/ COPY --from=website-builder /work/website/help/ /ak-root/website/help/ -COPY --from=geoip /usr/share/GeoIP /ak-root/geoip +COPY --from=geoip /usr/share/GeoIP /data/geoip USER 1000 diff --git a/authentik/blueprints/migrations/0001_initial.py b/authentik/blueprints/migrations/0001_initial.py index 8f6fb1a0f..6a51d0b9a 100644 --- a/authentik/blueprints/migrations/0001_initial.py +++ b/authentik/blueprints/migrations/0001_initial.py @@ -30,7 +30,7 @@ def check_blueprint_v1_file(BlueprintInstance: type, path: Path): return blueprint_file.seek(0) instance: BlueprintInstance = BlueprintInstance.objects.filter(path=path).first() - rel_path = path.relative_to(Path(CONFIG.get("blueprints_dir"))) + rel_path = path.relative_to(Path(CONFIG.get("paths.blueprints"))) meta = None if metadata: meta = from_dict(BlueprintMetadata, metadata) @@ -55,7 +55,7 @@ def migration_blueprint_import(apps: Apps, schema_editor: BaseDatabaseSchemaEdit Flow = apps.get_model("authentik_flows", "Flow") db_alias = schema_editor.connection.alias - for file in glob(f"{CONFIG.get('blueprints_dir')}/**/*.yaml", recursive=True): + for file in glob(f"{CONFIG.get('paths.blueprints')}/**/*.yaml", recursive=True): check_blueprint_v1_file(BlueprintInstance, Path(file)) for blueprint in BlueprintInstance.objects.using(db_alias).all(): diff --git a/authentik/blueprints/models.py b/authentik/blueprints/models.py index 2551beacc..f8b3837f6 100644 --- a/authentik/blueprints/models.py +++ b/authentik/blueprints/models.py @@ -82,7 +82,7 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel): def retrieve_file(self) -> str: """Get blueprint from path""" try: - base = Path(CONFIG.get("blueprints_dir")) + base = Path(CONFIG.get("paths.blueprints")) full_path = base.joinpath(Path(self.path)).resolve() if not str(full_path).startswith(str(base.resolve())): raise BlueprintRetrievalFailed("Invalid blueprint path") diff --git a/authentik/blueprints/tests/test_v1_api.py b/authentik/blueprints/tests/test_v1_api.py index 6ee4bd7f6..6bcbf7081 100644 --- a/authentik/blueprints/tests/test_v1_api.py +++ b/authentik/blueprints/tests/test_v1_api.py @@ -19,7 +19,7 @@ class TestBlueprintsV1API(APITestCase): self.user = create_test_admin_user() self.client.force_login(self.user) - @CONFIG.patch("blueprints_dir", TMP) + @CONFIG.patch("paths.blueprints", TMP) def test_api_available(self): """Test valid file""" with NamedTemporaryFile(mode="w+", suffix=".yaml", dir=TMP) as file: diff --git a/authentik/blueprints/tests/test_v1_tasks.py b/authentik/blueprints/tests/test_v1_tasks.py index 913431d66..bfacd3aa9 100644 --- a/authentik/blueprints/tests/test_v1_tasks.py +++ b/authentik/blueprints/tests/test_v1_tasks.py @@ -16,7 +16,7 @@ TMP = mkdtemp("authentik-blueprints") class TestBlueprintsV1Tasks(TransactionTestCase): """Test Blueprints v1 Tasks""" - @CONFIG.patch("blueprints_dir", TMP) + @CONFIG.patch("paths.blueprints", TMP) def test_invalid_file_syntax(self): """Test syntactically invalid file""" with NamedTemporaryFile(suffix=".yaml", dir=TMP) as file: @@ -25,7 +25,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): blueprints = blueprints_find() self.assertEqual(blueprints, []) - @CONFIG.patch("blueprints_dir", TMP) + @CONFIG.patch("paths.blueprints", TMP) def test_invalid_file_version(self): """Test invalid file""" with NamedTemporaryFile(suffix=".yaml", dir=TMP) as file: @@ -34,7 +34,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): blueprints = blueprints_find() self.assertEqual(blueprints, []) - @CONFIG.patch("blueprints_dir", TMP) + @CONFIG.patch("paths.blueprints", TMP) def test_valid(self): """Test valid file""" blueprint_id = generate_id() @@ -64,7 +64,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): }, ) - @CONFIG.patch("blueprints_dir", TMP) + @CONFIG.patch("paths.blueprints", TMP) def test_valid_updated(self): """Test valid file""" BlueprintInstance.objects.filter(name="foo").delete() @@ -123,7 +123,7 @@ class TestBlueprintsV1Tasks(TransactionTestCase): }, ) - @CONFIG.patch("blueprints_dir", TMP) + @CONFIG.patch("paths.blueprints", TMP) def test_valid_disabled(self): """Test valid file""" with NamedTemporaryFile(mode="w+", suffix=".yaml", dir=TMP) as file: diff --git a/authentik/blueprints/v1/tasks.py b/authentik/blueprints/v1/tasks.py index 686e4747c..c4735fd25 100644 --- a/authentik/blueprints/v1/tasks.py +++ b/authentik/blueprints/v1/tasks.py @@ -62,7 +62,7 @@ def start_blueprint_watcher(): if _file_watcher_started: return observer = Observer() - observer.schedule(BlueprintEventHandler(), CONFIG.get("blueprints_dir"), recursive=True) + observer.schedule(BlueprintEventHandler(), CONFIG.get("paths.blueprints"), recursive=True) observer.start() _file_watcher_started = True @@ -75,7 +75,7 @@ class BlueprintEventHandler(FileSystemEventHandler): return if event.is_directory: return - root = Path(CONFIG.get("blueprints_dir")).absolute() + root = Path(CONFIG.get("paths.blueprints")).absolute() path = Path(event.src_path).absolute() rel_path = str(path.relative_to(root)) if isinstance(event, FileCreatedEvent): @@ -101,7 +101,7 @@ def blueprints_find_dict(): def blueprints_find() -> list[BlueprintFile]: """Find blueprints and return valid ones""" blueprints = [] - root = Path(CONFIG.get("blueprints_dir")) + root = Path(CONFIG.get("paths.blueprints")) for path in root.rglob("**/*.yaml"): rel_path = path.relative_to(root) # Check if any part in the path starts with a dot and assume a hidden file diff --git a/authentik/crypto/tasks.py b/authentik/crypto/tasks.py index 4a660ee81..bb4543f45 100644 --- a/authentik/crypto/tasks.py +++ b/authentik/crypto/tasks.py @@ -46,7 +46,7 @@ def certificate_discovery(self: MonitoredTask): certs = {} private_keys = {} discovered = 0 - for file in glob(CONFIG.get("cert_discovery_dir") + "/**", recursive=True): + for file in glob(CONFIG.get("path.cert_discovery") + "/**", recursive=True): path = Path(file) if not path.exists(): continue diff --git a/authentik/crypto/tests.py b/authentik/crypto/tests.py index 3a4f05ea5..b7e026047 100644 --- a/authentik/crypto/tests.py +++ b/authentik/crypto/tests.py @@ -265,7 +265,7 @@ class TestCrypto(APITestCase): _cert.write(builder.certificate) with open(f"{temp_dir}/foo.bar/privkey.pem", "w+", encoding="utf-8") as _key: _key.write(builder.private_key) - with CONFIG.patch("cert_discovery_dir", temp_dir): + with CONFIG.patch("path.cert_discovery", temp_dir): certificate_discovery() # pylint: disable=no-value-for-parameter keypair: CertificateKeyPair = CertificateKeyPair.objects.filter( managed=MANAGED_DISCOVERED % "foo" diff --git a/authentik/lib/default.yml b/authentik/lib/default.yml index 0f73d8fe4..0fd5206c4 100644 --- a/authentik/lib/default.yml +++ b/authentik/lib/default.yml @@ -54,7 +54,10 @@ cache: # url: "" paths: - media: ./media + media: /data/media + cert_discovery: /data/certs + email_templates: /data/email-templates + blueprints: /data/blueprints debug: false remote_debug: false @@ -78,7 +81,6 @@ email: use_ssl: false timeout: 10 from: authentik@localhost - template_dir: /templates throttle: providers: @@ -110,8 +112,8 @@ disable_startup_analytics: false avatars: env://AUTHENTIK_AUTHENTIK__AVATARS?gravatar,initials events: context_processors: - geoip: "/ak-root/geoip/GeoLite2-City.mmdb" - asn: "/ak-root/geoip/GeoLite2-ASN.mmdb" + geoip: "/data/geoip/GeoLite2-City.mmdb" + asn: "/data/geoip/GeoLite2-ASN.mmdb" footer_links: [] @@ -120,12 +122,9 @@ default_user_change_email: false default_user_change_username: false gdpr_compliance: true -cert_discovery_dir: /certs default_token_length: 60 impersonation: true -blueprints_dir: /blueprints - web: # No default here as it's set dynamically # workers: 2 diff --git a/authentik/root/settings.py b/authentik/root/settings.py index 87d4bde9f..cc80e2b7a 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -237,7 +237,7 @@ ROOT_URLCONF = "authentik.root.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [CONFIG.get("email.template_dir")], + "DIRS": [CONFIG.get("paths.email_templates")], "APP_DIRS": True, "OPTIONS": { "context_processors": [ diff --git a/authentik/root/test_runner.py b/authentik/root/test_runner.py index bc3b3b968..2a94855e4 100644 --- a/authentik/root/test_runner.py +++ b/authentik/root/test_runner.py @@ -34,7 +34,7 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover CONFIG.set("avatars", "none") CONFIG.set("events.context_processors.geoip", "tests/GeoLite2-City-Test.mmdb") CONFIG.set("events.context_processors.asn", "tests/GeoLite2-ASN-Test.mmdb") - CONFIG.set("blueprints_dir", "./blueprints") + CONFIG.set("paths.blueprints", "./blueprints") CONFIG.set( "outposts.container_image_base", f"ghcr.io/goauthentik/dev-%(type)s:{get_docker_tag()}", diff --git a/scripts/generate_config.py b/scripts/generate_config.py index 965e3e15e..db055488f 100644 --- a/scripts/generate_config.py +++ b/scripts/generate_config.py @@ -15,8 +15,13 @@ with open("local.env.yml", "w", encoding="utf-8") as _config: "outposts": { "container_image_base": "ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s", }, - "blueprints_dir": "./blueprints", - "cert_discovery_dir": "./certs", + "paths.blueprints": "./blueprints", + "paths": { + "cert_discovery": "./data/certs", + "media": "./data/media", + "email_templates": "./data/email-templates", + "blueprints": "./blueprints", + }, "events": { "processors": { "geoip": "tests/GeoLite2-City-Test.mmdb",