Installation Guide
Full MatrixEasyMode installation guide for deploying Matrix + Element on your own infrastructure.
If you want the shortest setup path, start with Get Started. This page is the fuller installation reference covering the deployment flow, runtime model, helper scripts, and command reference.
MatrixEasyMode helps you deploy and run Matrix + Element on infrastructure you control.
This guide walks through the full installation flow, including Docker Compose, Nginx Proxy Manager, certificates, staged startup, and the supporting services required for a working deployment.
You do not need to be an infrastructure engineer, but you should be comfortable working with Linux, Docker, domains, and basic self-hosting concepts.
Who this installation path is for
This installation path is aimed at:
- self-hosters
- homelab users
- VPS operators
- teams running Matrix on their own infrastructure
- Linux users comfortable with Docker and domains
You should already be comfortable with:
- Linux shell access
- Docker Engine and Docker Compose
- public hostnames and DNS
- HTTPS and certificate management
- reverse proxies, especially Nginx Proxy Manager
- reading logs and troubleshooting service startup issues
What is in the deployment pack
The repository includes:
docker-compose.ymlfor the main MatrixEasyMode stackdocker-compose.local.ymlfor local developer image buildsdocker-compose.pgadmin.ymlfor optional pgAdmin accessinstall.shfor guided environment setup and staged startup preparationstack.shfor starting, stopping, restarting, building, and viewing logstools.shfor optional tooling such as pgAdmin and Portainer.env.exampleas a reference template
This repository contains the deployment pack used to install and manage a MatrixEasyMode environment.
Architecture at a glance
The standard stack includes:
- PostgreSQL
- Nginx Proxy Manager
- MatrixEasyMode API
- MatrixEasyMode web frontend
The deployment includes infrastructure concerns such as:
- reverse proxy integration
- public hostname management
- certificate-aware ingress configuration
- Docker-backed provisioning
- persistent instance data under
/opt/mem/instances - Matrix bootstrap and Element image settings used during provisioning flows
- automated ingress bootstrapping for the main web and API entrypoints
Image modes
MatrixEasyMode supports two application image modes.
Registry mode
Registry mode uses published container images from a registry.
This is the normal mode for most installations using published images.
In this mode, the stack uses:
MEM_IMAGE_SOURCE=registryMEM_REGISTRYMEM_VERSION
Local mode
Local mode uses locally built application images for development and testing.
This is mainly intended for contributors and local development.
In this mode, the stack uses:
MEM_IMAGE_SOURCE=localMEM_API_IMAGEMEM_WEB_IMAGE
When local mode is enabled, stack.sh automatically includes
docker-compose.local.yml.
Staged startup model
MatrixEasyMode uses a staged startup model.
Infrastructure first
The infrastructure layer includes:
postgresnpm
Application second
The app layer includes:
apiweb
The startup order matters because:
The MatrixEasyMode API bootstraps platform ingress routes into Nginx Proxy Manager, so NPM must already be running and the wildcard certificate must already exist before the application layer is started.
Standard installation flow
1. Get the deployment pack
First-time setup:
git clone https://github.com/matrix-easy-mode/mem-deploy
cd mem-deployIf you already have a checkout and want the latest changes:
git pull --ff-only2. Confirm what you need before you start
Before running anything, make sure you already have:
- a Linux host
- Docker Engine installed
- the Docker Compose plugin installed
- a domain you control
- DNS records you can manage
- a plan for HTTPS certificates in Nginx Proxy Manager
- permission to bind ports 80, 81, 443, 3000, and 7000 as required by your environment
MatrixEasyMode also depends on infrastructure setup such as:
- public hostnames
- reverse proxy routing
- certificate selection
- Docker-backed provisioning
- persistent instance data on the host
3. Make the helper scripts executable
chmod +x install.sh stack.sh tools.shYou can inspect installer help at any time with:
./install.sh --help4. Run the installer
./install.shThe installer will:
- create
.env - generate random secrets for JWT, NextAuth, and Matrix bootstrap values
- prompt you for the image source:
registryorlocal - prompt you for the public app hostname and public API hostname
- prompt you for the public host suffix and certificate name
- prompt you for Nginx Proxy Manager credentials used by MatrixEasyMode integration
- let you enter a PostgreSQL password or press Enter to auto-generate one
- validate the Docker Compose configuration
- optionally start the infrastructure services for you
The installer will also try to create the required instance data path:
/opt/mem/instancesIf it cannot do that automatically, it will tell you which sudo commands to run.
What the installer will ask you for
Image source
You will choose one of:
registry
localChoose registry for published images.
Choose local if you want to build the API and web images yourself.
Public app hostname
This is the public hostname users will open in their browser for MatrixEasyMode.
Example:
admin.your-domain.comPublic API hostname
This is the public hostname browsers will use to reach the API.
Example:
api.your-domain.comPublic host suffix
This is the base suffix MatrixEasyMode uses when generating public hostnames.
Example:
your-domain.comIngress certificate name
This must be the certificate name that already exists in Nginx Proxy Manager and will be used for managed host creation.
Example:
*.your-domain.comNginx Proxy Manager identity and secret
These are the credentials the MatrixEasyMode API will use to talk to the NPM API.
Use an email address accepted by your NPM instance. Do not use placeholder
domains such as example.com.
Example:
admin@your-domain.comPostgreSQL password
You can:
- enter your own PostgreSQL password, as long as it is at least 7 characters, or
- press Enter and let the installer generate one for you
Local image tags
If you chose local, the installer will also prompt you for local application image tags.
Typical values are:
mem-api:local
mem-web:localReview the generated .env
After ./install.sh, review the generated file if you want to confirm values before
proceeding:
cat .envTreat .env as sensitive. It contains secrets and should not be committed to source
control.
Start or verify infrastructure
If the installer already started infrastructure for you, verify it with:
./stack.sh statusIf not, start it manually:
./stack.sh up infraThis starts:
postgresnpm
At this point, do not start the app layer yet.
Open Nginx Proxy Manager
Open the NPM admin UI:
http://<your-server>:81If this is the first time NPM has been started, complete the initial admin account flow.
Use the same credentials you entered into install.sh for:
NPM_IDENTITYNPM_SECRET
The MatrixEasyMode API later authenticates against the NPM API using those same credentials.
Create the wildcard certificate in NPM
Before starting the MatrixEasyMode application layer, create the wildcard SSL certificate in NPM.
It must match the certificate name you supplied during install. For example:
*.your-domain.comand it must match:
INGRESS_CERTIFICATE_NAMEThis is required for the current deployment model.
If the certificate does not exist yet, ingress bootstrap cannot complete successfully.
Confirm DNS is correct
Before expecting public access to work, confirm:
- your chosen public hostnames resolve to the correct server
- ports 80 and 443 are reachable as required by your environment
- NPM is able to use the certificate you configured
- the certificate name in
.envmatches the one actually present in NPM
Typical hostnames might look like:
https://admin.your-domain.comhttps://api.your-domain.com
Start the MatrixEasyMode application layer
Only after NPM is running and the wildcard certificate exists, start the app layer:
./stack.sh up appThis starts:
apiweb
If using local mode, build the application images first
Only for local mode:
./stack.sh build appThis builds:
apiweb
using docker-compose.local.yml.
Local mode assumes you have the required MatrixEasyMode application source repositories
available locally, and that the build contexts in docker-compose.local.yml point to
valid paths.
If your local repository layout differs from the default expected layout, update
docker-compose.local.yml before building.
Verify startup
Check the stack:
./stack.sh statusFollow app logs:
./stack.sh logs appIf you want service-specific logs:
./stack.sh logs api
./stack.sh logs web
./stack.sh logs postgres
./stack.sh logs npmVerify first access
Once everything is up, verify these endpoints as appropriate for your environment:
- MatrixEasyMode web frontend
- MatrixEasyMode API
- Nginx Proxy Manager admin UI on port 81
Typical URLs may look like:
https://admin.your-domain.comhttps://api.your-domain.comhttp://your-server:81
Core commands
Start infrastructure only
./stack.sh up infraStart app only
./stack.sh up appStart everything
./stack.sh up allCheck status
./stack.sh statusFollow infrastructure logs
./stack.sh logs infraFollow app logs
./stack.sh logs appBuild local application images
./stack.sh build appThis is intended for local mode only.
Stop app only
./stack.sh down appStop infrastructure only
./stack.sh down infraStop everything
./stack.sh down allRestart app only
./stack.sh restart appManual Docker Compose usage
If you prefer to bypass the helper scripts, the staged model is:
Registry mode
Start infrastructure first:
docker compose up -dStart the app layer second:
docker compose --profile app up -d api webView full stack status:
docker compose --profile app psStop everything:
docker compose --profile app down --remove-orphansLocal mode
In local mode, include the local override file.
Build local images:
docker compose -f docker-compose.yml -f docker-compose.local.yml --profile app build api webStart infrastructure:
docker compose -f docker-compose.yml -f docker-compose.local.yml up -d postgres npmStart the app layer:
docker compose -f docker-compose.yml -f docker-compose.local.yml --profile app up -d api webView full stack status:
docker compose -f docker-compose.yml -f docker-compose.local.yml --profile app psStop everything:
docker compose -f docker-compose.yml -f docker-compose.local.yml --profile app down --remove-orphansThe script-first path is still the recommended flow.
Optional tools
pgAdmin
./tools.sh pgadmin start
./tools.sh pgadmin stop
./tools.sh pgadmin status
./tools.sh pgadmin logsPortainer
./tools.sh portainer start
./tools.sh portainer stop
./tools.sh portainer status
./tools.sh portainer logsThese are optional convenience tools and are not part of the core MatrixEasyMode runtime.
What to do if something is wrong
If startup does not look right:
-
check current state
bashbash./stack.sh status -
inspect infrastructure logs
bashbash./stack.sh logs infra -
inspect app logs
bashbash./stack.sh logs app -
confirm NPM is reachable and the wildcard certificate exists
-
confirm
.envvalues are correct, especially:MEM_IMAGE_SOURCENEXTAUTH_URLNEXT_PUBLIC_API_URLNPM_BASEURLNPM_IDENTITYINGRESS_CERTIFICATE_NAME
-
if using local mode, confirm:
./stack.sh build appcompleted successfully- the local source repositories exist where
docker-compose.local.ymlexpects them MEM_API_IMAGEandMEM_WEB_IMAGEmatch the built image tags
Related documentation
Current deployment model
MatrixEasyMode currently uses a staged self-hosted deployment model built around Docker Compose, PostgreSQL, and Nginx Proxy Manager.
The goal is to make Matrix deployment easier without hiding how the underlying infrastructure works. As the project evolves, future installation flows may reduce setup friction further.
