diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index e9d13cc3c265..8c50807caade 100644 --- a/nixos/doc/manual/release-notes/rl-2405.section.md +++ b/nixos/doc/manual/release-notes/rl-2405.section.md @@ -94,6 +94,8 @@ Use `services.pipewire.extraConfig` or `services.pipewire.configPackages` for Pi - [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable). +- [Flarum](https://flarum.org/), a delightfully simple discussion platform for your website. Available as [services.flarum](#opt-services.flarum.enable). + - [PhotonVision](https://photonvision.org/), a free, fast, and easy-to-use computer vision solution for the FIRSTĀ® Robotics Competition. - [clatd](https://github.com/toreanderson/clatd), a CLAT / SIIT-DC Edge Relay implementation for Linux. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3cbb4617517a..93f25f6ced31 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1347,6 +1347,7 @@ ./services/web-apps/engelsystem.nix ./services/web-apps/ethercalc.nix ./services/web-apps/firefly-iii.nix + ./services/web-apps/flarum.nix ./services/web-apps/fluidd.nix ./services/web-apps/freshrss.nix ./services/web-apps/galene.nix diff --git a/nixos/modules/services/web-apps/flarum.nix b/nixos/modules/services/web-apps/flarum.nix new file mode 100644 index 000000000000..a967c3b121bd --- /dev/null +++ b/nixos/modules/services/web-apps/flarum.nix @@ -0,0 +1,210 @@ +{ pkgs, lib, config, ... }: + +with lib; + +let + cfg = config.services.flarum; + + flarumInstallConfig = pkgs.writeText "config.json" (builtins.toJSON { + debug = false; + offline = false; + + baseUrl = cfg.baseUrl; + databaseConfiguration = cfg.database; + adminUser = { + username = cfg.adminUser; + password = cfg.initialAdminPassword; + email = cfg.adminEmail; + }; + settings = { + forum_title = cfg.forumTitle; + }; + }); +in { + options.services.flarum = { + enable = mkEnableOption "Flarum discussion platform"; + + package = mkPackageOption pkgs "flarum" { }; + + forumTitle = mkOption { + type = types.str; + default = "A Flarum Forum on NixOS"; + description = "Title of the forum."; + }; + + domain = mkOption { + type = types.str; + default = "localhost"; + example = "forum.example.com"; + description = "Domain to serve on."; + }; + + baseUrl = mkOption { + type = types.str; + default = "http://localhost"; + example = "https://forum.example.com"; + description = "Change `domain` instead."; + }; + + adminUser = mkOption { + type = types.str; + default = "flarum"; + description = "Username for first web application administrator"; + }; + + adminEmail = mkOption { + type = types.str; + default = "admin@example.com"; + description = "Email for first web application administrator"; + }; + + initialAdminPassword = mkOption { + type = types.str; + default = "flarum"; + description = "Initial password for the adminUser"; + }; + + user = mkOption { + type = types.str; + default = "flarum"; + description = "System user to run Flarum"; + }; + + group = mkOption { + type = types.str; + default = "flarum"; + description = "System group to run Flarum"; + }; + + stateDir = mkOption { + type = types.path; + default = "/var/lib/flarum"; + description = "Home directory for writable storage"; + }; + + database = mkOption rec { + type = with types; attrsOf (oneOf [str bool int]); + description = "MySQL database parameters"; + default = { + # the database driver; i.e. MySQL; MariaDB... + driver = "mysql"; + # the host of the connection; localhost in most cases unless using an external service + host = "localhost"; + # the name of the database in the instance + database = "flarum"; + # database username + username = "flarum"; + # database password + password = ""; + # the prefix for the tables; useful if you are sharing the same database with another service + prefix = ""; + # the port of the connection; defaults to 3306 with MySQL + port = 3306; + strict = false; + }; + }; + + createDatabaseLocally = mkOption { + type = types.bool; + default = true; + description = "Create the database and database user locally, and run installation."; + }; + }; + + config = mkIf cfg.enable { + users.users.${cfg.user} = { + isSystemUser = true; + home = cfg.stateDir; + createHome = true; + group = cfg.group; + }; + users.groups.${cfg.group} = {}; + + services.phpfpm.pools.flarum = { + user = cfg.user; + settings = { + "listen.owner" = config.services.nginx.user; + "listen.group" = config.services.nginx.group; + "listen.mode" = "0600"; + "pm" = mkDefault "dynamic"; + "pm.max_children" = mkDefault 10; + "pm.max_requests" = mkDefault 500; + "pm.start_servers" = mkDefault 2; + "pm.min_spare_servers" = mkDefault 1; + "pm.max_spare_servers" = mkDefault 3; + }; + phpOptions = '' + error_log = syslog + log_errors = on + ''; + }; + + services.nginx = { + enable = true; + virtualHosts."${cfg.domain}" = { + root = "${cfg.stateDir}/public"; + locations."~ \.php$".extraConfig = '' + fastcgi_pass unix:${config.services.phpfpm.pools.flarum.socket}; + fastcgi_index site.php; + ''; + extraConfig = '' + index index.php; + include ${cfg.package}/share/php/flarum/.nginx.conf; + ''; + }; + }; + + services.mysql = mkIf cfg.enable { + enable = true; + package = pkgs.mysql; + ensureDatabases = [cfg.database.database]; + ensureUsers = [ + { + name = cfg.database.username; + ensurePermissions = { + "${cfg.database.database}.*" = "ALL PRIVILEGES"; + }; + } + ]; + }; + + assertions = [ + { + assertion = !cfg.createDatabaseLocally || cfg.database.driver == "mysql"; + message = "Flarum can only be automatically installed in MySQL/MariaDB."; + } + ]; + + systemd.services.flarum-install = { + description = "Flarum installation"; + requiredBy = ["phpfpm-flarum.service"]; + before = ["phpfpm-flarum.service"]; + requires = ["mysql.service"]; + after = ["mysql.service"]; + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.group; + }; + path = [config.services.phpfpm.phpPackage]; + script = '' + mkdir -p ${cfg.stateDir}/{extensions,public/assets/avatars} + mkdir -p ${cfg.stateDir}/storage/{cache,formatter,sessions,views} + cd ${cfg.stateDir} + cp -f ${cfg.package}/share/php/flarum/{extend.php,site.php,flarum} . + ln -sf ${cfg.package}/share/php/flarum/vendor . + ln -sf ${cfg.package}/share/php/flarum/public/index.php public/ + chmod a+x . public + chmod +x site.php extend.php flarum + '' + optionalString (cfg.createDatabaseLocally && cfg.database.driver == "mysql") '' + if [ ! -f config.php ]; then + php flarum install --file=${flarumInstallConfig} + fi + php flarum migrate + php flarum cache:clear + ''; + }; + }; + + meta.maintainers = with lib.maintainers; [ fsagbuya jasonodoom ]; +}