nixos/castopod: init
This commit is contained in:
parent
17f036f4fb
commit
cf6e43a3dd
4 changed files with 312 additions and 0 deletions
|
@ -41,6 +41,8 @@
|
|||
|
||||
- [GoToSocial](https://gotosocial.org/), an ActivityPub social network server, written in Golang. Available as [services.gotosocial](#opt-services.gotosocial.enable).
|
||||
|
||||
- [Castopod](https://castopod.org/), an open-source hosting platform made for podcasters who want to engage and interact with their audience. Available as [services.castopod](#opt-services.castopod.enable).
|
||||
|
||||
- [Typesense](https://github.com/typesense/typesense), a fast, typo-tolerant search engine for building delightful search experiences. Available as [services.typesense](#opt-services.typesense.enable).
|
||||
|
||||
* [NS-USBLoader](https://github.com/developersu/ns-usbloader/), an all-in-one tool for managing Nintendo Switch homebrew. Available as [programs.ns-usbloader](#opt-programs.ns-usbloader.enable).
|
||||
|
|
|
@ -324,6 +324,7 @@
|
|||
./services/amqp/rabbitmq.nix
|
||||
./services/audio/alsa.nix
|
||||
./services/audio/botamusique.nix
|
||||
./services/audio/castopod.nix
|
||||
./services/audio/gmediarender.nix
|
||||
./services/audio/gonic.nix
|
||||
./services/audio/goxlr-utility.nix
|
||||
|
|
22
nixos/modules/services/audio/castopod.md
Normal file
22
nixos/modules/services/audio/castopod.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Castopod {#module-services-castopod}
|
||||
|
||||
Castopod is an open-source hosting platform made for podcasters who want to engage and interact with their audience.
|
||||
|
||||
## Quickstart {#module-services-castopod-quickstart}
|
||||
|
||||
Use the following configuration to start a public instance of Castopod on `castopod.example.com` domain:
|
||||
|
||||
```nix
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
services.castopod = {
|
||||
enable = true;
|
||||
database.createLocally = true;
|
||||
nginx.virtualHost = {
|
||||
serverName = "castopod.example.com";
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Go to `https://castopod.example.com/cp-install` to create superadmin account after applying the above configuration.
|
287
nixos/modules/services/audio/castopod.nix
Normal file
287
nixos/modules/services/audio/castopod.nix
Normal file
|
@ -0,0 +1,287 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.castopod;
|
||||
fpm = config.services.phpfpm.pools.castopod;
|
||||
|
||||
user = "castopod";
|
||||
stateDirectory = "/var/lib/castopod";
|
||||
|
||||
# https://docs.castopod.org/getting-started/install.html#requirements
|
||||
phpPackage = pkgs.php.withExtensions ({ enabled, all }: with all; [
|
||||
intl
|
||||
curl
|
||||
mbstring
|
||||
gd
|
||||
exif
|
||||
mysqlnd
|
||||
] ++ enabled);
|
||||
in
|
||||
{
|
||||
meta.doc = ./castopod.md;
|
||||
meta.maintainers = with lib.maintainers; [ alexoundos misuzu ];
|
||||
|
||||
options.services = {
|
||||
castopod = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "Castopod");
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.castopod;
|
||||
defaultText = lib.literalMD "pkgs.castopod";
|
||||
description = lib.mdDoc "Which Castopod package to use.";
|
||||
};
|
||||
database = {
|
||||
createLocally = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Create the database and database user locally.
|
||||
'';
|
||||
};
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = lib.mdDoc "Database hostname.";
|
||||
};
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "castopod";
|
||||
description = lib.mdDoc "Database name.";
|
||||
};
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = user;
|
||||
description = lib.mdDoc "Database user.";
|
||||
};
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/run/keys/castopod-dbpassword";
|
||||
description = lib.mdDoc ''
|
||||
A file containing the password corresponding to
|
||||
[](#opt-services.castopod.database.user).
|
||||
'';
|
||||
};
|
||||
};
|
||||
settings = lib.mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ str int bool ]);
|
||||
default = { };
|
||||
example = {
|
||||
"email.protocol" = "smtp";
|
||||
"email.SMTPHost" = "localhost";
|
||||
"email.SMTPUser" = "myuser";
|
||||
"email.fromEmail" = "castopod@example.com";
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
Environment variables used for Castopod.
|
||||
See [](https://code.castopod.org/adaures/castopod/-/blob/main/.env.example)
|
||||
for available environment variables.
|
||||
'';
|
||||
};
|
||||
environmentFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/run/keys/castopod-env";
|
||||
description = lib.mdDoc ''
|
||||
Environment file to inject e.g. secrets into the configuration.
|
||||
See [](https://code.castopod.org/adaures/castopod/-/blob/main/.env.example)
|
||||
for available environment variables.
|
||||
'';
|
||||
};
|
||||
configureNginx = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc "Configure nginx as a reverse proxy for CastoPod.";
|
||||
};
|
||||
localDomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "castopod.example.org";
|
||||
description = lib.mdDoc "The domain serving your CastoPod instance.";
|
||||
};
|
||||
poolSettings = lib.mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ str int bool ]);
|
||||
default = {
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = "32";
|
||||
"pm.start_servers" = "2";
|
||||
"pm.min_spare_servers" = "2";
|
||||
"pm.max_spare_servers" = "4";
|
||||
"pm.max_requests" = "500";
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
Options for Castopod's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.castopod.settings =
|
||||
let
|
||||
sslEnabled = with config.services.nginx.virtualHosts.${cfg.localDomain}; addSSL || forceSSL || onlySSL || enableACME || useACMEHost != null;
|
||||
baseURL = "http${lib.optionalString sslEnabled "s"}://${cfg.localDomain}";
|
||||
in
|
||||
lib.mapAttrs (name: lib.mkDefault) {
|
||||
"app.forceGlobalSecureRequests" = sslEnabled;
|
||||
"app.baseURL" = baseURL;
|
||||
|
||||
"media.baseURL" = "/";
|
||||
"media.root" = "media";
|
||||
"media.storage" = stateDirectory;
|
||||
|
||||
"admin.gateway" = "admin";
|
||||
"auth.gateway" = "auth";
|
||||
|
||||
"database.default.hostname" = cfg.database.hostname;
|
||||
"database.default.database" = cfg.database.name;
|
||||
"database.default.username" = cfg.database.user;
|
||||
"database.default.DBPrefix" = "cp_";
|
||||
|
||||
"cache.handler" = "file";
|
||||
};
|
||||
|
||||
services.phpfpm.pools.castopod = {
|
||||
inherit user;
|
||||
group = config.services.nginx.group;
|
||||
phpPackage = phpPackage;
|
||||
phpOptions = ''
|
||||
# https://code.castopod.org/adaures/castopod/-/blob/main/docker/production/app/uploads.ini
|
||||
file_uploads = On
|
||||
memory_limit = 512M
|
||||
upload_max_filesize = 500M
|
||||
post_max_size = 512M
|
||||
max_execution_time = 300
|
||||
max_input_time = 300
|
||||
'';
|
||||
settings = {
|
||||
"listen.owner" = config.services.nginx.user;
|
||||
"listen.group" = config.services.nginx.group;
|
||||
} // cfg.poolSettings;
|
||||
};
|
||||
|
||||
systemd.services.castopod-setup = {
|
||||
after = lib.optional config.services.mysql.enable "mysql.service";
|
||||
requires = lib.optional config.services.mysql.enable "mysql.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.openssl phpPackage ];
|
||||
script =
|
||||
let
|
||||
envFile = "${stateDirectory}/.env";
|
||||
media = "${cfg.settings."media.storage"}/${cfg.settings."media.root"}";
|
||||
in
|
||||
''
|
||||
mkdir -p ${stateDirectory}/writable/{cache,logs,session,temp,uploads}
|
||||
|
||||
if [ ! -d ${lib.escapeShellArg media} ]; then
|
||||
cp --no-preserve=mode,ownership -r ${cfg.package}/share/castopod/public/media ${lib.escapeShellArg media}
|
||||
fi
|
||||
|
||||
if [ ! -f ${stateDirectory}/salt ]; then
|
||||
openssl rand -base64 33 > ${stateDirectory}/salt
|
||||
fi
|
||||
|
||||
cat <<'EOF' > ${envFile}
|
||||
${lib.generators.toKeyValue { } cfg.settings}
|
||||
EOF
|
||||
|
||||
echo "analytics.salt=$(cat ${stateDirectory}/salt)" >> ${envFile}
|
||||
|
||||
${if (cfg.database.passwordFile != null) then ''
|
||||
echo "database.default.password=$(cat ${lib.escapeShellArg cfg.database.passwordFile})" >> ${envFile}
|
||||
'' else ''
|
||||
echo "database.default.password=" >> ${envFile}
|
||||
''}
|
||||
|
||||
${lib.optionalString (cfg.environmentFile != null) ''
|
||||
cat ${lib.escapeShellArg cfg.environmentFile}) >> ${envFile}
|
||||
''}
|
||||
|
||||
php spark castopod:database-update
|
||||
'';
|
||||
serviceConfig = {
|
||||
StateDirectory = "castopod";
|
||||
WorkingDirectory = "${cfg.package}/share/castopod";
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
User = user;
|
||||
Group = config.services.nginx.group;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.castopod-scheduled = {
|
||||
after = [ "castopod-setup.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ phpPackage ];
|
||||
script = ''
|
||||
php public/index.php scheduled-activities
|
||||
php public/index.php scheduled-websub-publish
|
||||
php public/index.php scheduled-video-clips
|
||||
'';
|
||||
serviceConfig = {
|
||||
StateDirectory = "castopod";
|
||||
WorkingDirectory = "${cfg.package}/share/castopod";
|
||||
Type = "oneshot";
|
||||
User = user;
|
||||
Group = config.services.nginx.group;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.castopod-scheduled = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* *:*:00";
|
||||
Unit = "castopod-scheduled.service";
|
||||
};
|
||||
};
|
||||
|
||||
services.mysql = lib.mkIf cfg.database.createLocally {
|
||||
enable = true;
|
||||
package = lib.mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [{
|
||||
name = cfg.database.user;
|
||||
ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
|
||||
}];
|
||||
};
|
||||
|
||||
services.nginx = lib.mkIf cfg.configureNginx {
|
||||
enable = true;
|
||||
virtualHosts."${cfg.localDomain}" = {
|
||||
root = lib.mkForce "${cfg.package}/share/castopod/public";
|
||||
|
||||
extraConfig = ''
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
index index.php index.html;
|
||||
'';
|
||||
|
||||
locations."^~ /${cfg.settings."media.root"}/" = {
|
||||
root = cfg.settings."media.storage";
|
||||
extraConfig = ''
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
expires max;
|
||||
access_log off;
|
||||
'';
|
||||
};
|
||||
|
||||
locations."~ \.php$" = {
|
||||
fastcgiParams = {
|
||||
SERVER_NAME = "$host";
|
||||
};
|
||||
extraConfig = ''
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_pass unix:${fpm.socket};
|
||||
try_files $uri =404;
|
||||
fastcgi_read_timeout 3600;
|
||||
fastcgi_send_timeout 3600;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users.users.${user} = lib.mapAttrs (name: lib.mkDefault) {
|
||||
description = "Castopod user";
|
||||
isSystemUser = true;
|
||||
group = config.services.nginx.group;
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue