From c0a33e111a91d94b563c6fa96c17722c55db938d Mon Sep 17 00:00:00 2001 From: Kiana Sheibani Date: Wed, 2 Apr 2025 05:52:23 -0400 Subject: [PATCH 1/3] fix: always require ACME email --- modules/forgejo/options.nix | 9 +-------- modules/options.nix | 10 +++++++--- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/modules/forgejo/options.nix b/modules/forgejo/options.nix index 102255d..6a4d101 100644 --- a/modules/forgejo/options.nix +++ b/modules/forgejo/options.nix @@ -1,4 +1,4 @@ -args@{ config, lib, ... }: +{ config, lib, ... }: { imports = [ ../options.nix ]; @@ -49,11 +49,4 @@ args@{ config, lib, ... }: }; }; }; - - config.assertions = lib.mkIf config.aether.https [ - { - assertion = !(builtins.isNull config.aether.acmeEmail); - message = "HTTPS support requires providing a contact email"; - } - ]; } diff --git a/modules/options.nix b/modules/options.nix index a482a52..09ca8bd 100644 --- a/modules/options.nix +++ b/modules/options.nix @@ -9,13 +9,17 @@ https = lib.mkOption { type = lib.types.boolByOr; default = true; - description = "Whether to force HTTPS connections for websites."; + description = '' + Whether to force HTTPS connections for websites. + + This option is ignored if the service strictly requires HTTPS. + ''; }; acmeEmail = lib.mkOption { - type = lib.types.nullOr lib.types.str; + type = lib.types.str; default = null; - description = "Email address for ACME."; + description = "Email address to provide to the ACME service."; }; }; } From b66ac7683bce3284411ba1de84a93e0a67e71474 Mon Sep 17 00:00:00 2001 From: Kiana Sheibani Date: Wed, 2 Apr 2025 05:55:01 -0400 Subject: [PATCH 2/3] feat: add mastodon module --- README.md | 18 ++++++++++-- aether/config.nix | 11 ++++++- aether/mastodon/increase_limits.patch | 41 ++++++++++++++++++++++++++ modules/mastodon/default.nix | 37 +++++++++++++++++++++++ modules/mastodon/options.nix | 42 +++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 aether/mastodon/increase_limits.patch create mode 100644 modules/mastodon/default.nix create mode 100644 modules/mastodon/options.nix diff --git a/README.md b/README.md index 7bda54c..60a3aeb 100644 --- a/README.md +++ b/README.md @@ -31,14 +31,28 @@ module has options, they can be found in the `options.nix` file inside the module directory. More general options used by multiple modules are documented in `modules/options.nix`. -### Module Checklist +### Modules + +Modules listed here may be unimplemented or unfinished. + +#### Basic - [x] `basic` - Basic Internet support - [x] `ssh` - SSH support -- [ ] `site` - Static site hosting - [x] `fail2ban` - IP moderation + +#### Public Sites + +- [ ] `site` - Static site hosting - [x] `forgejo` - Code forge + +#### Social + +- [x] `mastodon` - Mastodon server instance - [ ] `mail` - Mail server + +#### Storage + - [ ] `cachix` - Nix build caching - [ ] `backup` - Automated backup system diff --git a/aether/config.nix b/aether/config.nix index bc9b490..df8203a 100644 --- a/aether/config.nix +++ b/aether/config.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, aether, forgejo-tokyo-night, ... }: +{ pkgs, aether, forgejo-tokyo-night, ... }: { networking.hostName = "toki-aether"; time.timeZone = "America/New_York"; @@ -65,5 +65,14 @@ federation.ENABLED = true; }; + aether.mastodon.subdomain = "social"; + services.mastodon = { + package = pkgs.mastodon.override { + patches = [ ./mastodon/increase_limits.patch ]; + }; + extraConfig.SINGLE_USER_MODE = "true"; + streamingProcesses = 3; + }; + system.stateVersion = "24.05"; } diff --git a/aether/mastodon/increase_limits.patch b/aether/mastodon/increase_limits.patch new file mode 100644 index 0000000..33178e4 --- /dev/null +++ b/aether/mastodon/increase_limits.patch @@ -0,0 +1,41 @@ +diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js +index bda2edb..1be1ce2 100644 +--- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js ++++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js +@@ -28,7 +28,7 @@ const mapStateToProps = state => ({ + anyMedia: state.getIn(['compose', 'media_attachments']).size > 0, + isInReply: state.getIn(['compose', 'in_reply_to']) !== null, + lang: state.getIn(['compose', 'language']), +- maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 500), ++ maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 1000000), + }); + + const mapDispatchToProps = (dispatch) => ({ +diff --git a/app/validators/poll_validator.rb b/app/validators/poll_validator.rb +index a327277..5d3134d 100644 +--- a/app/validators/poll_validator.rb ++++ b/app/validators/poll_validator.rb +@@ -1,8 +1,8 @@ + # frozen_string_literal: true + + class PollValidator < ActiveModel::Validator +- MAX_OPTIONS = 4 +- MAX_OPTION_CHARS = 50 ++ MAX_OPTIONS = 100 ++ MAX_OPTION_CHARS = 1000 + MAX_EXPIRATION = 1.month.freeze + MIN_EXPIRATION = 5.minutes.freeze + +diff --git a/app/validators/status_length_validator.rb b/app/validators/status_length_validator.rb +index dc841de..f0f1b25 100644 +--- a/app/validators/status_length_validator.rb ++++ b/app/validators/status_length_validator.rb +@@ -1,7 +1,7 @@ + # frozen_string_literal: true + + class StatusLengthValidator < ActiveModel::Validator +- MAX_CHARS = 500 ++ MAX_CHARS = 1000000 + URL_PLACEHOLDER_CHARS = 23 + URL_PLACEHOLDER = 'x' * 23 + diff --git a/modules/mastodon/default.nix b/modules/mastodon/default.nix new file mode 100644 index 0000000..5b4495f --- /dev/null +++ b/modules/mastodon/default.nix @@ -0,0 +1,37 @@ +{ config, lib, ... }: +let + cfg = config.aether.mastodon; + mastodon = config.services.mastodon; + + useSubdomain = !(builtins.isNull cfg.subdomain); + domain = lib.optionalString useSubdomain "${cfg.subdomain}." + + config.aether.domain; +in { + imports = [ ./options.nix ]; + + services.mastodon = { + enable = true; + user = cfg.user; + group = mastodon.user; + localDomain = domain; + configureNginx = true; + smtp.fromAddress = cfg.email; + }; + + security.acme.acceptTerms = true; + security.acme.defaults.email = config.aether.acmeEmail; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + users.users = lib.mkIf (cfg.createUser && mastodon.user != "mastodon") { + ${mastodon.user} = { + home = mastodon.package; + useDefaultShell = true; + group = mastodon.group; + isSystemUser = true; + }; + }; + users.groups = lib.mkIf (cfg.createUser && mastodon.group != "mastodon") { + ${mastodon.group} = {}; + }; +} diff --git a/modules/mastodon/options.nix b/modules/mastodon/options.nix new file mode 100644 index 0000000..259df26 --- /dev/null +++ b/modules/mastodon/options.nix @@ -0,0 +1,42 @@ +{ config, lib, ... }: +{ + imports = [ ../options.nix ]; + + options.aether = { + mastodon = { + subdomain = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = "mastodon"; + description = '' + The subdomain to host Mastodon under. + + If null, then Mastodon is hosted at the domain itself. + ''; + }; + + user = lib.mkOption { + type = lib.types.str; + default = "mastodon"; + description = '' + The user to run Mastodon with. + ''; + }; + + createUser = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to create the Mastodon user automatically. + ''; + }; + + email = lib.mkOption { + type = lib.types.str; + default = config.aether.acmeEmail; + description = '' + The email address used by Mastodon to send emails from. + ''; + }; + }; + }; +} From 69cefa72617e5f2f216daffebe98ee5482bc2712 Mon Sep 17 00:00:00 2001 From: Kiana Sheibani Date: Wed, 2 Apr 2025 05:56:55 -0400 Subject: [PATCH 3/3] chore: bump inputs --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 0e34e11..c563597 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1723293904, - "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "lastModified": 1736955230, + "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=", "owner": "ryantm", "repo": "agenix", - "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c", "type": "github" }, "original": { @@ -74,11 +74,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1736344531, - "narHash": "sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc+c2c=", + "lastModified": 1743448293, + "narHash": "sha256-bmEPmSjJakAp/JojZRrUvNcDX2R5/nuX6bm+seVaGhs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bffc22eb12172e6db3c5dde9e3e5628f8e3e7912", + "rev": "77b584d61ff80b4cef9245829a6f1dfad5afdfa3", "type": "github" }, "original": {