{"id":17800948,"url":"https://github.com/refi64/matrix-invite-panel","last_synced_at":"2025-04-02T04:40:43.444Z","repository":{"id":69429227,"uuid":"271925225","full_name":"refi64/matrix-invite-panel","owner":"refi64","description":"A customizable invite registration system for Synapse","archived":false,"fork":false,"pushed_at":"2020-06-20T06:08:57.000Z","size":181,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-25T05:06:46.831Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/refi64.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-13T02:18:06.000Z","updated_at":"2021-03-29T09:20:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"9be4a487-0eb2-48fb-93f3-ac5c9b15c314","html_url":"https://github.com/refi64/matrix-invite-panel","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refi64%2Fmatrix-invite-panel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refi64%2Fmatrix-invite-panel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refi64%2Fmatrix-invite-panel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refi64%2Fmatrix-invite-panel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/refi64","download_url":"https://codeload.github.com/refi64/matrix-invite-panel/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246758278,"owners_count":20828919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-27T12:32:42.299Z","updated_at":"2025-04-02T04:40:43.429Z","avatar_url":"https://github.com/refi64.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# matrix-invite-panel\n\nAn invite token system for Synapse, inspired by\n[matrix-registration](https://github.com/zeratax/matrix-registration), with some new additions:\n\n- A web frontend for issues new invites or revoking previously issued ones.\n- Automated invite expiration.\n- Looks pretty! With easily customizable looks and colors.\n\n![Registration page](images/register.png)\n![Invites page](images/invites.png)\n\n## Setup\n\n**NOTE:** As this is a brand-new project, these instructions may not be 100% perfect. They will\nbe refined as time passes and my own instance is refined.\n\n### Background\n\nmatrix-invite-panel requires three components to run:\n\n-  A gRPC-powered backend.\n-  An AngularDart-powered frontend.\n-  A gRPC-web proxy to allow the frontend to talk to the backend.\n\n### Backend\n\n#### Docker\n\nA premade, nightly-rebuilt Docker image is available of the backend at\n`gcr.io/refi64/matrix-invite-panel` (built using the Dockerfile in this repository).\nAll you need to do is mount the config file inside (see the below section), mount a\nstorage path, pass the path as an argument, and expose the ports. Example:\n\n```bash\n# Assuming that config.yaml has the server running on port 9090\n# and that the storage directory is /storage\n$ docker run --rm -it -p 9090:9090 -v $PWD/config.yaml:/app/config.yaml -v $PWD/storage:/storage \\\n  gcr.io/refi64/matrix-invite-panel config.yaml\n```\n\n#### Running by hand\n\nMake sure a recent version of [Dart](https://dart.dev/) is installed, then cd into\n`backend` and run `pub get` and `dart bin/backend.dart CONFIG_FILE` to get started.\nNote that, if you want faster boot time or more consistent performance, you can compile\nthe backend using dart2native and run the resulting binary (see the Dockerfile for an\nexample).\n\n#### Configuration\n\nPlease see `backend/config.ex.yaml` for an example configuration file.\n\n### gRPC Proxy\n\nThe gRPC protocol goes over raw HTTP/2, which a browser can't talk to. Therefore, a\nproxy server must be run to convert between the native gRPC format that the backend\nspeaks and the gRPC-web format.\n\nAlthough the official guidance seems to be leaning towards using Envoy, I honestly\ncould not make it work, and after spending an hour with 50 lines of YAML soup I gave\nup and switched to the far simpler\n[grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy)\ninstead. I have Docker images built nightly\n([source](https://bk.refi64.com/cloud/containers/grpcwebproxy/?PAGE=dir)), available\nat `gcr.io/refi64/grpcwebproxy`, or you can build and run it yourself. The arguments\nare documented at the grpcwebproxy page.\n\n#### Reverse proxies\n\nIf you're using a reverse proxy, you need to do the following:\n\n- Make sure it has CORS enabled.\n- Make sure it has authorization to forward all the special gRPC and matrix-invite-panel headers:\n\n  ```\n  auth-jwt,X-Grpc-Web,X-User-Agent\n  ```\n\n#### Rate limiting\n\nIt's recommended to have some form of rate limiting in front of grpcwebproxy, e.g.\n50 requests per minute, to avoid having people trying to hammer the login forms.\nHow you do this is up to you; as I generally use k8s, my preference would be using\nthe NGINX ingress controller's built-in rate limiting functionality.\n\nThe configuration I currently use is:\n\n```yaml\nnginx.ingress.kubernetes.io/limit-connections: \"2\"\nnginx.ingress.kubernetes.io/limit-rpm: \"70\"\nnginx.ingress.kubernetes.io/limit-rps: \"5\"\n```\n\n### Frontend\n\n#### Configuration\n\nThere are two files two configure the frontend: `frontend/web/config.json`\nand `frontend/web/_config.scss`. Both have example files available as\n`config.ex.json` and `_config.ex.scss` respectively; see those files for more details.\n\nPlease note that the backend server URL here should be pointing to grpcwebproxy, not\ndirectly to the underlying backend server itself.\n\nNote that, **without the config files present, the frontend will *not* build**.\n\n#### Building\n\nThe frontend is a static site, written in AngularDart. Grab [Dart](https://dart.dev), and\nrun:\n\n```\n$ cd frontend\n$ pub global activate webdev\n$ webdev build\n```\n\nto build it and drop the files in the `build` folder.\n\n#### Hosting\n\nFrom here, it's your choice where to place the files. Do note that this uses a history-based\nSPA routing strategy, which essentially means that your web server needs to redirect not-found\nfiles to `index.html`. You can generally google something like *\"spa my-web-server\"* or similar\nto find out how to do this.\n\nThe absolute simplest way would be to not host it yourself, rather relying on an online service.\nGitHub Pages would not work due to the routing requirement, but [Netlify](https://www.netlify.com/)\nor [Firebase](https://firebase.google.com/) (which is what I use) would both be excellent choices.\n\nThere's a quick overview of the routing mentioned above\n[here](https://www.netlify.com/blog/2020/04/07/creating-better-more-predictable-redirect-rules-for-spas/)\nfor Netlify and [here](https://firebase.google.com/docs/hosting/full-config#rewrites) for Firebase.\n\nAs an added performance boost, you could use HTTP/2 push to send over the main.dart.js and styles.css\nfiles along with index.html in one swoop. This is again host-dependent and is definitely outside of\nthe scope of this guide, as it's not really a must-have overall (despite being really cool).\n\n### Example setup\n\nTo bring it all together, let's assume we're using:\n\n- The Docker image of the backend\n- grpcwebproxy\n- Some SSL-enabled reverse proxy\n- Hosting the static site on Firebase\n\nFirst off, let's create a Docker network so the proxy can talk to the gRPC backend:\n\n```\n$ docker network create matrix-invite-panel\n```\n\nYour backend config file might look like this:\n\n```yaml\nport: 9090\ndatabase_path: /app/storage\n# yes I just rammed into the keyboard, please use an actual secure RNG for this secret!\njwt_secret: kasdjlaskjdas;lfsd\nhomeserver:\n  url: https://matrix.my-home.server\n  # This would again be taken from your Synapse instance's homeserver.yaml file\n  registration_secret: a;fajsdflksdafjdsl;fasd\n```\n\nThis will start the backend server on port 9090. Now I'll run:\n\n```bash\n$ docker run --rm -it --net matrix-invite-panel --name matrix-invite-panel \\\n  -v $PWD/config.yaml:/app/config.yaml:z \\\n  -v $PWD/storage:/app/storage:z \\\n  gcr.io/refi64/matrix-invite-panel /app/config.yaml\n```\n\nNext comes grpcwebproxy, running on port 8081:\n\n```bash\n$ docker run --rm -it --net matrix-invite-panel -p 8081:8081 --name grpcwebproxy \\\n  --server_http_debug_port=8081 --backend_addr=matrix-invite-panel:9090 \\\n  --backend_tls_noverify --run_tls_server=false \\\n  --allowed_origins https://MY-FRONTEND-URL/\n```\n\nNote that, as the two containers are running on the same network, there's no need for\nTLS between them, thus the --backend_tls_noverify. In addition, you would likely want\nSSL certificates active on grpcwebproxy if you're *not* using a reverse proxy. However,\nas there *is* a reverse proxy, the reverse proxy is what will be handling TLS, thus\ngrpcwebproxy itself runs unencrypted. (That's a lot of proxies...)\n\nYour frontend config may then look like:\n\n```json\n{\n  \"backend\": \"https://my-server.com:8081\",\n  \"homeserver\": {\n    \"url\": \"https://matrix.home.server/\",\n    \"name\": \"home.server\"\n  }\n}\n```\n\nThen, the `firebase.json` might be a bit like this:\n\n```json\n{\n  \"hosting\": {\n    \"public\": \"frontend/build\",\n    \"ignore\": [\n      \"config.ex.json\",\n      \"config.ex.scss\",\n      \"packages/**\",\n      \"**/.*\"\n    ],\n    \"rewrites\": [\n      {\n        \"source\": \"**\",\n        \"destination\": \"/index.html\"\n      }\n    ]\n  }\n}\n```\n\nThe \"rewrites\" section is what sets up the SPA-style routing.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frefi64%2Fmatrix-invite-panel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frefi64%2Fmatrix-invite-panel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frefi64%2Fmatrix-invite-panel/lists"}