Chat de echipa Mattermost rulat cu Docker Compose pe un VPS, cu baloane de chat, un server si un lacat
Self-hosting

Mattermost cu Docker Compose: alternativa ta la Slack

Echipa ta traieste deja intr-o aplicatie de chat. Decizii, parole care n-ar trebui sa fie acolo, capturi de ecran de la clienti, “intrebarea rapida” care se transforma in sedinta de design: totul ajunge in chat. Intrebarea reala e pe serverul cui sta chat-ul asta, cine il poate citi si ce se intampla cu istoricul cand planul gratuit isi schimba iar regulile. Cu Mattermost si un VPS mic raspunzi singur la toate trei: serverul tau, baza ta de date, regulile tale, si o interfata pe care colegii o recunosc din primul minut.

In tutorialul asta instalam Mattermost cu Docker Compose, cu PostgreSQL in spate si HTTPS automat in fata. Apoi configuram notificarile pe email si conectam aplicatiile desktop si mobile, ca la final sa ai un chat de echipa privat care merge oriunde lucreaza oamenii tai. Proiectul e pe mattermost.com , iar codul sursa pe github.com/mattermost/mattermost .

Ce este Mattermost si de ce sa-l gazduiesti singur

Mattermost e o platforma open source de mesagerie pentru echipe: canale, grupuri private, mesaje directe, thread-uri, partajare de fisiere, reactii cu emoji, cautare, integrari si webhook-uri. Daca ai folosit Slack, stii deja sa-l folosesti. Diferenta e ca serverul il rulezi tu, deci mesajele si fisierele stau pe un disc pe care il controlezi, intr-un data center ales de tine, sub jurisdictia aleasa de tine.

Pentru o firma mica sau un proiect de facultate asta conteaza din motive foarte practice: fara abonament lunar per utilizator, fara istoric care dispare dupa 90 de zile, fara surpriza ca un furnizor decide ca workspace-ul tau e acum “plan vechi”. In plus, primesti webhook-uri si boti care pot posta direct intr-un canal notificari de deploy, alerte de monitorizare sau formulare completate de clienti.

Team Edition sau imaginea Enterprise?

Mattermost publica doua imagini de server. Team Edition (mattermost/mattermost-team-edition) e varianta gratuita, complet open source, si pe ea o folosim aici. Imaginea Enterprise porneste si fara licenta, dar e construita in jurul functiilor platite, iar modul ei gratuit a avut limite care se schimba de la o versiune la alta. Pentru un chat privat de cateva zeci de oameni, Team Edition e alegerea simpla. Poti schimba imaginea mai tarziu daca vei cumpara o licenta, pentru ca ambele folosesc aceeasi baza de date.

Cum se leaga piesele intre ele

Inainte sa scriem vreo comanda, sa lamurim notiunile de baza, pentru ca apar in fiecare pas.

  • Un container e o aplicatie impachetata cu tot ce ii trebuie ca sa ruleze (biblioteci, runtime, configuratie implicita), izolata de restul sistemului. Docker ruleaza containere, iar Docker Compose ne lasa sa descriem intr-un singur fisier YAML mai multe containere care lucreaza impreuna.
  • Un port e o “usa” numerotata a serverului. Traficul web foloseste 80 (HTTP) si 443 (HTTPS), SSH foloseste 22. Mattermost asculta pe 8065, iar PostgreSQL pe 5432, dar pe acestea doua nu le deschidem niciodata spre internet.
  • Un reverse proxy e receptia: primeste cererile HTTPS din lume, se ocupa de certificatul TLS si trimite traficul mai departe catre containerul potrivit. Folosim Caddy, pentru ca obtine si reinnoieste automat certificate Let’s Encrypt si gestioneaza WebSocket-urile (prin care Mattermost livreaza mesajele in timp real) fara configurare suplimentara.
  • Un volum e spatiu de stocare care supravietuieste cand containerul e recreat. Mesajele stau in volumul PostgreSQL, iar fisierele incarcate si configuratia in folderele Mattermost.
Mattermost pe un VPS: drumul unui mesajUtilizatoriBrowserApp desktopApp mobilVPS-ul tau (Debian 13 / Ubuntu 24.04)ufwdoar pentru SSH :22Iesire din MattermostSMTP :587, push proxy mobilCaddyporturile 80 si 443HTTPS, Let's EncryptMattermost:8065, doar internserver aplicatiePostgreSQL 17:5432, internretea backendcaddy_datacertificate./volumesfisiere, config, pluginurivolum pgdatafisierele bazeiPorturile publicate de Docker ocolesc ufw. 8065 si 5432 nu sunt publicate.
Doar Caddy e accesibil din internet. Mattermost si PostgreSQL comunica prin retele Docker private, iar ufw protejeaza serviciile gazdei, cum e SSH.

Un detaliu important din imagine: Docker isi scrie propriile reguli de firewall pentru porturile publicate, iar acestea se aplica inaintea regulilor ufw. Adica ufw nu poate bloca un port publicat de Docker. De aceea designul nostru pur si simplu nu publica niciodata 8065 sau 5432: singurele porturi publicate sunt 80 si 443 ale lui Caddy, pe care oricum le vrem deschise.

De ce ai nevoie

  • Un VPS cu 2 vCPU si 2 GB RAM (4 GB daca te astepti la peste 50 de utilizatori activi sau la multe fisiere partajate) si minim 20 GB de disc. Un VPS KVM e varianta cea mai simpla. Intr-un container LXC neprivilegiat, Docker are nevoie de nesting activat (si de obicei keyctl); daca docker run hello-world esueaza acolo, cere suportului sa-l activeze.
  • Debian 13 sau Ubuntu 24.04, proaspat instalat, si un utilizator cu drepturi sudo.
  • Un domeniu sau subdomeniu caruia ii poti modifica DNS-ul, de exemplu chat.example.com.
  • Date de acces SMTP pentru notificarile pe email: o casuta pe serverul tau de mail sau un serviciu de email tranzactional. Le poti adauga si mai tarziu, dar invitatiile si resetarea parolei au nevoie de ele.
  • Cam 45 de minute.

Planul pe scurt

De la VPS gol la chat de echipa in 9 pasi1Domeniulrecord A catre IP-ul VPS2Firewall-ulufw: 22, 80, 4433Instalare DockerEngine + Compose v24Folder si secrete.env, chown 20005Compose + Caddyfile3 servicii, 2 retele6Pornire stackHTTPS in cam un minut7Admin si echipaprimul cont e admin8Email prin SMTPport 587, STARTTLS9Desktop si mobilintroduci URL-ul https
Cei noua pasi ai tutorialului, numerotati exact ca titlurile Pasul 1 pana la Pasul 9 de mai jos.

Pasul 1: Indreapta un domeniu catre VPS

Aplicatiile mobile refuza serverele fara certificat valid, iar Let’s Encrypt emite certificate doar pentru nume de domeniu, nu pentru adrese IP. Asa ca primul lucru e DNS-ul.

In panoul furnizorului de DNS, creeaza un record A pentru chat.example.com care sa indice adresa IPv4 a VPS-ului. Daca VPS-ul are si IPv6, adauga si un record AAAA cu adresa IPv6. Apoi verifica de pe VPS ca numele se rezolva:

getent hosts chat.example.com

Ar trebui sa vezi IP-ul VPS-ului langa nume. Daca nu apare nimic sau apare o adresa veche, mai asteapta cateva minute (schimbarile DNS se propaga in functie de TTL-ul recordului) si incearca din nou. Nu trece la Pasul 6 pana nu e corect, altfel cererea de certificat va esua.

Pasul 2: Deschide firewall-ul pentru SSH si web

Un firewall decide ce porturi accepta conexiuni. Folosim ufw (“uncomplicated firewall”). Ubuntu 24.04 il are din instalare; pe Debian 13 trebuie instalat intai:

# Doar pe Debian (Ubuntu are deja ufw)
sudo apt update && sudo apt install -y ufw

Acum permite SSH inainte sa activezi firewall-ul, altfel te blochezi singur pe dinafara. Daca ai mutat SSH pe alt port, foloseste acel numar in loc de 22.

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw enable
sudo ufw status verbose

Ultima comanda ar trebui sa afiseze 22/tcp, 80/tcp, 443/tcp si 443/udp cu ALLOW IN, iar politica implicita pentru trafic de intrare pe deny. Cum am explicat mai sus, Docker va deschide 80 si 443 pentru Caddy indiferent de ufw; regulile raman totusi utile ca documentare a intentiei si functioneaza corect daca vreodata muti proxy-ul in afara Docker. UDP 443 e pentru HTTP/3, pe care Caddy il suporta din cutie.

Intr-un container LXC neprivilegiat, ufw poate esua la incarcarea regulilor. Daca se intampla, nu rula alte servicii pe porturi publice si cere-ne ajutorul pentru filtrare la nivel de retea.

Pasul 3: Instaleaza Docker si pluginul Compose

Mai intai aducem sistemul la zi:

sudo apt update && sudo apt full-upgrade -y

Pe Ubuntu, daca dupa asta exista fisierul /var/run/reboot-required, reporneste cu sudo reboot. Pe Debian fisierul nu e creat intotdeauna, asa ca reporneste daca actualizarea a instalat un pachet linux-image nou.

Apoi adaugam repository-ul oficial Docker. Blocul de mai jos merge pe ambele distributii: citeste /etc/os-release ca sa afle daca rulezi Debian sau Ubuntu si ce versiune, apoi scrie fisierul de surse deb822 recomandat acum de Docker, /etc/apt/sources.list.d/docker.sources.

sudo apt install -y ca-certificates curl openssl
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release
sudo curl -fsSL "https://download.docker.com/linux/${ID}/gpg" -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/${ID}
Suites: ${UBUNTU_CODENAME:-$VERSION_CODENAME}
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Verifica daca totul merge:

sudo docker run --rm hello-world
sudo docker compose version

Prima comanda afiseaza “Hello from Docker!”, a doua ceva de genul Docker Compose version v2.x.x. Atentie, e docker compose cu spatiu: Compose v2 e un plugin Docker, vechea comanda docker-compose nu mai e necesara. In tot ghidul punem sudo in fata comenzilor Docker; ai putea adauga utilizatorul in grupul docker ca sa scapi de el, dar apartenenta la grupul asta e echivalenta cu acces root, asa ca preferam sa ramana explicit.

Pasul 4: Creeaza folderul proiectului si secretele

Tot ce tine de instalare sta intr-un singur folder, ~/mattermost. Containerul Mattermost ruleaza ca utilizator si grup 2000, nu ca root, deci folderele in care scrie trebuie sa apartina acestui ID:

mkdir -p ~/mattermost && cd ~/mattermost
mkdir -p volumes/mattermost/{config,data,logs,plugins,client-plugins,bleve-indexes}
sudo chown -R 2000:2000 volumes/mattermost

Acestea sunt bind mount-uri: foldere obisnuite de pe server care apar in interiorul containerului. Fac backup-ul usor, pentru ca vezi si arhivezi fisierele direct.

Urmeaza alegerea versiunii Mattermost. Mattermost scoate versiuni des, asa ca verifica versiunea curenta pe pagina de release-uri sau intreaba Docker Hub care sunt cele mai noi tag-uri:

curl -s "https://hub.docker.com/v2/repositories/mattermost/mattermost-team-edition/tags?page_size=25&ordering=last_updated" | grep -o '"name":"[^"]*"'

Alege cel mai mare numar de versiune de forma X.Y.Z (ignora nume ca latest). Fixam intentionat o versiune exacta in loc de latest: o actualizare Mattermost ruleaza migrari ale bazei de date, iar tu vrei sa decizi cand se intampla asta, dupa un backup, nu oricand se intampla sa fie recreat containerul.

Acum cream fisierul .env. Compose il citeste automat si inlocuieste valorile in fisierul compose. Parola bazei de date e generata aleator; folosim caractere hex pentru ca parola ajunge intr-un URL de conexiune, unde simboluri ca @ sau / l-ar strica.

cat > .env <<EOF
DOMAIN=chat.example.com
TZ=Europe/Bucharest
# Doar exemplu: inlocuieste cu cel mai nou tag X.Y.Z gasit mai sus
MM_TAG=11.1.0
POSTGRES_USER=mmuser
POSTGRES_DB=mattermost
POSTGRES_PASSWORD=$(openssl rand -hex 24)
EOF
chmod 600 .env
nano .env

In editor, pune la DOMAIN subdomeniul tau real si la MM_TAG versiunea aleasa, apoi salveaza cu Ctrl+O si iesi cu Ctrl+X. chmod 600 face fisierul citibil doar de tine, pentru ca contine parola bazei de date.

Pasul 5: Scrie docker-compose.yml si Caddyfile

Creeaza docker-compose.yml in acelasi folder (nano docker-compose.yml) si lipeste:

services:
  postgres:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      TZ: ${TZ}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend
    security_opt:
      - no-new-privileges:true

  mattermost:
    image: mattermost/mattermost-team-edition:${MM_TAG}
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      TZ: ${TZ}
      MM_SQLSETTINGS_DRIVERNAME: postgres
      MM_SQLSETTINGS_DATASOURCE: "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable&connect_timeout=10"
      MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes
      MM_SERVICESETTINGS_SITEURL: "https://${DOMAIN}"
    volumes:
      - ./volumes/mattermost/config:/mattermost/config
      - ./volumes/mattermost/data:/mattermost/data
      - ./volumes/mattermost/logs:/mattermost/logs
      - ./volumes/mattermost/plugins:/mattermost/plugins
      - ./volumes/mattermost/client-plugins:/mattermost/client/plugins
      - ./volumes/mattermost/bleve-indexes:/mattermost/bleve-indexes
    networks:
      - backend
      - frontend
    security_opt:
      - no-new-privileges:true

  caddy:
    image: caddy:2
    restart: unless-stopped
    depends_on:
      - mattermost
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    environment:
      DOMAIN: ${DOMAIN}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - frontend

networks:
  frontend:
  backend:
    internal: true

volumes:
  pgdata:
  caddy_data:
  caddy_config:

Ce face, serviciu cu serviciu:

  • postgres foloseste imaginea oficiala postgres:17, isi tine fisierele in volumul numit pgdata si are un healthcheck, ca Compose sa stie cand baza de date chiar accepta conexiuni. Sta doar in reteaua backend, marcata internal: true: fara porturi, fara acces la internet, accesibila doar din Mattermost. (Daca alegi mai tarziu PostgreSQL 18, retine ca imaginea lui asteapta volumul la /var/lib/postgresql, iar o schimbare de versiune majora cere dump si restore, nu doar un tag nou.)
  • mattermost asteapta o baza de date sanatoasa, se conecteaza la ea prin MM_SQLSETTINGS_DATASOURCE (Mattermost citeste orice variabila MM_... ca suprascriere a configuratiei) si isi afla adresa publica din MM_SERVICESETTINGS_SITEURL. Setarile definite asa apar gri in System Console, si e un avantaj: nimeni nu poate strica din greseala conexiunea la baza de date din interfata web. E conectat si la frontend, ca sa ajunga la Caddy si la internet (pentru email si notificari push). Observa ca nu are sectiune ports:: 8065 nu e expus niciodata.
  • caddy e singurul serviciu cu porturi publicate. Certificatele lui stau in caddy_data, deci supravietuiesc repornirilor si nu atingi limitele Let’s Encrypt.

no-new-privileges impiedica procesele din container sa obtina privilegii suplimentare prin binare setuid, o masura de securitate care nu costa nimic.

Acum Caddyfile (nano Caddyfile):

{$DOMAIN} {
	encode zstd gzip
	reverse_proxy mattermost:8065
}

Asta e toata configuratia de proxy. {$DOMAIN} e citit din variabila de mediu transmisa, Caddy cere un certificat pentru acel nume, redirectioneaza HTTP catre HTTPS si trimite tot traficul, inclusiv conexiunile WebSocket, catre containerul Mattermost dupa numele serviciului. Valideaza fisierul compose inainte de pornire:

sudo docker compose config --quiet && echo "compose file OK"

Daca vezi compose file OK, YAML-ul si variabilele sunt in regula. Altfel, mesajul de eroare iti spune linia de corectat (de obicei indentarea).

Pasul 6: Porneste stack-ul si obtine HTTPS

sudo docker compose up -d
sudo docker compose ps

La prima rulare se descarca imaginile, dureaza un minut sau doua. docker compose ps ar trebui sa arate trei containere, cu postgres marcat healthy. Acum urmareste cum isi ia Caddy certificatul:

sudo docker compose logs -f caddy

Cauta o linie care contine certificate obtained successfully pentru domeniul tau, apoi apasa Ctrl+C. Fa la fel si pentru Mattermost; prima pornire ruleaza migrarile bazei de date si poate dura un minut:

sudo docker compose logs -f mattermost

Cand vezi un mesaj care contine Server is listening on, Mattermost e pornit. O verificare rapida chiar de pe VPS:

curl -sI "https://chat.example.com" | head -n 1

Rezultat asteptat: HTTP/2 200. Stack-ul tau Mattermost cu Docker Compose ruleaza.

Pasul 7: Creeaza contul de admin si prima echipa

Deschide https://chat.example.com in browser. Mattermost iti cere sa creezi un cont: email, nume de utilizator si o parola puternica. Primul cont creat devine System Admin, asa ca fa asta imediat, inainte sa mai gaseasca altcineva pagina.

Apoi asistentul de configurare iti cere numele organizatiei si creeaza prima echipa (un spatiu de lucru cu propriile canale; o instalare poate gazdui mai multe echipe). Ajungi in canalele “Town Square” si “Off-Topic”, cu care porneste orice echipa.

Acum inchide inregistrarile libere. Deschide meniul de produs (stanga sus), mergi la System Console > Authentication > Signup si verifica daca Enable Open Server e pe false. Asa, oamenii pot intra doar printr-un link de invitatie sau printr-o invitatie pe email. Ca sa inviti colegi, foloseste Invite People din meniul echipei: poti copia un link de invitatie sau poti trimite invitatii pe email (pentru asta ai nevoie de Pasul 8). Daca un link de invitatie ajunge unde nu trebuie, il poti regenera din setarile echipei.

Pasul 8: Configureaza notificarile pe email (SMTP)

Prin email trimite Mattermost invitatiile, resetarile de parola si notificarile pentru mentiuni si mesaje directe pe care le-ai ratat cat ai fost offline. Mattermost nu livreaza singur mailul; il preda unui server SMTP (serverul care transmite emailul mai departe), de exemplu casuta firmei sau un serviciu de email tranzactional.

Foloseste portul 587 cu STARTTLS. Multi furnizori blocheaza portul 25 de iesire pe serverele virtuale, ca masura anti-spam, iar 587 e oricum portul standard pentru trimitere autentificata.

In interfata web, mergi la System Console > Environment > SMTP si completeaza:

  • SMTP Server: hostul furnizorului, de exemplu smtp.example.net
  • SMTP Server Port: 587
  • Enable SMTP Authentication: true
  • SMTP Server Username si SMTP Server Password: datele casutei de email
  • Connection Security: STARTTLS (foloseste TLS daca furnizorul cere portul 465)

Apasa Test Connection. O confirmare verde inseamna ca Mattermost s-a putut autentifica. Salveaza, apoi mergi la System Console > Site Configuration > Notifications si seteaza Enable Email Notifications pe true, un Notification Display Name (de exemplu “Chat Firma”) si un Notification From Address pe domeniul tau, cum ar fi chat@example.com. Salveaza din nou.

Ca mailurile sa ajunga in inbox si nu in spam, domeniul expeditor are nevoie de recorduri SPF si DKIM corecte care autorizeaza furnizorul SMTP; documentatia furnizorului iti da valorile exacte. Ca test complet, delogheaza-te si foloseste “Forgot your password?” cu emailul de admin.

Daca preferi configuratia ca cod, poti seta aceleasi valori ca variabile de mediu in serviciul mattermost, cu parola tinuta in .env (adauga acolo SMTP_PASSWORD=...):

      MM_EMAILSETTINGS_SENDEMAILNOTIFICATIONS: "true"
      MM_EMAILSETTINGS_SMTPSERVER: smtp.example.net
      MM_EMAILSETTINGS_SMTPPORT: "587"
      MM_EMAILSETTINGS_CONNECTIONSECURITY: STARTTLS
      MM_EMAILSETTINGS_ENABLESMTPAUTH: "true"
      MM_EMAILSETTINGS_SMTPUSERNAME: chat@example.com
      MM_EMAILSETTINGS_SMTPPASSWORD: ${SMTP_PASSWORD}
      MM_EMAILSETTINGS_FEEDBACKEMAIL: chat@example.com
      MM_EMAILSETTINGS_FEEDBACKNAME: Chat Firma

Dupa modificare, ruleaza sudo docker compose up -d ca sa fie recreat containerul. Campurile respective apar apoi doar in citire in System Console.

Cat esti in consola, deschide System Console > Environment > Push Notification Server. Notificarile pe telefon nu pot pleca direct de pe serverul tau catre iPhone-uri si telefoane Android: Apple si Google le accepta doar de la editorul aplicatiei, asa ca Mattermost le trimite prin propriul push proxy. Asigura-te ca notificarile push sunt activate cu optiunea gazduita de Mattermost disponibila pentru editia ta. Apoi, la Site Configuration > Notifications > Push Notification Contents, alege o descriere generica daca nu vrei ca textul mesajelor sa treaca prin acel proxy.

Pasul 9: Conecteaza aplicatiile desktop si mobile

Desktop: descarca aplicatia Mattermost pentru Windows, macOS sau Linux de pe mattermost.com/apps . La prima pornire iti cere un server: da-i un nume afisat si URL-ul https://chat.example.com, apoi autentifica-te. Aplicatia iti da notificari native, o iconita in tray cu numarul de mesaje necitite si iti permite sa adaugi mai multe servere unul langa altul.

Mobil: instaleaza “Mattermost” din App Store sau Google Play. Introdu acelasi URL, optional un nume afisat, si autentifica-te. Trimite-ti un mesaj direct de pe alt cont cat timp telefonul e blocat, ca sa confirmi ca notificarile push ajung.

Aplicatiile verifica strict certificatul, si exact de aceea am pus un certificat Let’s Encrypt real in Pasul 6. Daca aplicatia spune ca nu se poate conecta, deschide intai URL-ul in browserul telefonului: daca browserul afiseaza un avertisment, repara certificatul sau DNS-ul inainte sa dai vina pe aplicatie.

Cat RAM are nevoie Mattermost?

RAM folosit aproximativ, echipa mica (10-30 oameni)Valori tipice in repaus si folosire usoara; planifica 2 GB RAM ca rezervaCaddy~30 MBPostgreSQL 17~120 MBMattermost~450 MBTot stack-ul~600 MB0100200300400500600700RAM in MB (aproximativ)Container
Memorie aproximativa per container pentru o echipa mica. Valorile reale cresc cu numarul de utilizatori, pluginurile, indexarea pentru cautare si previzualizarile de fisiere.

Poti vedea valorile reale pe serverul tau cu sudo docker stats --no-stream. Mattermost e o aplicatie Go si e destul de cumpatat, dar creste odata cu conexiunile active, pluginurile activate (Calls, Playbooks, Boards) si previzualizarile de imagini. Sistemul de operare, cache-ul de pagini si memoria de lucru a PostgreSQL au si ele nevoie de loc, de aceea recomandam 2 GB ca minim confortabil, in loc sa inghesui stack-ul in 1 GB.

Backup si restaurare

Un server de chat tine memoria echipei, asa ca fa-i backup din prima zi. Conteaza doua lucruri: baza de date (toate mesajele, utilizatorii, canalele) si folderul de fisiere (atasamente, plus config.json, care contine parola SMTP, deci trateaza backup-urile ca date sensibile).

cd ~/mattermost
mkdir -p backup
sudo docker compose exec -T postgres pg_dump -U mmuser -d mattermost -Fc > "backup/db-$(date +%F).dump"
sudo tar czf "backup/files-$(date +%F).tar.gz" volumes/mattermost/config volumes/mattermost/data volumes/mattermost/plugins volumes/mattermost/client-plugins
sudo chown "$USER": backup/*
ls -lh backup/

pg_dump ruleaza in containerul bazei de date si se conecteaza prin socket-ul local PostgreSQL, deci nicio parola nu apare in linia de comanda. -Fc produce un dump comprimat in format custom. Arhiva tar e creata de root, asa ca linia cu chown ti-o da inapoi utilizatorului tau, altfel copierea ei de pe server cu scp sau rsync ca utilizator normal esueaza cu “permission denied”. Copiaza ambele fisiere pe alta masina sau alt storage; un backup care sta doar pe acelasi VPS nu supravietuieste pierderii acelui VPS. Ca sa-l automatizezi, pune liniile intr-un script si ruleaza-l noaptea din cron.

Restaurarea se face mereu intr-o baza de date noua, goala, niciodata peste cea live pe care Mattermost a migrat-o deja. Opreste aplicatia, recreeaza baza de date, restaureaza, apoi porneste din nou:

cd ~/mattermost
sudo docker compose stop mattermost
sudo docker compose exec -T postgres dropdb -U mmuser mattermost
sudo docker compose exec -T postgres createdb -U mmuser -O mmuser mattermost
sudo docker compose exec -T postgres pg_restore -U mmuser -d mattermost --no-owner < backup/db-2026-11-10.dump
sudo tar xzf backup/files-2026-11-10.tar.gz -C ~/mattermost
sudo docker compose start mattermost

Inlocuieste datele cu numele fisierelor tale de backup. Daca restaurezi pe un server complet nou, urmeaza Pasii 1-5, dezarhiveaza fisierele, porneste doar PostgreSQL cu sudo docker compose up -d postgres, restaureaza dump-ul si abia apoi porneste restul.

Actualizarea Mattermost

Citeste notele de release pentru versiunea la care treci, mai ales sectiunea “Important Upgrade Notes”, apoi:

  1. Fa un backup ca mai sus.
  2. Editeaza .env si schimba MM_TAG cu noua versiune.
  3. Descarca imaginile si recreeaza containerele:
cd ~/mattermost
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f mattermost

Mattermost migreaza baza de date la pornire; asteapta din nou mesajul Server is listening on. pull actualizeaza si caddy:2 si postgres:17 in cadrul versiunilor majore, ceea ce aduce reparatii de securitate. Daca preferi mai putine actualizari, Mattermost publica Extended Support Releases (ESR), care primesc reparatii o perioada mai lunga. Nu sari PostgreSQL la o versiune majora noua doar schimband tag-ul: asta cere dump si restore intr-un volum nou.

Depanare si greseli frecvente

  • Caddy nu poate obtine certificatul. Ruleaza sudo docker compose logs caddy. Aproape mereu recordul DNS nu indica inca spre acest VPS, sau portul 80 e blocat undeva mai sus. Repara DNS-ul, apoi sudo docker compose restart caddy.
  • Mattermost reporneste in bucla cu “permission denied”. Folderele volumelor nu apartin UID-ului 2000. Ruleaza sudo chown -R 2000:2000 ~/mattermost/volumes/mattermost si sudo docker compose up -d.
  • “password authentication failed for user mmuser”. PostgreSQL citeste POSTGRES_PASSWORD doar cand volumul e creat prima data. Daca ai schimbat parola in .env dupa aceea, fie o pui inapoi, fie setezi noua parola interactiv in baza de date: sudo docker compose exec postgres psql -U mmuser -d mattermost, apoi scrii \password mmuser si o introduci de doua ori.
  • Mesajele apar doar dupa refresh. Conexiunea WebSocket esueaza. Verifica daca Site URL-ul e exact adresa pe care o folosesti (https, fara cale in plus) si daca nu exista un al doilea proxy sau un CDN in fata lui Caddy care taie upgrade-urile WebSocket.
  • Emailurile nu ajung. Foloseste intai Test Connection din pagina SMTP. Daca da timeout, portul e blocat sau gresit; daca se autentifica, dar mailurile ajung in spam, repara SPF si DKIM pentru domeniul expeditor.
  • Aplicatia mobila spune ca nu se poate conecta. Deschide URL-ul in browserul telefonului. Avertismentele de certificat, domeniul gresit sau un Site URL cu http:// sunt cauzele obisnuite.
  • Containerele nu pornesc deloc pe un VPS LXC. Docker are nevoie de nesting activat in container; contacteaza suportul.

Note de securitate

  • Doar Caddy e publicat. Nu adauga niciodata ports: la serviciile mattermost sau postgres “doar pentru test”. Nu uita ca porturile publicate de Docker ocolesc ufw, deci un 5432 publicat ar fi deschis catre tot internetul.
  • Tine .env privat (chmod 600) si in afara oricarui repository Git. La fel si backup-urile, care contin config.json cu parola SMTP.
  • Inregistrari inchise, doar pe invitatie. Lasa Enable Open Server oprit si regenereaza linkul de invitatie daca ajunge unde nu trebuie.
  • Activeaza autentificarea multi-factor in System Console > Authentication > MFA, ca utilizatorii, incepand cu fiecare admin, sa-si protejeze conturile cu o aplicatie de autentificare.
  • Actualizeaza ambele niveluri. Actualizeaza regulat sistemul gazda (sudo apt update && sudo apt full-upgrade sau activeaza unattended-upgrades) si containerele, cum am descris mai sus. Mattermost publica reparatiile de securitate ca versiuni patch, asa ca aboneaza-te la anunturile de release.
  • Igiena SSH. Foloseste autentificare cu chei si dezactiveaza autentificarea cu parola pentru SSH; serverul de chat e doar atat de sigur cat e contul care il administreaza.

Deci, merita Mattermost gazduit de tine?

Daca echipa ta vrea o experienta de chat familiara fara taxe per utilizator, cu un istoric care ramane pe loc si date care stau pe un server pe care il controlezi, da. Instalarea Mattermost cu Docker Compose de mai sus inseamna trei containere, un fisier mic de configurare pentru proxy si o rutina de backup pe care o automatizezi in cinci minute. Munca de zi cu zi se reduce mai ales la citit note de release si rulat doua comenzi o data la cateva saptamani.

Poti porni stack-ul asta pe un VPS in data center-ul nostru din Romania in cateva minute, cu resurse suficiente pentru o echipa care creste. Iar daca preferi ca altcineva sa se ocupe de instalare, livrabilitatea emailurilor, backup-uri si actualizari, echipa noastra de administrare servere le poate configura si intretine pentru tine.

Intrebari frecvente

Cati utilizatori duce un VPS mic?

Un VPS cu 2 vCPU si 2 GB RAM serveste confortabil cateva zeci de utilizatori activi, cu chat si partajare de fisiere normale. Peste aproximativ 50-100 de utilizatori activi, sau cu apeluri vocale si multe pluginuri, treci la 4 GB RAM si urmareste docker stats si spatiul pe disc.

Pot importa istoricul din Slack?

Da. Exporta workspace-ul din Slack, converteste exportul cu utilitarul oficial Mattermost mmetl si importa-l cu mmctl. Documentatia Mattermost descrie procesul; testeaza-l intai pe o copie, pentru ca exporturile mari cu multe fisiere dureaza.

Mattermost Team Edition e chiar gratuit?

Da, Team Edition e open source si nu are limita de utilizatori. Editiile platite adauga lucruri ca SAML single sign-on, exporturi avansate pentru conformitate si clustering pentru disponibilitate ridicata, de care majoritatea echipelor mici nu au nevoie.

Notificarile push pleaca de pe serverul meu?

Da, notificarile push pe mobil trec prin push proxy-ul Mattermost, pentru ca Apple si Google accepta notificari doar de la editorul aplicatiei. Seteaza Push Notification Contents pe o descriere generica, ca textul mesajului sa nu fie inclus.

Pot folosi nginx in loc de Caddy?

Sigur. Orice reverse proxy merge daca termina TLS, trimite catre mattermost:8065 si paseaza headerele de upgrade WebSocket. Am ales Caddy pentru ca certificatele si WebSocket-urile functioneaza cu o configuratie de trei randuri.

Avem Incredere & Suntem Membri

Suntem membri ai principalelor organizatii de infrastructura internet.

RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX