# Element Matrix Services
# Add Additional Users
1. Click `Your Account` and `Manage Servers` or click this link https://ems.element.io/user/hosting.
1. Click the Hosts tab.
1. Change `Total Monthly Active User Seats` to the number of users you want and click `Save` at the bottom.
[](https://ems-docs.element.io/uploads/images/gallery/2022-04/image-1651236785028-51-31-pm.png)
- Note that you cannot decrease your user count later.
# Add Users
1. Click `Your Account` and `Manage Servers` or click this link: https://ems.element.io/user/hosting
1. Click `Server Admin`
1. Select your host
1. Click `Add user` Enter the username and click `Add`
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702382821288-34-01-pm.png)
1. Select `Make new user server admin` if you want this user to be able to use the Synapse Admin API to perform administrative tasks on your server. Be careful with this as this option has a lot of power on your server.
1. The username and password for the new user is displayed. You will only be able to see this information once so send the password to the user in a secure manner and then delete it
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702382889442-37-05-pm.png)
# Apply coupon/discount
Coupons can only be applied by new customers before purchasing any products. However, if you are an existing customer and want to add a coupon, please contact support at .
Terms and Conditions apply. See the page for your coupon or ask your Element contact or support.
- Create your EMS account normally
- If you have agreed to pay by invoice/bank transfer, stop here and let your Element contact know you have created your account so they can enable invoice payment for you
- Add your billing address and payment card on , or click `Your Account`, then `Billing`
[](https://ems-docs.element.io/uploads/images/gallery/2022-11/image-1667843563093-36-13-pm.png)
- Go to , or click `Your Account`, then `Account`
- If you are a business, you must enter your company name and if applicable, VAT ID here
[](https://ems-docs.element.io/uploads/images/gallery/2023-07/image-1689152455628-59-46-am.png)
- Click `Show Discounts`
- Enter your coupon code and click `Apply coupon`
[](https://ems-docs.element.io/uploads/images/gallery/2022-11/image-1667843574754-43-32-pm.png)
[](https://ems-docs.element.io/uploads/images/gallery/2022-11/image-1667843583549-43-46-pm.png)
- [Continue host setup normally](get-your-own-ems-server). The discount will automatically be applied to all applicable products
[](https://ems-docs.element.io/uploads/images/gallery/2022-11/image-1667843601268-48-08-pm.png)
# Client Look & Feel
This feature allows you to customize the home and welcome page on your EMS-provided Element Web client.
## Blog posts
See also our blog posts on the subject:
- [Build your own custom branded chat platform at the touch of a button!](https://element.io/blog/custom-branding/)
- [A white label messaging app to create your own brand messenger](https://element.io/blog/a-white-label-messaging-app-to-create-your-own-brand-messenger-2/)
## Create home and login template
1. Create the files you want to use.
1. Edit `ems_home.html`. This can be as simple as a couple of lines of HTML, for example:
```html
Snow Leopard LTD
Rooms to join
```
You can also add a more complex HTML and styling.
2. It looks like this in your web browser:
[](https://ems-docs.element.io/uploads/images/gallery/2022-10/image-1665155682392.png)
3. Edit `ems_welcome.html`. This is a bit more complex, but it can be almost anything you want as long as it has links to `Log in` (`/#/login`) and `Create account` (`/#/register`). The default design is based on this template. You can get creative with the CSS and the `!important` tag.
Click to see ems_welcome contents
The only change I made from the template is adding `This is some demo text!
` on line 177.
```html
This is some demo text!
```
4. It looks like this in your web browser:
[](https://ems-docs.element.io/uploads/images/gallery/2022-10/image-1665155688548.png)
## Serve the files
You must host the files somewhere where they are publickly accessible and you need to enable the CORS header `Access-Control-Allow-Origin: *` on the web server for these files. See https://enable-cors.org/ for instructions on how to do this.
## Configure your EMS server
1. Add the URLs to the `Client look & feel` section in the EMS Control Panel. Click `Save`.
[](https://ems-docs.element.io/uploads/images/gallery/2022-10/image-1665159064784-09-09-pm.png)
Unfortunately, we have a bug in the validator affecting files hosted on Matrix. Just ignore the error.
- Note if you are hosting the files on your own web server, you only need to change your EMS server configuration or reprovision if the URLs have changed. Changes to the contents of existing files are applied automatically
2. Once your host finishes reprovisioning, check your Element Web to ensure the changes are applied correctly.
1. Welcome page image and Welcome page content
[](https://ems-docs.element.io/uploads/images/gallery/2022-10/image-1665159230891-12-16-pm.png)
2. Client logo
[](https://ems-docs.element.io/uploads/images/gallery/2022-10/image-1665155735797.png)
3. Home page content
[](https://ems-docs.element.io/uploads/images/gallery/2022-10/image-1665159253171-12-49-pm.png)
## Image Credits
- [Client logo image](https://www.pexels.com/photo/close-up-photography-of-tiger-3660441/) by [Charles Miller](https://www.pexels.com/@charles-miller-1020744/) used under the terms of [Free to use License](https://www.pexels.com/license/).
- [Welcome page image](https://www.pexels.com/photo/animal-world-attention-branch-cat-267074/) by [Pixabay](https://www.pexels.com/@pixabay/) used under the terms of [Free to use (CC0) License](https://www.pexels.com/creative-commons-images/).
# Domains and IP addresses
This document contains a list of all domains users of your EMS hosted cloud server needs permission to connect to. The list may include content delivery or telemetry endpoints which may not be required, but not allowing them may have unintended effects. Blocking any endpoints is not a supported environment.
This page was last updated on January 30, 2024. **Subject to change at any time without notice.**
**We do not guarantee any IP addresses or CNAME values for EMS services. Both can change at any time without notice. We also cannot make any guarantees about external services, for example `api.github.com`.**
**Dependencies for services hosted by third parties, for example `status.element.io`, are outside our control and may change at any time without notice.**
## Domains
### Base Domains
- `https://sentry.tools.element.io:443/tcp`
#### Homeserver
This is the endpoint where your clients connect to the EMS Matrix homeserver. It is required for all services
- `https://ems-hostname.ems.host:443/tcp`
If your EMS server was set up before mid-2020, you also need `https://ems-hostname.modular.im:443/tcp`
#### Element
This is where your Element Web client is hosted. It is required for most services.
- `https://ems-hostname.element.io:443/tcp`
If your EMS server was set up before mid-2020, you also need `https://ems-hostname.riot.im:443/tcp`
##### Custom Element Web DNS
If you have Custom DNS configured for your Element Web client, `https://custom-dns-element-web.com:443/tcp` will be required in addition to `https://ems-hostname.element.io:443/tcp` for all services accessed through Element.
##### Element Desktop
For Element Desktop, neither `https://ems-hostname.element.io:443/tcp` or `https://custom-dns-element-web.com:443/tcp` are required when accessing any service through Element.
#### Identity Server
See [What is an Identity Server, and how does it work?](https://ems-docs.element.io/link/6#bkmrk-what-is-an-identity-) in the FAQ.
- `https://vector.im:443/tcp`
### Element Call
- `https://call.element.io:443/tcp`
- `https://call.ems.host:443/tcp`
- `https://livekit-jwt.call.element.io:443/tcp`
- `https://posthog-element-call.element.io:443/tcp`
#### SFU
- `wss://sfu.call.element.io`
#### Google STUN
- `stun.l.google.com:19302/udp`
- `stun1.l.google.com:19302/udp`
### Element Web
[Base domains](#bkmrk-base-domains) only
### EMS Control Panel
- `https://custom-dns-homeserver.com:443/tcp`
- `https://ems.element.io:443/tcp`
- `https://id.element.io:443/tcp`
- `https://js.stripe.com:443/tcp`
- `https://m.stripe.com:443/tcp`
- `https://m.stripe.network:443/tcp`
- `https://matomo.riot.im:443/tcp`
- `https://pay.stripe.com:443/tcp`
- `https://sentry.matrix.org:443/tcp`
### EMS Documentation
- `https://api.github.com:443/tcp`
- `https://element-hq.github.io:443/tcp`
- `https://ems-docs.element.io:443/tcp`
- `https://fonts.googleapis.com:443/tcp`
- `https://github.com:443/tcp`
- `https://img.shields.io:443/tcp`
- `https://matrix-org.github.io:443/tcp`
- `https://sonarcloud.io:443/tcp`
- `https://user-images.githubusercontent.com:443/tcp`
- `https://web-docs.element.dev:443/tcp`
### EMS Status page
- `https://dka575ofm4ao0.cloudfront.net:443/tcp`, possibly `*.cloudfront.net`
- `https://fonts.gstatic.com:443/tcp`
- `https://polyfill.io:443/tcp`
- `https://status.element.io:443/tcp`
- `https://www.google.com:443/tcp`
- `https://www.gstatic.com:443/tcp`
- `https://www.recaptcha.net:443/tcp`
### Hookshot (Dedicated)
[Base domains](#bkmrk-base-domains) only
### Identity Server
- `https://matrix.org:443/tcp`, for loading a logo/image on email verification page, not required
### Integration Server
- `https://integrations.element.io:443/tcp`
- `https://integrations.ems.host:443/tcp`
- `https://scalar.vector.im:443/tcp`
### Integration Widgets
The integration Server is required for all widgets
#### Ethercalc
- `https://ethercalc.net:443/tcp`
- `wss://ethercalc.net`
#### Etherpad
- `https://etherpad.integrations.element.io:443/tcp`
- `wss://etherpad.integrations.element.io`
#### Feeds
[Base domains](#bkmrk-base-domains) and [Integration Server domains](#bkmrk-integration-server) only
#### GitHub
[Base domains](#bkmrk-base-domains) and [Integration Server domains](#bkmrk-integration-server) only
##### Connect/Authenticate
- `https://api.github.com:443/tcp`
- `https://avatars.githubusercontent.com:443/tcp`
- `https://collector.github.com:443/tcp`
- `https://github.com:443/tcp`
- `https://github.githubassets.com:443/tcp`
#### Google Calendar
[Base domains](#bkmrk-base-domains) and [Integration Server domains](#bkmrk-integration-server) only
#### Grafana
[Base domains](#bkmrk-base-domains) and [Integration Server domains](#bkmrk-integration-server) only
#### Jitsi
- `https://meet.element.io:10000/udp`
- `https://meet.element.io:20000-20050/udp`
- `https://meet.element.io:443/tcp`
- `https://meet.element.io:80/tcp`
- `https://www.gravatar.com:443/tcp`
- `wss://meet.element.io`
#### Spotify
- `https://apresolve.spotify.com:443/tcp`
- `https://embed-cdn.spotifycdn.com:443/tcp`
- `https://encore.scdn.co:443/tcp`
- `https://gew1-spclient.spotify.com:443/tcp`
- `https://i.scdn.co:443/tcp`
- `https://open.spotify.com:443/tcp`
- `https://p.scdn.co:443/tcp`
- `https://spclient.wg.spotify.com:443/tcp`
- `https://web-sdk-assets.spotifycdn.com:443/tcp`
#### Sticker packs
- `https://matrix.org:443/tcp`
#### TradingView
- `https://economic-calendar.tradingview.com:443/tcp`
- `https://s.tradingview.com:443/tcp`
- `https://s3-symbol-logo.tradingview.com:443/tcp`
- `https://s3.tradingview.com:443/tcp`
- `https://static.tradingview.com:443/tcp`
- `https://www.tradingview-widget.com:443/tcp`
- `wss://pushstream.tradingview.com`
- `wss://widgetdata.tradingview.com`
#### Youtube
- `https://fonts.gstatic.com:443/tcp`
- `https://googleads.g.doubleclick.net:443/tcp`
- `https://i.ytimg.com:443/tcp`
- `https://jnn-pa.googleapis.com:443/tcp`
- `https://rr5---sn-aigzrn7e.googlevideo.com:443/tcp`, possibly `*.googlevideo.com`
- `https://static.doubleclick.net:443/tcp`
- `https://www.google.com:443/tcp`
- `https://www.gstatic.com:443/tcp`
- `https://www.youtube.com:443/tcp`
- `https://youtube.com:443/tcp`
- `https://yt3.ggpht.com:443/tcp`
### Legacy call in Element client
[Base domains](#bkmrk-base-domains) only
### Location Service (Maptiler)
- `https://api.maptiler.com:443/tcp`
#### Open in OpenStreetMap
- `https://matomo.openstreetmap.org:443/tcp`
- `https://tile.openstreetmap.org:443/tcp`
- `https://www.openstreetmap.org:443/tcp`
### Sliding Sync
[Base domains](#bkmrk-base-domains) only
### Synapse
[Base domains](#bkmrk-base-domains) only
### Well-Known
If you have Custom DNS for your homeserver:
- `https://custom-dns-homeserver.com:443/tcp`
### Notification Service Element Proxy
### Other
## IP Addresses
**We do not guarantee any IP addresses or CNAME values for EMS services. Both can change at any time without notice. We also cannot make any guarantees about external services, for example `api.github.com`.**
But for your convenience, here are the IP addresses and CNAME values as seen on January 30, 2024.
Click to expand
```bash
$ dig +noall +answer all api.github.com
api.github.com. 9 IN A 140.82.121.5
$ dig +noall +answer all api.maptiler.com
api.maptiler.com. 140 IN A 104.17.88.87
api.maptiler.com. 140 IN A 104.17.91.87
api.maptiler.com. 140 IN A 104.17.90.87
api.maptiler.com. 140 IN A 104.17.87.87
api.maptiler.com. 140 IN A 104.17.89.87
$ dig +noall +answer all apresolve.spotify.com
apresolve.spotify.com. 293 IN A 35.186.224.25
$ dig +noall +answer all avatars.githubusercontent.com
avatars.githubusercontent.com. 2561 IN A 185.199.108.133
avatars.githubusercontent.com. 2561 IN A 185.199.109.133
avatars.githubusercontent.com. 2561 IN A 185.199.111.133
avatars.githubusercontent.com. 2561 IN A 185.199.110.133
$ dig +noall +answer all call.element.io
call.element.io. 279 IN A 172.67.12.112
call.element.io. 279 IN A 104.22.49.198
call.element.io. 279 IN A 104.22.48.198
$ dig +noall +answer all call.ems.host
call.ems.host. 263 IN CNAME k8s-core-coreingr-23262e92df-35e512c9110f05c6.elb.eu-north-1.amazonaws.com.
k8s-core-coreingr-23262e92df-35e512c9110f05c6.elb.eu-north-1.amazonaws.com. 23 IN A 13.48.142.24
$ dig +noall +answer all collector.github.com
collector.github.com. 3588 IN CNAME glb-db52c2cf8be544.github.com.
glb-db52c2cf8be544.github.com. 48 IN A 140.82.113.22
$ dig +noall +answer all dka575ofm4ao0.cloudfront.net
dka575ofm4ao0.cloudfront.net. 23 IN A 13.225.20.102
dka575ofm4ao0.cloudfront.net. 23 IN A 13.225.20.200
dka575ofm4ao0.cloudfront.net. 23 IN A 13.225.20.12
dka575ofm4ao0.cloudfront.net. 23 IN A 13.225.20.70
$ dig +noall +answer all economic-calendar.tradingview.com
economic-calendar.tradingview.com. 20 IN A 89.43.104.119
$ dig +noall +answer all element-hq.github.io
element-hq.github.io. 3579 IN A 185.199.108.153
element-hq.github.io. 3579 IN A 185.199.110.153
element-hq.github.io. 3579 IN A 185.199.109.153
element-hq.github.io. 3579 IN A 185.199.111.153
$ dig +noall +answer all embed-cdn.spotifycdn.com
embed-cdn.spotifycdn.com. 286 IN CNAME tls13.spotifycdn.map.fastly.net.
tls13.spotifycdn.map.fastly.net. 16 IN A 199.232.150.250
$ dig +noall +answer all ems-docs.element.io
ems-docs.element.io. 280 IN CNAME k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com. 40 IN A 3.72.129.101
$ dig +noall +answer all ems.element.io
ems.element.io. 280 IN CNAME k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com. 40 IN A 3.64.237.143
$ dig +noall +answer all encore.scdn.co
encore.scdn.co. 287 IN CNAME encore.spotifycdn.com.
encore.spotifycdn.com. 287 IN CNAME default.cdn-gslb.spotify.com.
default.cdn-gslb.spotify.com. 47 IN CNAME common-eipb-ak.spotifycdn.com.edgesuite.net.
common-eipb-ak.spotifycdn.com.edgesuite.net. 21587 IN CNAME squadcdn.scdn.co.splitter-eip.akadns.net.
squadcdn.scdn.co.splitter-eip.akadns.net. 47 IN CNAME i.scdn.co-noeip.akamaized.net.
i.scdn.co-noeip.akamaized.net. 347 IN CNAME a1520.dscc.akamai.net.
a1520.dscc.akamai.net. 7 IN A 2.18.121.83
a1520.dscc.akamai.net. 7 IN A 2.18.121.91
$ dig +noall +answer all ethercalc.net
ethercalc.net. 280 IN A 172.67.129.164
ethercalc.net. 280 IN A 104.21.1.167
$ dig +noall +answer all etherpad.integrations.element.io
etherpad.integrations.element.io. 280 IN CNAME k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com. 40 IN A 3.64.237.143
$ dig +noall +answer all fonts.googleapis.com
fonts.googleapis.com. 23 IN A 64.233.167.95
$ dig +noall +answer all fonts.gstatic.com
fonts.gstatic.com. 245 IN A 108.177.15.94
$ dig +noall +answer all gew1-spclient.spotify.com
gew1-spclient.spotify.com. 236 IN CNAME edge-web-gew1.dual-gslb.spotify.com.
edge-web-gew1.dual-gslb.spotify.com. 86 IN A 35.186.224.18
$ dig +noall +answer all github.com
github.com. 6 IN A 140.82.121.4
$ dig +noall +answer all github.githubassets.com
github.githubassets.com. 767 IN A 185.199.108.154
github.githubassets.com. 767 IN A 185.199.109.154
github.githubassets.com. 767 IN A 185.199.110.154
github.githubassets.com. 767 IN A 185.199.111.154
$ dig +noall +answer all googleads.g.doubleclick.net
googleads.g.doubleclick.net. 224 IN A 173.194.76.156
googleads.g.doubleclick.net. 224 IN A 173.194.76.157
googleads.g.doubleclick.net. 224 IN A 173.194.76.155
googleads.g.doubleclick.net. 224 IN A 173.194.76.154
$ dig +noall +answer all i.scdn.co
i.scdn.co. 287 IN CNAME image-scdn.cdn-gslb.spotify.com.
image-scdn.cdn-gslb.spotify.com. 47 IN CNAME scdnco.spotify.map.fastly.net.
scdnco.spotify.map.fastly.net. 17 IN A 199.232.150.248
$ dig +noall +answer all i.ytimg.com
i.ytimg.com. 132 IN A 173.194.76.119
i.ytimg.com. 132 IN A 142.251.168.119
i.ytimg.com. 132 IN A 64.233.167.119
i.ytimg.com. 132 IN A 64.233.184.119
i.ytimg.com. 132 IN A 66.102.1.119
i.ytimg.com. 132 IN A 74.125.71.119
i.ytimg.com. 132 IN A 74.125.206.119
i.ytimg.com. 132 IN A 142.250.110.119
i.ytimg.com. 132 IN A 64.233.166.119
i.ytimg.com. 132 IN A 108.177.15.119
i.ytimg.com. 132 IN A 74.125.133.119
$ dig +noall +answer all id.element.io
id.element.io. 279 IN CNAME k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com. 39 IN A 3.64.237.143
$ dig +noall +answer all img.shields.io
img.shields.io. 285 IN A 172.64.195.2
img.shields.io. 285 IN A 172.64.194.2
$ dig +noall +answer all integrations.element.io
integrations.element.io. 279 IN CNAME k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com. 39 IN A 3.64.237.143
$ dig +noall +answer all integrations.ems.host
integrations.ems.host. 263 IN CNAME k8s-core-coreingr-b3a4d5441e-11aa9fe745bc6bd9.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3a4d5441e-11aa9fe745bc6bd9.elb.eu-central-1.amazonaws.com. 23 IN A 3.73.156.240
$ dig +noall +answer all jnn-pa.googleapis.com
jnn-pa.googleapis.com. 260 IN A 142.250.110.95
jnn-pa.googleapis.com. 260 IN A 64.233.184.95
jnn-pa.googleapis.com. 260 IN A 74.125.71.95
jnn-pa.googleapis.com. 260 IN A 66.102.1.95
jnn-pa.googleapis.com. 260 IN A 64.233.167.95
jnn-pa.googleapis.com. 260 IN A 108.177.15.95
jnn-pa.googleapis.com. 260 IN A 142.251.168.95
jnn-pa.googleapis.com. 260 IN A 173.194.76.95
jnn-pa.googleapis.com. 260 IN A 64.233.166.95
jnn-pa.googleapis.com. 260 IN A 142.251.173.95
jnn-pa.googleapis.com. 260 IN A 74.125.133.95
jnn-pa.googleapis.com. 260 IN A 74.125.206.95
$ dig +noall +answer all js.stripe.com
js.stripe.com. 13 IN CNAME dexeqbeb7giwr.cloudfront.net.
dexeqbeb7giwr.cloudfront.net. 43 IN A 13.227.219.58
dexeqbeb7giwr.cloudfront.net. 43 IN A 13.227.219.97
dexeqbeb7giwr.cloudfront.net. 43 IN A 13.227.219.101
dexeqbeb7giwr.cloudfront.net. 43 IN A 13.227.219.27
$ dig +noall +answer all livekit-jwt.call.element.io
livekit-jwt.call.element.io. 279 IN CNAME k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com. 39 IN A 3.72.129.101
$ dig +noall +answer all m.stripe.com
m.stripe.com. 48 IN A 44.238.119.32
m.stripe.com. 48 IN A 35.155.200.145
m.stripe.com. 48 IN A 44.225.16.159
m.stripe.com. 48 IN A 34.215.148.109
m.stripe.com. 48 IN A 44.241.18.241
m.stripe.com. 48 IN A 34.213.37.126
m.stripe.com. 48 IN A 34.208.13.71
m.stripe.com. 48 IN A 34.214.18.208
$ dig +noall +answer all m.stripe.network
m.stripe.network. 41 IN CNAME stripecdn.map.fastly.net.
stripecdn.map.fastly.net. 11 IN A 151.101.128.176
stripecdn.map.fastly.net. 11 IN A 151.101.64.176
stripecdn.map.fastly.net. 11 IN A 151.101.192.176
stripecdn.map.fastly.net. 11 IN A 151.101.0.176
$ dig +noall +answer all matomo.openstreetmap.org
matomo.openstreetmap.org. 107 IN A 184.104.226.110
$ dig +noall +answer all matomo.riot.im
matomo.riot.im. 280 IN A 104.26.5.138
matomo.riot.im. 280 IN A 104.26.4.138
matomo.riot.im. 280 IN A 172.67.70.226
$ dig +noall +answer all matrix-org.github.io
matrix-org.github.io. 3600 IN A 185.199.110.153
matrix-org.github.io. 3600 IN A 185.199.108.153
matrix-org.github.io. 3600 IN A 185.199.109.153
matrix-org.github.io. 3600 IN A 185.199.111.153
$ dig +noall +answer all matrix.org
matrix.org. 215 IN A 172.67.19.90
matrix.org. 215 IN A 104.20.201.37
matrix.org. 215 IN A 104.20.200.37
$ dig +noall +answer all meet.element.io
meet.element.io. 580 IN CNAME k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com.
k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com. 40 IN A 54.93.211.59
k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com. 40 IN A 3.124.80.226
k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com. 40 IN A 3.121.134.149
$ dig +noall +answer all modular.im
modular.im. 280 IN A 104.26.15.131
modular.im. 280 IN A 104.26.14.131
modular.im. 280 IN A 172.67.68.192
$ dig +noall +answer all open.spotify.com
open.spotify.com. 297 IN CNAME open.spotify.com.edgesuite.net.
open.spotify.com.edgesuite.net. 21597 IN CNAME a1676.dscb.akamai.net.
a1676.dscb.akamai.net. 17 IN A 104.97.14.88
a1676.dscb.akamai.net. 17 IN A 104.97.14.106
$ dig +noall +answer all p.scdn.co
p.scdn.co. 266 IN CNAME scdnco.spotify.map.fastly.net.
scdnco.spotify.map.fastly.net. 30 IN A 199.232.150.248
$ dig +noall +answer all pay.stripe.com
pay.stripe.com. 30 IN A 198.202.176.141
$ dig +noall +answer all polyfill.io
polyfill.io. 201 IN A 151.101.1.26
polyfill.io. 201 IN A 151.101.129.26
polyfill.io. 201 IN A 151.101.65.26
polyfill.io. 201 IN A 151.101.193.26
$ dig +noall +answer all posthog-element-call.element.io
posthog-element-call.element.io. 280 IN CNAME k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com. 40 IN A 3.72.129.101
$ dig +noall +answer all pushstream.tradingview.com
pushstream.tradingview.com. 56 IN CNAME pushstream-eu.tradingview.com.
pushstream-eu.tradingview.com. 56 IN A 93.123.102.208
$ dig +noall +answer all riot.im
riot.im. 104 IN A 172.67.70.226
riot.im. 104 IN A 104.26.4.138
riot.im. 104 IN A 104.26.5.138
$ dig +noall +answer all rr5---sn-aigzrn7e.googlevideo.com
rr5---sn-aigzrn7e.googlevideo.com. 1660 IN CNAME rr5.sn-aigzrn7e.googlevideo.com.
rr5.sn-aigzrn7e.googlevideo.com. 1660 IN A 173.194.5.42
$ dig +noall +answer all s.tradingview.com
s.tradingview.com. 24 IN A 52.222.139.19
s.tradingview.com. 24 IN A 52.222.139.111
s.tradingview.com. 24 IN A 52.222.139.34
s.tradingview.com. 24 IN A 52.222.139.36
$ dig +noall +answer all s3-symbol-logo.tradingview.com
s3-symbol-logo.tradingview.com. 193 IN CNAME s3-symbol-logo.b-cdn.net.
s3-symbol-logo.b-cdn.net. 35 IN A 207.211.214.145
$ dig +noall +answer all s3.tradingview.com
s3.tradingview.com. 39 IN A 52.222.139.42
s3.tradingview.com. 39 IN A 52.222.139.40
s3.tradingview.com. 39 IN A 52.222.139.55
s3.tradingview.com. 39 IN A 52.222.139.94
$ dig +noall +answer all scalar.vector.im
scalar.vector.im. 280 IN CNAME k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-baea756bc1-7748860684099c0d.elb.eu-central-1.amazonaws.com. 40 IN A 3.64.237.143
$ dig +noall +answer all sentry.matrix.org
sentry.matrix.org. 580 IN CNAME k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com.
k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com. 40 IN A 3.124.80.226
k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com. 40 IN A 3.121.134.149
k8s-global-88e07f8a34-1957068544.eu-central-1.elb.amazonaws.com. 40 IN A 54.93.211.59
$ dig +noall +answer all sentry.tools.element.io
sentry.tools.element.io. 165 IN CNAME k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com. 25 IN A 3.72.129.101
$ dig +noall +answer all sfu.call.element.io
sfu.call.element.io. 280 IN CNAME k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3bd03665a-d205ac2886bcb3d3.elb.eu-central-1.amazonaws.com. 40 IN A 3.72.129.101
$ dig +noall +answer all sonarcloud.io
sonarcloud.io. 29 IN A 54.192.137.29
sonarcloud.io. 29 IN A 54.192.137.113
sonarcloud.io. 29 IN A 54.192.137.14
sonarcloud.io. 29 IN A 54.192.137.16
$ dig +noall +answer all spclient.wg.spotify.com
spclient.wg.spotify.com. 298 IN CNAME edge-web.dual-gslb.spotify.com.
edge-web.dual-gslb.spotify.com. 148 IN A 35.186.224.25
$ dig +noall +answer all static.doubleclick.net
static.doubleclick.net. 250 IN A 173.194.76.149
static.doubleclick.net. 250 IN A 173.194.76.148
$ dig +noall +answer all static.tradingview.com
static.tradingview.com. 277 IN CNAME d34vo3dglcgqwn.cloudfront.net.
d34vo3dglcgqwn.cloudfront.net. 37 IN A 65.9.86.55
d34vo3dglcgqwn.cloudfront.net. 37 IN A 65.9.86.43
d34vo3dglcgqwn.cloudfront.net. 37 IN A 65.9.86.54
d34vo3dglcgqwn.cloudfront.net. 37 IN A 65.9.86.53
$ dig +noall +answer all status.element.io
status.element.io. 280 IN CNAME lkh3j7gmv7x4.stspg-customer.com.
lkh3j7gmv7x4.stspg-customer.com. 40 IN CNAME status-element-io-ba0b601b-1586-41ca-9c10-db2237fdc2ed.saas.atlassian.com.
status-element-io-ba0b601b-1586-41ca-9c10-db2237fdc2ed.saas.atlassian.com. 40 IN A 18.239.83.57
status-element-io-ba0b601b-1586-41ca-9c10-db2237fdc2ed.saas.atlassian.com. 40 IN A 18.239.83.106
status-element-io-ba0b601b-1586-41ca-9c10-db2237fdc2ed.saas.atlassian.com. 40 IN A 18.239.83.90
status-element-io-ba0b601b-1586-41ca-9c10-db2237fdc2ed.saas.atlassian.com. 40 IN A 18.239.83.101
$ dig +noall +answer all tile.openstreetmap.org
tile.openstreetmap.org. 285 IN CNAME dualstack.n.sni.global.fastly.net.
dualstack.n.sni.global.fastly.net. 15 IN A 151.101.1.91
dualstack.n.sni.global.fastly.net. 15 IN A 151.101.129.91
dualstack.n.sni.global.fastly.net. 15 IN A 151.101.65.91
dualstack.n.sni.global.fastly.net. 15 IN A 151.101.193.91
$ dig +noall +answer all user-images.githubusercontent.com
user-images.githubusercontent.com. 1389 IN A 185.199.109.133
user-images.githubusercontent.com. 1389 IN A 185.199.111.133
user-images.githubusercontent.com. 1389 IN A 185.199.108.133
user-images.githubusercontent.com. 1389 IN A 185.199.110.133
$ dig +noall +answer all vector.im
vector.im. 31 IN A 104.21.28.52
vector.im. 31 IN A 172.67.144.66
$ dig +noall +answer all web-docs.element.dev
web-docs.element.dev. 300 IN CNAME vector-im.github.io.
vector-im.github.io. 3600 IN A 185.199.110.153
vector-im.github.io. 3600 IN A 185.199.111.153
vector-im.github.io. 3600 IN A 185.199.109.153
vector-im.github.io. 3600 IN A 185.199.108.153
$ dig +noall +answer all web-sdk-assets.spotifycdn.com
web-sdk-assets.spotifycdn.com. 268 IN CNAME tls13.spotifycdn.map.fastly.net.
tls13.spotifycdn.map.fastly.net. 24 IN A 199.232.150.250
$ dig +noall +answer all widgetdata.tradingview.com
widgetdata.tradingview.com. 60 IN CNAME widgetdata-eu.tradingview.com.
widgetdata-eu.tradingview.com. 60 IN A 92.223.127.141
$ dig +noall +answer all www.google.com
www.google.com. 271 IN A 66.102.1.106
www.google.com. 271 IN A 66.102.1.147
www.google.com. 271 IN A 66.102.1.99
www.google.com. 271 IN A 66.102.1.103
www.google.com. 271 IN A 66.102.1.105
www.google.com. 271 IN A 66.102.1.104
$ dig +noall +answer all www.gravatar.com
www.gravatar.com. 288 IN A 192.0.73.2
$ dig +noall +answer all www.gstatic.com
www.gstatic.com. 24 IN A 108.177.15.94
$ dig +noall +answer all www.openstreetmap.org
www.openstreetmap.org. 94 IN A 184.104.179.139
www.openstreetmap.org. 94 IN A 184.104.179.140
www.openstreetmap.org. 94 IN A 184.104.179.141
$ dig +noall +answer all www.recaptcha.net
www.recaptcha.net. 272 IN A 74.125.206.94
$ dig +noall +answer all www.tradingview-widget.com
www.tradingview-widget.com. 60 IN A 52.222.139.32
www.tradingview-widget.com. 60 IN A 52.222.139.106
www.tradingview-widget.com. 60 IN A 52.222.139.108
www.tradingview-widget.com. 60 IN A 52.222.139.128
$ dig +noall +answer all www.youtube.com
www.youtube.com. 252 IN CNAME youtube-ui.l.google.com.
youtube-ui.l.google.com. 252 IN A 74.125.206.190
youtube-ui.l.google.com. 252 IN A 64.233.166.136
youtube-ui.l.google.com. 252 IN A 74.125.71.93
youtube-ui.l.google.com. 252 IN A 74.125.206.136
youtube-ui.l.google.com. 252 IN A 64.233.167.91
youtube-ui.l.google.com. 252 IN A 74.125.71.91
youtube-ui.l.google.com. 252 IN A 64.233.166.190
youtube-ui.l.google.com. 252 IN A 64.233.166.93
youtube-ui.l.google.com. 252 IN A 64.233.167.136
youtube-ui.l.google.com. 252 IN A 64.233.167.190
youtube-ui.l.google.com. 252 IN A 74.125.71.190
youtube-ui.l.google.com. 252 IN A 74.125.71.136
youtube-ui.l.google.com. 252 IN A 74.125.206.91
youtube-ui.l.google.com. 252 IN A 64.233.166.91
youtube-ui.l.google.com. 252 IN A 74.125.206.93
youtube-ui.l.google.com. 252 IN A 64.233.167.93
$ dig +noall +answer all youtube.com
youtube.com. 198 IN A 74.125.133.136
youtube.com. 198 IN A 74.125.133.93
youtube.com. 198 IN A 74.125.133.190
youtube.com. 198 IN A 74.125.133.91
$ dig +noall +answer all yt3.ggpht.com
yt3.ggpht.com. 253 IN CNAME photos-ugc.l.googleusercontent.com.
photos-ugc.l.googleusercontent.com. 253 IN A 64.233.166.132
```
The values for your base domains will depend on your region and custom domain, here are the values for our Element.io EMS server with the EMS domain `element.ems.host`, Custom homeserver domain `element.io`, and custom Element Web domain `chat.element.io`:
```bash
$ dig +noall +answer all chat.element.io
chat.element.io. 300 IN A 104.22.49.198
chat.element.io. 300 IN A 172.67.12.112
chat.element.io. 300 IN A 104.22.48.198
$ dig +noall +answer all element.element.io
element.element.io. 300 IN CNAME k8s-core-coreingr-b3a4d5441e-11aa9fe745bc6bd9.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3a4d5441e-11aa9fe745bc6bd9.elb.eu-central-1.amazonaws.com. 60 IN A 3.73.156.240
$ dig +noall +answer all element.ems.host
element.ems.host. 242 IN CNAME k8s-core-coreingr-b3a4d5441e-11aa9fe745bc6bd9.elb.eu-central-1.amazonaws.com.
k8s-core-coreingr-b3a4d5441e-11aa9fe745bc6bd9.elb.eu-central-1.amazonaws.com. 60 IN A 3.73.156.240
$ dig +noall +answer all element.io
element.io. 300 IN A 104.22.48.198
element.io. 300 IN A 104.22.49.198
element.io. 300 IN A 172.67.12.112
```
Your `.element.io` and `.ems.host` IP will be in AWS' IP ranges in your hosting region (Frankfurt/eu-central-1, Stockholm/eu-north-1, London/eu-west-2, or Ohio/us-east-2).
# EMS Server With Custom Domain
For this guide, I will be using the domain
element.io. I will set up EMS so that the
Matrix usernames becomes `@someone:element.io`, and the Element client will be at
https://chat.element.io/
From the guide at [Get Your Own EMS Server](get-your-own-ems-server), I will be replacing the EMS hostname
`ems-demo-staging.ems.host` with `element.ems.host`
Custom domains are only supported with Element Enterprise Cloud plans.
## Prerequisites
- You own and control the domain you want to use
- If you do not have a website on the domain you want to use with your EMS server:
- You can create a CNAME DNS record for the domain. Some providers call this ALIAS or CNAME Flattening when used on
the root of the domain (domain root = `yourdomain.com`, not `something.yourdomain.com`)
- If you have a website on the domain you want to use with your EMS server:
- Your website has HTTPS enabled using a valid certificate issued by a commonly recognized provider. For example,
Comodo or LetsEncrypt.
- You can serve plain-text JSON files at these exact paths
- `https://yourdomain.com/.well-known/matrix/client`
- `https://yourdomain.com/.well-known/matrix/server`
- Note that these files do not and cannot have a file extension
- You can add the header `Access-Control-Allow-Origin: *` to the client file on the web server
## See also
- [FAQ: Can I use a subdomain instead of the root domain with my EMS server?](https://ems-docs.element.io/link/6#bkmrk-can-i-use-a-subdomai)
- [FAQ: Can I use EMS-hosted well-knowns with the root of my domain?](https://ems-docs.element.io/link/6#bkmrk-can-i-use-ems-hosted)
## Setup
Some providers for DNS and website hosting providers need special configuration. See
[Provider specific instructions](#bkmrk-provider-specific-in) at the bottom for known solutions.
1. Follow steps 1 - 10 from [Get Your Own EMS Server](get-your-own-ems-server)
2. On step 10 from [Get Your Own EMS Server](get-your-own-ems-server), turn ON `Custom DNS`
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383058866-07-59-am.png)
3. In the `Custom Homeserver domain` field, enter `element.io`
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659627256442-57-31-pm.png)
4. Create two files on your website according to the instructions given.
The path cannot be changed, but up to 30 redirects are supported.
While not required, you should add the header `Content-Type application/json` to both files.
1. `https://element.io/.well-known/matrix/server`
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659627292963-32-20-pm.png)
```json
{
"m.server": "element.ems.host:443"
}
```
2. `https://element.io/.well-known/matrix/client`
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659627321046-32-38-pm.png)
You need to enable the CORS header `Access-Control-Allow-Origin: *` on the web server for this file. See
https://enable-cors.org/ for
instructions on how to do this. If you are using redicrects, the CORS headers must be set on all steps/hops.
```json
{
"m.homeserver": {
"base_url": "https://element.ems.host"
},
"m.identity_server": {
"base_url": "https://vector.im"
},
"org.matrix.msc3575.proxy": {
"url": "https://element.ems.host"
}
}
```
Optional Nginx-specific configuration
If your web server is running Nginx, you can set this in the Nginx config instead of creating actual files.
```plaintext
server {
server_name element.io
...
# Matrix well-known files
location /.well-known/matrix/client {
return 200 '{"m.homeserver":{"base_url":"https://element.ems.host"},"m.identity_server":{"base_url":"https://vector.im"},"org.matrix.msc3575.proxy":{"url":"https://element.ems.host"}}';
add_header Content-Type application/json;
add_header 'Access-Control-Allow-Origin' '*';
}
location /.well-known/matrix/server {
return 200 '{"m.server": "element.ems.host:443"}';
add_header Content-Type application/json;
}
}
```
5. Click `Check again` to verify that your `.well-known` files are configured correctly
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659627418181-36-42-pm.png)
You can also verify your `.well-known` files from the command line
Note the lines `access-control-allow-origin: *` and `content-type: application/json`
1. On Mac or Linux, using the `terminal`
```bash
$ curl -i https://element.io/.well-known/matrix/client
HTTP/2 200
date: Fri, 31 Jul 2020 09:11:21 GMT
content-type: application/json
content-length: 129
set-cookie: __cfduid=x...; expires=Sun, 30-Aug-20 09:11:21 GMT; path=/; domain=.element.io; HttpOnly; SameSite=Lax
access-control-allow-origin: *
cf-cache-status: DYNAMIC
cf-request-id: 0...
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 5...
{
"m.homeserver": {
"base_url": "https://element.ems.host"
},
"m.identity_server": {
"base_url": "https://vector.im"
},
"org.matrix.msc3575.proxy": {
"url": "https://element.ems.host"
}
}
$ curl -i https://element.io/.well-known/matrix/server
HTTP/2 200
date: Fri, 31 Jul 2020 09:11:25 GMT
content-type: application/json
content-length: 52
set-cookie: __cfduid=x...; expires=Sun, 30-Aug-20 09:11:25 GMT; path=/; domain=.element.io; HttpOnly; SameSite=Lax
access-control-allow-origin: *
cf-cache-status: DYNAMIC
cf-request-id: 0...
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 5...
{
"m.server": "element.ems.host:443"
}
```
2. On Windows, using `PowerShell`
```powershell
PS C:\Users\twilight> Invoke-WebRequest -Uri https://element.io/.well-known/matrix/client
StatusCode : 200
StatusDescription : OK
Content : {
"m.homeserver": {
"base_url": "https://element.ems.host"
},
"m.identity_server": {
"base_url": "https://vector.im"
},
"org.matrix.msc3575.proxy": {
"url": "https://element.ems.host"
}
}
RawContent : HTTP/1.1 200 OK
Connection: keep-alive
Access-Control-Allow-Origin: *
CF-Cache-Status: DYNAMIC
cf-request-id: 0...
Expect-CT: max-age=604800, report-uri="https://repor...
Forms : {}
Headers : {[Connection, keep-alive], [Access-Control-Allow-Origin, *], [CF-Cache-Status, DYNAMIC], [cf-request-id, 0...]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : System.__ComObject
RawContentLength : 129
PS C:\Users\twilight> Invoke-WebRequest -Uri https://element.io/.well-known/matrix/server
StatusCode : 200
StatusDescription : OK
Content : {
"m.server": "element.ems.host:443"
}
RawContent : HTTP/1.1 200 OK
Connection: keep-alive
Access-Control-Allow-Origin: *
CF-Cache-Status: DYNAMIC
cf-request-id: 0...
Expect-CT: max-age=604800, report-uri="https://repor...
Forms : {}
Headers : {[Connection, keep-alive], [Access-Control-Allow-Origin, *], [CF-Cache-Status, DYNAMIC], [cf-request-id, 0...]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : System.__ComObject
RawContentLength : 52
```
6. You can continue without the `.well-known` files in place, but your server will have limited functionality until this is fixed
7. In the `Custom Client domain` field, enter `chat.element.io`. This can be any domain, except the same as `Custom Homeserver domain`
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659627867813-44-13-pm.png)
8. Create a CNAME DNS record with your DNS provider according to the instructions given
`chat.element.io. CNAME element.element.io.`
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659627663519-40-24-pm.png)
9. This shows how this is done with Cloudflare DNS. Depending on your DNS provider, this might be different. Consult the
documentation for your provider. Note that Proxy must be turned off with Cloudflare.
[](https://ems-docs.element.io/uploads/images/gallery/2022-08/image-1659628294089-50-07-pm.png)
10. Back on EMS, click `Check again`. Note that sometimes it might take a while for your new DNS record to propagate.
You can continue, but functionality will be limited. Check back with the Hosts tab on
https://ems.element.io/user/hosting
and click `Rebuild Host` once the DNS record is in place.
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383120826-56-18-am.png)
You can also verify the CNAME DNS record using the command line
1. On Mac or Linux, using the `terminal`
```bash
$ dig chat.element.io CNAME
; <<>> DiG 9.10.6 <<>> chat.element.io CNAME
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57888
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;chat.element.io. IN CNAME
;; ANSWER SECTION:
chat.element.io. 299 IN CNAME element.element.io.
;; Query time: 32 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Fri Jul 31 10:21:56 BST 2020
;; MSG SIZE rcvd: 91
```
2. On Windows, using `PowerShell`
```powershell
PS C:\Users\twilight> Resolve-DnsName -Name chat.element.io -Type CNAME
Name Type TTL Section NameHost
---- ---- --- ------- --------
chat.element.io CNAME 299 Answer element.element.io
```
11. Continue from step 11 on [Get Your Own EMS Server](get-your-own-ems-server)
## Provider-specific instructions
### GitHub Pages
If you are hosting your website with GitHub Pages, add this to the Jekyll config file `_config.yml`
```yaml
include:
- .well-known
```
### Microsoft Azure
If you are using Microsoft 365 / Azure to manage your domain or the rest of your infrastructure, please use the following instructions to host the `.well-known/matrix` URI (RFC 8615).
In this section, we will configure Azure to serve `https://yourdomain.com/.well-known/matrix/client` and `https://yourdomain.com/.well-known/matrix/client`.
The summary of steps is as follows:
- prepare json files
- create a Storage account then enable a Static website
- upload the json files to .well-known/matrix/ in the `$web` container
- create a CDN and an endpoint for this container
- create a `CNAME` DNS entry for your custom domain, pointing to your CDN endpoint
- associate your custom domain to your CDN endpoint
#### Prepare client and server .well-known files locally
On your computer, prepare two plain text files called `client` and `server` (again, notice the lack of file extension such as ".txt") which contain the following:
##### client
```json
{
"m.homeserver": {
"base_url": "https://your-tenant.ems.host"
},
"m.identity_server": {
"base_url": "https://vector.im"
},
"org.matrix.msc3575.proxy": {
"url": "https://your-tenant.ems.host"
}
}
```
Remember to replace `your-tenant` by the name of your EMS tenant.
##### server
```json
{
"m.homeserver": {
"base_url": "https://your-tenant.ems.host:443"
}
}
```
Remember to replace `your-tenant` by the name of your EMS tenant.
You will be uploading these shortly.
#### Create a Storage account and Static website
##### Storage account
In the Azure Portal, [create a Storage account](https://portal.azure.com/#create/Microsoft.StorageAccount-ARM).
[](https://ems-docs.element.io/uploads/images/gallery/2023-11/screenshot-2023-11-10-at-14-20-46-microsoft-azure.png)
The name needs to be unique to Azure. `yourdomainwellknown` is an option that should work well in most scenarios.
Performarce can be left to Standard.
Redundancy should be set to Geo-redundant storage (GRS) as the .well-known URI will be a core part of your EMS deployment.
You can leave all other options to their default or change them to fit your specific deployment scenario.
Finally, click create.
##### Static website
Once the Storage account is created, you will need to create a Static website in this Storage account.
In the Storage account overview, choose "Static website", in the Data management section.
[](https://ems-docs.element.io/uploads/images/gallery/2023-11/H3rscreenshot-2023-11-10-at-15-15-32-microsoft-azure.png)
You do not need to provide a specific Index document name or Error document path.
Enabling the Static website in your Storage account will automatically create a `$web` storage container to which you can upload the json text files which will be served at the .well-known URI.
Go to "Containers", in the "Data storage" section, to upload the `client` and `server` files you prepered earlier.
Click on the `$web` container, then chose "Upload", which will open a panel on the right.
When uploading the `client` and `server` files, make sure to open the "advanced" part of the upload panel and choose to upload to a specific folder: `.well-known/matrix/`
[](https://ems-docs.element.io/uploads/images/gallery/2023-11/screenshot-2023-11-10-at-15-47-44-microsoft-azure.png)
#### Create a CDN, `CNAME` DNS entry for your custom domain and Custom domain name for the CDN endpoint
Creating a CDN is needed because Azure does not allow serving HTTPS over a custom domain using only a Storage account Static website. To do so, a CDN is necessary.
##### Create a CDN endpoint
Go back to your Storage account's main view and choose "Front Door and CDN" in the Security + Networking section, to create a CDN endpoint.
[](https://ems-docs.element.io/uploads/images/gallery/2023-11/screenshot-2023-11-10-at-15-57-51-microsoft-azure.png)
Service type: Azure CDN is sufficient, the more advanced features of Azure Front Door are not necessary here.
If you need to create a new profile, you may call the Profile name and Endpoint name as you wish.
For consistency, it is suggested to call them `yourdomainwellknown` as previously.
For Origin host name, pick your Static website.
For Query string caching behaviour, pick Ignore Query String, although this setting is not important in our context.
Once your endpoint is deployed, go to the resource, then go to your endpoint's further settings by clicking on it. Make note of its hostname (`rfc8615demo.azureedge.net` in our example) as you will need it shortly.
[](https://ems-docs.element.io/uploads/images/gallery/2023-11/screenshot-2023-11-10-at-16-09-22-microsoft-azure.png)
##### Create `CNAME` DNS entry for your custom domain
You will now create a DNS entry for your custom domain, a `CNAME` pointing to your Azure CDN endpoint's hostname. How to do so exactly will depend on who hosts your DNS servers. The specifics of this are beyond this documentation, but the following general information should be sufficient.
In your DNS provider's admin panel, add a DNS entry with the following details:
- Type: `CNAME`
- Domain: your custom domain, such as `yourdomain.com`
- Target: your Azure CDN Endpoint's hostname, such as `rfc8615demo.azureedge.net` in our example
Once created, this DNS entry may take some time to propagate, but in most cases will be picked up quickly by Azure, as needed in the next step.
##### Associate your custom domain with your CDN Endpoint
In the endpoint's settings, choose "+ custom domain" to start adding your custom domain. A panel will open on the right.
Enter your custom domain: `yourdomain.com` and finally, click add.
If the `CNAME` entry can be seen by Azure, after a few minutes your custom domain should be associated with your CDN Endpoint.
#### Final result
`https://yourdomain.com/.well-known/matrix/client` and `https://yourdomain.com/.well-known/matrix/server` are now served over HTTPS by Azure.
You should now have the following resources in your Azure account:
- Storage account
- Front Door and CDN Profile
- Endpoint
#### Resources
- https://learn.microsoft.com/en-us/azure/cdn/cdn-create-a-storage-account-with-cdn
- https://learn.microsoft.com/en-us/azure/cdn/cdn-storage-custom-domain-https
# How to Get an EMS Server
1. Go to https://ems.element.io/
1. Click `Sign up or Sign in`
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383169006-57-04-pm.png)
1. Enter your email address
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383213498-58-03-pm.png)
1. Click the confirmation link in the email
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383245452-59-54-pm.png)
1. Enter your name or company name and a password on https://ems.element.io/user/account. Then click Billing address and payment method
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383269217-13-48-pm.png)
1. Enter your billing address and credit card information on https://ems.element.io/user/billing
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383299104-15-49-pm.png)
1. Click `Your Account`, then `Manage Servers` to get started setting up your EMS server
1. Click the `Setup` tab, and choose your Host Size
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383341490-17-55-pm.png)
1. Select your hostname and click Check. Keep in mind that this cannot be changed later
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383386684-19-40-pm.png)
1. Configure your host settings, then click Next. If you want to use Custom DNS (ie. have your usernames be `@someone:yourdomain.com` instead of `@someone:yourhost.ems.host` and have your Element client on your own domain), see [EMS Server With Custom Domain](ems-server-with-custom-domain)
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383412035-20-45-pm.png)
1. Confirm your payment options. Then click Purchase
1. Sit tight for a few minutes while your server is being built
1. When it's done, click `Manage hosts` to configure additional settings and add users
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383506456-25-37-pm.png)
# Migrate From EMS to Self-Hosted
For support on Synapse or matrix-media-repo, ask in the Matrix rooms #synapse:matrix.org and #mediarepo:t2bot.io. For support on bridges, see the [bridge documentation](#bkmrk-bridges) for each bridge's support channel.
See also [this](https://matrix.org/blog/2024/01/migrating-from-ems-to-selfhosted-matrix/) excellent blog post by Josh Simmons at The Matrix.org Foundation.
## Important
- It is impossible to change the domain of any Matrix server. Therefore if your EMS server is not using Custom DNS (i.e. your Matrix IDs are `@someone:hostname.ems.host`), unfortunately it is not possible to import your export to your own or another environment.
- You can run an export with this domain in a local environment if you set up your own DNS and self-signed certificates. But you will not be able to federate with the public Matrix federation.
- Do not cancel your EMS server until you have downloaded your export and verified its content. Canceling your server will erase your data.
- You will experience some downtime as your server will be stopped while the export is running. The EMS export tool will estimate the actual downtime when initiated.
- Ensure all your users have key backup configured and working before starting the export and migration. All clients need to log out and in again after the migration. See the [Cross Signing](https://ems-docs.element.io/books/element-cloud-documentation/chapter/cross-signing) section for more information about key backup.
- It is impossible to read encrypted messages or media from the export. Encrypted data in Matrix can only be decrypted by the user in their client when they have the required decryption keys.
## Export data
1. Go to
1. Select the server you want to export from in the drop-down box, then click `Create export`
1. Wait for the export of your config, database, and media to complete
1. Once all exports have completed, download all files provided
## Import process
For all components, you must install the same version as your EMS server is running. Version information is provided in the `hostname-config.md` file. If a newer version is available, once the import is completed and verified, follow the official upgrade documentation for each component to upgrade.
All required configuration values are provided in the `hostname-config.md` file.
1. Following official documentation, install and configure
1. PostgreSQL. Refer to the Synapse PostgreSQL documentation for database setup
1. Synapse
1. Optional (see media step below): matrix-media-repo
1. When generating your Synapse configuration file, you MUST use the same domain as your EMS server
1. Do not start Synapse yet
1. In the Synapse config file (usually `homeserver.yaml`), set:
1. pepper. If you do not do this, you have to reset all passwords
1. Signing key. This is stored in a file. See this config file option for path. Alternatively, add the public key for your EMS hosted server to `old_signing_keys`. If your EMS server is still running, you can find your public signing key at
1. macaroon_secret_key
1. Import the Synapse database
1. Create a new database per the Synapse PostgreSQL documentation
1. Or, if your Synapse database is not empty, empty it
**WARNING - THIS WILL IMMEDIATELY AND IRRECOVERABLY DELETE DATA, PLEASE TAKE CARE. WE ACCEPT NO RESPONSIBILITY IF YOU DELETE THE WRONG DATABASE OR DATA**
Connect to the database with `psql`, then run the following queries:
```sql
DO $$ DECLARE
r RECORD;
BEGIN
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
EXECUTE 'DROP TABLE ' || quote_ident(r.tablename) || ' CASCADE';
END LOOP;
END $$;
DROP sequence cache_invalidation_stream_seq;
DROP sequence state_group_id_seq;
DROP sequence user_id_seq;
```
Disconnect from the database
1. Extract the database dump
```
unzip emsHostname-synapse-database.zip
```
1. Import the database dump
```bash
pg_restore \
--username USERNAME \
--host HOSTNAME \
--dbname DATABASE_NAME \
--no-owner \
/path/to/id-emsHostname-synapse-database.dir/
```
1. Verify that sequence was set correctly. Connect to the database and run the query
```sql
SELECT * FROM state_group_id_seq;
```
`last_value` should be greater than 1
1. Import media into matrix-media-repo according to documentation here or import media into Synapses built-in media repository using the `import_to_synapse` executable available from the latest [matrix-media-repo release](https://github.com/t2bot/matrix-media-repo/releases)
1. Start Synapse and ensure everything is working as expected
1. Optionally, install Element Web or use another Matrix client
1. Optionally, install the sliding-sync proxy. This is required for Element X
- Note, we do not provide an export of the Sliding Sync database as this would not provide any value. As you need to log out and back in from Element X after the migration and in doing so your Sliding Sync proxy needs to re-sync each user. All your data is already included in the Synapse database
1. If you have any bridges, please see the documentation for each bridge
Discord |
Hookshot |
IRC |
Signal |
Slack |
Telegram |
Whatsapp
- The process for importing the bridge databases is the same as with Synapse
1. Cancel your EMS server. See [this](https://ems-docs.element.io/link/6#bkmrk-please-discontinue-m) FAQ document for instructions. **Note, this cannot be undone and all your data will be lost. Ensure your imported server is working as expected before doing this**
# Migrate From Self-Hosted to EMS
## Notes
Before starting with this guide, please contact EMS support from https://ems.element.io/support or by emailing [ems-support@element.io](mailto:ems-support@element.io)
- Except where specified, you should be able to just copy-paste each command in succession.
- Please do not change any file names anywhere.
## Preparation
This section outlines what you should do ahead of the migration in order to ensure the migration goes as quickly as possible and without issues.
- At the latest 48 hours before your migration is scheduled, set the TTL on any DNS records that need to be updated to the lowest allowed value.
- Upgrade your Synapse to the same version as EMS is running. Generally this will be the latest stable release. https://element.ems.host/_matrix/federation/v1/version is a good indicator, but confirm version with your EMS contact.
- This is not required, but if your Synapse version is not the same as the EMS version, your migration will take longer.
- Check the size of your database and report to your EMS contact:
- PostgreSQL: Connect to your database and issue the command `\l+`
- SQLite: `ls -lah /path/to/homeserver.db`
- Check the size of your media repository and report to your EMS contact.
- Synapse Media Store: `du -hs /path/to/synapse/media_store/`
- Matrix Media Repo: https://github.com/turt2live/matrix-media-repo/blob/master/docs/admin.md#per-server-usage
- If you are using SQLite instead of PostgreSQL, you should port your database to PostgreSQL by following [this](https://element-hq.github.io/synapse/latest/postgres.html) guide before dumping your database and sending to your EMS contact.
- This step is not required, but will speed up your migration.
## SSH to your matrix server
You might want to run everything in a `tmux` or a `screen` session to avoid disruption in case of a lost SSH connection.
## Generate password for gpg encryption
```bash
pwgen -s 64 1
```
Alternatively, you can use our GPG key. Note, this expires on 2023-04-28, if this is soon, please talk to your EMS contact.
ems-support-public.pgp
## GPG
If `gpg` is being uncooperative, use the command `gpgconf --kill gpg-agent`.
## Create a folder to store everything
```bash
mkdir -p /tmp/synapse_export
cd /tmp/synapse_export
```
The guide from here on assumes your current working directory is `/tmp/synapse_export`.
### Set restrictive permissions on the folder
If you are working as root: (otherwise set restrictive permissions as needed):
```bash
chmod 000 /tmp/synapse_export
```
## Copy Synapse config
Copy the following files and send to EMS Support:
- Your Synapse configuration file (usually `homeserver.yaml`)
- Your message signing key.
- This is stored in a separate file. See the Synapse config file for the path. The variable is `signing_key_path` https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#signing_key_path
## Stop Synapse
**DO NOT START IT AGAIN AFTER THIS**
Doing so can cause issues with federation and inconsistent data for your users.
While you wait for the database to export or files to transfer, you should edit or create the well-known files and DNS records to point to your EMS host. This can take a while to update so should be done as soon as possible in order to ensure your server will function properly when the migration is complete.
## Database export
### PostgreSQL
#### Dump, compress and encrypt
Replace:
- `` (ip or fqdn for your database server)
- `` (username for your synapse database)
- `` (the name of the database for synapse)
```bash
pg_dump -O -h -U -d | gzip > customer_db_export.sql.gz
gpg --symmetric --no-symkey-cache customer_db_export.sql.gz
rm customer_db_export.sql.gz
```
#### If required, split into smaller files
Please only do this if you have a slow connection and are worried about transferring a single large file.
```bash
split -b 100m customer_db_export.sql.gz.gpg customer_db_export.sql.gz.gpg.part-
rm customer_db_export.sql.gz.gpg
```
### SQLIte
#### Compress and encrypt
```bash
tar -zcvf homeserver.db.tar.gz /path/to/homeserver.db
gpg --symmetric --no-symkey-cache homeserver.db.tar.gz
rm homeserver.db.tar.gz
```
#### If required, split into smaller files
Please only do this if you have a slow connection and are worried about transferring a single large file.
```bash
split -b 100m homeserver.db.tar.gz homeserver.db.tar.gz.part-
rm homeserver.db.tar.gz
```
## Media export
### If you are using SQLIte as database
Skip ahead to and follow [Backup media export](#bkmrk-backup-media-export).
### Download the export tool
Download the latest version of `export_synapse_for_import-linux-x64` (or `export_synapse_for_import-win-x64.exe`) from https://github.com/turt2live/matrix-media-repo/releases
```bash
wget https://github.com/turt2live/matrix-media-repo/releases/download/vx.x.x/export_synapse_for_import-linux-x64
chmod +x export_synapse_for_import-linux-x64
```
### Run the export
Replace:
- `` (ip or fqdn for your database server)
- `` (the name of the database for synapse)
- `` (username for your synapse database)
- `/path/to/synapse/media_store` (the path to where synapse stores your media)
- `` (the domain for your server. this is the part that is in your usernames)
```bash
./export_synapse_for_import-linux-x64 -h
./export_synapse_for_import-linux-x64 -dbHost -dbPort 5432 -dbName -dbUsername -mediaDirectory /path/to/synapse/media_store -serverName -destination ./customer_media_export
mv logs customer_media_export
mv media-repo.yaml customer_media_export
rm export_synapse_for_import-linux-x64
```
### Compress and encrypt
```bash
tar -zcvf customer_media_export.tar.gz customer_media_export
gpg --symmetric --no-symkey-cache customer_media_export.tar.gz
rm customer_media_export.tar.gz
rm -r customer_media_export
```
### If required, split into smaller files
Please only do this if you have a slow connection and are worried about transferring a single large file.
```bash
split -b 100m customer_media_export.tar.gz.gpg customer_media_export.tar.gz.gpg.part-
rm customer_media_export.tar.gz.gpg
```
## Backup media export
### Compress and encrypt
Replace * `/path/to/synapse/media_store` (the path to where synapse stores your media)
```bash
tar -zcvf customer_backup_media_export.tar.gz /path/to/synapse/media_store
gpg --symmetric --no-symkey-cache customer_backup_media_export.tar.gz
rm customer_backup_media_export.tar.gz
```
### If required, split into smaller files
Please only do this if you have a slow connection and are worried about transferring a single large file.
```bash
split -b 100m customer_backup_media_export.tar.gz.gpg customer_backup_media_export.tar.gz.gpg.part-
rm customer_backup_media_export.tar.gz.gpg
```
## Transfer
Download the files, then upload to the Google Drive folder shared by EMS or a location as agreed with your EMS contact.
On your local computer:
```bash
scp -r -P 1234 -i ~/.ssh/matrix-server youruser@1.2.3.4:/tmp/synapse_export /some/local/folder
```
## Cleanup
We strongly recommend that you leave the export and Synapse untouched until the import is finished and everything is verified working.
## Note on users and Element
Element does have support for changing the delegated homeserver URL. All your users will have to sign out and sign in again to Element. You should ensure everyone has Key Backup configured and working.
Your users will not be able to decrypt messages send in their encrypted rooms while your server is offline for the migration.
### Force logout of old sessions after migration
If you do not log out all sessions for your users before the migration, you can force this later. Below is a sample config file for `nginx` that tells all clients trying to connect to it to sign out.
Note that the headers are important, otherwise this will not work one one or more of the Element clients. Valid HTTPS is required.
This is not tested on any other Matrix clients, but it should work in theory if the client follows the Matrix Spec.
```nginx
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name old.delegated.url.com;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
default_type application/json;
return 401 '{"errcode":"M_UNKNOWN_TOKEN","error":"Server moved, please log in again."}';
}
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=63072000" always;
ssl_stapling on;
ssl_stapling_verify on;
error_log /var/log/nginx/old.delegated.url.com.error.log;
access_log /var/log/nginx/old.delegated.url.com.access.log;
ssl_certificate /etc/letsencrypt/live/old.delegated.url.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/old.delegated.url.com/privkey.pem;
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name old.delegated.url.com;
if ($host = old.delegated.url.com) {
return 301 https://$host$request_uri;
}
return 404;
}
```
# Reset User Password
Resetting an account password will log out all sessions. Before doing this, make sure that
- all sessions are connected to key backup,
- all sessions have backed up all their keys. See [Check Status](check-status), and
- the correct key backup passphrase is available.
1. Click `Your Account` and `Manage Servers` or click this link https://ems.element.io/user/hosting.
1. Click `Server Admin`, select your host, then `Users`
1. Click the user you want to manage
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383680400-45-40-pm.png)
1. Click `Reset password`, enter a new password and click `Go`
[](https://ems-docs.element.io/uploads/images/gallery/2023-12/image-1702383700656-47-25-pm.png)
# Token based registration
Create a new registration token using the [Synapse Admin API](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/registration_tokens.html). Give this to your users.
The registration flow looks like this:
1. Enter username, password and email as normal. Click `Register`
[](https://ems-docs.element.io/uploads/images/gallery/2022-07/image-1658392358640-26-06-am.png)
1. Enter the registration token and click `Continue`
[](https://ems-docs.element.io/uploads/images/gallery/2023-05/image-1683207542151-37-01-pm.png)
1. Continue registration like normal
[](https://ems-docs.element.io/uploads/images/gallery/2022-07/image-1658392458002-26-52-am.png)
# Adding a Trust & Safety Contact
1. Click `Your Account` and `Manage Servers` or click this link https://ems.element.io/user/hosting.
1. Click the Hosts tab.
1. Add an email address to the `Trust and Safety contact` field and click `Save` at the bottom.
This contact should be a user with access to respond to content takedown notices and other trust & safety concerns (such as deactivating users).