Compare commits
79 Commits
8671a28baf
...
main
Author | SHA1 | Date | |
---|---|---|---|
536f11bbfd
|
|||
271f3289e5
|
|||
ac56849a3b
|
|||
0050a4130b
|
|||
828d5853d6
|
|||
197d699fda
|
|||
ce10a8595d
|
|||
94eea2d425
|
|||
3eb40713b1
|
|||
a1183aab56
|
|||
de7e645f11
|
|||
67d2c839a5
|
|||
0f773262a1
|
|||
30dcbcb407
|
|||
98832beb27
|
|||
4008a92a49
|
|||
2b6d82229c
|
|||
d0c6d44528
|
|||
e429b56384
|
|||
5b174702d8
|
|||
703fcaec39
|
|||
69a4634f8a
|
|||
e349c5e0f3
|
|||
48b47cfa88
|
|||
660dd1854f
|
|||
69692faac5
|
|||
95153cd55b
|
|||
9f3c42e3f9
|
|||
67f9dc73e5
|
|||
58b4bc47a6
|
|||
7e62a9ff70
|
|||
ff4e5a634c
|
|||
79710d5afa
|
|||
97852db654
|
|||
08cca48255
|
|||
3294ff3da4
|
|||
dcc73050eb
|
|||
a1a3aaa9d3
|
|||
26e81611be
|
|||
1235104b10
|
|||
31c035ecf1
|
|||
4942e7c359
|
|||
2826305218
|
|||
7b317fbce3
|
|||
f6f58f17ca
|
|||
e796c9f657
|
|||
71b96ada37
|
|||
a29dc78eea
|
|||
9b352ec85a
|
|||
727c01f9d8
|
|||
dddbf8b35f
|
|||
a61b71c7c8
|
|||
3c0030b80b
|
|||
c4a780b7ff
|
|||
d5761ef11b
|
|||
77bdedef79
|
|||
e3b6a5243f
|
|||
68337eba4e
|
|||
ab04e2ada2
|
|||
d90e14a66d
|
|||
2d01f52342
|
|||
23b7957317
|
|||
88b88dba4b
|
|||
bb52306cf4
|
|||
308c661f90
|
|||
8186824c60
|
|||
8b5a67bdc1
|
|||
fcf4163154
|
|||
88269b9e74
|
|||
22d8579f67
|
|||
2397cd1090
|
|||
4c05645a50
|
|||
bbb267eafd
|
|||
43c7b76c7a
|
|||
249e6bc9d4
|
|||
a1424478ba
|
|||
d89f84fd5b
|
|||
e6db25d6e9
|
|||
0c0b5bb29a
|
@@ -1,8 +1,9 @@
|
|||||||
[
|
[
|
||||||
[ "selfprivacy", "domain" ],
|
[ "selfprivacy", "domain" ],
|
||||||
|
[ "selfprivacy", "username" ],
|
||||||
[ "selfprivacy", "modules", "auth", "enable" ],
|
[ "selfprivacy", "modules", "auth", "enable" ],
|
||||||
[ "selfprivacy", "modules", "mastodon" ],
|
[ "selfprivacy", "modules", "mastodon" ],
|
||||||
[ "selfprivacy", "passthru", "auth", "mkOAuth2ClientSecretFP" ],
|
[ "selfprivacy", "passthru", "auth" ],
|
||||||
[ "selfprivacy", "passthru", "auth", "oauth2-discovery-url" ],
|
[ "selfprivacy", "passthru", "auth", "oauth2-discovery-url" ],
|
||||||
[ "selfprivacy", "passthru", "auth", "oauth2-provider-name" ],
|
[ "selfprivacy", "passthru", "auth", "oauth2-provider-name" ],
|
||||||
[ "selfprivacy", "sso", "enable" ],
|
[ "selfprivacy", "sso", "enable" ],
|
||||||
@@ -11,6 +12,8 @@
|
|||||||
[ "services", "mastodon", "package" ],
|
[ "services", "mastodon", "package" ],
|
||||||
[ "services", "mastodon", "user" ],
|
[ "services", "mastodon", "user" ],
|
||||||
[ "services", "mastodon", "group" ],
|
[ "services", "mastodon", "group" ],
|
||||||
|
[ "services", "mastodon", "database" ],
|
||||||
[ "services", "postfix", "user" ],
|
[ "services", "postfix", "user" ],
|
||||||
[ "services", "postfix", "group" ]
|
[ "services", "postfix", "group" ],
|
||||||
|
[ "services", "kanidm", "serverSettings", "origin" ]
|
||||||
]
|
]
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
# TODO: check whether there is no TODOs
|
# TODO: check whether there is no TODOs
|
||||||
# TODO: check whether there is no hedgegdoc mentions
|
|
||||||
description = "Mastodon module";
|
description = "Mastodon module";
|
||||||
|
|
||||||
outputs = { ... }:
|
outputs = { ... }:
|
||||||
@@ -35,6 +34,7 @@
|
|||||||
supportLevel = "normal";
|
supportLevel = "normal";
|
||||||
sso = {
|
sso = {
|
||||||
userGroup = "sp.mastodon.users";
|
userGroup = "sp.mastodon.users";
|
||||||
|
adminsGroup = "sp.mastodon.admins";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
148
mastodon-kanidm-sync.py
Normal file
148
mastodon-kanidm-sync.py
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
import psycopg2 as ps
|
||||||
|
|
||||||
|
def read_file(path):
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
def getenv(name):
|
||||||
|
try:
|
||||||
|
return os.environ[name]
|
||||||
|
except KeyError:
|
||||||
|
print(f"[ERROR] Missing environment variable {name}. You should NOT run this script by hand, please use systemd mastodon-kanidm-sync.service.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Import configuration
|
||||||
|
KANIDM_URL = getenv("KANIDM_URL")
|
||||||
|
KANIDM_TOKEN = read_file(getenv("KANIDM_TOKEN_PATH")).strip()
|
||||||
|
OWNER_USERNAME = getenv("OWNER_USERNAME")
|
||||||
|
SLEEP_TIME = int(getenv("SLEEP_TIME"))
|
||||||
|
|
||||||
|
def sync_mastodon():
|
||||||
|
# Fetch kanidm users list from userdata file
|
||||||
|
# Userdata file is json list with information about what users are configured by kanidm
|
||||||
|
try:
|
||||||
|
USERDATA = read_file(getenv("USERDATA_FILE_PATH")).strip()
|
||||||
|
userdata = json.loads(USERDATA)
|
||||||
|
print("[INFO] ")
|
||||||
|
except FileNotFoundError:
|
||||||
|
userdata = []
|
||||||
|
|
||||||
|
# Load database
|
||||||
|
conn = ps.connect(
|
||||||
|
dbname=getenv("POSTGRES_DBNAME"),
|
||||||
|
user=getenv("POSTGRES_USER"),
|
||||||
|
host=getenv("POSTGRES_HOST")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fetch current userdata from database
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute('''
|
||||||
|
SELECT identities.uid, users.id, user_roles.name
|
||||||
|
FROM users
|
||||||
|
JOIN identities
|
||||||
|
ON users.id = identities.id
|
||||||
|
LEFT JOIN user_roles
|
||||||
|
ON users.role_id = user_roles.id;
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
|
state = cur.fetchall()
|
||||||
|
|
||||||
|
users = {}
|
||||||
|
for i in state:
|
||||||
|
users[i[0]] = {
|
||||||
|
"id": i[1],
|
||||||
|
"role": i[2],
|
||||||
|
"isKanidmUser": False
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch Kanidm userdata
|
||||||
|
kanidm_users_raw = requests.get(
|
||||||
|
f"{KANIDM_URL}/v1/person",
|
||||||
|
headers={
|
||||||
|
"Authorization": f"Bearer {KANIDM_TOKEN}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
timeout=5,
|
||||||
|
).json()
|
||||||
|
|
||||||
|
def give_role(uid, role, putUserdata = True):
|
||||||
|
if (uid not in userdata) and (putUserdata):
|
||||||
|
userdata.append(uid)
|
||||||
|
users[uid]["isKanidmUser"] = True
|
||||||
|
users[uid]["role"] = role
|
||||||
|
print(f"[INFO] {uid} is marked as {role}")
|
||||||
|
|
||||||
|
|
||||||
|
for i in kanidm_users_raw:
|
||||||
|
i = i["attrs"]
|
||||||
|
for uid in i["name"]: # [user].attrs.name is a list
|
||||||
|
if uid in users: # Don't apply anything for users who have no mastodon access (sp.mastodon.users) or didn't register
|
||||||
|
if uid == OWNER_USERNAME:
|
||||||
|
give_role(uid, "Owner", False)
|
||||||
|
continue
|
||||||
|
|
||||||
|
for group in i["memberof"]:
|
||||||
|
if group.startswith("sp.mastodon.admins@") or group.startswith("sp.admins@"):
|
||||||
|
give_role(uid, "Admin")
|
||||||
|
break
|
||||||
|
|
||||||
|
elif group.startswith("sp.mastodon.moderators@"):
|
||||||
|
give_role(uid, "Moderator")
|
||||||
|
break
|
||||||
|
|
||||||
|
elif uid in userdata:
|
||||||
|
# If user, who previously had a role, has no roles set by Kanidm, delete them from userdata list so allow setting roles directly by mastodon
|
||||||
|
give_role(uid, None, False)
|
||||||
|
userdata.remove(uid)
|
||||||
|
|
||||||
|
print("[DEBUG]", users)
|
||||||
|
|
||||||
|
# Fetch RoleIDs
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("SELECT id, name FROM user_roles;")
|
||||||
|
|
||||||
|
roles_raw = cur.fetchall()
|
||||||
|
roles = {}
|
||||||
|
for i in roles_raw:
|
||||||
|
roles[i[1]] = i[0]
|
||||||
|
|
||||||
|
# Give roles
|
||||||
|
for uid in users:
|
||||||
|
if not users[uid]["isKanidmUser"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if users[uid]["role"]:
|
||||||
|
rolename = users[uid]["role"]
|
||||||
|
roleid = roles[rolename]
|
||||||
|
else:
|
||||||
|
roleid = "NULL"
|
||||||
|
|
||||||
|
sqlcommand = f"UPDATE users SET role_id = {roleid} WHERE id = {users[uid]["id"]};"
|
||||||
|
print("[DEBUG] SQL:", sqlcommand)
|
||||||
|
cur.execute(sqlcommand)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
print("[INFO] Final userdata.json file content: ", userdata)
|
||||||
|
|
||||||
|
def write_userdata(mode):
|
||||||
|
with open(getenv("USERDATA_FILE_PATH"), mode) as f:
|
||||||
|
f.write(json.dumps(userdata))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
write_userdata("w")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("[INFO] userdata.json file doesn't exist. Creating it")
|
||||||
|
write_userdata("x")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
sync_mastodon()
|
||||||
|
time.sleep(SLEEP_TIME)
|
140
module.nix
140
module.nix
@@ -11,15 +11,19 @@ let
|
|||||||
auth-passthru = config.selfprivacy.passthru.auth;
|
auth-passthru = config.selfprivacy.passthru.auth;
|
||||||
oauthDiscoveryURL = auth-passthru.oauth2-discovery-url oauthClientID;
|
oauthDiscoveryURL = auth-passthru.oauth2-discovery-url oauthClientID;
|
||||||
issuer = lib.strings.removeSuffix "/.well-known/openid-configuration" oauthDiscoveryURL;
|
issuer = lib.strings.removeSuffix "/.well-known/openid-configuration" oauthDiscoveryURL;
|
||||||
|
oauthRedirectURL = "https://${cfg.subdomain}.${sp.domain}/auth/auth/openid_connect/callback";
|
||||||
|
|
||||||
usersGroup = "sp.mastodon.users";
|
usersGroup = "sp.mastodon.users";
|
||||||
adminsGroup = "sp.mastodon.admins";
|
adminsGroup = "sp.mastodon.admins";
|
||||||
|
|
||||||
oauthClientSecretFP = auth-passthru.mkOAuth2ClientSecretFP oauthClientID;
|
oauthClientSecretFP = auth-passthru.mkOAuth2ClientSecretFP oauthClientID;
|
||||||
oauthRedirectURL = "https://${cfg.subdomain}.${sp.domain}/auth/auth/openid_connect/callback";
|
serviceAccountFP = auth-passthru.mkServiceAccountTokenFP "mastodon";
|
||||||
|
|
||||||
# emailPassword = pkgs.runCommand "genpassword" {} "echo `head -c 32 /dev/urandom | base64 | sed 's/[+=\\/A-Z]//g'` > $out";
|
secrets = rec {
|
||||||
# emailPasswordHash = pkgs.runCommand "genpassword" {} "echo `head -c 32 /dev/urandom | base64 | sed 's/[+=\\/A-Z]//g'` > $out";
|
dir = "/run/keys/mastodon";
|
||||||
|
hashedPasswordFile = "${dir}/hashed_email_password";
|
||||||
|
passwordFile = "${dir}/email_password";
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.selfprivacy.modules.mastodon = {
|
options.selfprivacy.modules.mastodon = {
|
||||||
@@ -48,7 +52,7 @@ in
|
|||||||
(lib.mkOption {
|
(lib.mkOption {
|
||||||
default = "mastodon";
|
default = "mastodon";
|
||||||
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
|
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
|
||||||
description = "Subdomain";
|
description = "Subdomain (changing subdomain after setting up will cause breakage of the server!)";
|
||||||
})
|
})
|
||||||
// {
|
// {
|
||||||
meta = {
|
meta = {
|
||||||
@@ -58,6 +62,19 @@ in
|
|||||||
weight = 0;
|
weight = 0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dissallowUnauthenticatedAPI =
|
||||||
|
(lib.mkOption {
|
||||||
|
default = true;
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Allow unauthenticated API access";
|
||||||
|
})
|
||||||
|
// {
|
||||||
|
meta = {
|
||||||
|
type = "bool";
|
||||||
|
weight = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
@@ -68,71 +85,110 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# services.postgresql = {
|
|
||||||
# ensureDatabases = [ "mastodon" ];
|
|
||||||
# ensureUsers = [
|
|
||||||
# {
|
|
||||||
# name = "mastodon";
|
|
||||||
# ensureDBOwnership = true;
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
|
|
||||||
services.mastodon = {
|
services.mastodon = {
|
||||||
enable = true;
|
enable = true;
|
||||||
localDomain = "${cfg.subdomain}.${sp.domain}";
|
localDomain = "${cfg.subdomain}.${sp.domain}";
|
||||||
enableUnixSocket = false;
|
enableUnixSocket = false;
|
||||||
configureNginx = true;
|
configureNginx = true;
|
||||||
database.createLocally = true;
|
database.createLocally = true;
|
||||||
streamingProcesses = 3;
|
streamingProcesses = 2;
|
||||||
|
|
||||||
smtp = {
|
smtp = {
|
||||||
createLocally = false;
|
createLocally = false;
|
||||||
user = "noreply.mastodon@${sp.domain}";
|
|
||||||
fromAddress = "noreply.mastodon@${sp.domain}";
|
fromAddress = "noreply.mastodon@${sp.domain}";
|
||||||
passwordFile = "/run/keys/mastodon/email_password";
|
user = "noreply.mastodon";
|
||||||
|
passwordFile = secrets.passwordFile;
|
||||||
authenticate = true;
|
authenticate = true;
|
||||||
|
|
||||||
|
host = "hollowness.top";
|
||||||
|
port = 465;
|
||||||
|
};
|
||||||
|
extraConfig = {
|
||||||
|
"SMTP_ENABLE_STARTTLS_AUTO" = "true"; # Simple NixOS MailServer doesn't allow connections without SSL
|
||||||
|
"SMTP_ENABLE_STARTTLS" = "always";
|
||||||
|
"SMTP_TLS" = "true";
|
||||||
|
"SMTP_SSL" = "true";
|
||||||
|
|
||||||
|
"DISALLOW_UNAUTHENTICATED_API_ACCESS" = lib.boolToString cfg.dissallowUnauthenticatedAPI;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# mailserver.loginAccounts."noreply.mastodon@${sp.domain}" = {
|
selfprivacy.emails."noreplymastodon" = {
|
||||||
# hashedPasswordFile = "/run/keys/mastodon/email_password";
|
hashedPasswordFile = secrets.hashedPasswordFile;
|
||||||
# sendOnly = true;
|
systemdTargets = [ "mastodon-email-password-setup.service" ];
|
||||||
# };
|
sendOnly = true;
|
||||||
|
};
|
||||||
services.postfix.config.virtual_mailbox_maps = [ "hash:/run/postfix/mastodon.cf" ];
|
|
||||||
|
|
||||||
systemd = {
|
systemd = {
|
||||||
services.mastodon-email-password-setup = {
|
services.mastodon-email-password-setup = {
|
||||||
enable = true;
|
enable = true;
|
||||||
wantedBy = [ "multi-user.target" "mastodon-web.service" "postfix.service" ];
|
wantedBy = [ "multi-user.target" "mastodon-web.service" "postfix.service" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
Slice = "mastodon.slice";
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
ExecStart = pkgs.writeShellScript "gen-mastodon-email-password" ''
|
ExecStart = pkgs.writeShellScript "gen-mastodon-email-password" ''
|
||||||
export password=$(head -c 32 /dev/urandom | base64 | sed 's/[+=\\/A-Z]//g')
|
export password=$(head -c 32 /dev/urandom | base64 | sed 's/[+=\\/A-Z]//g')
|
||||||
|
mkdir ${secrets.dir} || true # Create ${secrets.dir} if it doesn't exist
|
||||||
|
|
||||||
rm -f /run/keys/mastodon/email_password || true
|
rm -f ${secrets.passwordFile} || true
|
||||||
mkdir /run/keys/mastodon/ || true # Create /run/keys/mastodon if it doesn't exist
|
echo "$password" > ${secrets.passwordFile}
|
||||||
echo $password > /run/keys/mastodon/email_password
|
chmod 400 ${secrets.passwordFile}
|
||||||
chmod 400 /run/keys/mastodon/email_password
|
chown ${config.services.mastodon.user}:${config.services.mastodon.group} ${secrets.passwordFile}
|
||||||
chown ${config.services.mastodon.user}:${config.services.mastodon.group} /run/keys/mastodon/email_password
|
|
||||||
|
|
||||||
rm -f /run/postfix/mastodon.cf || true
|
export hashedPassword=$(${lib.getExe pkgs.mkpasswd} -sm bcrypt "$password")
|
||||||
mkdir /run/postfix/ || true # Create /run/postfix if it doesn't exist
|
|
||||||
export hashedPassword=$(mkpasswd -sm bcrypt "$password")
|
rm -f ${secrets.hashedPasswordFile} || true
|
||||||
echo "noreply.mastodon@${sp.domain}: $hashedPassword" > /run/postfix/mastodon.cf
|
echo "$hashedPassword" > ${secrets.hashedPasswordFile}
|
||||||
chmod 440 /run/postfix/mastodon.cf
|
chmod 440 ${secrets.hashedPasswordFile}
|
||||||
chown ${config.services.postfix.user}:${config.services.postfix.group} /run/postfix/mastodon.cf
|
chown ${config.services.postfix.user}:${config.services.postfix.group} ${secrets.hashedPasswordFile}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.mastodon-kanidm-sync = {
|
||||||
|
after = [
|
||||||
|
"postgresql.service"
|
||||||
|
"kanidm.service"
|
||||||
|
];
|
||||||
|
requires = [
|
||||||
|
"kanidm.service"
|
||||||
|
"postgresql.service"
|
||||||
|
];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
environment = let db = config.services.mastodon.database;
|
||||||
|
in {
|
||||||
|
KANIDM_URL = config.services.kanidm.serverSettings.origin;
|
||||||
|
KANIDM_TOKEN_PATH = serviceAccountFP;
|
||||||
|
POSTGRES_DBNAME = db.name;
|
||||||
|
POSTGRES_USER = db.user;
|
||||||
|
POSTGRES_HOST = db.host;
|
||||||
|
USERDATA_FILE_PATH = "/var/lib/mastodon/.userdata.json";
|
||||||
|
OWNER_USERNAME = sp.username;
|
||||||
|
SLEEP_TIME = "30";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Slice = "mastodon.slice";
|
||||||
|
User = "mastodon";
|
||||||
|
Group = "mastodon";
|
||||||
|
LoadCredential = [ "kanidm-token:${serviceAccountFP}" ];
|
||||||
|
ExecStart = pkgs.writers.writePython3 "mas-kanidm-sync" {
|
||||||
|
doCheck = false;
|
||||||
|
libraries = with pkgs.python3Packages; [
|
||||||
|
requests
|
||||||
|
psycopg2
|
||||||
|
];
|
||||||
|
} (builtins.readFile ./mastodon-kanidm-sync.py);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services.mastodon-web = {
|
services.mastodon-web = {
|
||||||
unitConfig.RequiresMountsFor = lib.mkIf sp.useBinds "/volumes/${cfg.location}/mastodon";
|
unitConfig.RequiresMountsFor = lib.mkIf sp.useBinds "/volumes/${cfg.location}/mastodon";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
loadCredentials = ["client-secret:${oauthClientSecretFP}"];
|
Slice = "mastodon.slice";
|
||||||
|
LoadCredential = ["client-secret:${oauthClientSecretFP}"];
|
||||||
ExecStart = lib.mkForce (pkgs.writeShellScript "run-mastodon-with-client-secret" ''
|
ExecStart = lib.mkForce (pkgs.writeShellScript "run-mastodon-with-client-secret" ''
|
||||||
export CLIENT_SECRET=$(cat $CREDENTIALS_DIRECTORY/client-secret)
|
export OIDC_CLIENT_SECRET=$(cat $CREDENTIALS_DIRECTORY/client-secret)
|
||||||
${config.services.mastodon.package}/bin/puma -C config/puma.rb
|
${config.services.mastodon.package}/bin/puma -C config/puma.rb
|
||||||
'');
|
'');
|
||||||
};
|
};
|
||||||
@@ -141,26 +197,30 @@ in
|
|||||||
OIDC_DISPLAY_NAME= "Kanidm";
|
OIDC_DISPLAY_NAME= "Kanidm";
|
||||||
OIDC_ISSUER = issuer;
|
OIDC_ISSUER = issuer;
|
||||||
OIDC_DISCOVERY = "true";
|
OIDC_DISCOVERY = "true";
|
||||||
OIDC_SCOPE = "openid,profile";
|
OIDC_SCOPE = "openid,profile,email";
|
||||||
OIDC_UID_FIELD = "sub";
|
OIDC_UID_FIELD = "preferred_username";
|
||||||
OIDC_CLIENT_ID = oauthClientID;
|
OIDC_CLIENT_ID = oauthClientID;
|
||||||
OIDC_REDIRECT_URI = oauthRedirectURL;
|
OIDC_REDIRECT_URI = oauthRedirectURL;
|
||||||
};
|
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED = "false";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
slices.mastodon = {
|
slices.mastodon = {
|
||||||
description = "Mastodon service slice";
|
description = "Mastodon service slice";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.kanidm.provision.groups."sp.mastodon.moderators" = {};
|
||||||
selfprivacy.auth.clients.${oauthClientID} = {
|
selfprivacy.auth.clients.${oauthClientID} = {
|
||||||
inherit usersGroup;
|
inherit usersGroup;
|
||||||
inherit adminsGroup;
|
inherit adminsGroup;
|
||||||
|
isTokenNeeded = true;
|
||||||
|
|
||||||
subdomain = cfg.subdomain;
|
subdomain = cfg.subdomain;
|
||||||
originLanding = "https://${cfg.subdomain}.${sp.domain}/";
|
originLanding = "https://${cfg.subdomain}.${sp.domain}/";
|
||||||
originUrl = oauthRedirectURL;
|
originUrl = oauthRedirectURL;
|
||||||
clientSystemdUnits = [ "mastodon.service" ];
|
clientSystemdUnits = [ "mastodon.service" ];
|
||||||
# enablePkce = true;
|
|
||||||
enablePkce = false;
|
enablePkce = false;
|
||||||
|
useShortPreferredUsername = true;
|
||||||
linuxUserOfClient = "mastodon";
|
linuxUserOfClient = "mastodon";
|
||||||
linuxGroupOfClient = "mastodon";
|
linuxGroupOfClient = "mastodon";
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user