Initial commit
This commit is contained in:
11
config-paths-needed.json
Normal file
11
config-paths-needed.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
[ "selfprivacy", "domain" ],
|
||||||
|
[ "selfprivacy", "modules", "auth", "enable" ],
|
||||||
|
[ "selfprivacy", "modules", "hedgedoc" ],
|
||||||
|
[ "selfprivacy", "passthru", "auth", "mkOAuth2ClientSecretFP" ],
|
||||||
|
[ "selfprivacy", "passthru", "auth", "oauth2-discovery-url" ],
|
||||||
|
[ "selfprivacy", "passthru", "auth", "oauth2-provider-name" ],
|
||||||
|
[ "selfprivacy", "sso", "enable" ],
|
||||||
|
[ "selfprivacy", "useBinds" ],
|
||||||
|
[ "services", "kanidm", "serverSettings", "origin" ]
|
||||||
|
]
|
41
flake.nix
Normal file
41
flake.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
# TODO: check whether there is no TODOs
|
||||||
|
# TODO: check whether there is no hedgegdoc mentions
|
||||||
|
description = "Mastodon module";
|
||||||
|
|
||||||
|
outputs = { ... }:
|
||||||
|
{
|
||||||
|
nixosModules.default = import ./module.nix;
|
||||||
|
configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
|
||||||
|
meta =
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
spModuleSchemaVersion = 1;
|
||||||
|
id = "mastodon";
|
||||||
|
name = "Mastodon";
|
||||||
|
description = "Mastodon is a free non-profit decentralized social media, a part of Fediverse network, offering a web client and a mobile app.";
|
||||||
|
svgIcon = builtins.readFile ./icon.svg;
|
||||||
|
isMovable = true;
|
||||||
|
isRequired = false;
|
||||||
|
backupDescription = ".";
|
||||||
|
systemdServices = [
|
||||||
|
"mastodon.service"
|
||||||
|
];
|
||||||
|
folders = [
|
||||||
|
"/var/lib/mastodon"
|
||||||
|
];
|
||||||
|
postgreDatabases = [
|
||||||
|
"mastodon"
|
||||||
|
];
|
||||||
|
license = [
|
||||||
|
lib.licenses.agpl3Only # TODO: plus or only
|
||||||
|
];
|
||||||
|
homepage = "https://joinmastodon.org";
|
||||||
|
sourcePage = "https://github.com/mastodon/mastodon";
|
||||||
|
supportLevel = "normal";
|
||||||
|
sso = {
|
||||||
|
userGroup = "sp.mastodon.users";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
27
hedgedocClientSecretAsFile.patch
Normal file
27
hedgedocClientSecretAsFile.patch
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
diff --git a/lib/web/auth/oauth2/index.js b/lib/web/auth/oauth2/index.js
|
||||||
|
index b0ffa5e8a..45229358e 100644
|
||||||
|
--- a/lib/web/auth/oauth2/index.js
|
||||||
|
+++ b/lib/web/auth/oauth2/index.js
|
||||||
|
@@ -6,6 +6,7 @@ const { Strategy, InternalOAuthError } = require('passport-oauth2')
|
||||||
|
const config = require('../../../config')
|
||||||
|
const logger = require('../../../logger')
|
||||||
|
const { passportGeneralCallback } = require('../utils')
|
||||||
|
+const fs = require('fs')
|
||||||
|
|
||||||
|
const oauth2Auth = module.exports = Router()
|
||||||
|
|
||||||
|
@@ -130,11 +131,13 @@ OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
+const OAuth2clientSecretText = fs.readFileSync(config.oauth2.clientSecret, 'utf8').split("\n")[0]
|
||||||
|
+
|
||||||
|
passport.use(new OAuth2CustomStrategy({
|
||||||
|
authorizationURL: config.oauth2.authorizationURL,
|
||||||
|
tokenURL: config.oauth2.tokenURL,
|
||||||
|
clientID: config.oauth2.clientID,
|
||||||
|
- clientSecret: config.oauth2.clientSecret,
|
||||||
|
+ clientSecret: OAuth2clientSecretText,
|
||||||
|
callbackURL: config.serverURL + '/auth/oauth2/callback',
|
||||||
|
userProfileURL: config.oauth2.userProfileURL,
|
||||||
|
scope: config.oauth2.scope,
|
20
icon.svg
Normal file
20
icon.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 1772 1772" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<g>
|
||||||
|
<path d="M1553.66,961.083L1628.91,885.825L1553.66,810.579L1610.27,720.483L1520.17,663.867L1555.32,563.421L1454.88,528.279L1466.79,422.533L1361.05,410.621L1349.13,304.871L1243.39,316.783L1208.24,216.338L1107.81,251.483L1051.18,161.383L961.073,218L885.831,142.754L810.589,218.004L720.485,161.392L663.873,251.488L563.431,216.338L528.289,316.779L422.539,304.863L410.627,410.604L304.885,422.517L316.802,528.258L216.348,563.408L251.493,663.846L161.393,720.458L218.014,810.575L142.756,885.825L218.006,961.083L161.393,1051.19L251.493,1107.8L216.348,1208.24L316.798,1243.39L304.885,1349.12L410.627,1361.04L422.539,1466.78L528.289,1454.87L563.431,1555.3L663.868,1520.17L720.485,1610.27L810.581,1553.65L885.831,1628.2L961.081,1553.67L1051.18,1610.28L1107.79,1520.17L1208.24,1555.32L1243.38,1454.88L1349.13,1466.79L1361.04,1361.04L1466.79,1349.13L1454.87,1243.39L1555.32,1208.24L1520.17,1107.79L1610.27,1051.18L1553.66,961.083Z" style="fill:rgb(181,31,8);fill-rule:nonzero;"/>
|
||||||
|
<path d="M1401.3,1004.78C1401.3,859.343 1283.4,741.439 1137.96,741.439C1065.72,741.439 1000.28,770.551 952.708,817.664L952.675,817.63L885.579,884.73L830.717,829.868C782.45,774.801 711.646,739.989 632.675,739.989C487.233,739.989 369.333,857.893 369.333,1003.33C369.333,1079.33 401.563,1147.76 453.054,1195.82L885.833,1628.37L1309.05,1204.88C1361.93,1155.11 1401.3,1084.88 1401.3,1004.78" style="fill:rgb(252,202,140);fill-rule:nonzero;"/>
|
||||||
|
<path d="M885.579,884.73L830.717,829.868C782.45,774.801 711.646,739.989 632.675,739.989C487.233,739.989 369.333,857.893 369.333,1003.33C369.333,1079.33 401.563,1147.76 453.054,1195.82L885.833,1628.37" style="fill:url(#_Linear1);fill-rule:nonzero;"/>
|
||||||
|
</g>
|
||||||
|
<path d="M885.833,1628.37L885.579,884.73" style="fill:none;"/>
|
||||||
|
<g>
|
||||||
|
<path d="M961.011,1553.59C941.732,1534.24 915.094,1522.28 885.686,1522.28C856.269,1522.28 829.64,1534.24 810.357,1553.59C810.665,1594.93 844.265,1628.35 885.682,1628.35C927.098,1628.35 960.702,1594.92 961.011,1553.59" style="fill:rgb(1,0,7);fill-rule:nonzero;"/>
|
||||||
|
<path d="M797.707,1098.22C797.707,1130.02 771.94,1155.79 740.136,1155.79C708.349,1155.79 682.578,1130.02 682.578,1098.22C682.578,1066.42 708.349,1040.65 740.136,1040.65C771.94,1040.65 797.707,1066.42 797.707,1098.22" style="fill:rgb(1,0,7);fill-rule:nonzero;"/>
|
||||||
|
<path d="M777.962,1089.59C777.962,1098.41 770.816,1105.53 762.012,1105.53C753.204,1105.53 746.054,1098.41 746.054,1089.59C746.054,1080.78 753.204,1073.63 762.012,1073.63C770.816,1073.63 777.962,1080.78 777.962,1089.59" style="fill:rgb(255,255,250);fill-rule:nonzero;"/>
|
||||||
|
<path d="M1089.65,1098.22C1089.65,1130.02 1063.88,1155.79 1032.08,1155.79C1000.29,1155.79 974.513,1130.02 974.513,1098.22C974.513,1066.42 1000.29,1040.65 1032.08,1040.65C1063.88,1040.65 1089.65,1066.42 1089.65,1098.22" style="fill:rgb(1,0,7);fill-rule:nonzero;"/>
|
||||||
|
<path d="M1069.9,1089.59C1069.9,1098.41 1062.75,1105.53 1053.95,1105.53C1045.14,1105.53 1037.99,1098.41 1037.99,1089.59C1037.99,1080.78 1045.14,1073.63 1053.95,1073.63C1062.75,1073.63 1069.9,1080.78 1069.9,1089.59" style="fill:rgb(255,255,250);fill-rule:nonzero;"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(200,-420,420,200,660,1340)"><stop offset="0" style="stop-color:rgb(252,202,140);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(220,160,85);stop-opacity:1"/></linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
131
module.nix
Normal file
131
module.nix
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
sp = config.selfprivacy;
|
||||||
|
cfg = sp.modules.mastodon;
|
||||||
|
oauthClientID = "mastodon";
|
||||||
|
auth-passthru = config.selfprivacy.passthru.auth;
|
||||||
|
oauthDiscoveryURL = config.services.kanidm.serverSettings.origin;
|
||||||
|
issuer = lib.strings.removeSuffix "/.well-known/openid-configuration" oauthDiscoveryURL;
|
||||||
|
|
||||||
|
# SelfPrivacy uses SP Module ID to identify the group!
|
||||||
|
usersGroup = "sp.mastodon.users";
|
||||||
|
|
||||||
|
oauthClientSecretFP = auth-passthru.mkOAuth2ClientSecretFP oauthClientID;
|
||||||
|
oauthRedirectURL = "https://${cfg.subdomain}.${sp.domain}/auth/auth/openid_connect/callback";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.selfprivacy.modules.mastodon = {
|
||||||
|
enable =
|
||||||
|
(lib.mkOption {
|
||||||
|
default = false;
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Enable Mastodon";
|
||||||
|
})
|
||||||
|
// {
|
||||||
|
meta = {
|
||||||
|
type = "enable";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
location =
|
||||||
|
(lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Mastodon location";
|
||||||
|
})
|
||||||
|
// {
|
||||||
|
meta = {
|
||||||
|
type = "location";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
subdomain =
|
||||||
|
(lib.mkOption {
|
||||||
|
default = "mastodon";
|
||||||
|
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
|
||||||
|
description = "Subdomain";
|
||||||
|
})
|
||||||
|
// {
|
||||||
|
meta = {
|
||||||
|
widget = "subdomain";
|
||||||
|
type = "string";
|
||||||
|
regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
|
||||||
|
weight = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = sp.sso.enable;
|
||||||
|
message = "Mastodon cannot be enabled when SSO is disabled.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
fileSystems = lib.mkIf sp.useBinds {
|
||||||
|
"/var/lib/mastodon" = {
|
||||||
|
device = "/volumes/${cfg.location}/mastodon";
|
||||||
|
options = [ "bind" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# services.postgresql = {
|
||||||
|
# ensureDatabases = [ "mastodon" ];
|
||||||
|
# ensureUsers = [
|
||||||
|
# {
|
||||||
|
# name = "mastodon";
|
||||||
|
# ensureDBOwnership = true;
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
services.mastodon = {
|
||||||
|
enable = true;
|
||||||
|
localDomain = "${cfg.subdomain}.${sp.domain}";
|
||||||
|
enableUnixSocket = false;
|
||||||
|
configureNginx = true;
|
||||||
|
database.createLocally = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
systemd = {
|
||||||
|
services.mastodon = {
|
||||||
|
unitConfig.RequiresMountsFor = lib.mkIf sp.useBinds "/volumes/${cfg.location}/mastodon";
|
||||||
|
serviceConfig = {
|
||||||
|
loadCredentials = ["client-secret:${oauthClientSecretFP}"];
|
||||||
|
ExecStart = ''
|
||||||
|
export CLIENT_SECRET=$(cat $CREDENTIALS_DIRECTORY/client-secret)
|
||||||
|
${config.services.mastodon.package}/bin/puma -C config/puma.rb`
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
environment = {
|
||||||
|
OIDC_ENABLED = true;
|
||||||
|
OIDC_DISPLAY_NAME= "Kanidm";
|
||||||
|
OIDC_ISSUER = issuer;
|
||||||
|
OIDC_DISCOVERY = true;
|
||||||
|
OIDC_SCOPE = "openid,profile";
|
||||||
|
OIDC_UID_FIELD = "sub";
|
||||||
|
OIDC_CLIENT_ID = oauthClientID;
|
||||||
|
OIDC_REDIRECT_URI = oauthRedirectURL;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
slices.mastodon = {
|
||||||
|
description = "Mastodon service slice";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
selfprivacy.auth.clients.${oauthClientID} = {
|
||||||
|
inherit usersGroup;
|
||||||
|
subdomain = cfg.subdomain;
|
||||||
|
originLanding = "https://${cfg.subdomain}.${sp.domain}/";
|
||||||
|
originUrl = oauthRedirectURL;
|
||||||
|
clientSystemdUnits = [ "mastodon.service" ];
|
||||||
|
enablePkce = true;
|
||||||
|
linuxUserOfClient = "mastodon";
|
||||||
|
linuxGroupOfClient = "mastodon";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Reference in New Issue
Block a user