# Ubuntu VM Homelab Self-hosted communication platform with Mastodon, Mattermost, and Matrix/Element on a single Ubuntu VM sharing PostgreSQL. ## Current Deployment Status | Service | Status | Domain | Internal Port | Nginx Port | |---------|--------|--------|---------------|------------| | ✅ Mastodon | Running | mastodon.vish.gg | 3000, 4000 | 8082 | | ✅ Mattermost | Running | mm.crista.love | 8065 | 8081 | | ✅ Matrix (mx.vish.gg) | Running | mx.vish.gg | 8018 | 8082 | | ✅ Matrix (vish - legacy) | Running | matrix.thevish.io | 8008 | 8081 | | ✅ PostgreSQL | Running | - | 5432 | - | | ✅ Redis | Running | - | 6379 | - | | ✅ TURN (coturn) | Running | mx.vish.gg:3479 | 3479 | - | ## VM Specifications - **OS**: Ubuntu 24.04.4 LTS (x86_64) - **Hostname**: matrix-ubuntu - **LAN IP**: 192.168.0.154 (static) — `ssh ubuntu-matrix` - **Tailscale IP**: 100.85.21.51 - **SSH user**: test - **RAM**: 7.7 GB - **CPU**: 4 cores - **Storage**: 96 GB - **Network**: Static IP set via netplan (`/etc/netplan/99-static.yaml`), cloud-init network management disabled ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Cloudflare Proxy │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Nginx │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ :8080 │ │ :8081 │ │ :8082 │ │ │ │ Matrix │ │ Mattermost │ │ Mastodon │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Synapse │ │ Mattermost │ │ Mastodon │ │ :8008 │ │ Docker │ │ Docker │ │ + Element │ │ :8065 │ │ :3000 │ └─────────────┘ └─────────────┘ │ :4000 │ │ │ └─────────────┘ │ │ │ └───────────────────┴──────────────────┘ │ ▼ ┌─────────────────┐ │ PostgreSQL │ │ :5432 │ │ │ │ - synapse │ │ - mattermost │ │ - mastodon │ └─────────────────┘ ``` ## Databases All services share the same PostgreSQL 16 server: | Database | User | Purpose | |----------|------|---------| | synapse | synapse | Matrix homeserver (vish - legacy) | | synapse_mx | synapse_mx | Matrix homeserver (mx.vish.gg - federated) | | mattermost | mmuser | Mattermost | | mastodon_production | mastodon | Mastodon | ## Docker Containers ``` NAMES IMAGE STATUS mastodon-streaming-1 ghcr.io/mastodon/mastodon-streaming:v4.5.7 Up mastodon-web-1 ghcr.io/mastodon/mastodon:v4.5.7 Up mastodon-sidekiq-1 ghcr.io/mastodon/mastodon:v4.5.7 Up mastodon-redis-1 redis:7-alpine Up mattermost mattermost/mattermost-team-edition:11.4 Up (healthy) ``` ## Systemd Services (bare-metal) ``` UNIT SERVICE VERSION synapse.service Synapse (legacy) 1.148.0 — /opt/synapse, port 8008 synapse-mx.service Synapse (primary) 1.148.0 — /opt/synapse-mx, port 8018 ``` Both Synapse instances share the venv at `/opt/synapse/venv/`. ## Quick Start 1. Clone this repo to your VM 2. Copy environment templates and edit with your values 3. Run the setup script ```bash git clone https://git.vish.gg/Vish/Ubuntu-vm-homelab.git cd Ubuntu-vm-homelab ./scripts/setup.sh ``` ## Directory Structure ``` Ubuntu-vm-homelab/ ├── mastodon/ │ ├── docker-compose.yml │ └── .env.production.template ├── mattermost/ │ ├── docker-compose.yml │ └── config.json.template ├── matrix-element/ │ ├── homeserver.yaml.template │ └── element-config.json.template ├── nginx/ │ ├── mastodon.conf │ ├── mattermost.conf │ └── matrix.conf ├── scripts/ │ ├── setup.sh │ ├── backup.sh │ └── update.sh └── README.md ``` ## Credentials Stored securely on the server: - `/opt/mastodon/.env.production` - Mastodon secrets - `/opt/mattermost/config/config.json` - Mattermost config - `/opt/synapse/homeserver.yaml` - Matrix config ## Cloudflare Setup Each service requires a DNS record pointing to the VM's public IP with Cloudflare proxy enabled. Configure origin rules to route to the correct nginx port. ## Maintenance ### Backup ```bash ./scripts/backup.sh ``` ### View Logs ```bash # Mastodon cd /opt/mastodon && docker compose logs -f # Mattermost docker logs -f mattermost # Matrix (mx.vish.gg) tail -f /opt/synapse-mx/homeserver.log # Matrix (legacy vish) tail -f /opt/synapse/homeserver.log ``` --- ## Updating Services ### Update Mastodon ```bash cd /opt/mastodon # Pull latest images docker compose pull # Stop services docker compose down # Run database migrations docker compose run --rm web bundle exec rails db:migrate # Precompile assets (if needed) docker compose run --rm web bundle exec rails assets:precompile # Start services docker compose up -d # Verify docker compose ps ``` **Check for release notes:** https://github.com/mastodon/mastodon/releases ### Update Mattermost ```bash cd /opt/mattermost # Check current version docker exec mattermost mattermost version # Pull latest image docker compose pull # Stop and restart docker compose down docker compose up -d # Verify docker logs mattermost | head -20 ``` **Check for release notes:** https://docs.mattermost.com/about/mattermost-server-releases.html ### Update Matrix Synapse (both instances share the same venv) Both instances use `/opt/synapse/venv/` — upgrade once, restart both. ```bash # Check current version curl -s http://localhost:8018/_synapse/admin/v1/server_version # Upgrade (pin to a specific version, e.g. 1.148.0) sudo /opt/synapse/venv/bin/pip install 'matrix-synapse==1.148.0' # Restart both services sudo systemctl restart synapse synapse-mx # Verify curl -s http://localhost:8008/_synapse/admin/v1/server_version # legacy curl -s http://localhost:8018/_synapse/admin/v1/server_version # mx ``` **Check for release notes:** https://github.com/element-hq/synapse/releases > **Note:** If startup fails with `InsufficientPrivilege: must be owner of table`, see > the DB ownership fix in `docs/MATRIX.md#db-ownership-fix`. ### Update Element Web ```bash # Check latest version at https://github.com/element-hq/element-web/releases ELEMENT_VERSION="v1.12.11" # Change to latest version # Download and extract cd /tmp wget https://github.com/element-hq/element-web/releases/download/${ELEMENT_VERSION}/element-${ELEMENT_VERSION}.tar.gz tar -xzf element-${ELEMENT_VERSION}.tar.gz # Backup current config cp /opt/element/web/config.json /tmp/element-config-backup.json # Back up configs cp /opt/element/web/config.json /tmp/element-config-web.json cp /opt/element/web-thevish/config.json /tmp/element-config-thevish.json # Replace files (both installs share the same release) sudo rm -rf /opt/element/web/* /opt/element/web-thevish/* sudo cp -r element-${ELEMENT_VERSION}/* /opt/element/web/ sudo cp -r element-${ELEMENT_VERSION}/* /opt/element/web-thevish/ # Restore configs sudo cp /tmp/element-config-web.json /opt/element/web/config.json sudo cp /tmp/element-config-thevish.json /opt/element/web-thevish/config.json # Verify (nginx serves static files, no restart needed) cat /opt/element/web/version cat /opt/element/web-thevish/version # Cleanup rm -rf /tmp/element-${ELEMENT_VERSION}* /tmp/element-config-*.json ``` ### Update TURN Server (coturn) ```bash # Update via apt sudo apt update sudo apt upgrade coturn # Restart sudo systemctl restart coturn # Verify sudo systemctl status coturn ``` ### Update All Services (Quick Script) ```bash #!/bin/bash # Save as /opt/scripts/update-all.sh echo "=== Updating Mastodon ===" cd /opt/mastodon docker compose pull docker compose down docker compose run --rm web bundle exec rails db:migrate docker compose up -d echo "=== Updating Mattermost ===" cd /opt/mattermost docker compose pull docker compose down docker compose up -d echo "=== Updating Synapse ===" cd /opt/synapse source venv/bin/activate pip install --upgrade matrix-synapse pkill -f 'synapse.app.homeserver' sleep 2 sudo -u synapse /opt/synapse/venv/bin/python -m synapse.app.homeserver \ --config-path=/opt/synapse-mx/homeserver.yaml --daemonize sudo -u synapse /opt/synapse/venv/bin/python -m synapse.app.homeserver \ --config-path=/opt/synapse/homeserver.yaml --daemonize echo "=== Updating System Packages ===" sudo apt update && sudo apt upgrade -y echo "=== Done! ===" ``` --- ## Federation Status | Service | Protocol | Federation | |---------|----------|------------| | Matrix (mx.vish.gg) | Matrix | ✅ Enabled | | Matrix (vish) | Matrix | ❌ Disabled (invalid server_name) | | Mastodon | ActivityPub | ✅ Enabled | | Mattermost | Shared Channels | ❌ Enterprise only | ## License MIT