mirror of
https://github.com/nmasur/dotfiles
synced 2026-09-08 13:36:09 +00:00
paperless: configure OIDC authentication
This commit is contained in:
@@ -2,6 +2,14 @@
|
||||
|
||||
## 2026-09-07
|
||||
|
||||
- **Configured OpenID Connect (OIDC) authentication for Paperless-ngx**:
|
||||
- Added secret management for `paperless-oidc-secret.age` via `secrets.paperless-oidc-secret` owned by `paperless:paperless` (0440).
|
||||
- Configured `systemd.services.paperless-oidc-secret-secret` to run before and be required by all Paperless units, dynamically generating `/var/private/paperless-env` with `PAPERLESS_SOCIALACCOUNT_PROVIDERS` configured for Pocket ID (`auth.masu.rs`) using `client_id = "e6ff7fce-8e67-4c66-8f32-5ec3db4740a9"`, `oauth_pkce_enabled = true`, and email authentication linking (`email_authentication = true`, `verified_email = true`) in the native `APPS` schema.
|
||||
- Added `services.paperless.environmentFile = "${config.secretsDirectory}/paperless-env"` to securely pass the OIDC configuration to Paperless services without exposing secrets in the Nix store.
|
||||
- Configured Paperless settings to enable `allauth.socialaccount.providers.openid_connect` in `PAPERLESS_APPS` and enabled `PAPERLESS_REDIRECT_LOGIN_TO_SSO`.
|
||||
- Configured reverse proxy trust settings (`PAPERLESS_USE_X_FORWARD_HOST`, `PAPERLESS_PROXY_SSL_HEADER`, and `PAPERLESS_TRUSTED_PROXIES`) to ensure callback URIs preserve the `https://` scheme behind Caddy.
|
||||
- Fixed `systemd.services.paperless-secret` to order before and be required by `paperless-scheduler.service` instead of non-existent `paperless.service`.
|
||||
|
||||
- **Configured real client IP forwarding for Jellyfin reverse proxy**:
|
||||
- Added a `map` handler to Jellyfin's Caddy route in `platforms/nixos/modules/nmasur/presets/services/jellyfin.nix` to resolve `{client_ip}` using Cloudflare's `CF-Connecting-IP` header when available, falling back to `{http.request.remote.host}` for direct local LAN connections.
|
||||
- Configured `reverse_proxy.headers.request.set` to forward `X-Real-IP`, `X-Forwarded-For`, and `X-Forwarded-Proto` with the resolved client IP and request scheme to Jellyfin.
|
||||
|
||||
+21
-17
@@ -183,24 +183,28 @@ All client secrets should be encrypted with `agenix` under the respective servic
|
||||
```nix
|
||||
services.paperless.settings = {
|
||||
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
|
||||
PAPERLESS_SOCIALACCOUNT_PROVIDERS = builtins.toJSON {
|
||||
openid_connect = {
|
||||
SERVERS = [
|
||||
{
|
||||
id = "pocket-id";
|
||||
name = "Pocket ID";
|
||||
server_url = "https://auth.masu.rs";
|
||||
token_auth_method = "client_secret_basic";
|
||||
APP = {
|
||||
client_id = "paperless";
|
||||
secret = "..."; # or via environmentFile
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
PAPERLESS_REDIRECT_LOGIN_TO_SSO = "true"; # Optional: bypass local login
|
||||
PAPERLESS_REDIRECT_LOGIN_TO_SSO = true;
|
||||
};
|
||||
# Configured via environmentFile to pass the client secret, enable PKCE, and link by email:
|
||||
# PAPERLESS_SOCIALACCOUNT_PROVIDERS = builtins.toJSON {
|
||||
# openid_connect = {
|
||||
# APPS = [
|
||||
# {
|
||||
# provider_id = "pocket-id";
|
||||
# name = "Pocket ID";
|
||||
# client_id = "e6ff7fce-8e67-4c66-8f32-5ec3db4740a9";
|
||||
# secret = "...";
|
||||
# settings = {
|
||||
# server_url = "https://auth.masu.rs";
|
||||
# token_auth_method = "client_secret_basic";
|
||||
# oauth_pkce_enabled = true;
|
||||
# email_authentication = true;
|
||||
# verified_email = true;
|
||||
# };
|
||||
# }
|
||||
# ];
|
||||
# };
|
||||
# };
|
||||
```
|
||||
|
||||
### 6. Mealie (`cooking.masu.rs`)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBCa2J1
|
||||
QjFGRjdZa0RHcjd0V0JXL3lUNzRGczNHanIzb3BtaE93NlNvcGhnCnNOM3JBc0t3
|
||||
VENnWVp1b09Sd1JwcDk1Q0pQM3BBMlJmWHh5TTJHakIvcGsKLT4gc3NoLWVkMjU1
|
||||
MTkgWXlTVU1RIDljQUIrenlGZHMxSHlReG80VVhaSXhsbFZ0L2dtcCtWbTRvNE1i
|
||||
WEdOeVkKUk9HK25Fci9TYWRSS1htSU9BNHlqbHpGT3c5bkI4b3RUL09QK1BYTE1Y
|
||||
VQotPiBzc2gtZWQyNTUxOSBuanZYNUEgNXk5bzRhR1BoTjlMeHVRR2UyUEZJN0Y1
|
||||
ZXAyU3BjeFJvRHhER0ptaVlsVQo0K3p6bXBwcTVIdGlTajBucWV5dzZKM2JyWWNB
|
||||
R2s2UnhTMFVPRGwrVWhRCi0+IHNzaC1lZDI1NTE5IENxSU9VQSBaL3NTdHBjVFRX
|
||||
ODNrcDVmZGFxNVRwbGkrcC9heFN5bmVCZ0xId1NESUhFCm5aQS9xZmhkSWRwMFl1
|
||||
b3FPdUhPZU5YdVQvTEQ3eVdRODBhVzJSWjdyek0KLT4gc3NoLWVkMjU1MTkgejFP
|
||||
Y1p3IHdDR3YwYTFyWlZQZWFDZ1cvWk00bjdRdW16c1M4eDlDaHl4Y3lkbVFGVFEK
|
||||
dndhaG5pUTM3aU04WHZUSHJDdUdkZ0VWRXRaL2t6cUJoZTR1bTh6NlBFawotLS0g
|
||||
NXRDeDFZL0RvaURVK2k3R0NVZGdKR0diZ2RwZjQxTFhuNk82SW9GMGVaRQqYDG6J
|
||||
+/POhVn84NGh8ganDIzNUqQF7uBIxdUMiRoFa0kU4eJd9V4vmjsjtr/lbQ9O+Xfq
|
||||
WJJ8Hjwyzwopx1Phrw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
@@ -1,6 +1,11 @@
|
||||
# Paperless-ngx is a document scanning and management solution.
|
||||
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (config.nmasur.settings) hostnames username;
|
||||
@@ -17,12 +22,26 @@ in
|
||||
enable = true;
|
||||
mediaDir = "/data/generic/paperless";
|
||||
passwordFile = config.secrets.paperless.dest;
|
||||
environmentFile = "${config.secretsDirectory}/paperless-env";
|
||||
configureTika = true; # Enable processing of emails
|
||||
settings = {
|
||||
PAPERLESS_OCR_USER_ARGS = builtins.toJSON { invalidate_digital_signatures = true; };
|
||||
PAPERLESS_URL = "https://${hostnames.paperless}";
|
||||
PAPERLESS_DATE_ORDER = "MDY"; # Check document for US-formatted dates
|
||||
|
||||
# OIDC Authentication with Pocket ID
|
||||
PAPERLESS_APPS = "allauth.socialaccount.providers.openid_connect";
|
||||
PAPERLESS_REDIRECT_LOGIN_TO_SSO = true;
|
||||
PAPERLESS_USE_X_FORWARD_HOST = true;
|
||||
PAPERLESS_PROXY_SSL_HEADER = [
|
||||
"HTTP_X_FORWARDED_PROTO"
|
||||
"https"
|
||||
];
|
||||
PAPERLESS_TRUSTED_PROXIES = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
|
||||
# Enable if changing the path name in Caddy
|
||||
# PAPERLESS_FORCE_SCRIPT_NAME = "/paperless";
|
||||
# PAPERLESS_STATIC_URL = "/paperless/static/";
|
||||
@@ -61,8 +80,60 @@ in
|
||||
permissions = "0440";
|
||||
};
|
||||
systemd.services.paperless-secret = {
|
||||
requiredBy = [ "paperless.service" ];
|
||||
before = [ "paperless.service" ];
|
||||
requiredBy = [ "paperless-scheduler.service" ];
|
||||
before = [ "paperless-scheduler.service" ];
|
||||
};
|
||||
|
||||
secrets.paperless-oidc-secret = {
|
||||
source = ./paperless-oidc-secret.age;
|
||||
dest = "${config.secretsDirectory}/paperless-oidc-secret";
|
||||
owner = "paperless";
|
||||
group = "paperless";
|
||||
permissions = "0440";
|
||||
};
|
||||
systemd.services.paperless-oidc-secret-secret = {
|
||||
requiredBy = [
|
||||
"paperless-secret-key.service"
|
||||
"paperless-scheduler.service"
|
||||
"paperless-task-queue.service"
|
||||
"paperless-consumer.service"
|
||||
"paperless-web.service"
|
||||
];
|
||||
before = [
|
||||
"paperless-secret-key.service"
|
||||
"paperless-scheduler.service"
|
||||
"paperless-task-queue.service"
|
||||
"paperless-consumer.service"
|
||||
"paperless-web.service"
|
||||
];
|
||||
postStart = ''
|
||||
SECRET="$(tr -d '\r\n' < '${config.secrets.paperless-oidc-secret.dest}')"
|
||||
JSON=$(${pkgs.jq}/bin/jq -nc \
|
||||
--arg secret "$SECRET" \
|
||||
--arg auth "https://${hostnames.auth}" \
|
||||
'{
|
||||
openid_connect: {
|
||||
APPS: [
|
||||
{
|
||||
provider_id: "pocket-id",
|
||||
name: "Pocket ID",
|
||||
client_id: "e6ff7fce-8e67-4c66-8f32-5ec3db4740a9",
|
||||
secret: $secret,
|
||||
settings: {
|
||||
server_url: $auth,
|
||||
token_auth_method: "client_secret_basic",
|
||||
oauth_pkce_enabled: true,
|
||||
email_authentication: true,
|
||||
verified_email: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}')
|
||||
echo "PAPERLESS_SOCIALACCOUNT_PROVIDERS='$JSON'" > '${config.secretsDirectory}/paperless-env'
|
||||
chown paperless:paperless '${config.secretsDirectory}/paperless-env'
|
||||
chmod 0440 '${config.secretsDirectory}/paperless-env'
|
||||
'';
|
||||
};
|
||||
|
||||
# Fix paperless shared permissions
|
||||
|
||||
Reference in New Issue
Block a user