docker compose ```yaml services: networks: proxy: driver: bridge services: traefik: image: "traefik" restart: "unless-stopped" command: - "--api=true" - "--api.dashboard=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--certificatesresolvers.myresolver.acme.httpchallenge=true" - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web" # Ensure HTTP challenge uses the web entry point - "--certificatesresolvers.myresolver.acme.email=zhiqiang@windy.me" # Set your email for Let's Encrypt - "--certificatesresolvers.myresolver.acme.storage=/certs/acme.json" # Path to store certs - "--entrypoints.web.address=:80" # Entry point for HTTP - "--entrypoints.websecure.address=:443" # Entry point for HTTPS - "--log.level=DEBUG" # Set the log level (optional) ports: - "80:80" # Ensure port 80 is exposed for HTTP challenge - "443:443" # Port 443 for HTTPS - "8080:8080" # Dashboard (Optional) volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./certs/acme.json:/certs/acme.json" networks: - proxy well-known: image: "nginx" restart: "unless-stopped" volumes: - ./well-known:/etc/nginx/conf.d labels: - "traefik.enable=true" - "traefik.http.routers.well-known.entrypoints=websecure" - "traefik.http.routers.well-known.rule=Host(`chans.xyz`) && PathPrefix(`/.well-known`)" - "traefik.http.routers.well-known.tls=true" - "traefik.http.routers.well-known.tls.certresolver=myresolver" networks: - proxy synapse: image: docker.io/matrixdotorg/synapse restart: unless-stopped environment: - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml volumes: - ./data:/data healthcheck: test: ["CMD", "nc", "-z", "db", "5432"] interval: 10s retries: 5 start_period: 10s timeout: 2s depends_on: - db labels: - "traefik.enable=true" - "traefik.http.routers.synapse.rule=Host(`synapse.chans.xyz`)" # Router for synapse.chans.xyz - "traefik.http.routers.synapse.entrypoints=websecure" # HTTPS traffic - "traefik.http.routers.synapse.tls=true" # Enable TLS - "traefik.http.routers.synapse.tls.certresolver=myresolver" # Use Let's Encrypt resolver - "traefik.http.services.synapse.loadbalancer.server.port=8008" # Synapse backend port networks: - proxy db: image: docker.io/postgres:14-alpine restart: unless-stopped environment: - POSTGRES_USER=synapse - POSTGRES_PASSWORD=ucdN6Upc|J,V*J0? - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C volumes: - ./db:/var/lib/postgresql/data networks: - proxy ``` well-known default.conf ```conf location /.well-known/matrix/server { access_log off; add_header Access-Control-Allow-Origin *; default_type application/json; return 200 '{"m.server": "matrix.chans.xyz:443"}'; } location /.well-known/matrix/client { access_log off; add_header Access-Control-Allow-Origin *; default_type application/json; return 200 '{"m.homeserver": {"base_url": "https://app.chans.xyz"}}'; } ``` generate config: ```bash docker run -it --rm --volume ./data:/data -e SYNAPSE_SERVER_NAME=chans.xyz -e SYNAPSE_REPORT_STATS=yes matrixdotorg/synapse generate ``` homeserver.yml database: ```yaml name: psycopg2 txn_limit: 10000 args: user: synapse password: ucdN6Upc|J,V*J0? database: synapse host: synapse_db port: 5432 cp_min: 5 cp_max: 10 ``` ```yaml # # This is a YAML file: see [1] for a quick introduction. Note in particular # that *indentation is important*: all the elements of a list or dictionary # should have the same indentation. # # [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html # # For more information on how to configure Synapse, including a complete accounting of # each option, go to docs/usage/configuration/config_documentation.md or # https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html server_name: "chans.xyz" pid_file: /data/homeserver.pid listeners: - port: 8008 tls: false type: http x_forwarded: true resources: - names: [client, federation] compress: false database: name: psycopg2 txn_limit: 10000 args: user: synapse password: ucdN6Upc|J,V*J0? database: synapse host: synapse_db port: 5432 cp_min: 5 cp_max: 10 log_config: "/data/chans.xyz.log.config" media_store_path: /data/media_store registration_shared_secret: "lTjbS&oVJ7==Co+4YdbDxR,u7.:d+3qgofIR@9c#*1ULc;M2,*" report_stats: true macaroon_secret_key: "fe@vZvVnFFA3j:;hK;DI27;vZk@lHHk~w7foB*Q0D0nd.;tGho" form_secret: "G*bdHINrFR+@,A3^P=IpayYU3aluiAKcI5@L&E-f#Du:s@MgB6" signing_key_path: "/data/chans.xyz.signing.key" trusted_key_servers: - server_name: "matrix.org" ``` ``` sudo certbot --nginx -d chans.xyz -d synapse.chans.xyz ``` ``` register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008 ``` key: ``` EsT1 s6mK hgBT 3Cnv iYbW SNBD Bf3C LwPs nPbq dXJ8 cbbg aiEs ``` ```yaml # The Matrix integration matrix: homeserver: https://chans.xyz username: "@zhiqiang:chans.xyz" password: "vaz6PQV5vjg1aya-mvr" rooms: - "#hass:chans.xyz" commands: - word: testword name: testword rooms: - "#hass:chans.xyz" - expression: "My name is (?P.*)" name: introduction notify: - name: matrix_notify platform: matrix default_room: "#hass:chans.xyz" automation: - alias: "React to !testword" triggers: - trigger: event event_type: matrix_command event_data: command: testword actions: - action: notify.matrix_notify data: message: "It looks like you wrote !testword" - alias: "React to an introduction" triggers: - trigger: event event_type: matrix_command event_data: command: introduction actions: - action: notify.matrix_notify data: message: "Hello {{trigger.event.data.args['name']}}" ``` get token ``` curl -X POST -H "Content-Type: application/json" -d '{ "type": "m.login.password", "user": "hass", "password": ".P.fPdJL6.wz77q*9VjD" }' "https://chans.xyz/_matrix/client/r0/login" ``` ``` syt_aGFzcw_cBpXCxWpUSawmWXXmZFL_0v4BCE ``` new matrix ess recover key ``` EsTR 895B q1wv 4ibr ZRaK 9KCK 7nLc xHCm XUGX eYjh TcE5 4XSJ ``` iris account: ``` Awa5noeW9vzLiPRY ``` hass account: ``` sgHoMmOWn8SkYJf# ``` ``` kubectl -n ess exec deploy/ess-matrix-authentication-service -- mas-cli manage register-user --yes hass -p "sgHoMmOWn8SkYJf#" Defaulted container "matrix-authentication-service" out of: matrix-authentication-service, render-config (init), db-wait (init), database-migrate (init) User attributes Username: hass Matrix ID: @hass:chans.xyz Password: ******** No email address provided, user will be prompted to add one 2025-10-22T09:25:36.174135Z WARN mas_cli::commands::manage:818 No email address provided, user will need to add one 2025-10-22T09:25:36.209840Z INFO mas_cli::commands::manage:835 User registered user.id=01K85KSXSEB2FB6MJHNKZP0BDV ``` ``` matrix: homeserver: "https://chans.xyz" username: "@hass:chans.xyz" password: "sgHoMmOWn8SkYJf#" rooms: - "#guangzhou:chans.xyz" ``` ``` synapse: additional: config: | auto_join_rooms_for_users_on_first_login: true ```