diff options
Diffstat (limited to 'nixos/modules/services/web-apps')
-rw-r--r-- | nixos/modules/services/web-apps/akkoma.md | 284 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/discourse.md | 218 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/gotosocial.md | 52 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/keycloak.md | 22 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/lemmy.md | 14 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/pict-rs.md | 4 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/suwayomi-server.md | 2 |
7 files changed, 318 insertions, 278 deletions
diff --git a/nixos/modules/services/web-apps/akkoma.md b/nixos/modules/services/web-apps/akkoma.md index 83dd1a8b35f23..13b074b228a41 100644 --- a/nixos/modules/services/web-apps/akkoma.md +++ b/nixos/modules/services/web-apps/akkoma.md @@ -19,21 +19,23 @@ be run behind a HTTP proxy on `fediverse.example.com`. ```nix -services.akkoma.enable = true; -services.akkoma.config = { - ":pleroma" = { - ":instance" = { - name = "My Akkoma instance"; - description = "More detailed description"; - email = "admin@example.com"; - registration_open = false; - }; - - "Pleroma.Web.Endpoint" = { - url.host = "fediverse.example.com"; +{ + services.akkoma.enable = true; + services.akkoma.config = { + ":pleroma" = { + ":instance" = { + name = "My Akkoma instance"; + description = "More detailed description"; + email = "admin@example.com"; + registration_open = false; + }; + + "Pleroma.Web.Endpoint" = { + url.host = "fediverse.example.com"; + }; }; }; -}; +} ``` Please refer to the [configuration cheat sheet](https://docs.akkoma.dev/stable/configuration/cheatsheet/) @@ -55,19 +57,21 @@ Although it is possible to expose Akkoma directly, it is common practice to oper HTTP reverse proxy such as nginx. ```nix -services.akkoma.nginx = { - enableACME = true; - forceSSL = true; -}; - -services.nginx = { - enable = true; - - clientMaxBodySize = "16m"; - recommendedTlsSettings = true; - recommendedOptimisation = true; - recommendedGzipSettings = true; -}; +{ + services.akkoma.nginx = { + enableACME = true; + forceSSL = true; + }; + + services.nginx = { + enable = true; + + clientMaxBodySize = "16m"; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + }; +} ``` Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate. @@ -78,51 +82,53 @@ Without the media proxy function, Akkoma does not store any remote media like pi locally, and clients have to fetch them directly from the source server. ```nix -# Enable nginx slice module distributed with Tengine -services.nginx.package = pkgs.tengine; - -# Enable media proxy -services.akkoma.config.":pleroma".":media_proxy" = { - enabled = true; - proxy_opts.redirect_on_failure = true; -}; - -# Adjust the persistent cache size as needed: -# Assuming an average object size of 128 KiB, around 1 MiB -# of memory is required for the key zone per GiB of cache. -# Ensure that the cache directory exists and is writable by nginx. -services.nginx.commonHttpConfig = '' - proxy_cache_path /var/cache/nginx/cache/akkoma-media-cache - levels= keys_zone=akkoma_media_cache:16m max_size=16g - inactive=1y use_temp_path=off; -''; - -services.akkoma.nginx = { - locations."/proxy" = { - proxyPass = "http://unix:/run/akkoma/socket"; - - extraConfig = '' - proxy_cache akkoma_media_cache; - - # Cache objects in slices of 1 MiB - slice 1m; - proxy_cache_key $host$uri$is_args$args$slice_range; - proxy_set_header Range $slice_range; - - # Decouple proxy and upstream responses - proxy_buffering on; - proxy_cache_lock on; - proxy_ignore_client_abort on; - - # Default cache times for various responses - proxy_cache_valid 200 1y; - proxy_cache_valid 206 301 304 1h; - - # Allow serving of stale items - proxy_cache_use_stale error timeout invalid_header updating; - ''; +{ + # Enable nginx slice module distributed with Tengine + services.nginx.package = pkgs.tengine; + + # Enable media proxy + services.akkoma.config.":pleroma".":media_proxy" = { + enabled = true; + proxy_opts.redirect_on_failure = true; }; -}; + + # Adjust the persistent cache size as needed: + # Assuming an average object size of 128 KiB, around 1 MiB + # of memory is required for the key zone per GiB of cache. + # Ensure that the cache directory exists and is writable by nginx. + services.nginx.commonHttpConfig = '' + proxy_cache_path /var/cache/nginx/cache/akkoma-media-cache + levels= keys_zone=akkoma_media_cache:16m max_size=16g + inactive=1y use_temp_path=off; + ''; + + services.akkoma.nginx = { + locations."/proxy" = { + proxyPass = "http://unix:/run/akkoma/socket"; + + extraConfig = '' + proxy_cache akkoma_media_cache; + + # Cache objects in slices of 1 MiB + slice 1m; + proxy_cache_key $host$uri$is_args$args$slice_range; + proxy_set_header Range $slice_range; + + # Decouple proxy and upstream responses + proxy_buffering on; + proxy_cache_lock on; + proxy_ignore_client_abort on; + + # Default cache times for various responses + proxy_cache_valid 200 1y; + proxy_cache_valid 206 301 304 1h; + + # Allow serving of stale items + proxy_cache_use_stale error timeout invalid_header updating; + ''; + }; + }; +} ``` #### Prefetch remote media {#modules-services-akkoma-prefetch-remote-media} @@ -132,10 +138,12 @@ fetches all media associated with a post through the media proxy, as soon as the received by the instance. ```nix -services.akkoma.config.":pleroma".":mrf".policies = - map (pkgs.formats.elixirConf { }).lib.mkRaw [ - "Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy" -]; +{ + services.akkoma.config.":pleroma".":mrf".policies = + map (pkgs.formats.elixirConf { }).lib.mkRaw [ + "Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy" + ]; +} ``` #### Media previews {#modules-services-akkoma-media-previews} @@ -143,11 +151,13 @@ services.akkoma.config.":pleroma".":mrf".policies = Akkoma can generate previews for media. ```nix -services.akkoma.config.":pleroma".":media_preview_proxy" = { - enabled = true; - thumbnail_max_width = 1920; - thumbnail_max_height = 1080; -}; +{ + services.akkoma.config.":pleroma".":media_preview_proxy" = { + enabled = true; + thumbnail_max_width = 1920; + thumbnail_max_height = 1080; + }; +} ``` ## Frontend management {#modules-services-akkoma-frontend-management} @@ -160,29 +170,31 @@ The following example overrides the primary frontend’s default configuration u derivation. ```nix -services.akkoma.frontends.primary.package = pkgs.runCommand "akkoma-fe" { - config = builtins.toJSON { - expertLevel = 1; - collapseMessageWithSubject = false; - stopGifs = false; - replyVisibility = "following"; - webPushHideIfCW = true; - hideScopeNotice = true; - renderMisskeyMarkdown = false; - hideSiteFavicon = true; - postContentType = "text/markdown"; - showNavShortcuts = false; - }; - nativeBuildInputs = with pkgs; [ jq xorg.lndir ]; - passAsFile = [ "config" ]; -} '' - mkdir $out - lndir ${pkgs.akkoma-frontends.akkoma-fe} $out - - rm $out/static/config.json - jq -s add ${pkgs.akkoma-frontends.akkoma-fe}/static/config.json ${config} \ - >$out/static/config.json -''; +{ + services.akkoma.frontends.primary.package = pkgs.runCommand "akkoma-fe" { + config = builtins.toJSON { + expertLevel = 1; + collapseMessageWithSubject = false; + stopGifs = false; + replyVisibility = "following"; + webPushHideIfCW = true; + hideScopeNotice = true; + renderMisskeyMarkdown = false; + hideSiteFavicon = true; + postContentType = "text/markdown"; + showNavShortcuts = false; + }; + nativeBuildInputs = with pkgs; [ jq xorg.lndir ]; + passAsFile = [ "config" ]; + } '' + mkdir $out + lndir ${pkgs.akkoma-frontends.akkoma-fe} $out + + rm $out/static/config.json + jq -s add ${pkgs.akkoma-frontends.akkoma-fe}/static/config.json ${config} \ + >$out/static/config.json + ''; +} ``` ## Federation policies {#modules-services-akkoma-federation-policies} @@ -198,28 +210,30 @@ of the fediverse and providing a pleasant experience to the users of an instance ```nix -services.akkoma.config.":pleroma" = with (pkgs.formats.elixirConf { }).lib; { - ":mrf".policies = map mkRaw [ - "Pleroma.Web.ActivityPub.MRF.SimplePolicy" - ]; - - ":mrf_simple" = { - # Tag all media as sensitive - media_nsfw = mkMap { - "nsfw.weird.kinky" = "Untagged NSFW content"; - }; - - # Reject all activities except deletes - reject = mkMap { - "kiwifarms.cc" = "Persistent harassment of users, no moderation"; - }; - - # Force posts to be visible by followers only - followers_only = mkMap { - "beta.birdsite.live" = "Avoid polluting timelines with Twitter posts"; +{ + services.akkoma.config.":pleroma" = with (pkgs.formats.elixirConf { }).lib; { + ":mrf".policies = map mkRaw [ + "Pleroma.Web.ActivityPub.MRF.SimplePolicy" + ]; + + ":mrf_simple" = { + # Tag all media as sensitive + media_nsfw = mkMap { + "nsfw.weird.kinky" = "Untagged NSFW content"; + }; + + # Reject all activities except deletes + reject = mkMap { + "kiwifarms.cc" = "Persistent harassment of users, no moderation"; + }; + + # Force posts to be visible by followers only + followers_only = mkMap { + "beta.birdsite.live" = "Avoid polluting timelines with Twitter posts"; + }; }; }; -}; +} ``` ## Upload filters {#modules-services-akkoma-upload-filters} @@ -228,12 +242,14 @@ This example strips GPS and location metadata from uploads, deduplicates them an the file name. ```nix -services.akkoma.config.":pleroma"."Pleroma.Upload".filters = - map (pkgs.formats.elixirConf { }).lib.mkRaw [ - "Pleroma.Upload.Filter.Exiftool" - "Pleroma.Upload.Filter.Dedupe" - "Pleroma.Upload.Filter.AnonymizeFilename" - ]; +{ + services.akkoma.config.":pleroma"."Pleroma.Upload".filters = + map (pkgs.formats.elixirConf { }).lib.mkRaw [ + "Pleroma.Upload.Filter.Exiftool" + "Pleroma.Upload.Filter.Dedupe" + "Pleroma.Upload.Filter.AnonymizeFilename" + ]; +} ``` ## Migration from Pleroma {#modules-services-akkoma-migration-pleroma} @@ -286,9 +302,11 @@ To re‐use the Pleroma data in place, disable Pleroma and enable Akkoma, pointi Pleroma database and upload directory. ```nix -# Adjust these settings according to the database name and upload directory path used by Pleroma -services.akkoma.config.":pleroma"."Pleroma.Repo".database = "pleroma"; -services.akkoma.config.":pleroma".":instance".upload_dir = "/var/lib/pleroma/uploads"; +{ + # Adjust these settings according to the database name and upload directory path used by Pleroma + services.akkoma.config.":pleroma"."Pleroma.Repo".database = "pleroma"; + services.akkoma.config.":pleroma".":instance".upload_dir = "/var/lib/pleroma/uploads"; +} ``` Please keep in mind that after the Akkoma service has been started, any migrations applied by @@ -304,7 +322,9 @@ details. The Akkoma systemd service may be confined to a chroot with ```nix -services.systemd.akkoma.confinement.enable = true; +{ + services.systemd.akkoma.confinement.enable = true; +} ``` Confinement of services is not generally supported in NixOS and therefore disabled by default. diff --git a/nixos/modules/services/web-apps/discourse.md b/nixos/modules/services/web-apps/discourse.md index 799a01c6ff5b3..d4b9c93c4ead0 100644 --- a/nixos/modules/services/web-apps/discourse.md +++ b/nixos/modules/services/web-apps/discourse.md @@ -7,19 +7,21 @@ modern and open source discussion platform. A minimal configuration using Let's Encrypt for TLS certificates looks like this: ```nix -services.discourse = { - enable = true; - hostname = "discourse.example.com"; - admin = { - email = "admin@example.com"; - username = "admin"; - fullName = "Administrator"; - passwordFile = "/path/to/password_file"; +{ + services.discourse = { + enable = true; + hostname = "discourse.example.com"; + admin = { + email = "admin@example.com"; + username = "admin"; + fullName = "Administrator"; + passwordFile = "/path/to/password_file"; + }; + secretKeyBaseFile = "/path/to/secret_key_base_file"; }; - secretKeyBaseFile = "/path/to/secret_key_base_file"; -}; -security.acme.email = "me@example.com"; -security.acme.acceptTerms = true; + security.acme.email = "me@example.com"; + security.acme.acceptTerms = true; +} ``` Provided a proper DNS setup, you'll be able to connect to the @@ -35,19 +37,21 @@ and [](#opt-services.discourse.sslCertificateKey) options: ```nix -services.discourse = { - enable = true; - hostname = "discourse.example.com"; - sslCertificate = "/path/to/ssl_certificate"; - sslCertificateKey = "/path/to/ssl_certificate_key"; - admin = { - email = "admin@example.com"; - username = "admin"; - fullName = "Administrator"; - passwordFile = "/path/to/password_file"; +{ + services.discourse = { + enable = true; + hostname = "discourse.example.com"; + sslCertificate = "/path/to/ssl_certificate"; + sslCertificateKey = "/path/to/ssl_certificate_key"; + admin = { + email = "admin@example.com"; + username = "admin"; + fullName = "Administrator"; + passwordFile = "/path/to/password_file"; + }; + secretKeyBaseFile = "/path/to/secret_key_base_file"; }; - secretKeyBaseFile = "/path/to/secret_key_base_file"; -}; +} ``` ## Database access {#module-services-discourse-database} @@ -81,26 +85,28 @@ A basic setup which assumes you want to use your configured email domain can be done like this: ```nix -services.discourse = { - enable = true; - hostname = "discourse.example.com"; - sslCertificate = "/path/to/ssl_certificate"; - sslCertificateKey = "/path/to/ssl_certificate_key"; - admin = { - email = "admin@example.com"; - username = "admin"; - fullName = "Administrator"; - passwordFile = "/path/to/password_file"; - }; - mail.outgoing = { - serverAddress = "smtp.emailprovider.com"; - port = 587; - username = "user@emailprovider.com"; - passwordFile = "/path/to/smtp_password_file"; +{ + services.discourse = { + enable = true; + hostname = "discourse.example.com"; + sslCertificate = "/path/to/ssl_certificate"; + sslCertificateKey = "/path/to/ssl_certificate_key"; + admin = { + email = "admin@example.com"; + username = "admin"; + fullName = "Administrator"; + passwordFile = "/path/to/password_file"; + }; + mail.outgoing = { + serverAddress = "smtp.emailprovider.com"; + port = 587; + username = "user@emailprovider.com"; + passwordFile = "/path/to/smtp_password_file"; + }; + mail.incoming.enable = true; + secretKeyBaseFile = "/path/to/secret_key_base_file"; }; - mail.incoming.enable = true; - secretKeyBaseFile = "/path/to/secret_key_base_file"; -}; +} ``` This assumes you have set up an MX record for the address you've @@ -163,43 +169,45 @@ Discourse instance and enables GitHub login in the site settings, and changes a few request limits in the backend settings: ```nix -services.discourse = { - enable = true; - hostname = "discourse.example.com"; - sslCertificate = "/path/to/ssl_certificate"; - sslCertificateKey = "/path/to/ssl_certificate_key"; - admin = { - email = "admin@example.com"; - username = "admin"; - fullName = "Administrator"; - passwordFile = "/path/to/password_file"; - }; - mail.outgoing = { - serverAddress = "smtp.emailprovider.com"; - port = 587; - username = "user@emailprovider.com"; - passwordFile = "/path/to/smtp_password_file"; - }; - mail.incoming.enable = true; - siteSettings = { - required = { - title = "My Cats"; - site_description = "Discuss My Cats (and be nice plz)"; +{ + services.discourse = { + enable = true; + hostname = "discourse.example.com"; + sslCertificate = "/path/to/ssl_certificate"; + sslCertificateKey = "/path/to/ssl_certificate_key"; + admin = { + email = "admin@example.com"; + username = "admin"; + fullName = "Administrator"; + passwordFile = "/path/to/password_file"; }; - login = { - enable_github_logins = true; - github_client_id = "a2f6dfe838cb3206ce20"; - github_client_secret._secret = /run/keys/discourse_github_client_secret; + mail.outgoing = { + serverAddress = "smtp.emailprovider.com"; + port = 587; + username = "user@emailprovider.com"; + passwordFile = "/path/to/smtp_password_file"; }; + mail.incoming.enable = true; + siteSettings = { + required = { + title = "My Cats"; + site_description = "Discuss My Cats (and be nice plz)"; + }; + login = { + enable_github_logins = true; + github_client_id = "a2f6dfe838cb3206ce20"; + github_client_secret._secret = /run/keys/discourse_github_client_secret; + }; + }; + backendSettings = { + max_reqs_per_ip_per_minute = 300; + max_reqs_per_ip_per_10_seconds = 60; + max_asset_reqs_per_ip_per_10_seconds = 250; + max_reqs_per_ip_mode = "warn+block"; + }; + secretKeyBaseFile = "/path/to/secret_key_base_file"; }; - backendSettings = { - max_reqs_per_ip_per_minute = 300; - max_reqs_per_ip_per_10_seconds = 60; - max_asset_reqs_per_ip_per_10_seconds = 250; - max_reqs_per_ip_mode = "warn+block"; - }; - secretKeyBaseFile = "/path/to/secret_key_base_file"; -}; +} ``` In the resulting site settings file, the @@ -254,33 +262,35 @@ plugins, and disable `discourse-spoiler-alert` by default: ```nix -services.discourse = { - enable = true; - hostname = "discourse.example.com"; - sslCertificate = "/path/to/ssl_certificate"; - sslCertificateKey = "/path/to/ssl_certificate_key"; - admin = { - email = "admin@example.com"; - username = "admin"; - fullName = "Administrator"; - passwordFile = "/path/to/password_file"; - }; - mail.outgoing = { - serverAddress = "smtp.emailprovider.com"; - port = 587; - username = "user@emailprovider.com"; - passwordFile = "/path/to/smtp_password_file"; - }; - mail.incoming.enable = true; - plugins = with config.services.discourse.package.plugins; [ - discourse-spoiler-alert - discourse-solved - ]; - siteSettings = { - plugins = { - spoiler_enabled = false; +{ + services.discourse = { + enable = true; + hostname = "discourse.example.com"; + sslCertificate = "/path/to/ssl_certificate"; + sslCertificateKey = "/path/to/ssl_certificate_key"; + admin = { + email = "admin@example.com"; + username = "admin"; + fullName = "Administrator"; + passwordFile = "/path/to/password_file"; + }; + mail.outgoing = { + serverAddress = "smtp.emailprovider.com"; + port = 587; + username = "user@emailprovider.com"; + passwordFile = "/path/to/smtp_password_file"; + }; + mail.incoming.enable = true; + plugins = with config.services.discourse.package.plugins; [ + discourse-spoiler-alert + discourse-solved + ]; + siteSettings = { + plugins = { + spoiler_enabled = false; + }; }; + secretKeyBaseFile = "/path/to/secret_key_base_file"; }; - secretKeyBaseFile = "/path/to/secret_key_base_file"; -}; +} ``` diff --git a/nixos/modules/services/web-apps/gotosocial.md b/nixos/modules/services/web-apps/gotosocial.md index a290d7d1893a1..b3540f0d5811f 100644 --- a/nixos/modules/services/web-apps/gotosocial.md +++ b/nixos/modules/services/web-apps/gotosocial.md @@ -8,17 +8,19 @@ The following configuration sets up the PostgreSQL as database backend and binds GoToSocial to `127.0.0.1:8080`, expecting to be run behind a HTTP proxy on `gotosocial.example.com`. ```nix -services.gotosocial = { - enable = true; - setupPostgresqlDB = true; - settings = { - application-name = "My GoToSocial"; - host = "gotosocial.example.com"; - protocol = "https"; - bind-address = "127.0.0.1"; - port = 8080; +{ + services.gotosocial = { + enable = true; + setupPostgresqlDB = true; + settings = { + application-name = "My GoToSocial"; + host = "gotosocial.example.com"; + protocol = "https"; + bind-address = "127.0.0.1"; + port = 8080; + }; }; -}; +} ``` Please refer to the [GoToSocial Documentation](https://docs.gotosocial.org/en/latest/configuration/general/) @@ -30,24 +32,26 @@ Although it is possible to expose GoToSocial directly, it is common practice to HTTP reverse proxy such as nginx. ```nix -networking.firewall.allowedTCPPorts = [ 80 443 ]; -services.nginx = { - enable = true; - clientMaxBodySize = "40M"; - virtualHosts = with config.services.gotosocial.settings; { - "${host}" = { - enableACME = true; - forceSSL = true; - locations = { - "/" = { - recommendedProxySettings = true; - proxyWebsockets = true; - proxyPass = "http://${bind-address}:${toString port}"; +{ + networking.firewall.allowedTCPPorts = [ 80 443 ]; + services.nginx = { + enable = true; + clientMaxBodySize = "40M"; + virtualHosts = with config.services.gotosocial.settings; { + "${host}" = { + enableACME = true; + forceSSL = true; + locations = { + "/" = { + recommendedProxySettings = true; + proxyWebsockets = true; + proxyPass = "http://${bind-address}:${toString port}"; + }; }; }; }; }; -}; +} ``` Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate. diff --git a/nixos/modules/services/web-apps/keycloak.md b/nixos/modules/services/web-apps/keycloak.md index 2ab6e96e5e6ed..020bee4003489 100644 --- a/nixos/modules/services/web-apps/keycloak.md +++ b/nixos/modules/services/web-apps/keycloak.md @@ -127,15 +127,17 @@ should be set to. See the description of A basic configuration with some custom settings could look like this: ```nix -services.keycloak = { - enable = true; - settings = { - hostname = "keycloak.example.com"; - hostname-strict-backchannel = true; +{ + services.keycloak = { + enable = true; + settings = { + hostname = "keycloak.example.com"; + hostname-strict-backchannel = true; + }; + initialAdminPassword = "e6Wcm0RrtegMEHl"; # change on first login + sslCertificate = "/run/keys/ssl_cert"; + sslCertificateKey = "/run/keys/ssl_key"; + database.passwordFile = "/run/keys/db_password"; }; - initialAdminPassword = "e6Wcm0RrtegMEHl"; # change on first login - sslCertificate = "/run/keys/ssl_cert"; - sslCertificateKey = "/run/keys/ssl_key"; - database.passwordFile = "/run/keys/db_password"; -}; +} ``` diff --git a/nixos/modules/services/web-apps/lemmy.md b/nixos/modules/services/web-apps/lemmy.md index faafe096d1382..0ed23607d00b9 100644 --- a/nixos/modules/services/web-apps/lemmy.md +++ b/nixos/modules/services/web-apps/lemmy.md @@ -7,13 +7,15 @@ Lemmy is a federated alternative to reddit in rust. the minimum to start lemmy is ```nix -services.lemmy = { - enable = true; - settings = { - hostname = "lemmy.union.rocks"; - database.createLocally = true; +{ + services.lemmy = { + enable = true; + settings = { + hostname = "lemmy.union.rocks"; + database.createLocally = true; + }; + caddy.enable = true; }; - caddy.enable = true; } ``` diff --git a/nixos/modules/services/web-apps/pict-rs.md b/nixos/modules/services/web-apps/pict-rs.md index 2fa6bb3aebced..56c51e0d72594 100644 --- a/nixos/modules/services/web-apps/pict-rs.md +++ b/nixos/modules/services/web-apps/pict-rs.md @@ -7,7 +7,9 @@ pict-rs is a a simple image hosting service. the minimum to start pict-rs is ```nix -services.pict-rs.enable = true; +{ + services.pict-rs.enable = true; +} ``` this will start the http server on port 8080 by default. diff --git a/nixos/modules/services/web-apps/suwayomi-server.md b/nixos/modules/services/web-apps/suwayomi-server.md index 18e7a631443f4..2185556a87212 100644 --- a/nixos/modules/services/web-apps/suwayomi-server.md +++ b/nixos/modules/services/web-apps/suwayomi-server.md @@ -100,7 +100,7 @@ Not all the configuration options are available directly in this module, but you server = { port = 4567; autoDownloadNewChapters = false; - maxSourcesInParallel" = 6; + maxSourcesInParallel = 6; extensionRepos = [ "https://raw.githubusercontent.com/MY_ACCOUNT/MY_REPO/repo/index.min.json" ]; |