Walkthrough

Choose a scenario below. Each guide walks you through every step with real examples.

📋 What We'll Do

Get clean usernames like @user:example.com while the server runs at matrix.example.com. This uses .well-known delegation — Caddy handles it automatically.

  1. Prerequisites — What you need before starting
  2. DNS Setup — Two A records needed
  3. Run the Installer — Mode 1 with delegation
  4. Health Check — Verify everything works
  5. Create Accounts — Add users to your server
  6. Sign In & Chat — Connect with a Matrix client

1. Prerequisites

Same as subdomain mode, plus one extra DNS record:

WhatDetails
A VPS / serverDebian 13 (tested on 1 GB RAM / 1 CPU / 25 GB SSD — DigitalOcean $6/mo droplet). Not tested on other OS or specs
Root accessEither logged in as root, or a user with sudo
A domain nameAny domain you own (e.g., example.com)
DNS accessYou'll need two A records — one for the root domain and one for the subdomain
⚠️ Key difference from Subdomain Mode: Your root domain (example.com) must also point to this server. If you already have a website at example.com, choose Option B during install (see Step 3).

2. DNS Setup

Add both records to your DNS provider:

TypeNameValueWhy
A@ (root)Your server IPServes .well-known delegation files
AmatrixYour server IPRuns the actual Matrix server
AAAA@ (root)IPv6 (if available)Optional but recommended
AAAAmatrixIPv6 (if available)Optional but recommended
⚠️ Cloudflare users: Set both records to DNS Only (grey cloud 🔘), not Proxied (orange cloud). Port 8448 for federation won't work through Cloudflare's proxy.
# Verify both records resolve
dig example.com +short        # → your server IP
dig matrix.example.com +short # → your server IP

3. Run the Installer

ssh root@your-server-ip
curl -fsSL https://raw.githubusercontent.com/balnaimi/conduit-deploy/main/conduit-deploy.sh -o conduit-deploy.sh
sudo bash conduit-deploy.sh

3a. Choose Mode 1 (Clean Username)

* How do you want your usernames to look?

  1) Clean username — @user:example.com (server at matrix.example.com)
  2) Subdomain only — @user:chat.example.com (simpler, no delegation)

  ⚠ This is permanent — you cannot change it later!

Choose [1/2]: 1

3b. Enter Your Domain

Your domain name: example.com
VPS public IP [203.0.113.10]: ↵ (press Enter to accept)

3c. Delegation Method

The script asks how you want to handle .well-known delegation:

* .well-known Delegation
  Your usernames will be @user:example.com but the server runs at matrix.example.com
  The root domain needs to tell clients where to find the server.

  A) Root domain (example.com) has NO existing website — Caddy handles it
  B) Root domain (example.com) has an existing website — I'll give you instructions

Choose [A/B]: A
💡 Option A vs B:
  • A — Caddy serves .well-known files on your root domain automatically. Best if this server is your only use for example.com. ✅ Tested
  • B — The script tells you exactly what .well-known JSON files to add to your existing web server. Use this if example.com already hosts a website elsewhere. ⚠️ Not fully tested yet

3d. Media Settings

Same as subdomain mode — defaults are fine for most setups:

SettingDefault
Max upload size100 MB (enter number in MB only, max 1024)
Max media storage10 GB
Cached files idle expiry30 days
Cached files max age90 days
User files idle expiry365 days
Thumbnail storage1 GB

3e. Confirm & Install

Summary:
  Server name: example.com
  Usernames:   @user:example.com
  Matrix URL:  https://matrix.example.com
  VPS IP:      203.0.113.10
  .well-known: Caddy (automatic)

Start installation? [Y/n] Y

Installation takes about 5–10 minutes. The script will:

  1. Install dependencies (Docker, firewalld, Fail2ban)
  2. Verify ports and DNS
  3. Generate config files with .well-known delegation
  4. Pull Docker images and start services
  5. Obtain TLS certificates for both example.com and matrix.example.com
  6. Set up TURN server for voice/video calls
  7. Create your admin account (you'll be prompted)
═══ Create Your Admin Account ═══

  ⚠  This is the ONLY admin account.
  The first account on the server automatically gets admin privileges.
  You'll use this account to manage everything from the Admin Room.

Username: alice
Password: ********

✅ Account created: @alice:example.com

═══ You're All Set! 🎉 ═══
  Server
  URL:          https://matrix.example.com
  Server name:  example.com

  Admin Account
  Username:     @alice:example.com
  Role:         Server Administrator

  Admin Room Commands (quick reference)
  Create user:      @conduit:example.com create-user <name> <pass>
  List users:       @conduit:example.com list-local-users
  Reset password:   @conduit:example.com reset-password <user_id> <pass>
⚠️ Security: Credentials are saved in plain text at /opt/conduit/CREDENTIALS.txt. The script will ask if you want to delete it — say yes after saving the info. If you forget your password later, use Services → Password Recovery (no credentials file needed).

4. Verify .well-known Delegation

After install, verify that delegation is working:

# These should return JSON responses
curl -s https://example.com/.well-known/matrix/server
# → {"m.server": "matrix.example.com:443"}

curl -s https://example.com/.well-known/matrix/client
# → {"m.homeserver": {"base_url": "https://matrix.example.com"}}
💡 How it works: When someone messages @user:example.com, their client checks example.com/.well-known/matrix/server to find where the actual server is (matrix.example.com). Caddy serves these files automatically.

5. Health Check

From the main menu, choose 3:

Services:
  ✅ conduit is running
  ✅ caddy is running
  ✅ coturn is running

Connectivity:
  ✅ HTTPS working (matrix.example.com)
  ✅ Federation port 8448 working
  ✅ IPv6 working

Security:
  ✅ firewalld active
  ✅ firewalld interface bound (eth0)
  ✅ firewalld masquerade enabled
  ✅ Docker internet access OK
  ✅ Fail2ban active
  ✅ SSH password auth disabled

6. Create Accounts

The first account was created during installation. To add more users, log in to Element and find the Admin Room:

# In the Admin Room, type:
@conduit:example.com create-user alice MySecurePass123!

# Response:
✅ Account created: @alice:example.com

Notice the clean username: @alice:example.com — no "matrix" subdomain in the user ID! 🎉

See the Admin Room guide for all available commands (reset password, deactivate user, etc.).

7. Sign In & Chat

Open any Matrix client (Element, SchildiChat, FluffyChat):

  1. Tap "Sign In"
  2. Change homeserver to: example.com
  3. Enter username and password
  4. You're in! 🎉
💡 Homeserver = root domain: Even though the server runs at matrix.example.com, users enter example.com as the homeserver. The client follows the .well-known redirect automatically.
🌐 Federation works too: Other Matrix servers will find yours via the .well-known delegation. Message anyone on matrix.org and it just works!

📋 What We'll Do

  1. Prerequisites — What you need before starting
  2. DNS Setup — Point your domain to your server
  3. Run the Installer — Launch the script and configure
  4. Health Check — Verify everything works
  5. Create Accounts — Add users to your server
  6. Sign In & Chat — Connect with a Matrix client

1. Prerequisites

Before you start, make sure you have:

WhatDetails
A VPS / serverDebian 13 (tested on 1 GB RAM / 1 CPU / 25 GB SSD — DigitalOcean $6/mo droplet). Not tested on other OS or specs
Root accessEither logged in as root, or a user with sudo
A domain nameAny domain you own (e.g., example.com). You'll create a subdomain like matrix.example.com
DNS accessAbility to add DNS records (A and AAAA) at your domain registrar or DNS provider
💡 Tip: Not sure which mode to choose? Check the Domain Setup page first. This walkthrough uses Subdomain Mode (Mode 2), which gives you usernames like @user:matrix.example.com.

2. DNS Setup

Go to your DNS provider and add these records pointing to your server's IP address:

TypeNameValueTTL
AmatrixYour server's IPv4 (e.g. 203.0.113.10)3600
AAAAmatrixYour server's IPv6 (if available)3600
⏱️ Wait for DNS: After adding the records, wait a few minutes for them to propagate. Verify with:
dig matrix.example.com +short

3. Run the Installer

SSH into your server and run the script:

# SSH into your server
ssh root@your-server-ip

# Download and run the installer
curl -fsSL https://raw.githubusercontent.com/balnaimi/conduit-deploy/main/conduit-deploy.sh -o conduit-deploy.sh
sudo bash conduit-deploy.sh

3a. Choose Your Mode

* How do you want your usernames to look?

  1) Clean username — @user:example.com (server at matrix.example.com)
  2) Subdomain only — @user:matrix.example.com (simpler, no delegation)

Choose [1/2]: 2

3b. Enter Your Domain

Your domain name: example.com
Subdomain for the server [matrix]: matrix
VPS public IP [203.0.113.10]: ↵ (press Enter to accept)
💡 Note: Enter just the root domain (e.g. example.com), not the full address.

3c. Media Settings

The defaults are good for most setups — just press Enter to accept each one:

SettingDefaultWhat It Means
Max upload size100 MBLargest file a user can send (enter MB only, max 1024)
Max media storage10 GBTotal space for all files (auto-cleans oldest)
Cached files idle expiry30 daysDelete cached federation files after 30 days idle
Cached files max age90 daysHard limit for cached federation files
User files idle expiry365 daysDelete user uploads after 1 year idle
Thumbnail storage1 GBAuto-generated image previews

3d. Confirm & Install

Summary:
  Server name: matrix.example.com
  Usernames:   @user:matrix.example.com
  Matrix URL:  https://matrix.example.com
  VPS IP:      203.0.113.10
  .well-known: Not needed (subdomain mode)

Start installation? [Y/n] Y

The installer will:

  1. Install missing dependencies (Docker, firewalld, Fail2ban, etc.)
  2. Verify ports 80, 443, and 8448 are available
  3. Verify DNS resolves to your IP
  4. Optionally set your timezone
  5. Generate configuration files and secrets
  6. Pull Docker images and start services
  7. Obtain a Let's Encrypt TLS certificate
  8. Set up TURN server (for voice/video calls)
  9. Create your admin account (you'll be prompted)
⏱️ How long? About 5–10 minutes depending on your server speed.
═══ Create Your Admin Account ═══

  ⚠  This is the ONLY admin account.

Username: alice
Password: ********

✅ Account created: @alice:matrix.example.com

═══ You're All Set! 🎉 ═══
  Admin Account
  Username:     @alice:matrix.example.com
  Role:         Server Administrator

  Forgot your password? Run this script again → Services → Password Recovery
⚠️ Security: Credentials are in plain text at /opt/conduit/CREDENTIALS.txt. Delete the file after saving your info! If you forget your password, use Services → Password Recovery. See the Admin Room guide for managing users.

4. Health Check

From the main menu, choose 3 (Health Check):

Services:
  ✅ conduit is running
  ✅ caddy is running
  ✅ coturn is running

Connectivity:
  ✅ HTTPS working (matrix.example.com)
  ✅ Federation port 8448 working
  ✅ IPv6 working

Security:
  ✅ firewalld active
  ✅ firewalld interface bound (eth0)
  ✅ firewalld masquerade enabled
  ✅ Docker internet access OK
  ✅ Fail2ban active
  ✅ SSH password auth disabled





TLS Certificates:
  ✅ Coturn TLS cert valid (89 days left)
  ✅ TLS auto-sync watcher active

Resources:
  ✅ Disk: 4.1G used / 20G free
  ✅ RAM: 442Mi / 967Mi

Registration:
  ✅ Registration is CLOSED
💡 All green? Your server is ready! If any check fails, see Troubleshooting.

5. Create Accounts

The first account was created during installation. To add more users, log in to Element and find the Admin Room:

# In the Admin Room, type:
@conduit:matrix.example.com create-user alice MySecurePass123!

# Response:
✅ Account created: @alice:matrix.example.com
🔒 Security: Registration is closed by default. Only you can create accounts via the Admin Room.

See the Admin Room guide for all available commands.

6. Sign In & Chat

ClientPlatformsLink
ElementWeb, Desktop, iOS, Androidelement.io
SchildiChatDesktop, iOS, Androidschildi.chat
FluffyChatiOS, Android, Linuxfluffychat.im
  1. Open the app → "Sign In"
  2. Change homeserver to: matrix.example.com
  3. Enter your username and password
  4. You're in! 🎉 Messages are end-to-end encrypted by default 🔐
🌐 Federation: Your server can talk to any other Matrix server. Try messaging someone on matrix.org — it just works!

📋 What's in a Backup

ComponentWhat It Contains
DatabaseAll rooms, messages, user accounts, encryption keys (exported from Docker volume)
Media filesImages, videos, documents uploaded by users (optional — can be excluded)
Configuration.env, docker-compose.yml, conduit.toml, Caddyfile, turnserver.conf
TLS certificatesLet's Encrypt certs and Caddy data (exported from Docker volume)
SecretsRegistration token, TURN secret
Pinned image versionsSHA256 digests of the exact Docker images that were running
/opt/conduit/          ← Your live installation (database, config, media)
/opt/conduit-backups/  ← Your backups (separate — survives uninstall!)

1. Create a Backup

From the main menu: 5 (Services) → 7 (Backup with version pinning)

# The script checks disk space (includes Docker volume sizes)
✅ Disk space OK (need ~84MB, have 19604MB free)

# If you have 3+ old backups, it offers cleanup
⚠ You have 3 old backups in /opt/conduit-backups/
Delete old backups? Keep only the latest 2. [y/N]: y
✅ Deleted: conduit-backup-2026-03-15-082818.tar.gz

# Saves the exact Docker image versions
═══ Saving current image versions ═══
✅ conduit: matrixconduit/matrix-conduit:latest → 4078e80577cc
✅ caddy: caddy:2-alpine → fce4f15aad23
✅ coturn: coturn/coturn:alpine → 229f87ef2428

# Exports database and certificates from Docker volumes
ℹ Exporting database and certificates from Docker volumes...
✅ Database exported
✅ TLS certificates exported

# If you have media files, you can choose to include or exclude them
  Media files: 30M
  Media includes user uploads (images, videos, documents)
  and cached federation files.

Include media files in backup? [Y/n]: y

# Creates the backup
ℹ Creating backup...
✅ Backup saved: conduit-backup-2026-03-16-022313.tar.gz (30M)
💡 Media Exclusion: Choose n to skip media files for a much smaller backup. Accounts and messages are always saved. No-media backups get a -no-media suffix.

2. Why Pinned Image Versions?

When you restore, the script pulls the exact same Docker images (by SHA256 digest) that were running when the backup was taken:

  • No surprise breaking changes from a newer version
  • Your database format matches the software version
  • You can update later on your own terms

3. When to Backup

  • Before updating containers — the script offers this automatically
  • Before configuration changes — in case something breaks
  • Periodically — weekly or monthly for peace of mind
  • Before migrating — see the Migrate tab

4. Download a Copy Off-Server

For extra safety, keep a copy on your local machine:

# From your local machine (not the server)
scp root@your-server:/opt/conduit-backups/conduit-backup-*.tar.gz ~/backups/

🔄 When to Use

Something broke after an update, configuration change, or you just want to roll back to a known good state. Your server is the same machine — you just want to go back in time.

1. Open the Script

ssh root@your-server
bash conduit-deploy.sh

2. Go to Restore

From the main menu: 5 (Services) → 8 (Restore from backup)

💡 Even if Conduit is not installed (e.g., after an Uninstall), the Services menu still shows Restore as an option.

3. Choose Your Backup

═══ Restore from Backup ═══

  Backups are stored in: /opt/conduit-backups/

  Available backups:
  conduit-backup-2026-03-15-180609.tar.gz
  conduit-backup-2026-03-15-145926.tar.gz

Backup file path: /opt/conduit-backups/conduit-backup-2026-03-15-180609.tar.gz

4. Confirm & Wait

⛔ WARNING: This will replace your current installation!
  All current data, accounts, and messages will be overwritten.

Type 'RESTORE' to confirm: RESTORE

ℹ Restoring from backup...
✅ Files restored

# Imports database and certificates into Docker volumes
ℹ Importing database from backup...
✅ Database imported
✅ TLS certificates imported

═══ Restoring pinned image versions ═══
  Pulling the exact same images that were running at backup time.
  ✅ conduit
  ✅ caddy
  ✅ coturn

ℹ Starting services...
✅ Restore complete! Services are running.

# Re-creates infrastructure (firewall, TLS sync)
✅ Firewall rules verified
✅ TLS cert auto-sync restored
✅ UDP redirect rule restored

5. Verify

Run a Health Check (3) to confirm everything is working. All your accounts, messages, and rooms should be exactly as they were when the backup was taken.

💡 What About Updates After Restore?

Restore brings you back to the exact software versions from the backup (pinned by SHA256 digest). But your server isn't frozen there — after verifying everything works, you can update normally:

# After restore, update to latest versions anytime:
Menu → Services → Update containers (pull latest)

The pinning only applies during the restore itself — to give you a known-good starting point. After that, your server works like any other and you control when to update.

🚚 When to Use

Moving to a bigger VPS, switching providers, or setting up a disaster recovery server. Everything transfers: accounts, messages, rooms, media, and settings.

⚠️ Important: Your domain DNS must point to the new server's IP before you restore — otherwise HTTPS certificates won't work and federation will break.

1. Backup the Old Server

On your current/old server, create a fresh backup:

# On the old server
bash conduit-deploy.sh
# Menu: 5 (Services) → 7 (Backup)

2. Copy Backup to New Server

# From your local machine — download from old, upload to new
scp root@old-server:/opt/conduit-backups/conduit-backup-*.tar.gz /tmp/

# Upload to the new server
ssh root@new-server "mkdir -p /opt/conduit-backups"
scp /tmp/conduit-backup-*.tar.gz root@new-server:/opt/conduit-backups/
💡 Or direct server-to-server:
scp root@old-server:/opt/conduit-backups/*.tar.gz root@new-server:/opt/conduit-backups/

3. Update DNS

Point your domain to the new server's IP address:

TypeNameNew Value
Amatrix (or your subdomain)New server's IPv4
AAAAmatrix (or your subdomain)New server's IPv6
# Verify DNS points to the new server
dig matrix.example.com +short
# Should return the NEW server's IP

4. Download Script on New Server

ssh root@new-server
curl -sL https://raw.githubusercontent.com/balnaimi/conduit-deploy/main/conduit-deploy.sh -o conduit-deploy.sh
chmod +x conduit-deploy.sh
bash conduit-deploy.sh

5. Restore from Backup

The script detects Conduit is not installed. Go to 5 (Services) — only Restore is available:

═══ Service Management ═══

  Conduit is not installed. Only restore is available.

  8) Restore from backup
  0) Back to main menu

Choose: 8

Select your backup file and confirm:

Type 'RESTORE' to confirm: RESTORE

ℹ Restoring from backup...
✅ Files restored
✅ Database imported
✅ TLS certificates imported
✅ conduit, caddy, coturn pulled
ℹ Starting services...
✅ Restore complete! Services are running.
✅ Firewall rules verified
✅ TLS cert auto-sync restored
✅ UDP redirect rule restored

6. Verify

Run Health Check (3) on the new server:

  • All services running ✅
  • HTTPS working (Caddy gets new certs automatically) ✅
  • Federation port 8448 accessible ✅
  • All your accounts, messages, and rooms present ✅
💡 Updates after migration: The restore uses the exact Docker images from your backup (pinned by SHA256). Once you've verified everything works, you can update to the latest versions anytime via Services → Update containers. Your server is not locked to the old versions — the pinning just ensures a safe, known-good starting point.

7. Shut Down the Old Server

# On the OLD server — stop services
bash conduit-deploy.sh
# Menu: 5 → 2 (Stop all services)
# Or: Menu: 6 (Uninstall) to remove everything
⚠️ Don't run both servers at the same time with the same domain — this causes federation conflicts and split-brain data issues.

📋 Migration Checklist

  1. ☐ Create backup on old server
  2. ☐ Copy backup file to new server (/opt/conduit-backups/)
  3. ☐ Update DNS records to new server's IP
  4. ☐ Verify DNS propagation (dig matrix.example.com +short)
  5. ☐ Download script on new server
  6. ☐ Restore from backup (Services → Restore)
  7. ☐ Run Health Check — all green?
  8. ☐ Test login with a Matrix client
  9. ☐ Stop/uninstall old server
  10. ☐ 🎉 Done!