sharkey: init at 2025.4.3 (#411635)
This commit is contained in:
@@ -23891,6 +23891,14 @@
|
||||
githubId = 18124752;
|
||||
email = "m@rvinvogt.com";
|
||||
};
|
||||
srxl = {
|
||||
name = "Ruby Iris Juric";
|
||||
email = "ruby@srxl.me";
|
||||
matrix = "@ruby:isincredibly.gay";
|
||||
github = "Sorixelle";
|
||||
githubId = 38685302;
|
||||
keys = [ { fingerprint = "2D76 76C7 A28E 16FC 75C7 268D 1B55 6ED8 4B0E 303A"; } ];
|
||||
};
|
||||
Srylax = {
|
||||
name = "Srylax";
|
||||
email = "srylax+nixpkgs@srylax.dev";
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
|
||||
- [SuiteNumérique Docs](https://github.com/suitenumerique/docs), a collaborative note taking, wiki and documentation web platform and alternative to Notion or Outline. Available as [services.lasuite-docs](#opt-services.lasuite-docs.enable).
|
||||
|
||||
[dwl](https://codeberg.org/dwl/dwl), a compact, hackable compositor for Wayland based on wlroots. Available as [programs.dwl](#opt-programs.dwl.enable).
|
||||
- [dwl](https://codeberg.org/dwl/dwl), a compact, hackable compositor for Wayland based on wlroots. Available as [programs.dwl](#opt-programs.dwl.enable).
|
||||
|
||||
- [Sharkey](https://joinsharkey.org), a Sharkish microblogging platform. Available as [services.sharkey](#opt-services.sharkey.enable).
|
||||
|
||||
- [mautrix-discord](https://github.com/mautrix/discord), a Matrix-Discord puppeting/relay bridge. Available as [services.mautrix-discord](#opt-services.mautrix-discord.enable).
|
||||
|
||||
|
||||
@@ -1660,6 +1660,7 @@
|
||||
./services/web-apps/screego.nix
|
||||
./services/web-apps/selfoss.nix
|
||||
./services/web-apps/sftpgo.nix
|
||||
./services/web-apps/sharkey.nix
|
||||
./services/web-apps/shiori.nix
|
||||
./services/web-apps/silverbullet.nix
|
||||
./services/web-apps/simplesamlphp.nix
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.sharkey;
|
||||
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
configFile = settingsFormat.generate "config.yml" cfg.settings;
|
||||
in
|
||||
{
|
||||
options.services.sharkey =
|
||||
let
|
||||
inherit (lib)
|
||||
mkEnableOption
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
enable = mkEnableOption "Sharkey, a Sharkish microblogging platform";
|
||||
package = mkPackageOption pkgs "sharkey" { };
|
||||
|
||||
environmentFiles = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [ ];
|
||||
example = [ "/run/secrets/sharkey-env" ];
|
||||
description = ''
|
||||
List of paths to files containing environment variables for Sharkey to use at runtime.
|
||||
|
||||
This is useful for keeping secrets out of the Nix store. See
|
||||
https://docs.joinsharkey.org/docs/install/configuration/ for how to configure Sharkey using environment
|
||||
variables.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to open ports in the NixOS firewall for Sharkey.
|
||||
'';
|
||||
};
|
||||
|
||||
setupMeilisearch = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to automatically set up a local Meilisearch instance and configure Sharkey to use it.
|
||||
|
||||
You need to ensure `services.meilisearch.masterKeyEnvironmentFile` is correctly configured for a working
|
||||
Meilisearch setup. You also need to configure Sharkey to use an API key obtained from Meilisearch with the
|
||||
`MK_CONFIG_MEILISEARCH_APIKEY` environment variable, and set `services.sharkey.settings.meilisearch.index` to
|
||||
the created index. See https://docs.joinsharkey.org/docs/customisation/search/meilisearch/ for how to create
|
||||
an API key and index.
|
||||
'';
|
||||
};
|
||||
|
||||
setupPostgresql = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether to automatically set up a local PostgreSQL database and configure Sharkey to use it.
|
||||
'';
|
||||
};
|
||||
|
||||
setupRedis = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether to automatically set up a local Redis cache and configure Sharkey to use it.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
url = mkOption {
|
||||
type = types.str;
|
||||
example = "https://blahaj.social/";
|
||||
description = ''
|
||||
The full URL that the Sharkey instance will be publically accessible on.
|
||||
|
||||
Do NOT change this after initial setup!
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 3000;
|
||||
description = ''
|
||||
The port that Sharkey will listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
example = "127.0.0.1";
|
||||
description = ''
|
||||
The address that Sharkey binds to.
|
||||
'';
|
||||
};
|
||||
|
||||
socket = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/run/sharkey/sharkey.sock";
|
||||
description = ''
|
||||
If specified, creates a UNIX socket at the given path that Sharkey listens on.
|
||||
'';
|
||||
};
|
||||
|
||||
mediaDirectory = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/sharkey";
|
||||
description = ''
|
||||
Path to the folder where Sharkey stores uploaded media such as images and attachments.
|
||||
'';
|
||||
};
|
||||
|
||||
fulltextSearch.provider = mkOption {
|
||||
type = types.enum [
|
||||
"sqlLike"
|
||||
"sqlPgroonga"
|
||||
"sqlTsvector"
|
||||
"meilisearch"
|
||||
];
|
||||
default = "sqlLike";
|
||||
example = "sqlPgroonga";
|
||||
description = ''
|
||||
Which provider to use for full text search.
|
||||
|
||||
All options other than `sqlLike` require extra setup - see the comments in
|
||||
https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/.config/example.yml for details.
|
||||
|
||||
If `sqlPgroonga` is set, and `services.sharkey.setupPostgres` is `true`, the pgroonga extension will
|
||||
automatically be setup. You still need to create an index manually.
|
||||
|
||||
If using Meilisearch, consider setting `services.sharkey.setupMeilisearch` instead, which will
|
||||
configure Meilisearch for you.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.enum [
|
||||
"aid"
|
||||
"aidx"
|
||||
"meid"
|
||||
"ulid"
|
||||
"objectid"
|
||||
];
|
||||
default = "aidx";
|
||||
description = ''
|
||||
The ID generation method for Sharkey to use.
|
||||
|
||||
Do NOT change this after initial setup!
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration options for Sharkey.
|
||||
|
||||
See https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/.config/example.yml for a list of all
|
||||
available configuration options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
inherit (lib) mkDefault mkIf mkMerge;
|
||||
in
|
||||
mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
systemd.services.sharkey = {
|
||||
description = "Sharkey";
|
||||
documentation = [ "https://docs.joinsharkey.org/" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
startLimitBurst = 5;
|
||||
startLimitIntervalSec = 60;
|
||||
environment.MISSKEY_CONFIG_DIR = "/etc/sharkey";
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${lib.getExe cfg.package} migrateandstart";
|
||||
EnvironmentFile = cfg.environmentFiles;
|
||||
DynamicUser = true;
|
||||
TimeoutSec = 60;
|
||||
Restart = "always";
|
||||
SyslogIdentifier = "sharkey";
|
||||
ConfigurationDirectory = "sharkey";
|
||||
RuntimeDirectory = "sharkey";
|
||||
StateDirectory = "sharkey";
|
||||
CapabilityBoundingSet = "";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateUsers = true;
|
||||
PrivateTmp = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = [ cfg.settings.mediaDirectory ];
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_NETLINK";
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"~@cpu-emulation @debug @mount @obsolete @privileged @resources"
|
||||
"@chown"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."sharkey/default.yml".source = configFile;
|
||||
}
|
||||
(mkIf cfg.openFirewall {
|
||||
networking.firewall.allowedTCPPorts = [ cfg.settings.port ];
|
||||
})
|
||||
(mkIf cfg.setupMeilisearch {
|
||||
services.meilisearch = {
|
||||
enable = mkDefault true;
|
||||
environment = mkDefault "production";
|
||||
};
|
||||
|
||||
services.sharkey.settings = {
|
||||
fulltextSearch.provider = "meilisearch";
|
||||
meilisearch = {
|
||||
host = config.services.meilisearch.listenAddress;
|
||||
port = config.services.meilisearch.listenPort;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.sharkey = {
|
||||
after = [ "meilisearch.service" ];
|
||||
wants = [ "meilisearch.service" ];
|
||||
};
|
||||
})
|
||||
(mkIf cfg.setupPostgresql {
|
||||
services.postgresql = {
|
||||
enable = mkDefault true;
|
||||
ensureDatabases = [ "sharkey" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "sharkey";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
|
||||
extensions = mkIf (cfg.settings.fulltextSearch.provider == "sqlPgroonga") (ps: [ ps.pgroonga ]);
|
||||
};
|
||||
|
||||
services.sharkey.settings.db = {
|
||||
host = "/run/postgresql";
|
||||
db = "sharkey";
|
||||
};
|
||||
|
||||
systemd.services.sharkey = {
|
||||
after = [ "postgresql.target" ];
|
||||
bindsTo = [ "postgresql.target" ];
|
||||
};
|
||||
})
|
||||
(mkIf cfg.setupRedis {
|
||||
services.redis.servers.sharkey.enable = mkDefault true;
|
||||
|
||||
services.sharkey.settings.redis.path = config.services.redis.servers.sharkey.unixSocket;
|
||||
|
||||
systemd.services.sharkey = {
|
||||
after = [ "redis-sharkey.service" ];
|
||||
bindsTo = [ "redis-sharkey.service" ];
|
||||
|
||||
serviceConfig.SupplementaryGroups = [
|
||||
config.services.redis.servers.sharkey.group
|
||||
];
|
||||
};
|
||||
})
|
||||
]);
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ srxl ];
|
||||
}
|
||||
@@ -1277,6 +1277,7 @@ in
|
||||
sgt-puzzles = runTest ./sgt-puzzles.nix;
|
||||
shadow = runTest ./shadow.nix;
|
||||
shadowsocks = handleTest ./shadowsocks { };
|
||||
sharkey = runTest ./web-apps/sharkey.nix;
|
||||
shattered-pixel-dungeon = runTest ./shattered-pixel-dungeon.nix;
|
||||
shiori = runTest ./shiori.nix;
|
||||
signal-desktop = runTest ./signal-desktop.nix;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
meilisearchKey = "TESTKEY-naXRkVX7nhvLaGOmGGuicDKxZAj0khEaoOZPeEZafv8w9j8V6aKb0NVdXRChL5kR";
|
||||
in
|
||||
{
|
||||
name = "sharkey";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.sharkey = {
|
||||
enable = true;
|
||||
setupMeilisearch = true;
|
||||
environmentFiles = [ "/run/secrets/sharkey-env" ];
|
||||
settings = {
|
||||
url = "http://exampleurl.invalid";
|
||||
meilisearch.index = "exampleurl_invalid";
|
||||
};
|
||||
};
|
||||
|
||||
services.meilisearch.masterKeyEnvironmentFile = pkgs.writeText "meilisearch-key" ''
|
||||
MEILI_MASTER_KEY=${meilisearchKey}
|
||||
'';
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
createIndexPayload = builtins.toJSON {
|
||||
description = "Sharkey API key";
|
||||
actions = [ "*" ];
|
||||
indexes = [ "exampleurl_invalid---notes" ];
|
||||
expiresAt = null;
|
||||
};
|
||||
in
|
||||
''
|
||||
import json
|
||||
|
||||
with subtest("Setting up Meilisearch API key and index"):
|
||||
machine.wait_for_unit("meilisearch.service")
|
||||
machine.wait_for_open_port(7700)
|
||||
|
||||
json_body = '${createIndexPayload}'
|
||||
create_index_result = json.loads(machine.succeed(f"curl -s -X POST 'http://localhost:7700/keys' -H 'Content-Type: application/json' -H 'Authorization: Bearer ${meilisearchKey}' --data-binary '{json_body}'"))
|
||||
machine.succeed(f"mkdir /run/secrets; echo 'MK_CONFIG_MEILISEARCH_APIKEY={create_index_result["key"]}' > /run/secrets/sharkey-env")
|
||||
|
||||
with subtest("Testing Sharkey is running and listening to HTTP requests"):
|
||||
machine.systemctl("restart sharkey")
|
||||
machine.wait_for_open_port(3000)
|
||||
|
||||
machine.succeed("curl --fail http://localhost:3000")
|
||||
'';
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ srxl ];
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
fetchFromGitLab,
|
||||
nixosTests,
|
||||
bash,
|
||||
cairo,
|
||||
cctools,
|
||||
ffmpeg-headless,
|
||||
jemalloc,
|
||||
makeWrapper,
|
||||
nodejs,
|
||||
pango,
|
||||
pixman,
|
||||
pkg-config,
|
||||
pnpm_9,
|
||||
python3,
|
||||
vips,
|
||||
xcbuild,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "sharkey";
|
||||
version = "2025.4.3";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
domain = "activitypub.software";
|
||||
owner = "TransFem-org";
|
||||
repo = "Sharkey";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-B268bSR5VFyJ/TaWg3xxpnP4oRj07XUpikJZ2Tb9FEY=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
pnpmDeps = pnpm_9.fetchDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
hash = "sha256-S8LxawbtguFOEZyYbS1FQWw/TcRm4Z6mG7dUhfXbf1c=";
|
||||
};
|
||||
|
||||
nativeBuildInputs =
|
||||
[
|
||||
makeWrapper
|
||||
nodejs
|
||||
pkg-config
|
||||
pnpm_9.configHook
|
||||
python3
|
||||
]
|
||||
++ (lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
cctools
|
||||
xcbuild
|
||||
]);
|
||||
|
||||
buildInputs = [
|
||||
cairo
|
||||
pango
|
||||
pixman
|
||||
vips
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
# pnpm.fetchDeps doesn't run build scripts, so we need to run postinstall for this package otherwise the frontend
|
||||
# build fails
|
||||
pushd node_modules/.pnpm/node_modules/v-code-diff
|
||||
pnpm postinstall
|
||||
popd
|
||||
|
||||
# rebuild some node modules that have native dependencies
|
||||
export npm_config_nodedir=${nodejs}
|
||||
|
||||
pushd node_modules/.pnpm/node_modules/re2
|
||||
pnpm rebuild
|
||||
popd
|
||||
|
||||
pushd node_modules/.pnpm/node_modules/sharp
|
||||
pnpm run install
|
||||
popd
|
||||
|
||||
pushd node_modules/.pnpm/node_modules/canvas
|
||||
pnpm run install
|
||||
popd
|
||||
|
||||
pnpm build
|
||||
node scripts/trim-deps.mjs
|
||||
pnpm prune --prod --ignore-scripts
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase =
|
||||
let
|
||||
binPath = lib.makeBinPath [
|
||||
bash
|
||||
nodejs
|
||||
pnpm_9
|
||||
];
|
||||
libPath = lib.makeLibraryPath [
|
||||
ffmpeg-headless
|
||||
jemalloc
|
||||
stdenv.cc.cc
|
||||
];
|
||||
in
|
||||
''
|
||||
runHook preInstall
|
||||
|
||||
# adapted from repo dockerfile
|
||||
# https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/Dockerfile?ref_type=heads
|
||||
mkdir -p $out/sharkey
|
||||
cp -r built fluent-emojis node_modules package.json pnpm-workspace.yaml $out/sharkey/
|
||||
|
||||
mkdir -p $out/sharkey/packages/backend
|
||||
cp -r packages/backend/{assets,built,migration,node_modules,ormconfig.js,package.json} $out/sharkey/packages/backend/
|
||||
mkdir -p $out/sharkey/packages/backend/scripts
|
||||
cp -r packages/backend/scripts/check_connect.js $out/sharkey/packages/backend/scripts/
|
||||
|
||||
mkdir -p $out/sharkey/packages/megalodon
|
||||
cp -r packages/megalodon/{lib,node_modules,package.json} $out/sharkey/packages/megalodon/
|
||||
|
||||
mkdir -p $out/sharkey/packages/misskey-{bubble-game,js,reversi}
|
||||
cp -r packages/misskey-bubble-game/{built,node_modules,package.json} $out/sharkey/packages/misskey-bubble-game/
|
||||
cp -r packages/misskey-js/{built,node_modules,package.json} $out/sharkey/packages/misskey-js/
|
||||
cp -r packages/misskey-reversi/{built,node_modules,package.json} $out/sharkey/packages/misskey-reversi/
|
||||
|
||||
mkdir -p $out/sharkey/packages/frontend{,-embed}
|
||||
cp -r packages/frontend/assets $out/sharkey/packages/frontend/
|
||||
cp -r packages/frontend-embed/assets $out/sharkey/packages/frontend-embed/
|
||||
|
||||
mkdir -p $out/sharkey/tossface-emojis
|
||||
cp -r tossface-emojis/dist $out/sharkey/tossface-emojis/
|
||||
|
||||
# create a wrapper script for running sharkey commands (ie. alias for pnpm run)
|
||||
makeWrapper ${lib.getExe pnpm_9} $out/bin/sharkey \
|
||||
--chdir $out/sharkey \
|
||||
--add-flags run \
|
||||
--set-default NODE_ENV production \
|
||||
--prefix PATH : ${binPath} \
|
||||
--prefix LD_LIBRARY_PATH : ${libPath}
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
fixupPhase = ''
|
||||
runHook preFixup
|
||||
|
||||
# cleanup dangling symlinks in node_modules, referencing workspace packages we don't include in the final output
|
||||
rm -r $out/sharkey/node_modules/.pnpm/node_modules/{sw,misskey-js-type-generator,frontend-shared}
|
||||
|
||||
# remove packageManager line from package.json; tries to download a different pnpm version into $HOME otherwise
|
||||
sed -i -e '9d' $out/sharkey/package.json
|
||||
|
||||
runHook postFixup
|
||||
'';
|
||||
|
||||
passthru.tests.sharkey = nixosTests.sharkey;
|
||||
|
||||
meta = {
|
||||
description = "Sharkish microblogging platform";
|
||||
homepage = "https://joinsharkey.org";
|
||||
changelog = "https://activitypub.software/TransFem-org/Sharkey/-/releases/${finalAttrs.version}";
|
||||
license = lib.licenses.agpl3Only;
|
||||
platforms = with lib.platforms; linux ++ darwin;
|
||||
mainProgram = "sharkey";
|
||||
maintainers = with lib.maintainers; [ srxl ];
|
||||
};
|
||||
})
|
||||
Reference in New Issue
Block a user