1. The problem I’m having:
I’m running a matrix server and trying to get synapse-admin from etke.cc from GitHub - etkecc/synapse-admin: A maintained fork of the admin console for (Matrix) Synapse homeservers, including additional features to work to control things. I have gotten most of the parts of matrix that I wanted up and running, but I can’t get synapse-admin to run. I thought it was a bug with the software, but it works just fine if I use my install to connect to another server. It keeps saying:
I’ve been putting all the header lines in as many places as I could to try and find where I have to put it for it to actually take effect. I also went through several tutorials about getting matrix up and running with caddy and have mixed things together to try and find what will actually work for this. Matrix has worked fine from near the start, but synapse-admin has been failing. I spoke to etke.cc about configuration and they told me it was a caddy issue, so I’m hoping someone here can tell me what I’m doing wrong.
I am running synapse-admin in 2 places because it’s made to be the root level but can be run from a subfolder type as well. I wanted to see what would work, so I have it in the subdomain madmin as well as ../synapse-admin/ and neither works, but they give different errors.
I’m using caddy 2.9.1 with the linode dns plugin
2. Error messages and/or full log output:
(matrix-well-known-header) {
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
Content-Type "application/json"
}
}
(matrix) {
handle /.well-known/matrix/server {
import matrix-well-known-header
respond `{"m.server":"matrix.dragonmail.cloud"}`
}
handle /.well-known/matrix/client {
import matrix-well-known-header
respond `{"m.homeserver":{"base_url":"https://chat.dragonmail.cloud"}}`
}
}
dragonmail.cloud {
import matrix
respond "placeholder"
}
}
matrix.dragonmail.cloud {
header {
X-Content-Type-Options nosniff
#Referrer-Policy strict-origin-when-cross-origin
Access-Control-Allow-Origin "*"
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
#X-Frame-Options SAMEORIGIN
#Access-Control-Allow-Credentials true
X-XSS-Protection 1
X-Robots-Tag none
-server
X-Real-IP {remote_host}
X-Forwarded-For {remote_host}
X-Permitted-Cross-Domain-Policies "*"
defer
}
handle /.well-known/matrix/server {
# #import matrix-well-known-header
#respond `{"m.server":"matrix.dragonmail.cloud:443"}`
respond `{"m.server":"matrix.dragonmail.cloud"}`
}
#
handle /.well-known/matrix/client {
#import matrix-well-known-header
respond `{"m.homeserver":{"base_url":"https://matrix.dragonmail.cloud"}}`
}
#@media {
# path_regexp /_synapse/admin/v1/(purge_media_cache|((room|user)/.*/media.*)|media/.*|/quarantine_media/.*)$
# path_regexp /_matrix/media(/?(.*)?)$
#}
#route @media {
# reverse_proxy matrix-synapse:8015
#}
@federation {
path_regexp /_matrix/federation/(v1|v2)/(send|event|state|state_ids|backfill|get_missing_events|publicRooms|query|make_join|make_leave|send_join|send>
#path_regexp /_matrix/key/v2/query/?$
}
route @federation {
reverse_proxy matrix-synapse:8017
}
# Handle Synapse Admin requests
handle_path /synapse-admin* {
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
Access-Control-Allow-Credentials true
defer
}
#try_files {path} {path}/ /index.html
#@static_files {
# path_regexp .*(css|js|jpg|jpeg|gif|png|svg|ico|woff|woff2|ttf|eot|webp)$
#}
#header @static_files Cache-Control "public, max-age=2592000"
reverse_proxy http://matrix-synapse-admin:80
}
reverse_proxy /_matrix/* matrix-synapse:8008
reverse_proxy /_synapse/client/* matrix-synapse:8008
reverse_proxy /_matrix/media/* matrix-synapse:8008
#reverse_proxy /_synapse/admin/* matrix-synapse:8008
header {
X-Content-Type-Options nosniff
#Referrer-Policy strict-origin-when-cross-origin
#Access-Control-Allow-Origin "http://192.168.3.50:8195"
Access-Control-Allow-Origin *
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
#X-Frame-Options SAMEORIGIN
#Access-Control-Allow-Credentials true
X-XSS-Protection 1
X-Robots-Tag none
-server
X-Real-IP {remote_host}
X-Forwarded-For {remote_host}
defer
}
}
element.dragonmail.cloud {
encode zstd gzip
#reverse_proxy element:80
#reverse_proxy 10.10.10.3:80
reverse_proxy matrix-element:80
header {
X-Content-Type-Options nosniff
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
X-Frame-Options SAMEORIGIN
X-XSS-Protection 1
X-Robots-Tag none
-server
}
}
chat.dragonmail.cloud {
encode zstd gzip
#reverse_proxy element:80
#reverse_proxy 10.10.10.3:80
reverse_proxy matrix-element:80
header {
X-Content-Type-Options nosniff
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
X-Frame-Options SAMEORIGIN
X-XSS-Protection 1
X-Robots-Tag none
-server
}
}
3. Caddy version:
2.9.1 in docker compose but built from git
4. How I installed and ran Caddy:
services:
caddy:
container_name: caddy
build:
dockerfile: dockerfile-caddy
context: ./caddy
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
- /media/configs/caddy/Caddyfile:/etc/caddy/Caddyfile
- /media/configs/caddy/config:/config
- /media/configs/caddy/data:/data
- /media/configs/caddy/site:/srv
environment:
PUID: '1000'
PGID: '1000'
TZ: 'America/vancouver'
#GODADDY_TOKEN: '####'
LINODE_TOKEN: '####'
networks:
dragonio:
aliases: []
My dockerfile:
FROM caddy:2.9.1-builder AS builder
ENV GOTOOLCHAIN=go1.24.1
RUN xcaddy build \
--with github.com/caddy-dns/linode
FROM caddy:2.9.1
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
a. System environment:
popos 22.04 LTS
b. Command:
docker compose up caddy
c. Service/unit/compose file:
---
name: "dragonmail"
networks:
dragonio:
name: 'dragonio'
driver: 'bridge'
external: true
matrix_net:
name: 'matrix_net'
driver: 'bridge'
external: true
services:
caddy:
container_name: caddy
build:
dockerfile: dockerfile-caddy
context: ./caddy
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
- /media/configs/caddy/Caddyfile:/etc/caddy/Caddyfile
- /media/configs/caddy/config:/config
- /media/configs/caddy/data:/data
- /media/configs/caddy/site:/srv
environment:
PUID: '1000'
PGID: '1000'
TZ: 'America/vancouver'
LINODE_TOKEN: '####'
networks:
dragonio:
aliases: []
###########################################################################################
matrix-synapse:
container_name: 'matrix-synapse'
image: 'matrixdotorg/synapse:latest'
#image: 'matrixdotorg/synapse:v1.119.0'
init: true
restart: 'unless-stopped'
#pull_policy: always
networks:
matrix_net:
aliases: []
#ipv4_address: 10.10.10.4
dragonio:
aliases: []
environment:
SYNAPSE_SERVER_NAME: 'matrix.dragonmail.cloud'
SYNAPSE_REPORT_STATS: 'yes'
allow_unsafe_locale: true
volumes:
- '/media/matrix/synapse:/data'
#- '/media/matrix/synapse/homeserver.log:/homeserver.log'
- '/media/matrix/whatsapp/data:/data/appservices/whatsapp'
- '/media/matrix/telegram:/data/appservices/telegram'
- '/media/matrix/meta:/data/appservices/meta'
ports:
- 8008:8008
depends_on:
- matrix-postgres
- caddy
- authentik
###########################################################################################
matrix-element:
container_name: 'matrix-element'
image: 'vectorim/element-web:latest'
restart: 'unless-stopped'
#pull_policy: always
volumes:
- '/media/matrix/element/element-config.json:/app/config.json'
#ports:
# - 8180:80
networks:
dragonio:
aliases: []
matrix_net:
#ipv4_address: 10.10.10.3
aliases: []
depends_on:
- matrix-synapse
- matrix-postgres
- caddy
###########################################################################################
matrix-postgres:
#image: 'docker.io/library/postgres:16-alpine'
image: 'postgres:14'
container_name: 'matrix-postgres'
restart: 'unless-stopped'
#pull_policy: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
volumes:
- '/media/matrix/database:/var/lib/postgresql/data'
environment:
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_DB: ${POSTGRES_DB}
allow_unsafe_locale: true
env_file:
- .env
networks:
matrix_net:
#ipv4_address: 10.10.10.2
aliases: []
###########################################################################################
matrix-synapse-admin:
container_name: matrix-synapse-admin
hostname: matrix-synapse-admin
build:
context: https://github.com/etkecc/synapse-admin.git
dockerfile: Dockerfile.build
args:
- BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
# - NODE_OPTIONS="--max_old_space_size=1024"
- BASE_PATH=/synapse-admin
restart: unless-stopped
networks:
matrix_net:
aliases: []
dragonio:
aliases: []
depends_on:
- caddy
- matrix-synapse
###########################################################################################
d. My complete Caddy config:
{
#admin :2019
email ####
acme_dns linode {env.LINODE_TOKEN}
debug
}
(matrix-well-known-header) {
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
Content-Type "application/json"
}
}
(matrix) {
handle /.well-known/matrix/server {
import matrix-well-known-header
respond `{"m.server":"matrix.dragonmail.cloud"}`
}
handle /.well-known/matrix/client {
import matrix-well-known-header
respond `{"m.homeserver":{"base_url":"https://chat.dragonmail.cloud"}}`
}
}
dragonmail.cloud {
handle /.well-known/matrix/server {
import matrix-well-known-header
respond `{"m.server":"matrix.dragonmail.cloud:443"}`
}
handle /.well-known/matrix/client {
import matrix-well-known-header
respond `{"m.homeserver":{"base_url":"https://matrix.dragonmail.cloud"}}`
}
}
auth.dragonmail.cloud {
#reverse_proxy http://authentik:9000
reverse_proxy authentik:9000
}
mail.dragonmail.social {
reverse_proxy http://stalwart-mail:8080
}
https://nextcloud.dragonmail.cloud:443 {
redir /.well-known/carddav /remote.php/dav/ 301
redir /.well-known/caldav /remote.php/dav/ 301
reverse_proxy nextcloud-aio-apache:11000
}
nextcloud.dragonmail.cloud:8080 {
#redir /.well-known/carddav /remote.php/dav/ 301
#redir /.well-known/caldav /remote.php/dav/ 301
reverse_proxy nextcloud-aio-apache:8080
}
matrix.dragonmail.cloud {
header {
X-Content-Type-Options nosniff
#Referrer-Policy strict-origin-when-cross-origin
#Access-Control-Allow-Origin "http://192.168.3.50:8195"
Access-Control-Allow-Origin "*"
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
#X-Frame-Options SAMEORIGIN
#Access-Control-Allow-Credentials true
X-XSS-Protection 1
X-Robots-Tag none
-server
X-Real-IP {remote_host}
X-Forwarded-For {remote_host}
X-Permitted-Cross-Domain-Policies "*"
defer
}
handle /.well-known/matrix/server {
#import matrix-well-known-header
respond `{"m.server":"matrix.dragonmail.cloud"}`
}
handle /.well-known/matrix/client {
#import matrix-well-known-header
respond `{"m.homeserver":{"base_url":"https://matrix.dragonmail.cloud"}}`
}
#@media {
# path_regexp /_synapse/admin/v1/(purge_media_cache|((room|user)/.*/media.*)|media/.*|/quarantine_media/.*)$
# path_regexp /_matrix/media(/?(.*)?)$
#}
#route @media {
# reverse_proxy matrix-synapse:8015
#}
@federation {
path_regexp /_matrix/federation/(v1|v2)/(send|event|state|state_ids|backfill|get_missing_events|publicRooms|query|make_join|make_leave|send_join|send>
#path_regexp /_matrix/key/v2/query/?$
}
route @federation {
reverse_proxy matrix-synapse:8017
}
# Handle Synapse Admin requests
handle_path /synapse-admin* {
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization"
Access-Control-Allow-Credentials true
defer
}
#try_files {path} {path}/ /index.html
#@static_files {
# path_regexp .*(css|js|jpg|jpeg|gif|png|svg|ico|woff|woff2|ttf|eot|webp)$
#}
#header @static_files Cache-Control "public, max-age=2592000"
reverse_proxy http://matrix-synapse-admin:80
}
reverse_proxy /_matrix/* matrix-synapse:8008
reverse_proxy /_synapse/client/* matrix-synapse:8008
reverse_proxy /_matrix/media/* matrix-synapse:8008
#reverse_proxy /_synapse/admin/* matrix-synapse:8008
header {
X-Content-Type-Options nosniff
#Referrer-Policy strict-origin-when-cross-origin
Access-Control-Allow-Origin *
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
#X-Frame-Options SAMEORIGIN
#Access-Control-Allow-Credentials true
X-XSS-Protection 1
X-Robots-Tag none
-server
X-Real-IP {remote_host}
X-Forwarded-For {remote_host}
defer
}
}
element.dragonmail.cloud {
encode zstd gzip
reverse_proxy matrix-element:80
header {
X-Content-Type-Options nosniff
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
X-Frame-Options SAMEORIGIN
X-XSS-Protection 1
X-Robots-Tag none
-server
}
}
chat.dragonmail.cloud {
encode zstd gzip
reverse_proxy matrix-element:80
header {
X-Content-Type-Options nosniff
Strict-Transport-Security "max-age=63072000; includeSubDomains;"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
X-Frame-Options SAMEORIGIN
X-XSS-Protection 1
X-Robots-Tag none
-server
}
}
track.dragonmail.cloud {
reverse_proxy http://ryot:8000
}
#srv.dragonmail.cloud {
# respond "placeholder"
#}
#matrix.dragonmail.cloud/synapse-admin {
# reverse_proxy http://synapse-admin:80
#}
madmin.dragonmail.cloud {
tls internal
reverse_proxy http://matrix-synapse-admin-test:80
}