301 lines
9.3 KiB
Nix
301 lines
9.3 KiB
Nix
{
|
|
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 ];
|
|
}
|