-
Notifications
You must be signed in to change notification settings - Fork 345
Declarative installation on NixOS
Jan Tojnar edited this page May 12, 2024
·
6 revisions
NixOS contains a module for installing selfoss as a PHP-FPM service.
By default the module assumes a nginx server so we will need to set it up too.
{ config, lib, pkgs, ... }:
{
networking.firewall.allowedTCPPorts = [
80
443
];
services = {
nginx = {
enable = true;
virtualHosts = {
"reader.example.org" = {
root = "/var/lib/selfoss"; # hardcoded in the module
extraConfig = ''
include /var/lib/selfoss/.nginx.conf;
location ~ \.php$ {
fastcgi_pass unix:${config.services.phpfpm.pools.${config.services.selfoss.pool}.socket};
include ${config.services.nginx.package}/conf/fastcgi.conf;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
}
'';
};
};
};
selfoss = {
enable = true;
};
};
}
You can also choose a different database engine using services.selfoss.database
option or specify any other settings in services.selfoss.extraConfig
.
The module however installs selfoss into mutable /var/lib/selfoss
which can potentially be exploited. Additionally, it runs a stable version of selfoss, but we might want to install development build to get the latest and greatest features.
We will leave downloading and installing selfoss to Nix. selfoss will be loaded from a read-only directory in Nix store so data will need to be written to a different location. We will use systemd for that.
{ stdenv
, fetchurl
, lib
, unzip
}:
stdenv.mkDerivation (finalAttrs: {
pname = "selfoss";
version = "2.20-2429274";
src = fetchurl {
url = "https://dl.cloudsmith.io/public/fossar/selfoss-git/raw/names/selfoss.zip/versions/${finalAttrs.version}/selfoss-${finalAttrs.version}.zip";
hash = "sha256-4/qxXL5RGW+h9swcxP1fwMQqkwu3lhPqT40MVgjJz5M=";
};
nativeBuildInputs = [
unzip
];
installPhase = ''
runHook preInstall
cp -r . $out
runHook postInstall
'';
meta = {
description = "Multipurpose RSS reader and aggregation web app";
homepage = "https://selfoss.aditu.de";
license = lib.licenses.gpl3Only;
maintainers = with lib.maintainers; [ jtojnar ];
platforms = lib.platforms.all;
};
})
{ config, lib, pkgs, ... }:
let
settings = {
username = "myname";
password = "$2y$10$V5mUC2qhO4hGaiIi/d.IhOAuTu6PYAwHvIDI5FjrhakOPo1XA4hz6";
auto_mark_as_read = true;
share = "p";
homepage = "unread";
datadir = "/var/lib/selfoss";
logger_destination = "file:php://stderr";
logger_level = "DEBUG";
debug = "1"; # extra logging info
base_url = "https://reader.example.org/";
items_lifetime = "9999";
};
settingsEnv = lib.mapAttrs' (name: value: lib.nameValuePair "selfoss_${name}" value) settings;
# Modify the upstream nginx config to point to our mutable datadir.
nginxConf =
pkgs.runCommand
"selfoss.nginx.conf"
{
src = "${pkgs.selfoss}/.nginx.conf";
}
''
substitute "$src" "$out" \
--replace 'try_files $uri /data/$uri;' 'root ${settings.datadir};'
'';
in {
networking.firewall.allowedTCPPorts = [
80
443
];
services = {
nginx = {
enable = true;
virtualHosts = {
"reader.example.org" = {
root = pkgs.selfoss;
extraConfig = ''
include ${nginxConf};
location ~ \.php$ {
fastcgi_pass unix:${config.services.phpfpm.pools.reader.socket};
include ${config.services.nginx.package}/conf/fastcgi.conf;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
}
'';
};
};
};
phpfpm = rec {
pools = {
reader = {
user = "reader";
settings = {
"listen.owner" = "nginx";
"listen.group" = "root";
"pm" = "dynamic";
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
# push stderr output to journal
"catch_workers_output" = true;
# Accept settings from the systemd service.
"clear_env" = false;
};
phpOptions = ''
; Set up $_ENV superglobal.
; https://php.net/request-order
variables_order = "EGPCS"
'';
};
};
};
};
users = {
users = {
nginx.extraGroups = [
"reader"
];
reader = { uid = 501; group = "reader"; isSystemUser = true; };
};
groups = {
reader = { gid = 501; };
};
};
# I was not able to pass the variables through services.phpfpm.pools.reader.phpEnv:
# https://github.com/NixOS/nixpkgs/issues/79469#issuecomment-631461513
systemd.services.phpfpm-reader.environment = settingsEnv;
systemd.services.phpfpm-reader.serviceConfig.StateDirectory = "selfoss"; # TODO: make it create cache, sqlite, thumbnails and favicons subdirectories.
systemd.services.selfoss-update = {
serviceConfig = {
ExecStart = "${pkgs.php}/bin/php ${pkgs.selfoss}/cliupdate.php";
User = "reader";
StateDirectory = "selfoss";
};
environment = settingsEnv;
startAt = "hourly";
wantedBy = [ "multi-user.target" ];
};
nixpkgs.overlays = [
(final: prev: {
# Let’s use latest development build selfoss instead of the stable version from Nixpkgs.
selfoss = prev.callPackage ./selfoss.nix { };
})
];
}