2023-07-08 12:01:21 -07:00
|
|
|
{ config, lib, pkgs, ... }@toplevel:
|
2023-07-07 22:11:33 -07:00
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
2023-07-07 23:06:24 -07:00
|
|
|
cfg = config.services.lemmyDocker;
|
|
|
|
|
2023-07-07 23:09:21 -07:00
|
|
|
hostSecrets = config.fudo.secrets.host-secrets."${config.instance.hostname}";
|
|
|
|
|
2023-07-16 10:48:07 -07:00
|
|
|
makeEnvFile = envVars:
|
2023-07-16 22:41:11 -07:00
|
|
|
let envLines = mapAttrsToList (var: val: ''${var}="${val}"'') envVars;
|
2023-07-16 10:48:07 -07:00
|
|
|
in pkgs.writeText "envFile" (concatStringsSep "\n" envLines);
|
|
|
|
|
|
|
|
makeLemmyImage = { port, stateDirectory, proxyCfg, lemmyCfg, lemmyUiCfg
|
|
|
|
, pictrsCfg, postgresCfg, ... }:
|
2023-07-14 11:59:57 -07:00
|
|
|
{ pkgs, ... }: {
|
|
|
|
project.name = "lemmy";
|
|
|
|
services = {
|
|
|
|
proxy = {
|
|
|
|
service = {
|
2023-07-16 10:48:07 -07:00
|
|
|
image = proxyCfg.image;
|
2023-07-16 12:06:31 -07:00
|
|
|
ports = [ "${toString port}:8536" ];
|
2023-07-16 10:48:07 -07:00
|
|
|
volumes = [ "${proxyCfg.configFile}:/etc/nginx/nginx.conf:ro,Z" ];
|
2023-07-14 11:59:57 -07:00
|
|
|
depends_on = [ "pictrs" "lemmy-ui" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
lemmy = {
|
|
|
|
service = {
|
2023-07-16 10:48:07 -07:00
|
|
|
image = lemmyCfg.image;
|
2023-07-14 11:59:57 -07:00
|
|
|
hostname = "lemmy";
|
2023-07-16 11:50:57 -07:00
|
|
|
env_file = [ lemmyCfg.envFile ];
|
2023-07-16 10:48:07 -07:00
|
|
|
volumes = [ "${lemmyCfg.configFile}:/config/config.hjson:ro,Z" ];
|
2023-07-14 11:59:57 -07:00
|
|
|
depends_on = [ "postgres" "pictrs" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
lemmy-ui = {
|
|
|
|
service = {
|
2023-07-16 10:48:07 -07:00
|
|
|
image = lemmyUiCfg.image;
|
2023-07-14 11:59:57 -07:00
|
|
|
hostname = "lemmy-ui";
|
|
|
|
depends_on = [ "lemmy" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
pictrs = {
|
|
|
|
service = {
|
2023-07-16 10:48:07 -07:00
|
|
|
image = pictrsCfg.image;
|
2023-07-14 11:59:57 -07:00
|
|
|
hostname = "pictrs";
|
|
|
|
volumes = [ "${stateDirectory}/pictrs:/mnt:Z" ];
|
2023-07-16 23:07:28 -07:00
|
|
|
# user = "991:991";
|
2023-07-16 11:50:57 -07:00
|
|
|
env_file = [ pictrsCfg.envFile ];
|
2023-07-14 11:59:57 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
postgres = {
|
|
|
|
service = {
|
2023-07-16 10:48:07 -07:00
|
|
|
image = postgresCfg.image;
|
2023-07-14 11:59:57 -07:00
|
|
|
hostname = "postgres";
|
|
|
|
volumes = [
|
|
|
|
"${stateDirectory}/postgres:/var/lib/postgresql/data:Z"
|
2023-07-16 10:48:07 -07:00
|
|
|
"${postgresCfg.configFile}:/etc/postgresql.conf"
|
2023-07-14 11:59:57 -07:00
|
|
|
];
|
2023-07-16 11:50:57 -07:00
|
|
|
env_file = [ postgresCfg.envFile ];
|
2023-07-14 11:59:57 -07:00
|
|
|
};
|
|
|
|
};
|
2023-07-07 22:11:33 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-07-08 09:43:21 -07:00
|
|
|
nginxCfgFile = pkgs.writeText "lemmy-nginx.conf" ''
|
2023-07-07 22:11:33 -07:00
|
|
|
worker_processes auto;
|
|
|
|
|
|
|
|
events {
|
|
|
|
worker_connections 1024;
|
|
|
|
}
|
|
|
|
|
|
|
|
http {
|
|
|
|
map "$request_method:$http_accept" $proxpass {
|
|
|
|
default "http://lemmy-ui";
|
|
|
|
"~^(?:GET|HEAD):.*?application\/(?:activity|ld)\+json" "http://lemmy";
|
|
|
|
"~^(?!(GET|HEAD)).*:" "http://lemmy";
|
|
|
|
}
|
|
|
|
|
|
|
|
upstream lemmy {
|
|
|
|
server "lemmy:8536";
|
|
|
|
}
|
|
|
|
|
|
|
|
upstream lemmy-ui {
|
|
|
|
server "lemmy-ui:1234";
|
|
|
|
}
|
|
|
|
|
|
|
|
server {
|
|
|
|
listen 1236;
|
|
|
|
listen 8536;
|
|
|
|
|
|
|
|
server_name localhost;
|
|
|
|
server_tokens off;
|
|
|
|
|
|
|
|
gzip on;
|
|
|
|
gzip_types text/css application/javascript image/svg+xml;
|
|
|
|
gzip_vary on;
|
|
|
|
|
|
|
|
client_max_body_size 20M;
|
|
|
|
|
|
|
|
add_header X-Frame-Options SAMEORIGIN;
|
|
|
|
add_header X-Content-Type-Options nosniff;
|
|
|
|
add_header X-XSS-Protection "1; mode=block";
|
|
|
|
|
|
|
|
location / {
|
|
|
|
proxy_pass $proxpass;
|
|
|
|
|
|
|
|
rewrite ^(.+)/+$ $1 permanent;
|
|
|
|
|
|
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
|
|
proxy_set_header Host $host;
|
|
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
}
|
|
|
|
|
|
|
|
location ~ ^/(api|pictrs|feeds|nodeinfo|.well-known) {
|
|
|
|
proxy_pass "http://lemmy";
|
|
|
|
|
|
|
|
proxy_http_version 1.1;
|
|
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
|
|
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
|
|
proxy_set_header Host $host;
|
|
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'';
|
|
|
|
|
2023-07-16 11:35:55 -07:00
|
|
|
makeLemmyCfg = { hostname, postgresPasswd, pictrsApiKey, smtpServer, ... }:
|
2023-07-08 12:04:33 -07:00
|
|
|
pkgs.writeText "lemmy.hjson" (builtins.toJSON {
|
|
|
|
database = {
|
|
|
|
host = "postgres";
|
|
|
|
password = postgresPasswd;
|
|
|
|
};
|
|
|
|
hostname = hostname;
|
|
|
|
pictrs = {
|
|
|
|
url = "http://pictrs:8080/";
|
|
|
|
api_key = pictrsApiKey;
|
|
|
|
};
|
|
|
|
email = {
|
|
|
|
smtp_server = smtpServer;
|
|
|
|
tls_type = "none";
|
|
|
|
smtp_from_address = "noreply@${hostname}";
|
|
|
|
};
|
|
|
|
});
|
2023-07-07 22:11:33 -07:00
|
|
|
|
2023-07-16 10:48:07 -07:00
|
|
|
postgresCfgFile = pkgs.writeText "lemmy-postgres.conf" ''
|
2023-07-08 12:08:50 -07:00
|
|
|
# DB Version: 15
|
|
|
|
# OS Type: linux
|
|
|
|
# DB Type: web
|
|
|
|
# Total Memory (RAM): 8 GB
|
|
|
|
# CPUs num: 4
|
|
|
|
# Data Storage: ssd
|
|
|
|
|
|
|
|
max_connections = 200
|
|
|
|
shared_buffers = 2GB
|
|
|
|
effective_cache_size = 6GB
|
|
|
|
maintenance_work_mem = 512MB
|
|
|
|
checkpoint_completion_target = 0.9
|
|
|
|
checkpoint_timeout = 86400
|
|
|
|
wal_buffers = 16MB
|
|
|
|
default_statistics_target = 100
|
|
|
|
random_page_cost = 1.1
|
|
|
|
effective_io_concurrency = 200
|
|
|
|
work_mem = 5242kB
|
|
|
|
min_wal_size = 1GB
|
|
|
|
max_wal_size = 30GB
|
|
|
|
max_worker_processes = 4
|
|
|
|
max_parallel_workers_per_gather = 2
|
|
|
|
max_parallel_workers = 4
|
|
|
|
max_parallel_maintenance_workers = 2
|
|
|
|
|
|
|
|
# Other custom params
|
|
|
|
temp_file_size=1GB
|
|
|
|
synchronous_commit=off
|
|
|
|
# This one shouldn't be on regularly, because DB migrations often take a long time
|
|
|
|
# statement_timeout = 10000
|
|
|
|
'';
|
|
|
|
|
2023-07-07 22:11:33 -07:00
|
|
|
lemmyDockerComposeCfg = { hostname, port, lemmyCfgFile, nginxCfgFile
|
|
|
|
, pictrsApiKey, stateDirectory, postgresPasswd, lemmyDockerImage
|
2023-07-08 12:08:50 -07:00
|
|
|
, lemmyUiDockerImage, pictrsDockerImage, postgresCfg, postgresDockerImage
|
|
|
|
, ... }:
|
2023-07-07 22:11:33 -07:00
|
|
|
let
|
|
|
|
defaultLogging = {
|
|
|
|
driver = "json-file";
|
|
|
|
options = {
|
|
|
|
max-size = "50m";
|
|
|
|
max-file = "4";
|
|
|
|
};
|
|
|
|
};
|
2023-07-08 11:55:23 -07:00
|
|
|
in pkgs.writeTextDir "docker-compose.yml" (builtins.toJSON {
|
2023-07-07 22:11:33 -07:00
|
|
|
version = "3.7";
|
|
|
|
|
|
|
|
services = {
|
|
|
|
proxy = {
|
|
|
|
image = "nginx:1-alpine";
|
2023-07-08 12:13:04 -07:00
|
|
|
ports = [ "${toString port}:8536" ];
|
2023-07-08 12:20:47 -07:00
|
|
|
volumes = [ "${nginxCfgFile}:/etc/nginx/nginx.conf:ro,Z" ];
|
2023-07-07 22:11:33 -07:00
|
|
|
restart = "always";
|
|
|
|
logging = defaultLogging;
|
|
|
|
};
|
|
|
|
|
|
|
|
lemmy = {
|
|
|
|
image = lemmyDockerImage;
|
|
|
|
hostname = "lemmy";
|
|
|
|
restart = "always";
|
|
|
|
logging = defaultLogging;
|
|
|
|
volumes = [ "${lemmyCfgFile}:/config/config.hjson:Z" ];
|
|
|
|
depends_on = [ "postgres" "pictrs" ];
|
|
|
|
};
|
|
|
|
|
|
|
|
lemmy-ui = {
|
|
|
|
image = lemmyUiDockerImage;
|
|
|
|
restart = "always";
|
|
|
|
logging = defaultLogging;
|
|
|
|
depends_on = [ "lemmy" ];
|
|
|
|
};
|
|
|
|
|
|
|
|
pictrs = {
|
|
|
|
image = pictrsDockerImage;
|
|
|
|
hostname = "pictrs";
|
|
|
|
restart = "always";
|
|
|
|
logging = defaultLogging;
|
|
|
|
user = "991:991";
|
|
|
|
volumes = [ "${stateDirectory}/pictrs:/mnt:Z" ];
|
|
|
|
deploy.resources.limits.memory = "690m";
|
|
|
|
};
|
|
|
|
|
|
|
|
postgres = {
|
|
|
|
image = postgresDockerImage;
|
|
|
|
hostname = "postgres";
|
|
|
|
restart = "always";
|
|
|
|
logging = defaultLogging;
|
|
|
|
volumes = [
|
|
|
|
"${stateDirectory}/database:/var/lib/postgresql/data:Z"
|
|
|
|
"${postgresCfg}:/etc/postgresql.conf"
|
|
|
|
];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
in {
|
|
|
|
options.services.lemmyDocker = with types; {
|
|
|
|
enable = mkEnableOption "Enable Lemmy running in a Docker container.";
|
|
|
|
|
|
|
|
hostname = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Hostname at which this server is accessible.";
|
|
|
|
};
|
|
|
|
|
|
|
|
port = mkOption {
|
|
|
|
type = port;
|
|
|
|
description = "Port on which to listen for Lemmy connections.";
|
|
|
|
default = 8536;
|
|
|
|
};
|
|
|
|
|
|
|
|
version = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Lemmy version.";
|
|
|
|
};
|
|
|
|
|
|
|
|
state-directory = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Directory at which to store application state.";
|
|
|
|
};
|
|
|
|
|
2023-07-08 09:43:21 -07:00
|
|
|
smtp-server = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "SMTP server to use for outgoing messages.";
|
|
|
|
};
|
|
|
|
|
2023-07-07 22:11:33 -07:00
|
|
|
docker-images = {
|
|
|
|
lemmy = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Docker image to use for Lemmy.";
|
2023-07-07 22:33:11 -07:00
|
|
|
default =
|
|
|
|
"dessalines/lemmy:${toplevel.config.services.lemmyDocker.version}";
|
2023-07-07 22:11:33 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
lemmy-ui = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Docker image to use for Lemmy UI.";
|
2023-07-07 22:33:11 -07:00
|
|
|
default =
|
|
|
|
"dessalines/lemmy-ui:${toplevel.config.services.lemmyDocker.version}";
|
2023-07-07 22:11:33 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
pictrs = mkOption {
|
|
|
|
type = str;
|
2023-07-07 22:33:11 -07:00
|
|
|
description = "Docker image to use for PictRS.";
|
2023-07-07 22:11:33 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
postgres = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Docker image to use for Postgres.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable (let
|
|
|
|
postgresPasswd =
|
|
|
|
readFile (pkgs.lib.passwd.random-passwd-file "lemmy-postgres-passwd" 30);
|
|
|
|
pictrsApiKey =
|
|
|
|
readFile (pkgs.lib.passwd.random-passwd-file "lemmy-pictrs-api-key" 30);
|
|
|
|
in {
|
2023-07-07 23:10:46 -07:00
|
|
|
fudo.secrets.host-secrets."${config.instance.hostname}" = {
|
2023-07-16 10:48:07 -07:00
|
|
|
lemmyPictrsEnv = {
|
|
|
|
source-file = makeEnvFile {
|
2023-07-07 22:11:33 -07:00
|
|
|
PICTRS_OPENTELEMETRY_URL = "http://otel:4137";
|
|
|
|
PICTRS__MEDIA__VIDEO_CODEC = "vp9";
|
|
|
|
PICTRS__MEDIA__GIF__MAX_WIDTH = "256";
|
|
|
|
PICTRS__MEDIA__GIF__MAX_HEIGHT = "256";
|
|
|
|
PICTRS__MEDIA__GIF__MAX_AREA = "65536";
|
|
|
|
PICTRS__MEDIA__GIF__MAX_FRAME_COUNT = "400";
|
2023-07-16 10:48:07 -07:00
|
|
|
RUST_LOG = "debug";
|
2023-07-16 16:55:37 -07:00
|
|
|
RUST_BACKTRACE = "full";
|
2023-07-16 11:32:24 -07:00
|
|
|
PICTRS__API_KEY = pictrsApiKey;
|
2023-07-16 10:48:07 -07:00
|
|
|
};
|
|
|
|
target-file = "/run/lemmy/pictrs.env";
|
|
|
|
};
|
|
|
|
lemmyPostgresEnv = {
|
|
|
|
source-file = makeEnvFile {
|
2023-07-07 22:11:33 -07:00
|
|
|
POSTGRES_USER = "lemmy";
|
2023-07-16 10:48:07 -07:00
|
|
|
POSTGRES_PASSWORD = postgresPasswd;
|
2023-07-07 22:11:33 -07:00
|
|
|
POSTGRES_DB = "lemmy";
|
|
|
|
};
|
2023-07-16 10:48:07 -07:00
|
|
|
target-file = "/run/lemmy/postgres.env";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
virtualisation = {
|
|
|
|
arion = {
|
|
|
|
backend = "podman-socket";
|
|
|
|
projects.lemmy.settings = let
|
|
|
|
lemmyImage = makeLemmyImage {
|
|
|
|
port = cfg.port;
|
|
|
|
stateDirectory = cfg.state-directory;
|
|
|
|
proxyCfg = {
|
|
|
|
image = "nginx:1-alpine";
|
|
|
|
configFile = nginxCfgFile;
|
|
|
|
};
|
|
|
|
lemmyCfg = {
|
|
|
|
image = cfg.docker-images.lemmy;
|
2023-07-16 11:35:55 -07:00
|
|
|
configFile = makeLemmyCfg {
|
2023-07-16 10:48:07 -07:00
|
|
|
inherit (cfg) hostname;
|
|
|
|
inherit postgresPasswd pictrsApiKey;
|
|
|
|
smtpServer = cfg.smtp-server;
|
|
|
|
};
|
2023-07-16 16:55:37 -07:00
|
|
|
envFile = toString (makeEnvFile {
|
|
|
|
RUST_LOG = "warn";
|
|
|
|
RUST_BACKTRACE = "full";
|
|
|
|
});
|
2023-07-16 10:48:07 -07:00
|
|
|
};
|
|
|
|
lemmyUiCfg = {
|
|
|
|
image = cfg.docker-images.lemmy-ui;
|
2023-07-16 11:50:57 -07:00
|
|
|
envFile = makeEnvFile {
|
|
|
|
LEMMY_UI_LEMMY_INTERNAL_HOST = "lemmy:8536";
|
|
|
|
LEMMY_UI_LEMMY_EXTERNAL_HOST = cfg.hostname;
|
|
|
|
LEMMY_UI_HTTPS = true;
|
|
|
|
};
|
2023-07-16 10:48:07 -07:00
|
|
|
};
|
|
|
|
pictrsCfg = {
|
|
|
|
image = cfg.docker-images.pictrs;
|
2023-07-16 12:02:51 -07:00
|
|
|
envFile = hostSecrets.lemmyPictrsEnv.target-file;
|
2023-07-16 10:48:07 -07:00
|
|
|
};
|
|
|
|
postgresCfg = {
|
|
|
|
image = cfg.docker-images.postgres;
|
2023-07-16 12:04:43 -07:00
|
|
|
envFile = hostSecrets.lemmyPostgresEnv.target-file;
|
2023-07-16 10:48:07 -07:00
|
|
|
configFile = postgresCfgFile;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
in { imports = [ lemmyImage ]; };
|
2023-07-07 22:11:33 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
services.nginx = {
|
|
|
|
enable = true;
|
|
|
|
virtualHosts."${cfg.hostname}" = {
|
|
|
|
enableACME = true;
|
|
|
|
forceSSL = true;
|
|
|
|
locations = {
|
|
|
|
"/" = {
|
|
|
|
proxyPass = "http://localhost:${toString cfg.port}";
|
|
|
|
proxyWebsockets = true;
|
|
|
|
extraConfig = ''
|
|
|
|
proxy_set_header Host $host;
|
|
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
|
|
proxy_set_header Connection "Upgrade";
|
|
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|