From fe7d8c4f1279f0498fdfccf0b49d9b544c449e79 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 15 Oct 2022 13:02:13 -0700 Subject: [PATCH 1/6] add nix flake Also add `.envrc` for direnv + Nix users. This makes developing locally easier for us NixOS folks. The flake itself will allow NixOS users to pull code directly from Conduit's repository, making it completely trivial to stay up-to-date with every commit. I'd also like to add a NixOS module directly to this repository at some point so that new configuration options will be available in the NixOS module faster. But for now, NixOS users can simply override `serivces.matrix-conduit.package` and get pretty much all the functionality. I've added myself to the `CODEOWNERS` file for the Nix files, since I am willing to maintain this stuff. I use Conduit on NixOS so I'm personally invested in having this work. Lastly, `.gitignore` was updated to exclude symlinks created by `direnv` and `nix build` and other such Nix commands. This doesn't come without maintenance burden, however: * The `sha256` in `flake.nix` will need to be updated whenever Conduit's MSRV is updated, but that should be pretty infrequent. * `nix flake update` should be run every so often to pull in updates to `nixpkgs` and other flake inputs. I think downstream users can also override this themselves with `inputs..inputs..follows`. * `nix flake check` should be run in CI to ensure Nix builds keep working. * `nixpkgs-fmt --check $(fd '\.nix')` (or similar) should be run in CI to ensure style uniformity. --- .envrc | 1 + .gitignore | 6 +++ .gitlab/CODEOWNERS | 4 ++ flake.lock | 102 +++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 75 +++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+) create mode 100644 .envrc create mode 100644 .gitlab/CODEOWNERS create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index f5e9505b..19f05ce3 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,9 @@ conduit.db # Etc. **/*.rs.bk + +# Nix artifacts +/result* + +# Direnv cache +/.direnv diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS new file mode 100644 index 00000000..20ec9fa7 --- /dev/null +++ b/.gitlab/CODEOWNERS @@ -0,0 +1,4 @@ +# Nix things +.envrc @CobaltCause +flake.lock @CobaltCause +flake.nix @CobaltCause diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..9217ff26 --- /dev/null +++ b/flake.lock @@ -0,0 +1,102 @@ +{ + "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1665815894, + "narHash": "sha256-Vboo1L4NMGLKZKVLnOPi9OHlae7uoNyfgvyIUm+SVXE=", + "owner": "nix-community", + "repo": "fenix", + "rev": "2348450241a5f945f0ba07e44ecbfac2f541d7f4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "naersk": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1662220400, + "narHash": "sha256-9o2OGQqu4xyLZP9K6kNe1pTHnyPz0Wr3raGYnr9AIgY=", + "owner": "nix-community", + "repo": "naersk", + "rev": "6944160c19cb591eb85bbf9b2f2768a935623ed3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1665856037, + "narHash": "sha256-/RvIWnGKdTSoIq5Xc2HwPIL0TzRslzU6Rqk4Img6UNg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c95ebc5125ffffcd431df0ad8620f0926b8125b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "fenix": "fenix", + "flake-utils": "flake-utils", + "naersk": "naersk", + "nixpkgs": "nixpkgs" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1665765556, + "narHash": "sha256-w9L5j0TIB5ay4aRwzGCp8mgvGsu5dVJQvbEFutwr6xE=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "018b8429cf3fa9d8aed916704e41dfedeb0f4f78", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..924300cf --- /dev/null +++ b/flake.nix @@ -0,0 +1,75 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + naersk = { + url = "github:nix-community/naersk"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { self + , nixpkgs + , flake-utils + + , fenix + , naersk + }: flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + # Nix-accessible `Cargo.toml` + cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); + + # The Rust toolchain to use + toolchain = fenix.packages.${system}.toolchainOf { + # Use the Rust version defined in `Cargo.toml` + channel = cargoToml.package.rust-version; + + # This will need to be updated when `package.rust-version` is changed in + # `Cargo.toml` + sha256 = "sha256-KXx+ID0y4mg2B3LHp7IyaiMrdexF6octADnAtFIOjrY="; + }; + + builder = (pkgs.callPackage naersk { + inherit (toolchain) rustc cargo; + }).buildPackage; + in + { + packages.default = builder { + src = ./.; + + nativeBuildInputs = (with pkgs.rustPlatform; [ + bindgenHook + ]); + }; + + devShells.default = pkgs.mkShell { + # Rust Analyzer needs to be able to find the path to default crate + # sources, and it can read this environment variable to do so + RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library"; + + # Development tools + nativeBuildInputs = (with pkgs.rustPlatform; [ + bindgenHook + ]) ++ (with toolchain; [ + cargo + clippy + rust-src + rustc + rustfmt + ]); + }; + + checks = { + packagesDefault = self.packages.${system}.default; + devShellsDefault = self.devShells.${system}.default; + }; + }); +} From 716f82db6dbd324bbd0b142db740e8f5e39b2a6c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 15 Oct 2022 15:21:04 -0700 Subject: [PATCH 2/6] add nix/nixos deployment documentation --- .gitlab/CODEOWNERS | 1 + README.md | 1 + nix/README.md | 188 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 nix/README.md diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 20ec9fa7..665aaaa7 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -2,3 +2,4 @@ .envrc @CobaltCause flake.lock @CobaltCause flake.nix @CobaltCause +nix/ @CobaltCause diff --git a/README.md b/README.md index 730b2512..ab471769 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Check out the [Conduit 1.0 Release Milestone](https://gitlab.com/famedly/conduit - Simple install (this was tested the most): [DEPLOY.md](DEPLOY.md) - Debian package: [debian/README.Debian](debian/README.Debian) +- Nix/NixOS: [nix/README.md](nix/README.md) - Docker: [docker/README.md](docker/README.md) If you want to connect an Appservice to Conduit, take a look at [APPSERVICES.md](APPSERVICES.md). diff --git a/nix/README.md b/nix/README.md new file mode 100644 index 00000000..d92f910b --- /dev/null +++ b/nix/README.md @@ -0,0 +1,188 @@ +# Conduit for Nix/NixOS + +This guide assumes you have a recent version of Nix (^2.4) installed. + +Since Conduit ships as a Nix flake, you'll first need to [enable +flakes][enable_flakes]. + +You can now use the usual Nix commands to interact with Conduit's flake. For +example, `nix run gitlab:famedly/conduit` will run Conduit (though you'll need +to provide configuration and such manually as usual). + +If your NixOS configuration is defined as a flake, you can depend on this flake +to provide a more up-to-date version than provided by `nixpkgs`. In your flake, +add the following to your `inputs`: + +```nix +conduit = { + url = "gitlab:famedly/conduit"; + + # Assuming you have an input for nixpkgs called `nixpkgs`. If you experience + # build failures while using this, try commenting/deleting this line. This + # will probably also require you to always build from source. + inputs.nixpkgs.follows = "nixpkgs"; +}; +``` + +Next, make sure you're passing your flake inputs to the `specialArgs` argument +of `nixpkgs.lib.nixosSystem` [as explained here][specialargs]. This guide will +assume you've named the group `flake-inputs`. + +Now you can configure Conduit and a reverse proxy for it. Add the following to +a new Nix file and include it in your configuration: + +```nix +{ config +, pkgs +, flake-inputs +, ... +}: + +let + # You'll need to edit these values + + # The hostname that will appear in your user and room IDs + server_name = "example.com"; + + # The hostname that Conduit actually runs on + # + # This can be the same as `server_name` if you want. This is only necessary + # when Conduit is running on a different machine than the one hosting your + # root domain. This configuration also assumes this is all running on a single + # machine, some tweaks will need to be made if this is not the case. + matrix_hostname = "matrix.${server_name}"; + + # An admin email for TLS certificate notifications + admin_email = "admin@${server_name}"; + + # These ones you can leave alone + + # Build a dervation that stores the content of `${server_name}/.well-known/matrix/server` + well_known_server = pkgs.writeText "well-known-matrix-server" '' + { + "m.server": "${matrix_hostname}" + } + ''; + + # Build a dervation that stores the content of `${server_name}/.well-known/matrix/client` + well_known_client = pkgs.writeText "well-known-matrix-client" '' + { + "m.homeserver": { + "base_url": "https://${matrix_hostname}" + } + } + ''; +in + +{ + # Configure Conduit itself + services.matrix-conduit = { + enable = true; + + # This causes NixOS to use the flake defined in this repository instead of + # the build of Conduit built into nixpkgs. + package = flake-inputs.conduit.packages.${pkgs.system}.default; + + settings.global = { + inherit server_name; + }; + }; + + # Configure automated TLS acquisition/renewal + security.acme = { + acceptTerms = true; + defaults = { + email = admin_email; + }; + }; + + # ACME data must be readable by the NGINX user + users.users.nginx.extraGroups = [ + "acme" + ]; + + # Configure NGINX as a reverse proxy + services.nginx = { + enable = true; + recommendedProxySettings = true; + + virtualHosts = { + "${server_name}" = { + forceSSL = true; + enableACME = true; + + listen = [ + { + addr = "0.0.0.0"; + port = 443; + ssl = true; + } + { + addr = "0.0.0.0"; + port = 8448; + ssl = true; + } + ]; + + extraConfig = '' + merge_slashes off; + ''; + + "${matrix_hostname}" = { + forceSSL = true; + enableACME = true; + + locations."/_matrix/" = { + proxyPass = "http://backend_conduit$request_uri"; + proxyWebsockets = true; + extraConfig = '' + proxy_set_header Host $host; + proxy_buffering off; + ''; + }; + + locations."=/.well-known/matrix/server" = { + # Use the contents of the derivation built previously + alias = "${well_known_server}"; + + extraConfig = '' + # Set the header since by default NGINX thinks it's just bytes + default_type application/json; + ''; + }; + + locations."=/.well-known/matrix/client" = { + # Use the contents of the derivation built previously + alias = "${well_known_client}"; + + extraConfig = '' + # Set the header since by default NGINX thinks it's just bytes + default_type application/json; + + # https://matrix.org/docs/spec/client_server/r0.4.0#web-browser-clients + add_header Access-Control-Allow-Origin "*"; + ''; + }; + }; + }; + + upstreams = { + "backend_conduit" = { + servers = { + "localhost:${toString config.services.matrix-conduit.settings.global.port}" = { }; + }; + }; + }; + }; + + # Open firewall ports for HTTP, HTTPS, and Matrix federation + networking.firewall.allowedTCPPorts = [ 80 443 8448 ]; + networking.firewall.allowedUDPPorts = [ 80 443 8448 ]; +} +``` + +Now you can rebuild your system configuration and you should be good to go! + +[enable_flakes]: https://nixos.wiki/wiki/Flakes#Enable_flakes + +[specialargs]: https://nixos.wiki/wiki/Flakes#Using_nix_flakes_with_NixOS From 10d2da30091d9e8aeaa9dee2ee626ecdf85059df Mon Sep 17 00:00:00 2001 From: AndSDev Date: Tue, 25 Oct 2022 12:53:58 +0300 Subject: [PATCH 3/6] fix(main): fix request size limit to max_request_size (axum defaults 2MB) --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/main.rs | 10 ++++++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48ce6c04..bdadf716 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,9 +109,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e3356844c4d6a6d6467b8da2cffb4a2820be256f50a3a386c9d152bab31043" +checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" dependencies = [ "async-trait", "axum-core", @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b" +checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" dependencies = [ "async-trait", "bytes", diff --git a/Cargo.toml b/Cargo.toml index e7e48c83..db51f4a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ edition = "2021" [dependencies] # Web framework -axum = { version = "0.5.8", default-features = false, features = ["form", "headers", "http1", "http2", "json", "matched-path"], optional = true } +axum = { version = "0.5.17", default-features = false, features = ["form", "headers", "http1", "http2", "json", "matched-path"], optional = true } axum-server = { version = "0.4.0", features = ["tls-rustls"] } tower = { version = "0.4.8", features = ["util"] } tower-http = { version = "0.3.4", features = ["add-extension", "cors", "compression-full", "sensitive-headers", "trace", "util"] } diff --git a/src/main.rs b/src/main.rs index 626de3ae..88a48389 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use std::{future::Future, io, net::SocketAddr, time::Duration}; use axum::{ - extract::{FromRequest, MatchedPath}, + extract::{DefaultBodyLimit, FromRequest, MatchedPath}, handler::Handler, response::IntoResponse, routing::{get, on, MethodFilter}, @@ -164,7 +164,13 @@ async fn run_server() -> io::Result<()> { header::AUTHORIZATION, ]) .max_age(Duration::from_secs(86400)), - ); + ) + .layer(DefaultBodyLimit::max( + config + .max_request_size + .try_into() + .expect("failed to convert max request size"), + )); let app = routes().layer(middlewares).into_make_service(); let handle = ServerHandle::new(); From 3bc0a1924b230e0a3fe28fcba2830aa46f3f1156 Mon Sep 17 00:00:00 2001 From: James Blachly Date: Tue, 25 Oct 2022 20:47:41 +0000 Subject: [PATCH 4/6] Return 403 to 3pid token routes to signal not implemented --- src/api/client_server/account.rs | 33 ++++++++++++++++++++++++++++++-- src/main.rs | 2 ++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index ce4dadda..c9e3c9b9 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -3,7 +3,8 @@ use crate::{api::client_server, services, utils, Error, Result, Ruma}; use ruma::{ api::client::{ account::{ - change_password, deactivate, get_3pids, get_username_availability, register, whoami, + change_password, deactivate, get_3pids, get_username_availability, register, + request_3pid_management_token_via_email, request_3pid_management_token_via_msisdn, whoami, ThirdPartyIdRemovalStatus, }, error::ErrorKind, @@ -406,7 +407,7 @@ pub async fn deactivate_route( }) } -/// # `GET _matrix/client/r0/account/3pid` +/// # `GET _matrix/client/v3/account/3pid` /// /// Get a list of third party identifiers associated with this account. /// @@ -418,3 +419,31 @@ pub async fn third_party_route( Ok(get_3pids::v3::Response::new(Vec::new())) } + +/// # `POST /_matrix/client/v3/account/3pid/email/requestToken` +/// +/// "This API should be used to request validation tokens when adding an email address to an account" +/// +/// - 403 signals that The homeserver does not allow the third party identifier as a contact option. +pub async fn request_3pid_management_token_via_email_route( + _body: Ruma, +) -> Result { + Err(Error::BadRequest( + ErrorKind::ThreepidDenied, + "Third party identifier is not allowed", + )) +} + +/// # `POST /_matrix/client/v3/account/3pid/msisdn/requestToken` +/// +/// "This API should be used to request validation tokens when adding an phone number to an account" +/// +/// - 403 signals that The homeserver does not allow the third party identifier as a contact option. +pub async fn request_3pid_management_token_via_msisdn_route( + _body: Ruma, +) -> Result { + Err(Error::BadRequest( + ErrorKind::ThreepidDenied, + "Third party identifier is not allowed", + )) +} diff --git a/src/main.rs b/src/main.rs index 626de3ae..38fdfdd1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -217,6 +217,8 @@ fn routes() -> Router { .ruma_route(client_server::change_password_route) .ruma_route(client_server::deactivate_route) .ruma_route(client_server::third_party_route) + .ruma_route(client_server::request_3pid_management_token_via_email_route) + .ruma_route(client_server::request_3pid_management_token_via_msisdn_route) .ruma_route(client_server::get_capabilities_route) .ruma_route(client_server::get_pushrules_all_route) .ruma_route(client_server::set_pushrule_route) From 238ebcfcac94973c486653f9e5ad3ca35753c9c5 Mon Sep 17 00:00:00 2001 From: Nabulator Date: Thu, 27 Oct 2022 04:20:56 +0000 Subject: [PATCH 5/6] Update nginx configuration to allow for larger uploads. --- DEPLOY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DEPLOY.md b/DEPLOY.md index 1c7d1af5..a248d81f 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -214,6 +214,9 @@ server { server_name your.server.name; # EDIT THIS merge_slashes off; + # Nginx default to only allow 1MB uploads. + client_max_body_size 20M; + location /_matrix/ { proxy_pass http://127.0.0.1:6167$request_uri; proxy_set_header Host $http_host; From 1aff2a54ef5ef571b622d5bb27710c3119b5714d Mon Sep 17 00:00:00 2001 From: Nabulator Date: Thu, 27 Oct 2022 04:23:07 +0000 Subject: [PATCH 6/6] comment typo --- DEPLOY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPLOY.md b/DEPLOY.md index a248d81f..51f310e3 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -214,7 +214,7 @@ server { server_name your.server.name; # EDIT THIS merge_slashes off; - # Nginx default to only allow 1MB uploads. + # Nginx defaults to only allow 1MB uploads client_max_body_size 20M; location /_matrix/ {