snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 00:29:55 +05:00
commit 240db4e2a7
15309 changed files with 2173406 additions and 0 deletions

3
server/build/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
diff.txt
latest.sql
migrated.sql

88
server/build/Dockerfile Normal file
View File

@@ -0,0 +1,88 @@
# First stage - Ubuntu with document processing dependencies and curl for downloading
FROM ubuntu:noble-20251013@sha256:c35e29c9450151419d9448b0fd75374fec4fff364a27f176fb458d472dfc9e54 AS builder
# Setting bash as our shell, and enabling pipefail option
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Build Arguments
ARG PUID=2000
ARG PGID=2000
# MM_PACKAGE build arguments controls which version of mattermost to install, defaults to latest stable enterprise
# e.g. https://releases.mattermost.com/9.7.1/mattermost-9.7.1-linux-amd64.tar.gz
ARG MM_PACKAGE="https://latest.mattermost.com/mattermost-enterprise-linux"
# Install needed packages and indirect dependencies
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
ca-certificates \
curl \
media-types \
mailcap \
unrtf \
wv \
poppler-utils \
tidy \
tzdata \
&& rm -rf /var/lib/apt/lists/*
# Set mattermost group/user and download Mattermost
RUN mkdir -p /mattermost/data /mattermost/plugins /mattermost/client/plugins \
&& groupadd --gid ${PGID} mattermost \
&& useradd --uid ${PUID} --gid ${PGID} --comment "" --home-dir /mattermost mattermost \
&& curl -L $MM_PACKAGE | tar -xvz \
&& chown -R mattermost:mattermost /mattermost /mattermost/data /mattermost/plugins /mattermost/client/plugins
# Create PostgreSQL client SSL directory structure for ssl_mode=require
RUN mkdir -p /mattermost/.postgresql \
&& chmod 700 /mattermost/.postgresql
# Final stage using distroless for minimal attack surface
FROM gcr.io/distroless/base-debian12
# Some ENV variables
ENV PATH="/mattermost/bin:${PATH}"
ENV MM_SERVICESETTINGS_ENABLELOCALMODE="true"
ENV MM_INSTALL_TYPE="docker"
# Copy over metadata files needed by runtime
COPY --from=builder /etc/mime.types /etc
# Copy CA certificates for SSL/TLS validation with proper ownership
COPY --from=builder --chown=2000:2000 /etc/ssl/certs /etc/ssl/certs
# Copy document processing utilities and necessary support files
COPY --from=builder /usr/bin/pdftotext /usr/bin/pdftotext
COPY --from=builder /usr/bin/wvText /usr/bin/wvText
COPY --from=builder /usr/bin/wvWare /usr/bin/wvWare
COPY --from=builder /usr/bin/unrtf /usr/bin/unrtf
COPY --from=builder /usr/bin/tidy /usr/bin/tidy
COPY --from=builder /usr/share/wv /usr/share/wv
# Copy necessary libraries for document processing utilities
COPY --from=builder /usr/lib/libpoppler.so* /usr/lib/
COPY --from=builder /usr/lib/libfreetype.so* /usr/lib/
COPY --from=builder /usr/lib/libpng.so* /usr/lib/
COPY --from=builder /usr/lib/libwv.so* /usr/lib/
COPY --from=builder /usr/lib/libtidy.so* /usr/lib/
COPY --from=builder /usr/lib/libfontconfig.so* /usr/lib/
# Copy mattermost from builder stage
COPY --from=builder --chown=2000:2000 /mattermost /mattermost
# Copy passwd including mattermost user
COPY passwd /etc/passwd
# We should refrain from running as privileged user
USER mattermost
# Healthcheck to make sure container is ready - using mmctl instead of curl for distroless compatibility
HEALTHCHECK --interval=30s --timeout=10s \
CMD ["/mattermost/bin/mmctl", "system", "status", "--local"]
# Configure entrypoint and command with proper permissions
WORKDIR /mattermost
CMD ["/mattermost/bin/mattermost"]
EXPOSE 8065 8067 8074
# Declare volumes for mount point directories
VOLUME ["/mattermost/data", "/mattermost/logs", "/mattermost/config", "/mattermost/plugins", "/mattermost/client/plugins"]

View File

@@ -0,0 +1,17 @@
FROM golang:1.26.7-bookworm@sha256:6ef6e30f0ea5c384f6d111cf856e024e3086bbdcb1779da3f3b3fbba0aea53d2
ARG NODE_VERSION=24.11.1
RUN apt-get update && apt-get install -y make git apt-transport-https ca-certificates curl software-properties-common build-essential zip xmlsec1 jq pgloader gnupg
# Download and install node via nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
RUN bash -c "source /root/.nvm/nvm.sh && nvm install $NODE_VERSION && nvm use $NODE_VERSION && nvm alias default $NODE_VERSION"
# Make node and npm globally available
ENV PATH="/root/.nvm/versions/node/v$NODE_VERSION/bin:$PATH"
RUN git config --global --add safe.directory /mattermost
# Remove any existing entrypoint, and use bash as the default command
ENTRYPOINT []
CMD ["bash"]

View File

@@ -0,0 +1,17 @@
FROM cgr.dev/mattermost.com/go-msft-fips:1.26.7.1-dev@sha256:ae345a37a612265894a7e7f318be45680663346cb7992613916e196daf38e839
ARG NODE_VERSION=24.11.1
RUN apk add curl ca-certificates mailcap unrtf wv poppler-utils tzdata gpg xmlsec
# Download and install node via nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
RUN bash -c "source /root/.nvm/nvm.sh && nvm install $NODE_VERSION && nvm use $NODE_VERSION && nvm alias default $NODE_VERSION"
# Make node and npm globally available
ENV PATH="/root/.nvm/versions/node/v$NODE_VERSION/bin:$PATH"
RUN git config --global --add safe.directory /mattermost
# Remove any existing entrypoint, and use bash as the default command
ENTRYPOINT []
CMD ["bash"]

View File

@@ -0,0 +1,4 @@
ARG ELASTICSEARCH_VERSION=9.0.0
FROM docker.elastic.co/elasticsearch/elasticsearch:${ELASTICSEARCH_VERSION}
RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch analysis-icu analysis-nori analysis-kuromoji analysis-smartcn

View File

@@ -0,0 +1,91 @@
# First stage - FIPS dev image with dependencies for building
FROM cgr.dev/mattermost.com/glibc-openssl-fips:16-dev@sha256:e971e3eb6b5ffd227e17d0fa7944e3430d3e8e24e9587d5488a833139629ab0f AS builder
# Setting bash as our shell, and enabling pipefail option
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Build Arguments
ARG PUID=2000
ARG PGID=2000
# MM_PACKAGE build arguments controls which version of mattermost to install, defaults to latest stable enterprise
# e.g. https://releases.mattermost.com/9.7.1/mattermost-9.7.1-linux-amd64.tar.gz
ARG MM_PACKAGE="https://latest.mattermost.com/mattermost-enterprise-linux"
# Install needed packages and indirect dependencies
USER 0:0
RUN apk add \
curl \
ca-certificates \
mailcap \
unrtf \
wv \
poppler-utils \
tzdata
# Set mattermost group/user and download Mattermost
RUN mkdir -p /mattermost/data /mattermost/plugins /mattermost/client/plugins \
&& addgroup -g ${PGID} mattermost \
&& adduser -D -u ${PUID} -G mattermost -g "" -s /bin/sh -h /mattermost mattermost \
&& curl -L $MM_PACKAGE | tar -xvz \
&& chown -R mattermost:mattermost /mattermost /mattermost/data /mattermost/plugins /mattermost/client/plugins
# Create PostgreSQL client SSL directory structure for ssl_mode=require
RUN mkdir -p /mattermost/.postgresql \
&& chmod 700 /mattermost/.postgresql
# Create /var/tmp directory needed for local socket files
RUN mkdir -p /var/tmp \
&& chmod 755 /var/tmp
# Final stage using FIPS runtime image
FROM cgr.dev/mattermost.com/glibc-openssl-fips:16@sha256:a636adba740bb6a53e55c14f7deb979802bcff2203f4aaecfe6f1d159cdfe3a1
# Some ENV variables
ENV PATH="/mattermost/bin:${PATH}"
ENV MM_SERVICESETTINGS_ENABLELOCALMODE="true"
ENV MM_INSTALL_TYPE="docker"
# Copy over metadata files needed by runtime
COPY --from=builder /etc/mime.types /etc
# Copy CA certificates for SSL/TLS validation with proper ownership
COPY --from=builder --chown=2000:2000 /etc/ssl/certs /etc/ssl/certs
# Copy document processing utilities and necessary support files
COPY --from=builder /usr/bin/pdftotext /usr/bin/pdftotext
COPY --from=builder /usr/bin/wvText /usr/bin/wvText
COPY --from=builder /usr/bin/wvWare /usr/bin/wvWare
COPY --from=builder /usr/bin/unrtf /usr/bin/unrtf
COPY --from=builder /usr/share/wv /usr/share/wv
# Copy necessary libraries for document processing utilities
COPY --from=builder /usr/lib/libpoppler.so* /usr/lib/
COPY --from=builder /usr/lib/libfreetype.so* /usr/lib/
COPY --from=builder /usr/lib/libpng16.so* /usr/lib/
COPY --from=builder /usr/lib/libwv.so* /usr/lib/
COPY --from=builder /usr/lib/libfontconfig.so* /usr/lib/
# Copy mattermost from builder stage
COPY --from=builder --chown=2000:2000 /mattermost /mattermost
# Copy group and passwd files including mattermost user
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
# Copy /var/tmp directory needed for local socket files
COPY --from=builder --chown=2000:2000 /var/tmp /var/tmp
# We should refrain from running as privileged user
USER mattermost
# Healthcheck to make sure container is ready - using mmctl instead of curl for distroless compatibility
HEALTHCHECK --interval=30s --timeout=10s \
CMD ["/mattermost/bin/mmctl", "system", "status", "--local"]
# Configure entrypoint and command with proper permissions
WORKDIR /mattermost
CMD ["/mattermost/bin/mattermost"]
EXPOSE 8065 8067 8074
# Declare volumes for mount point directories
VOLUME ["/mattermost/data", "/mattermost/logs", "/mattermost/config", "/mattermost/plugins", "/mattermost/client/plugins"]

View File

@@ -0,0 +1,4 @@
ARG OPENSEARCH_VERSION=3.0.0
FROM opensearchproject/opensearch:$OPENSEARCH_VERSION
RUN /usr/share/opensearch/bin/opensearch-plugin install analysis-icu analysis-nori analysis-kuromoji analysis-smartcn

View File

@@ -0,0 +1,11 @@
Mattermost MIT Compiled License
**Note: this license does not cover source code, for information on source code licensing see LICENSE.txt in the Mattermost source code.
Copyright (c) 2016-present Mattermost, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1 @@
https://mattermost.com/pl/privacy-policy/

21
server/build/README.md Normal file
View File

@@ -0,0 +1,21 @@
## About this folder
This folder contains some files that we use to build the `mattermost-server` and other files like privacy policy and licenses.
The `Dockerfile` in this folder (`Dockerfile.buildenv`) is the build environment for our current builds you can find the docker image to download [here](https://hub.docker.com/r/mattermost/mattermost-build-server/tags/) or build your own.
### Docker Image for building the Server
We have a docker image to build `mattermost-server` and it is based on Go docker image.
In our Docker Hub Repository we have the following images:
- `mattermost/mattermost-build-server:dec-7-2018` which is based on Go 1.11 you can use for MM versions <= `5.8.0`
- `mattermost/mattermost-build-server:feb-28-2019` which is based on Go 1.12 you can use for MM versions >= `5.9.0` <= `5.15.0`
- `mattermost/mattermost-build-server:sep-17-2019` which is based on Go 1.12.9 you can use for MM versions >= `5.16.0`
- `mattermost/mattermost-build-server:20200322_golang-1.14.1` which is based on Go 1.14.1 you can use for MM versions >= `5.24.x`
- `mattermost/mattermost-build-server:20201023_golang-1.14.6` which is based on Go 1.14.6 you can use for MM versions >= `5.25.x`
- `mattermost/mattermost-build-server:20201119_golang-1.15.5` which is based on Go 1.15.5 you can use for MM versions >= `5.26.x` to `5.37.x`
- `mattermost/mattermost-build-server:20210810_golang-1.16.7` which is based on Go 1.16.X you can use for MM versions >= `5.38.x`

57
server/build/buildenv-tag.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Prints the tag identifying the mattermost-build-server image, e.g.
# "go1.26.7-node24.11.1". The image bakes in both toolchains, so the tag names
# both. CI resolves this once and propagates it as BUILD_SERVER_TAG.
#
# The tag comes from the Dockerfiles, since those are what actually determine
# the image, and they are checked against .go-version and .nvmrc so the pins
# cannot drift apart unnoticed.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
DOCKERFILES=(server/build/Dockerfile.buildenv server/build/Dockerfile.buildenv-fips)
fail() {
echo "$*" >&2
exit 1
}
# A pin may be more specific than its source of truth: the FIPS base image
# carries a fourth component, 1.26.7.1 for Go 1.26.7.
satisfies() {
[[ "$1" == "$2" || "$1" == "$2."* ]]
}
go_version=$(cat server/.go-version)
node_spec=$(cat .nvmrc)
node_version=""
for dockerfile in "${DOCKERFILES[@]}"; do
from=$(awk '$1 == "FROM" { print $2; exit }' "${dockerfile}")
[[ -n "${from}" ]] || fail "${dockerfile}: no FROM"
base_version="${from#*:}"
base_version="${base_version%%@*}"
base_version="${base_version%-*}"
satisfies "${base_version}" "${go_version}" ||
fail "${dockerfile}: base image is Go ${base_version}, but server/.go-version says ${go_version}"
version=$(awk -F= '$1 == "ARG NODE_VERSION" { print $2; exit }' "${dockerfile}")
[[ -n "${version}" ]] || fail "${dockerfile}: no ARG NODE_VERSION"
satisfies "${version}" "${node_spec}" ||
fail "${dockerfile}: ARG NODE_VERSION is ${version}, but .nvmrc says ${node_spec}"
# A single tag covers both images, so they have to agree.
if [[ -n "${node_version}" && "${version}" != "${node_version}" ]]; then
fail "${DOCKERFILES[0]} has Node ${node_version} but ${dockerfile} has ${version}"
fi
node_version="${version}"
done
tag="go${go_version}-node${node_version}"
# CI interpolates this tag into shell commands and workflow files, so refuse
# anything that isn't a well-formed Docker tag.
[[ "${tag}" =~ ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ ]] || fail "invalid tag: ${tag}"
echo "${tag}"

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package main
import (
"fmt"
"os"
"strings"
"github.com/goccy/go-yaml"
)
type DockerCompose struct {
Services map[string]*Container `yaml:"services"`
}
type Container struct {
Command string `yaml:"command,omitempty"`
Image string `yaml:"image,omitempty"`
Network []string `yaml:"networks,omitempty"`
DependsOn []string `yaml:"depends_on,omitempty"`
}
func main() {
validServices := map[string]int{
"postgres": 5432,
"minio": 9000,
"azurite": 10000,
"inbucket": 9001,
"openldap": 389,
"elasticsearch": 9200,
"opensearch": 9201,
"redis": 6379,
"dejavu": 1358,
"keycloak": 8080,
"prometheus": 9090,
"grafana": 3000,
"loki": 3100,
"otel-collector": 13133,
}
command := []string{}
for _, arg := range os.Args[1:] {
port, ok := validServices[arg]
if !ok {
panic(fmt.Sprintf("Unknown service %s", arg))
}
command = append(command, fmt.Sprintf("%s:%d", arg, port))
}
var dockerCompose DockerCompose
dockerCompose.Services = map[string]*Container{}
dockerCompose.Services["start_dependencies"] = &Container{
Image: "mattermost/mattermost-wait-for-dep:latest",
Network: []string{"mm-test"},
DependsOn: os.Args[1:],
Command: strings.Join(command, " "),
}
resultData, err := yaml.Marshal(dockerCompose)
if err != nil {
panic(fmt.Sprintf("Unable to serialize the docker-compose file: %s.", err.Error()))
}
fmt.Println(string(resultData))
}

View File

@@ -0,0 +1,167 @@
x-logging: &default-logging
driver: "json-file"
options:
tag: "{{.Name}}"
services:
postgres:
image: "postgres:15"
logging: *default-logging
restart: always
networks:
- mm-test
environment:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mostest_password}
POSTGRES_DB: mattermost_test
POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=scram-sha-256"
command: postgres -c 'config_file=/etc/postgresql/postgresql.conf'
volumes:
- "./docker/postgres.conf:/etc/postgresql/postgresql.conf:Z"
- "./docker/postgres_node_database.sql:/docker-entrypoint-initdb.d/postgres_node_database.sql:Z"
healthcheck:
test: [ "CMD", "pg_isready", "-h", "localhost" ]
interval: 5s
timeout: 10s
retries: 3
minio:
image: "cgr.dev/chainguard/minio:latest"
logging: *default-logging
command: "server /data --console-address :9002"
networks:
- mm-test
environment:
MINIO_ROOT_USER: minioaccesskey
MINIO_ROOT_PASSWORD: miniosecretkey
MINIO_KMS_SECRET_KEY: my-minio-key:OSMM+vkKUTCvQs9YL/CVMIMt43HFhkUpqJxTmGl6rYw=
azurite:
image: "mcr.microsoft.com/azure-storage/azurite:3.34.0"
logging: *default-logging
command: "azurite-blob --blobHost 0.0.0.0 --blobPort 10000 --skipApiVersionCheck"
networks:
- mm-test
inbucket:
image: "inbucket/inbucket:3.1.1"
logging: *default-logging
restart: always
environment:
INBUCKET_WEB_ADDR: "0.0.0.0:9001"
INBUCKET_POP3_ADDR: "0.0.0.0:10110"
INBUCKET_SMTP_ADDR: "0.0.0.0:10025"
networks:
- mm-test
openldap:
image: "osixia/openldap:1.4.0"
logging: *default-logging
restart: always
networks:
- mm-test
environment:
LDAP_TLS_VERIFY_CLIENT: "never"
LDAP_ORGANISATION: "Mattermost Test"
LDAP_DOMAIN: "mm.test.com"
LDAP_ADMIN_PASSWORD: "mostest_password"
elasticsearch:
build:
context: .
dockerfile: ./Dockerfile.elasticsearch
args:
ELASTICSEARCH_VERSION: ${ELASTICSEARCH_VERSION:-9.0.0}
networks:
- mm-test
environment:
http.host: "0.0.0.0"
http.port: 9200
http.cors.enabled: "true"
http.cors.allow-origin: "http://localhost:1358,http://127.0.0.1:1358"
http.cors.allow-headers: "X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization"
http.cors.allow-credentials: "true"
transport.host: "127.0.0.1"
xpack.security.enabled: "false"
action.destructive_requires_name: "false"
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
opensearch:
build:
context: .
dockerfile: ./Dockerfile.opensearch
args:
OPENSEARCH_VERSION: ${OPENSEARCH_VERSION:-3.0.0}
networks:
- mm-test
environment:
http.host: "0.0.0.0"
http.port: 9201
http.cors.enabled: "true"
http.cors.allow-origin: "http://localhost:1358,http://127.0.0.1:1358"
http.cors.allow-headers: "X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization"
http.cors.allow-credentials: "true"
transport.host: "127.0.0.1"
discovery.type: single-node
plugins.security.disabled: "true"
DISABLE_INSTALL_DEMO_CONFIG: "true"
OPENSEARCH_INITIAL_ADMIN_PASSWORD: "Test@dmin_123"
OPENSEARCH_JAVA_OPTS: "-Xms512m -Xmx512m"
redis:
image: "redis:7.4.0"
logging: *default-logging
networks:
- mm-test
dejavu:
image: "appbaseio/dejavu:3.4.2"
logging: *default-logging
networks:
- mm-test
keycloak:
image: "quay.io/keycloak/keycloak:23.0.7"
logging: *default-logging
restart: always
entrypoint: /opt/keycloak/bin/kc.sh start --import-realm
networks:
- mm-test
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_HOSTNAME_STRICT: 'false'
KC_HOSTNAME_STRICT_HTTPS: 'false'
KC_HTTP_ENABLED: 'true'
volumes:
- "./docker/keycloak/realm-export.json:/opt/keycloak/data/import/realm-export.json:Z"
prometheus:
image: "prom/prometheus:v2.46.0"
logging: *default-logging
user: root
volumes:
- "./docker/prometheus.yml:/etc/prometheus/prometheus.yml:Z"
- "/var/run/docker.sock:/var/run/docker.sock"
networks:
- mm-test
extra_hosts:
- "host.docker.internal:host-gateway"
grafana:
image: "grafana/grafana:10.4.2"
logging: *default-logging
volumes:
- "./docker/grafana/grafana.ini:/etc/grafana/grafana.ini:Z"
- "./docker/grafana/provisioning:/etc/grafana/provisioning:Z"
- "./docker/grafana/dashboards:/var/lib/grafana/dashboards:Z"
networks:
- mm-test
loki:
image: "grafana/loki:3.0.0"
logging: *default-logging
volumes:
- "./docker/loki/loki-config.yaml:/etc/loki/local-config.yaml:Z"
networks:
- mm-test
otel-collector:
image: "otel/opentelemetry-collector-contrib:0.145.0"
logging: *default-logging
user: "0:0"
volumes:
- "./docker/otel-collector/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:Z"
- "/var/lib/docker/containers:/var/lib/docker/containers:ro"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "../logs:/logs:ro,Z"
command: ["--config=/etc/otelcol-contrib/config.yaml"]
networks:
- mm-test

View File

@@ -0,0 +1,77 @@
services:
postgres:
extends:
file: docker-compose.common.yml
service: postgres
tmpfs: /var/lib/postgresql/data
minio:
extends:
file: docker-compose.common.yml
service: minio
azurite:
extends:
file: docker-compose.common.yml
service: azurite
inbucket:
extends:
file: docker-compose.common.yml
service: inbucket
openldap:
extends:
file: docker-compose.common.yml
service: openldap
elasticsearch:
extends:
file: docker-compose.common.yml
service: elasticsearch
opensearch:
extends:
file: docker-compose.common.yml
service: opensearch
redis:
extends:
file: docker-compose.common.yml
service: redis
dejavu:
extends:
file: docker-compose.common.yml
service: dejavu
keycloak:
extends:
file: docker-compose.common.yml
service: keycloak
prometheus:
extends:
file: docker-compose.common.yml
service: prometheus
grafana:
extends:
file: docker-compose.common.yml
service: grafana
loki:
extends:
file: docker-compose.common.yml
service: loki
otel-collector:
extends:
file: docker-compose.common.yml
service: otel-collector
start_dependencies:
image: mattermost/mattermost-wait-for-dep:latest
networks:
- mm-test
depends_on:
- postgres
- minio
- azurite
- inbucket
- openldap
- elasticsearch
- opensearch
- redis
command: postgres:5432 minio:9000 azurite:10000 inbucket:9001 openldap:389 elasticsearch:9200 opensearch:9201 redis:6379
networks:
mm-test:
driver: bridge

View File

@@ -0,0 +1,38 @@
# Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
# See License.txt for license information.
FROM postgres:14
RUN apt-get update && apt-get install -y ca-certificates
ARG MATTERMOST_VERSION
#
# Configure PostgreSQL
#
ENV POSTGRES_USER=mmuser
ENV POSTGRES_PASSWORD=mostest_password
ENV POSTGRES_DB=mattermost_test
#
# Configure Mattermost
#
WORKDIR /mm
# Copy over files
ADD https://releases.mattermost.com/${MATTERMOST_VERSION}/mattermost-team-${MATTERMOST_VERSION}-linux-amd64.tar.gz .
RUN tar -zxvf mattermost-team-${MATTERMOST_VERSION}-linux-amd64.tar.gz
ADD config_docker.json ./mattermost/config/config_docker.json
ADD docker-entry.sh .
RUN chmod +x ./docker-entry.sh
ENTRYPOINT ./docker-entry.sh
# Mattermost environment variables
ENV PATH="/mm/mattermost/bin:${PATH}"
# Create default storage directory
RUN mkdir ./mattermost-data
VOLUME /mm/mattermost-data
# Ports
EXPOSE 8065

View File

@@ -0,0 +1,19 @@
# Mattermost Docker Preview Image
This is a Docker image to install Mattermost in *Preview Mode* for exploring product functionality on a single machine using Docker.
Note: This configuration should not be used in production, as it’s using a known password string and contains other non-production configuration settings, and it does not support upgrade. If you’re looking for a production installation with Docker, please see the [Mattermost Production Docker Deployment Guide](https://docs.mattermost.com/install/install-docker.html#deploy-mattermost-on-docker-for-production-use).
To contribute, please see [Contribution Guidelines](https://developers.mattermost.com/contribute/more-info/getting-started/).
To file issues, [search for existing bugs and file a GitHub issue if your bug is new](https://developers.mattermost.com/contribute/why-contribute/#youve-found-a-bug).
## Usage
Please see [documentation for usage](http://docs.mattermost.com/install/docker-local-machine.html).
If you have Docker already set up, you can run this image in one line:
```
docker run --name mattermost-preview -d --publish 8065:8065 --add-host dockerhost:127.0.0.1 mattermost/mattermost-preview
```

View File

@@ -0,0 +1,28 @@
{
"ServiceSettings": {
"EnableOAuthServiceProvider": true,
"EnableDeveloper": false,
"EnableGifPicker": true
},
"SqlSettings": {
"DriverName": "postgres",
"DataSource": "postgres://mmuser:mostest_password@localhost/mattermost_test?sslmode=disable\u0026connect_timeout=10\u0026binary_parameters=yes"
},
"FileSettings": {
"DriverName": "local",
"Directory": "/mm/mattermost-data",
"PublicLinkSalt": ""
},
"EmailSettings": {
"SMTPServer": "",
"SMTPPort": "",
"PushNotificationContents": "generic"
},
"ElasticsearchSettings": {
"ConnectionUrl": ""
},
"PluginSettings": {
"EnableUploads": true,
"PluginStates": {}
}
}

View File

@@ -0,0 +1,18 @@
#!/bin/bash
# Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
# See License.txt for license information.
echo "Starting PostgreSQL"
docker-entrypoint.sh -c 'shared_buffers=256MB' -c 'max_connections=300' &
until pg_isready -hlocalhost -p 5432 -U "$POSTGRES_USER" &> /dev/null; do
echo "postgres still not ready, sleeping"
sleep 5
done
echo "Updating CA certificates"
update-ca-certificates --fresh >/dev/null
echo "Starting platform"
cd mattermost
exec ./bin/mattermost --config=config/config_docker.json

View File

@@ -0,0 +1,15 @@
# Developer Dashboards
This folder contains a modified form of the following Grafana dashboards:
* [Mattermost Performance Monitoring](https://grafana.com/grafana/dashboards/2542)
* [Mattermost Performance Monitoring (Bonus Metrics)](https://grafana.com/grafana/dashboards/2545)
* [Mattermost Performance KPI Metrics](https://grafana.com/grafana/dashboards/2539)
The dashboards are modified from the version available on grafana.com since [Grafana doesn't currently support variables](https://github.com/grafana/grafana/issues/10786) (i.e. `${DS_MATTERMOST}`) and has no way of binding the datasource with the dashboards at the time of provisioning. Instead of falling back to the REST API to effect these changes, the following in-place changes were made to the exported dashboards available above:
* Remove the top-level `__inputs` key
* Remove the top-level `__requires` key
* Replace all instances of `${DS_MATTERMOST}` with `Prometheus`, matching the name of the provisioned datasource.
Upon using the dashboards within Grafana however, it immediately adds various missing fields, presumably due to some internal migration. This results in a spurious prompt to "save" the dashboard. To avoid confusion, these changes were subsequently exported and written back into the provisioned dashboards above.
This entire process above will need to be repeated in the event newer versions of these dashboards are published.

View File

@@ -0,0 +1,428 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 5,
"links": [],
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"gridPos": {
"h": 3,
"w": 24,
"x": 0,
"y": 0
},
"id": 1,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"refId": "A"
}
],
"type": "welcome"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 3
},
"id": 3,
"options": {
"includeVars": false,
"keepTime": false,
"maxItems": 30,
"query": "Mattermost",
"showHeadings": true,
"showRecentlyViewed": false,
"showSearch": true,
"showStarred": false,
"tags": []
},
"pluginVersion": "10.4.2",
"tags": [],
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"refId": "A"
}
],
"title": "Dashboards",
"type": "dashlist"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"0": {
"color": "red",
"index": 0,
"text": "Offline"
},
"1": {
"color": "green",
"index": 1,
"text": "Online"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 12,
"w": 12,
"x": 12,
"y": 3
},
"id": 7,
"options": {
"colorMode": "value",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "/^(?!Time)/",
"values": false
},
"showPercentChange": false,
"textMode": "value_and_name",
"wideLayout": true
},
"pluginVersion": "10.4.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-postgres\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-postgres\"})) < 15) or vector(0)",
"legendFormat": "Postgres",
"range": true,
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-inbucket\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-inbucket\"})) < 15) or vector(0)",
"legendFormat": "Inbucket",
"range": true,
"refId": "C"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-minio\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-minio\"})) < 15) or vector(0)",
"legendFormat": "MinIO",
"range": true,
"refId": "D"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-openldap\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-openldap\"})) < 15) or vector(0)",
"legendFormat": "OpenLDAP",
"range": true,
"refId": "E"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-dejavu\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-dejavu\"})) < 15) or vector(0)",
"legendFormat": "DejaVu",
"range": true,
"refId": "F"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-keycloak\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-keycloak\"})) < 15) or vector(0)",
"legendFormat": "Keycloak",
"range": true,
"refId": "G"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-elasticsearch\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-elasticsearch\"})) < 15) or vector(0)",
"legendFormat": "Elasticsearch",
"range": true,
"refId": "H"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-prometheus\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-prometheus\"})) < 15) or vector(0)",
"legendFormat": "Prometheus",
"range": true,
"refId": "I"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-grafana\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-grafana\"})) < 15) or vector(0)",
"legendFormat": "Grafana",
"range": true,
"refId": "J"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-loki\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-loki\"})) < 15) or vector(0)",
"legendFormat": "Loki",
"range": true,
"refId": "K"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-otel-collector\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-otel-collector\"})) < 15) or vector(0)",
"legendFormat": "OTel Collector",
"range": true,
"refId": "L"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"editorMode": "code",
"expr": "max(container_uptime_seconds{container_name=\"mattermost-redis\"}) >bool 0 and on() (time() - max(timestamp(container_uptime_seconds{container_name=\"mattermost-redis\"})) < 15) or vector(0)",
"legendFormat": "Redis",
"range": true,
"refId": "M"
}
],
"title": "Docker containers",
"type": "stat"
},
{
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"description": "Links to common queries.",
"gridPos": {
"h": 5,
"w": 12,
"x": 0,
"y": 10
},
"id": 6,
"options": {
"code": {
"language": "plaintext",
"showLineNumbers": false,
"showMiniMap": false
},
"content": "* [Mattermost Error Logs](/explore?schemaVersion=1&panes=%7B%22z8g%22:%7B%22datasource%22:%22P8E80F9AEF21F6940%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bapp%3D%5C%22mattermost%5C%22%7D%20%7C%20level%3D%5C%22error%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22P8E80F9AEF21F6940%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&orgId=1)\n* [Plugin Logs](/explore?schemaVersion=1&panes=%7B%22z8g%22:%7B%22datasource%22:%22P8E80F9AEF21F6940%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bapp%3D%5C%22mattermost%5C%22%7D%20%7C%20json%20%7C%20plugin_id%20%21%3D%20%5C%22%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22P8E80F9AEF21F6940%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&orgId=1)",
"mode": "markdown"
},
"pluginVersion": "10.4.2",
"title": "Links",
"type": "text"
},
{
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"description": "Logs from the localhost Mattermost instance.",
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 15
},
"id": 4,
"options": {
"dedupStrategy": "none",
"enableLogDetails": true,
"prettifyLogMessage": false,
"showCommonLabels": false,
"showLabels": false,
"showTime": false,
"sortOrder": "Descending",
"wrapLogMessage": false
},
"targets": [
{
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"editorMode": "code",
"expr": "{app=\"mattermost\"}",
"queryType": "range",
"refId": "A"
}
],
"title": "Mattermost Logs",
"type": "logs"
},
{
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"description": "Logs from the Docker services running to support Mattermost.",
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 25
},
"id": 5,
"options": {
"dedupStrategy": "none",
"enableLogDetails": true,
"prettifyLogMessage": false,
"showCommonLabels": false,
"showLabels": false,
"showTime": false,
"sortOrder": "Descending",
"wrapLogMessage": false
},
"targets": [
{
"datasource": {
"type": "loki",
"uid": "P8E80F9AEF21F6940"
},
"editorMode": "code",
"expr": "{job=\"docker\"}",
"queryType": "range",
"refId": "A"
}
],
"title": "Docker Logs",
"type": "logs"
}
],
"schemaVersion": 39,
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"hidden": true,
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
],
"type": "timepicker"
},
"timezone": "browser",
"title": "Home",
"uid": "4yRNKfaGz",
"version": 1,
"weekStart": ""
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,456 @@
{
"__elements": [],
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "8.3.4"
},
{
"type": "panel",
"id": "graph",
"name": "Graph (old)",
"version": ""
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"iteration": 1646759397232,
"links": [],
"liveNow": false,
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"description": "",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 2,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.3.4",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "histogram_quantile (\n 0.99,\n sum by (le,instance)(\n rate(mattermost_db_store_time_bucket{instance=~\"$server\",method=\"ThreadStore.GetThreadsForUser\"}[5m])\n )\n)",
"interval": "",
"legendFormat": "p99-{{instance}}",
"refId": "A"
},
{
"expr": "histogram_quantile (\n 0.50,\n sum by (le,instance)(\n rate(mattermost_db_store_time_bucket{instance=~\"$server\",method=\"ThreadStore.GetThreadsForUser\"}[5m])\n )\n)",
"interval": "",
"legendFormat": "p50-{{instance}}",
"refId": "B"
}
],
"thresholds": [],
"timeRegions": [],
"title": "GetThreadsForUser duration",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:98",
"format": "s",
"logBase": 1,
"show": true
},
{
"$$hashKey": "object:99",
"format": "short",
"logBase": 1,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 9,
"w": 12,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.3.4",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(mattermost_db_store_time_count{instance=~\"$server\",method=\"ThreadStore.GetThreadsForUser\"}[1m])) by (instance)",
"interval": "",
"legendFormat": "count-{{instance}}",
"refId": "A"
},
{
"expr": "sum(rate(mattermost_db_store_time_count{instance=~\"$server\",method=\"ThreadStore.GetThreadsForUser\"}[1m]))",
"interval": "",
"legendFormat": "Total",
"refId": "B"
}
],
"thresholds": [],
"timeRegions": [],
"title": "GetThreadsForUser Requests Per Second",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:396",
"format": "short",
"logBase": 1,
"show": true
},
{
"$$hashKey": "object:397",
"format": "short",
"logBase": 1,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"hiddenSeries": false,
"id": 6,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.3.4",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"exemplar": true,
"expr": "histogram_quantile (\n 0.99,\n sum by (le,instance)(\n rate(mattermost_db_store_time_bucket{instance=~\"$server\",method=\"ThreadStore.MarkAllAsReadByChannels\"}[5m])\n )\n)",
"interval": "",
"legendFormat": "p99-{{instance}}",
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"exemplar": true,
"expr": "histogram_quantile (\n 0.50,\n sum by (le,instance)(\n rate(mattermost_db_store_time_bucket{instance=~\"$server\",method=\"ThreadStore.MarkAllAsReadByChannels\"}[5m])\n )\n)",
"interval": "",
"legendFormat": "p50-{{instance}}",
"refId": "B"
}
],
"thresholds": [],
"timeRegions": [],
"title": "MarkAllAsReadByChannels duration",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:504",
"format": "s",
"logBase": 1,
"show": true
},
{
"$$hashKey": "object:505",
"format": "short",
"logBase": 1,
"show": true
}
],
"yaxis": {
"align": false
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"hiddenSeries": false,
"id": 8,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.3.4",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"exemplar": true,
"expr": "sum(rate(mattermost_db_store_time_count{instance=~\"$server\",method=\"ThreadStore.MarkAllAsReadByChannels\"}[1m])) by (instance)",
"interval": "",
"legendFormat": "count-{{instance}}",
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"exemplar": true,
"expr": "sum(rate(mattermost_db_store_time_count{instance=~\"$server\",method=\"ThreadStore.MarkAllAsReadByChannels\"}[1m]))",
"interval": "",
"legendFormat": "Total",
"refId": "B"
}
],
"thresholds": [],
"timeRegions": [],
"title": "MarkAllAsReadByChannels Requests Per Second",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"mode": "time",
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:714",
"format": "short",
"logBase": 1,
"show": true
},
{
"$$hashKey": "object:715",
"format": "short",
"logBase": 1,
"show": true
}
],
"yaxis": {
"align": false
}
}
],
"refresh": "10s",
"schemaVersion": 34,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"definition": "label_values(instance)",
"hide": 0,
"includeAll": true,
"label": "server",
"multi": true,
"name": "server",
"options": [],
"query": {
"query": "label_values(instance)",
"refId": "Prometheus-server-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-3h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Collapsed Reply Threads Performance",
"uid": "cZY9yFJ7z",
"version": 5,
"weekStart": ""
}

View File

@@ -0,0 +1,412 @@
{
"__elements": {},
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "10.4.2"
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"description": "The average amount of a machine's CPU used by the given Desktop App process over the measuring interval (usually 1 minute). ",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"editorMode": "code",
"expr": "histogram_quantile($percentile / 100, sum by(le) (increase(mattermost_desktopapp_cpu_usage_bucket{processName=~\"$processName\",version=~\"$version\",platform=~\"$platform\"}[$decay])))",
"instant": false,
"legendFormat": "[[percentile]]th Percentile",
"range": true,
"refId": "A"
}
],
"title": "CPU Usage (%)",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"description": "The number of megabytes used by a Desktop App process at the time of measurement.",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic-by-name"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 24,
"x": 0,
"y": 10
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"editorMode": "code",
"expr": "histogram_quantile($percentile / 100, sum by(le) (increase(mattermost_desktopapp_memory_usage_bucket{processName=~\"$processName\",version=~\"$version\",platform=~\"$platform\"}[$decay])))",
"instant": false,
"legendFormat": "[[percentile]]th Percentile",
"range": true,
"refId": "A"
}
],
"title": "Memory Usage (MBs)",
"type": "timeseries"
}
],
"refresh": "1m",
"schemaVersion": 39,
"tags": [],
"templating": {
"list": [
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"definition": "label_values(mattermost_desktopapp_cpu_usage_bucket,processName)",
"hide": 0,
"includeAll": true,
"label": "Process",
"multi": true,
"name": "processName",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(mattermost_desktopapp_cpu_usage_bucket,processName)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"definition": "label_values(mattermost_desktopapp_cpu_usage_bucket,version)",
"hide": 0,
"includeAll": true,
"label": "App Version",
"multi": true,
"name": "version",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(mattermost_desktopapp_cpu_usage_bucket,version)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "Prometheus"
},
"definition": "label_values(mattermost_desktopapp_cpu_usage_bucket,platform)",
"hide": 0,
"includeAll": true,
"multi": true,
"name": "platform",
"options": [],
"query": {
"qryType": 1,
"query": "label_values(mattermost_desktopapp_cpu_usage_bucket,platform)",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {
"selected": true,
"text": "50",
"value": "50"
},
"hide": 0,
"includeAll": false,
"label": "Percentile",
"multi": false,
"name": "percentile",
"options": [
{
"selected": true,
"text": "50",
"value": "50"
},
{
"selected": false,
"text": "75",
"value": "75"
},
{
"selected": false,
"text": "90",
"value": "90"
},
{
"selected": false,
"text": "99",
"value": "99"
}
],
"query": "50,75,90,99",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
},
{
"current": {
"selected": false,
"text": "30m",
"value": "30m"
},
"hide": 0,
"includeAll": false,
"label": "Decay Time",
"multi": false,
"name": "decay",
"options": [
{
"selected": true,
"text": "30m",
"value": "30m"
},
{
"selected": false,
"text": "1h",
"value": "1h"
},
{
"selected": false,
"text": "3h",
"value": "3h"
},
{
"selected": false,
"text": "6h",
"value": "6h"
},
{
"selected": false,
"text": "12h",
"value": "12h"
},
{
"selected": false,
"text": "1d",
"value": "1d"
}
],
"query": "30m,1h,3h,6h,12h,1d",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
}
]
},
"time": {
"from": "now-24h",
"to": "now"
},
"timepicker": {},
"timezone": "browser",
"title": "Desktop App Metrics",
"uid": "fe12lkd7062v4a",
"version": 4,
"weekStart": ""
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
[auth]
disable_login_form = false
[auth.anonymous]
enabled = true
org_role = Editor
[dashboards]
default_home_dashboard_path = /var/lib/grafana/dashboards/home.json

View File

@@ -0,0 +1,14 @@
apiVersion: 1
providers:
- name: 'mattermost'
orgId: 1
folder: 'mattermost'
type: file
disableDeletion: true
updateIntervalSeconds: 300
allowUiUpdates: true
options:
# <string, required> path to dashboard files on disk. Required when using the 'file' type
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true

View File

@@ -0,0 +1,11 @@
apiVersion: 1
datasources:
- name: Loki
type: 'loki'
access: 'proxy'
orgId: 1
url: 'http://loki:3100'
isDefault: false
version: 1
editable: false

View File

@@ -0,0 +1,11 @@
apiVersion: 1
datasources:
- name: Prometheus
type: 'prometheus'
access: 'proxy'
orgId: 1
url: 'http://prometheus:9090'
isDefault: true
version: 1
editable: false

View File

@@ -0,0 +1,39 @@
# Keycloak development environment
## Setting up
### OpenID
Overwrite your `OpenIdSettings` section in your config.json file by running `make config-openid` and restarting your server.
- [Official OpenID with Keycloak documentation](https://docs.mattermost.com/onboard/sso-openidconnect.html)
### SAML
Overwrite your `SamlSettings` section in your config.json file by running `make config-saml` and restarting your server.
- [Official SAML with Keycloak documentation](https://docs.mattermost.com/onboard/sso-saml-keycloak.html)
### LDAP
Overwrite your `LdapSettings` section in your config.json file by running `make config-ldap` and restarting your server.
- [Official LDAP with Keycloak documentation](https://docs.mattermost.com/onboard/ad-ldap.html)
## Credentials to log in
- **Admin account**, used to log in to the Keycloak Admin UI:
- `admin`/`admin`
- **User accounts**, used to log in to Mattermost:
- `homer`/`password`
- `marge`/`password`
- `lisa`/`password`
## Updating the `realm-export.json`
The `realm-export.json` file is automatically imported by the keycloak development container. If you make any modifications to this file or to the base configuration, export it by running a terminal in the container and running:
```bash
/opt/keycloak/bin/kc.sh export --realm mattermost --users realm_file --file /opt/keycloak/data/import/realm-export.json
```

View File

@@ -0,0 +1,5 @@
#!/bin/bash
set -eu -o pipefail
/opt/keycloak/bin/kcadm.sh config credentials -x --server http://localhost:8080 --realm master --user "$KEYCLOAK_ADMIN" --password "$KEYCLOAK_ADMIN_PASSWORD"
/opt/keycloak/bin/kcadm.sh get realms/mattermost >/dev/null

View File

@@ -0,0 +1,3 @@
-----BEGIN CERTIFICATE-----
MIICozCCAYsCBgGNzWfMwjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDAptYXR0ZXJtb3N0MB4XDTI0MDIyMTIwNDA0OFoXDTM0MDIyMTIwNDIyOFowFTETMBEGA1UEAwwKbWF0dGVybW9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOnsgNexkO5tbKkFXN+SdMUuLHbqdjZ9/JSnKrYPHLarf8801YDDzV8wI9jjdCCgq+xtKFKWlwU2rGpjPbefDLV1m7CSu0Iq+hNxDiBdX3wkEIK98piDpx+xYGL0aAbXn3nAlqFOWQJLKLM1I65ZmK31YZeVj4Kn01W4WfsvKHoxPjLPwPTug4HB6vaQXqEpzYYYHyuJKvIYNuVwo0WQdaPRXb0poZoYzOnoB6tOFrim6B7/chqtZeXQc7h6/FejBsV59aO5uATI0aAJw1twzjCNIiOeJLB2jlLuIMR3/Yaqr8IRpRXzcRPETpisWNilhV07ZBW0YL9ZwuU4sHWy+iMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAW4I1egm+czdnnZxTtth3cjCmLg/UsalUDKSfFOLAlnbe6TtVhP4DpAl+OaQO4+kdEKemLENPmh4ddaHUjSSbbCQZo8B7IjByEe7x3kQdj2ucQpA4bh0vGZ11pVhk5HfkGqAO+UVNQsyLpTmWXQ8SEbxcw6mlTM4SjuybqaGOva1LBscI158Uq5FOVT6TJaxCt3dQkBH0tK+vhRtIM13pNZ/+SFgecn16AuVdBfjjqXynefrSihQ20BZ3NTyjs/N5J2qvSwQ95JARZrlhfiS++L81u2N/0WWni9cXmHsdTLxRrDZjz2CXBNeFOBRio74klSx8tMK27/2lxMsEC7R+DA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,36 @@
{
"LdapSettings": {
"Enable": true,
"EnableSync": false,
"LdapServer": "localhost",
"LdapPort": 389,
"ConnectionSecurity": "",
"BaseDN": "dc=mm,dc=test,dc=com",
"BindUsername": "cn=admin,dc=mm,dc=test,dc=com",
"BindPassword": "mostest_password",
"UserFilter": "",
"GroupFilter": "",
"GuestFilter": "",
"EnableAdminFilter": false,
"AdminFilter": "",
"GroupDisplayNameAttribute": "cn",
"GroupIdAttribute": "entryUUID",
"FirstNameAttribute": "cn",
"LastNameAttribute": "sn",
"EmailAttribute": "mail",
"UsernameAttribute": "uid",
"NicknameAttribute": "cn",
"IdAttribute": "uid",
"PositionAttribute": "title",
"LoginIdAttribute": "uid",
"PictureAttribute": "",
"SyncIntervalMinutes": 60,
"SkipCertificateVerification": false,
"PublicCertificateFile": "",
"PrivateKeyFile": "",
"QueryTimeout": 60,
"MaxPageSize": 0,
"LoginFieldName": "",
"Trace": false
}
}

View File

@@ -0,0 +1,14 @@
{
"OpenIdSettings": {
"Enable": true,
"Secret": "9Y7dykcoA9luTC77XtXxOu9UbNx3rhj6",
"Id": "mattermost-openid",
"Scope": "profile openid email",
"AuthEndpoint": "",
"TokenEndpoint": "",
"UserAPIEndpoint": "",
"DiscoveryEndpoint": "http://localhost:8484/realms/mattermost/.well-known/openid-configuration",
"ButtonText": "Login using OpenID",
"ButtonColor": "#ffaa4c"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
{
"SamlSettings": {
"Enable": true,
"EnableSyncWithLdap": false,
"EnableSyncWithLdapIncludeAuth": false,
"IgnoreGuestsLdapSync": false,
"Verify": false,
"Encrypt": false,
"SignRequest": false,
"IdpURL": "http://localhost:8484/realms/mattermost/protocol/saml",
"IdpDescriptorURL": "http://localhost:8484/realms/mattermost",
"IdpMetadataURL": "http://localhost:8484/realms/mattermost/protocol/saml/descriptor",
"ServiceProviderIdentifier": "mattermost",
"AssertionConsumerServiceURL": "http://localhost:8065/login/sso/saml",
"SignatureAlgorithm": "RSAwithSHA256",
"CanonicalAlgorithm": "Canonical1.0",
"ScopingIDPProviderId": "",
"ScopingIDPName": "",
"IdpCertificateFile": "saml-idp.crt",
"PublicCertificateFile": "",
"PrivateKeyFile": "",
"IdAttribute": "id",
"GuestAttribute": "",
"EnableAdminAttribute": false,
"AdminAttribute": "",
"FirstNameAttribute": "givenName",
"LastNameAttribute": "surname",
"EmailAttribute": "email",
"UsernameAttribute": "username",
"NicknameAttribute": "",
"LocaleAttribute": "",
"PositionAttribute": "",
"LoginButtonText": "SAML"
}
}

View File

@@ -0,0 +1,45 @@
auth_enabled: false
server:
http_listen_port: 3100
common:
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
replication_factor: 1
path_prefix: /loki
schema_config:
configs:
- from: "2026-01-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: loki_index_
period: 24h
storage_config:
filesystem:
directory: /loki/chunks
distributor:
otlp_config:
default_resource_attributes_as_index_labels:
- service.name
- service.instance.id
- job
- app
- container.name
ingester:
max_chunk_age: 480h
limits_config:
allow_structured_metadata: true
unordered_writes: true
reject_old_samples: false
ingestion_rate_mb: 64
ingestion_burst_size_mb: 64

View File

@@ -0,0 +1,38 @@
upstream app_cluster {
server leader:8065 fail_timeout=10s max_fails=10;
server follower:8065 fail_timeout=10s max_fails=10;
server follower2:8065 fail_timeout=10s max_fails=10;
}
server {
listen 8065;
location ~ /api/v[0-9]+/(users/)?websocket$ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
client_max_body_size 50M;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
proxy_read_timeout 600s;
proxy_pass http://app_cluster;
}
location / {
client_max_body_size 100M;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_pass http://app_cluster;
}
}

View File

@@ -0,0 +1,83 @@
receivers:
filelog/mattermost:
include:
- /logs/*.log
start_at: beginning
operators:
- type: json_parser
timestamp:
parse_from: attributes.timestamp
layout_type: gotime
layout: '2006-01-02 15:04:05.000 -07:00'
severity:
parse_from: attributes.level
filelog/docker:
include:
- /var/lib/docker/containers/*/*-json.log
start_at: beginning
operators:
- type: json_parser
timestamp:
parse_from: attributes.time
layout_type: gotime
layout: '2006-01-02T15:04:05.999999999Z'
- type: move
from: attributes.log
to: body
- type: move
from: attributes.attrs.tag
to: resource["container.name"]
docker_stats:
endpoint: unix:///var/run/docker.sock
collection_interval: 10s
metrics:
container.uptime:
enabled: true
processors:
resource/mattermost:
attributes:
- key: service.name
value: mattermost
action: upsert
- key: job
value: mattermost
action: upsert
- key: app
value: mattermost
action: upsert
resource/docker:
attributes:
- key: job
value: docker
action: upsert
exporters:
otlp_http/loki:
endpoint: http://loki:3100/otlp
prometheus:
endpoint: 0.0.0.0:8889
resource_to_telemetry_conversion:
enabled: true
extensions:
health_check:
endpoint: 0.0.0.0:13133
service:
extensions: [health_check]
pipelines:
logs/mattermost:
receivers: [filelog/mattermost]
processors: [resource/mattermost]
exporters: [otlp_http/loki]
logs/docker:
receivers: [filelog/docker]
processors: [resource/docker]
exporters: [otlp_http/loki]
metrics/docker:
receivers: [docker_stats]
exporters: [prometheus]

View File

@@ -0,0 +1,8 @@
max_connections = 500
listen_addresses = '*'
fsync = off
full_page_writes = off
default_text_search_config = 'pg_catalog.english'
commit_delay=1000
logging_collector=off
password_encryption = 'scram-sha-256'

View File

@@ -0,0 +1,2 @@
CREATE DATABASE mattermost_node_test;
GRANT ALL PRIVILEGES ON DATABASE mattermost_node_test TO mmuser;

View File

@@ -0,0 +1,21 @@
global:
scrape_interval: 5s
evaluation_interval: 60s
scrape_configs:
- job_name: 'mattermost'
static_configs:
- targets: ['host.docker.internal:8067']
- job_name: 'otel-collector'
static_configs:
- targets: ['otel-collector:8889']
- job_name: fmetrics_scrape
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'logstream'

View File

@@ -0,0 +1 @@
IS_CI=true

View File

@@ -0,0 +1,14 @@
TEST_DATABASE_POSTGRESQL_DSN=postgres://mmuser:mostest_password@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10
GOBIN=/mattermost/server/bin
CI_INBUCKET_HOST=inbucket
CI_MINIO_HOST=minio
CI_AZURITE_HOST=azurite
CI_INBUCKET_PORT=9001
CI_MINIO_PORT=9000
CI_AZURITE_PORT=10000
CI_INBUCKET_SMTP_PORT=10025
CI_LDAP_HOST=openldap
IS_CI=true
MM_EMAILSETTINGS_SMTPSERVER=inbucket
MM_ELASTICSEARCHSETTINGS_CONNECTIONURL=http://elasticsearch:9200

7
server/build/entrypoint.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
if [ "${1:0:1}" = '-' ]; then
set -- mattermost "$@"
fi
exec "$@"

72
server/build/local-test-env.sh Executable file
View File

@@ -0,0 +1,72 @@
#!/bin/bash
export COMPOSE_PROJECT_NAME=localdev
local_cmdname=${0##*/}
usage()
{
cat << USAGE >&2
Usage:
$local_cmdname up/down
USAGE
exit 1
}
up()
{
docker compose run --rm start_dependencies
docker compose exec openldap bash -c 'echo -e "dn: ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: organizationalunit" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest_password'
docker compose exec openldap bash -c 'echo -e "dn: uid=test.one,ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: iNetOrgPerson\nsn: User\ncn: Test1\nmail: success+testone@simulator.amazonses.com" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest_password'
docker compose exec openldap bash -c 'ldappasswd -s Password1 -D "cn=admin,dc=mm,dc=test,dc=com" -x "uid=test.one,ou=testusers,dc=mm,dc=test,dc=com" -w mostest_password'
docker compose exec openldap bash -c 'echo -e "dn: uid=test.two,ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: iNetOrgPerson\nsn: User\ncn: Test2\nmail: success+testtwo@simulator.amazonses.com" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest_password'
docker compose exec openldap bash -c 'ldappasswd -s Password1 -D "cn=admin,dc=mm,dc=test,dc=com" -x "uid=test.two,ou=testusers,dc=mm,dc=test,dc=com" -w mostest_password'
docker compose exec openldap bash -c 'echo -e "dn: cn=tgroup,ou=testusers,dc=mm,dc=test,dc=com\nobjectclass: groupOfUniqueNames\nuniqueMember: uid=test.one,ou=testusers,dc=mm,dc=test,dc=com" | ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest_password'
docker run -it -u root \
--privileged \
-v $GOPATH:/go \
-w /go/src/github.com/mattermost/mattermost-server/ \
--net ${COMPOSE_PROJECT_NAME}_mm-test \
--env-file=dotenv/test.env
-e GOPATH="/go" \
-e MM_SQLSETTINGS_DATASOURCE="postgres://mmuser:mostest_password@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10" \
-e MM_SQLSETTINGS_DRIVERNAME=postgres
mattermost/mattermost-build-server:20210810_golang-1.16.7 bash
}
down()
{
docker compose down
}
# process arguments
while [[ $# -gt 0 ]]
do
case "$1" in
up)
echo "Starting Containers"
up
break
;;
down)
echo "Stopping Containers"
down
break
;;
--help)
usage
;;
*)
echo "Unknown argument: $1" >&2
usage
;;
esac
done
if [[ "$1" == "" ]]; then
usage
fi

View File

@@ -0,0 +1,28 @@
# Notice.txt File Configuration
We are automatically generating Notice.txt by using first-level dependencies of the project. The related pipeline uses `config.yaml` stored in this folder.
## Configuration
Sample:
```
title: "Mattermost Playbooks"
copyright: "©2015-present Mattermost, Inc. All Rights Reserved. See LICENSE for license information."
description: "This document includes a list of open source components used in Mattermost Playbooks, including those that have been modified."
search:
- "go.mod"
- "client/go.mod"
dependencies: []
devDependencies: []
```
| Field | Type | Purpose |
| :-- | :-- | :-- |
| title | string | Field content will be used as a title of the application. See first line of `NOTICE.txt` file. |
| copyright | string | Field content will be used as a copyright message. See second line of `NOTICE.txt` file. |
| description | string | Field content will be used as notice file description. See third line of `NOTICE.txt` file. |
| dependencies | array | If any dependency name mentioned, it will be automatically added even if it is not a first-level dependency. |
| devDependencies | array | If any dependency name mentioned, it will be added when it is referenced in devDependency section. |
| search | array | Pipeline will search for package.json/go.mod files mentioned here. Globstar format is supported ie. `x/**/go.mod`. |

View File

@@ -0,0 +1,11 @@
---
title: "Mattermost Server"
copyright: "©2015-present Mattermost,Inc. All Rights Reserved. See LICENSE for license information."
description: "This document includes a list of open source components used in Mattermost Server, including those that have been modified."
search:
- "server/go.mod"
- "webapp/package.json"
- "webapp/channels/package.json"
ignoreDependencies:
- "@mattermost/shared"
includeDevDependencies: false

4
server/build/passwd Normal file
View File

@@ -0,0 +1,4 @@
root:x:0:0:root:/root:/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin
nonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin
mattermost:x:2000:2000:mattermost:/mattermost:/sbin/nologin

View File

@@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF3YTiEBEACgkhnZ5+xylKZhLVj193b6d/rSQuCU/zwWeZJnqyR8wRsPotXO
CMXOUM9bTTaGfItCP9KlPPcyrshNEIgqcqhB6TSKkWSyrV5XS95Opd9Esbjw1VZq
PMezLG3m36cytEmM82+Zpagm20/1PSQS2cQxEfieUDVkM7o4iE5TpifD6rgSaObQ
njbV1z+yljWfK+1OvM4VLAQ4dC5U0NS9SwRcencGyTnw9Vynoc+tRyQn5R+RST8h
rFEjpY11BsVJ+vAdZ7NoNH6P3gOTXI8lpcSn1G0lXJrJGyd45fGR8IT1imDIdmHN
B/nIg9J+PtMmH3BuybtYzxIgZF3SKan1avirpZCKkiW/93UK02Z/aHgoth27fJLf
kKNgO+5Rvf9TOdWujAgOnGHMedEslGzFv74tlnrGYvqo/hWhHuV6jFFEtZvI5LuL
RD5lzZePEgN9XQ80In6LD1TAIOs3LPLvg7+Wxd9foc0qAMLUtmYjKG0/hmXPjrPY
shuXUVCj0VD0RATdhWGKV8cWlOnh6elnUr9/BBZ32SP1ID76oLXjoPgy/jWxAvJf
UqxYkwcGpEJqxywE5BAw4v29mz4nbzxLcpgK30soeIIu7A+tYtgMaJ89TPA53Hwt
h+8+pPsVG2uB5Iz2SFiHQ1GymGpwxsqPRJosC5/6xsoKIqfvLFNCx83FhQARAQAB
tClNYXR0ZXJtb3N0LCBJbmMuIDxzdXBwb3J0QG1hdHRlcm1vc3QuY29tPokCTgQT
AQoAOBYhBMVYgbgPaehjuFrV0dG1S0elzv7EBQJd2E4hAhsDBQsJCAcDBRUKCQgL
BRYCAwEAAh4BAheAAAoJENG1S0elzv7ETDsQAIthyS2tHHmZKVnWrwTuhcls88GI
gTOzGzlUCyMH7mAQzv9PgtUz9LVDN1wiIRzqdVUc0ljKFF5urjLcg1t1ni3Ocy87
ysE+bpOtBJcVK7fLV/XVAGmxtGblkWaCHaYFCXSqrXialXm588Bnsbfd+2HNPX63
8mlfYgCIO5Kowlk2OPCACiB4TM8vOi0q6xV740hWfDor7BQo7jK/LL24EPGY4m30
nMXHsZnyLCDvfJ8y3clb7ac0qCyF2g8npU2EVdE01IpYuOVCIZ8zenXKCHeTKisl
ahUpm+WbhFGrys1cXLad1TaBVjw1aPmBA1PGh9yDCIxI4WBX5l0qqr3rxT7DdrBh
YD7biejekWYlw/MDkK1bp6tryiR2H7kK4Jp8zUcrsBT0cIr7m2UdP/qChK7Z9jBA
gUEMM0gmZYyaK7dqOESifg+67tm1D35qrD8lAb1xXjk76PdzkTleMJfpVgONs870
GLsqbik2ZAWX/dP7g6k3TRMOkDW2TvnzKjK7K6ETMWFObB+k8FgOibdgmLyXfMAq
IAEmCqhGv17qd+99xru76TCRIisnzG0/kSALBKny9w/nuUDx6xS4w7E8szEe5geg
VJ3CxBNSOlA8YJo2BpCG9LH7O6l4gg65jGQZ//8LSJel7EXsFJQizwPTdh5T61xb
ktH5ucon5W99mvpuuQINBF3YTiEBEAC3ottuAdWtXjZEQg1k9c3enb+aYlqcElY1
5izMqha/t+ySZn4ZRjux/6soPDUEEH1kAasrewvAcG4dcFEhRUSv67AJ+Jc0dpEd
RNcZBCYGVqo/PxHwSKdxQduKSd6Qwm19UPpRvw5ETV83mOcpUCiupS3Chx8pjQB0
vxCf9L545dLOFppWKcAjB96Snhl9IuwluzoPjO2zuY5qCHfWtyw4n5XVfvMbkL3v
KRaVHPheT6L4Hrr12D+BycYUE1yztWoX2wqMpRole3qpvkCQ46pPok/XLMIlCKgp
Hc/RbnKKFCYjIhQEQLR9WhnBBnhhXS6lglgyHzTVOIMEAe6jXDfSb0pk29g6NTjW
7YycWKNO6Cwzpnbu/fHOzeP4oBURKAzPBgGBRzTZiBtMoViQy3l6HoCsWhMeyez7
5jvk3ZrRvijNenE6gzuMsN6LnKgLGRMRYerDP466uZmp6qrVQbAgHSWZzK7j2fv8
NsJw+Abf/sN+UrDPZqxLnSvMy2qtr+ZXAEjfVEerN9OSyC5wnEpRoPbV3vSsjImo
JWeVtxPUBubTGns92/9CjV0jHPQofpKnWqFPh0OzNCZWtFdv5J1FrMnZo+sg1vTb
4Vkx3SXg69JriicmbD5Ohd0cfcDfhAB/Ip5W/uNOUNWDHfFdInCywMzILrNJNPYU
aqj2uxdKlwARAQABiQI2BBgBCgAgFiEExViBuA9p6GO4WtXR0bVLR6XO/sQFAl3Y
TiECGwwACgkQ0bVLR6XO/sRHIw//WwLthCOZABhq1H+wvF8MPmkKE/JOBaLCYgCz
vIZ2aOeDilKEfQdhjv4257VuKet+VjC7dnWafVi7S51PIgmrOh3VUT9+RDB3dDTZ
OT3uD4xpNdbkgfIzRo0FgOGYpnE6SBxF9Tr9U9ENjyfqrt1w0odvuVp1WK1jJhDz
HWRqDyNrdMYLS/VsgXv5Pz8XoFpKryyOYqG/x3rU62cZ5McFBu/b9dVyyZuxfmKV
rhe5zXKIaBVnv9G7U9+1Zqbkhbfj5irne4hwuGT9RHRkxfuM0+YW0nopIniKYDFI
F7mX2QHf7HN4jip8N+vht6fsRe1UY9Ktp6jOlNkCJEAhhoLI/bOenop3i07xAMry
gHk/FGNbpM9M7oCn7XDRTr4afw0JUIFQQ9/NUPv5Ktjf3CAuY1NCivzSIqRwEnsc
MO/8PtKxycbLAxfZe3QIp/bD9czU3F00rM4JIc+sBS5l373BJY3gqqpKd6/Oe1uK
Pl1UP/KBMTTBnpcwvRnAXzg7petoNojBnbtmRzsHoNwNYVRu7Gpscb1WU/+IgBe6
VbpFWCb4naPYMMhl/2afOKtmASJnw3MQkMXlTyf59+NoYRtAEh7mQ2AzBqYcsYbs
ue8bSAG/lgJ7XKl4JyfhvC/63CTi/xMklsW5BGQn77vGjKo0bv5Oi1XfqhEujFqY
d+eYY64=
=UePK
-----END PGP PUBLIC KEY BLOCK-----

341
server/build/release.mk Normal file
View File

@@ -0,0 +1,341 @@
.PHONY: dist
dist: | check-style test package
.PHONY: build-linux
build-linux: build-linux-amd64 build-linux-arm64
.PHONY: build-linux-amd64
build-linux-amd64: setup-go-work
@echo Build Linux amd64
ifeq ($(BUILDER_GOOS_GOARCH),"linux_amd64")
env GOOS=linux GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/linux_amd64
env GOOS=linux GOARCH=amd64 $(GO) build -o $(GOBIN)/linux_amd64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
endif
ifeq ($(FIPS_ENABLED),true)
@echo Verifying Build Linux amd64 for FIPS
$(GO) version -m $(GOBIN)/$(MM_BIN_NAME) | grep -q "GOEXPERIMENT=systemcrypto" || (echo "ERROR: FIPS mattermost binary missing GOEXPERIMENT=systemcrypto" && exit 1)
$(GO) version -m $(GOBIN)/$(MM_BIN_NAME) | grep "\-tags" | grep -q "requirefips" || (echo "ERROR: FIPS mattermost binary missing -tags=requirefips" && exit 1)
$(GO) tool nm $(GOBIN)/$(MM_BIN_NAME) | grep -qE "func_go_openssl_OpenSSL_version|_mkcgo_OpenSSL_version" || (echo "ERROR: FIPS mattermost binary missing OpenSSL integration" && exit 1)
$(GO) version -m $(GOBIN)/$(MMCTL_BIN_NAME) | grep -q "GOEXPERIMENT=systemcrypto" || (echo "ERROR: FIPS mmctl binary missing GOEXPERIMENT=systemcrypto" && exit 1)
$(GO) version -m $(GOBIN)/$(MMCTL_BIN_NAME) | grep "\-tags" | grep -q "requirefips" || (echo "ERROR: FIPS mmctl binary missing -tags=requirefips" && exit 1)
$(GO) tool nm $(GOBIN)/$(MMCTL_BIN_NAME) | grep -qE "func_go_openssl_OpenSSL_version|_mkcgo_OpenSSL_version" || (echo "ERROR: FIPS mmctl binary missing OpenSSL integration" && exit 1)
endif
.PHONY: build-linux-arm64
build-linux-arm64: setup-go-work
ifeq ($(FIPS_ENABLED),true)
@echo Skipping Build Linux arm64 for FIPS
else
@echo Build Linux arm64
ifeq ($(BUILDER_GOOS_GOARCH),"linux_arm64")
env GOOS=linux GOARCH=arm64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/linux_arm64
env GOOS=linux GOARCH=arm64 $(GO) build -o $(GOBIN)/linux_arm64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
endif
endif
.PHONY: build-osx
build-osx: setup-go-work
@echo Build OSX amd64
ifeq ($(BUILDER_GOOS_GOARCH),"darwin_amd64")
env GOOS=darwin GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/darwin_amd64
env GOOS=darwin GOARCH=amd64 $(GO) build -o $(GOBIN)/darwin_amd64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
endif
@echo Build OSX arm64
ifeq ($(BUILDER_GOOS_GOARCH),"darwin_arm64")
env GOOS=darwin GOARCH=arm64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/darwin_arm64
env GOOS=darwin GOARCH=arm64 $(GO) build -o $(GOBIN)/darwin_arm64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
endif
.PHONY: build-freebsd
build-freebsd: build-freebsd-amd64 build-freebsd-arm64
.PHONY: build-freebsd-amd64
build-freebsd-amd64: setup-go-work
@echo Build FreeBSD amd64
ifeq ($(BUILDER_GOOS_GOARCH),"freebsd_amd64")
env GOOS=freebsd GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/freebsd_amd64
env GOOS=freebsd GOARCH=amd64 $(GO) build -o $(GOBIN)/freebsd_amd64 $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./...
endif
.PHONY: build-freebsd-arm64
build-freebsd-arm64: setup-go-work
@echo Build FreeBSD arm64
ifeq ($(BUILDER_GOOS_GOARCH),"freebsd_arm64")
env GOOS=freebsd GOARCH=arm64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/freebsd_arm64
env GOOS=freebsd GOARCH=arm64 $(GO) build -o $(GOBIN)/freebsd_arm64 $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./...
endif
.PHONY: build-windows
build-windows: setup-go-work
@echo Build Windows amd64
ifeq ($(BUILDER_GOOS_GOARCH),"windows_amd64")
env GOOS=windows GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
else
mkdir -p $(GOBIN)/windows_amd64
env GOOS=windows GOARCH=amd64 $(GO) build -o $(GOBIN)/windows_amd64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./...
endif
.PHONY: build-cmd-linux
build-cmd-linux: setup-go-work
@echo Build CMD Linux amd64
ifeq ($(BUILDER_GOOS_GOARCH),"linux_amd64")
env GOOS=linux GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/linux_amd64
env GOOS=linux GOARCH=amd64 $(GO) build -o $(GOBIN)/linux_amd64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
endif
ifeq ($(FIPS_ENABLED),true)
@echo Verifying Build Linux amd64 for FIPS
$(GO) version -m $(GOBIN)/mattermost | grep -q "GOEXPERIMENT=systemcrypto" || (echo "ERROR: FIPS mattermost binary missing GOEXPERIMENT=systemcrypto" && exit 1)
$(GO) version -m $(GOBIN)/mattermost | grep "\-tags" | grep -q "requirefips" || (echo "ERROR: FIPS mattermost binary missing -tags=requirefips" && exit 1)
$(GO) tool nm $(GOBIN)/mattermost | grep -qE "func_go_openssl_OpenSSL_version|_mkcgo_OpenSSL_version" || (echo "ERROR: FIPS mattermost binary missing OpenSSL integration" && exit 1)
$(GO) version -m $(GOBIN)/mmctl | grep -q "GOEXPERIMENT=systemcrypto" || (echo "ERROR: FIPS mmctl binary missing GOEXPERIMENT=systemcrypto" && exit 1)
$(GO) version -m $(GOBIN)/mmctl | grep "\-tags" | grep -q "requirefips" || (echo "ERROR: FIPS mmctl binary missing -tags=requirefips" && exit 1)
$(GO) tool nm $(GOBIN)/mmctl | grep -qE "func_go_openssl_OpenSSL_version|_mkcgo_OpenSSL_version" || (echo "ERROR: FIPS mmctl binary missing OpenSSL integration" && exit 1)
endif
ifeq ($(FIPS_ENABLED),true)
@echo Skipping Build Linux arm64 for FIPS
else
@echo Build CMD Linux arm64
ifeq ($(BUILDER_GOOS_GOARCH),"linux_arm64")
env GOOS=linux GOARCH=arm64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/linux_arm64
env GOOS=linux GOARCH=arm64 $(GO) build -o $(GOBIN)/linux_arm64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
endif
endif
.PHONY: build-cmd-osx
build-cmd-osx: setup-go-work
@echo Build CMD OSX amd64
ifeq ($(BUILDER_GOOS_GOARCH),"darwin_amd64")
env GOOS=darwin GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/darwin_amd64
env GOOS=darwin GOARCH=amd64 $(GO) build -o $(GOBIN)/darwin_amd64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
endif
@echo Build CMD OSX arm64
ifeq ($(BUILDER_GOOS_GOARCH),"darwin_arm64")
env GOOS=darwin GOARCH=arm64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/darwin_arm64
env GOOS=darwin GOARCH=arm64 $(GO) build -o $(GOBIN)/darwin_arm64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
endif
.PHONY: build-cmd-freebsd
build-cmd-freebsd: setup-go-work
@echo Build CMD FreeBSD amd64
ifeq ($(BUILDER_GOOS_GOARCH),"freebsd_amd64")
env GOOS=freebsd GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/freebsd_amd64
env GOOS=freebsd GOARCH=amd64 $(GO) build -o $(GOBIN)/freebsd_amd64 $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./cmd/...
endif
@echo Build CMD FreeBSD arm64
ifeq ($(BUILDER_GOOS_GOARCH),"freebsd_arm64")
env GOOS=freebsd GOARCH=arm64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/freebsd_arm64
env GOOS=freebsd GOARCH=arm64 $(GO) build -o $(GOBIN)/freebsd_arm64 $(GOFLAGS) -trimpath -tags production -ldflags '$(LDFLAGS)' ./cmd/...
endif
.PHONY: build-cmd-windows
build-cmd-windows: setup-go-work
@echo Build CMD Windows amd64
ifeq ($(BUILDER_GOOS_GOARCH),"windows_amd64")
env GOOS=windows GOARCH=amd64 $(GO) build -o $(GOBIN) $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
else
mkdir -p $(GOBIN)/windows_amd64
env GOOS=windows GOARCH=amd64 $(GO) build -o $(GOBIN)/windows_amd64 $(GOFLAGS) -trimpath -tags '$(BUILD_TAGS) production' -ldflags '$(LDFLAGS)' ./cmd/...
endif
# Only build linux by default. Other platforms can be built by specifying the platform.
.PHONY: build
build: setup-go-work build-client build-linux
# Only build linux by default. Other platforms can be built by specifying the platform.
.PHONY: build-cmd
build-cmd: setup-go-work build-client build-cmd-linux
.PHONY: build-client
build-client:
@echo Building mattermost web app
cd $(BUILD_WEBAPP_DIR) && $(MAKE) dist
.PHONY: package-prep
package-prep: setup-go-work
@ echo Packaging mattermost
@# Remove any old files
rm -Rf $(DIST_ROOT)
@# Resource directories
mkdir -p $(DIST_PATH)/config
cp -L config/README.md $(DIST_PATH)/config
OUTPUT_CONFIG=$(PWD)/$(DIST_PATH)/config/config.json go run ./scripts/config_generator
cp -RL fonts $(DIST_PATH)
cp -RL templates $(DIST_PATH)
rm -rf $(DIST_PATH)/templates/*.mjml $(DIST_PATH)/templates/partials/
mkdir -p $(DIST_PATH)/i18n
cp -L i18n/*.json $(DIST_PATH)/i18n
@# Disable developer settings
sed -i'' -e 's|"ConsoleLevel": "DEBUG"|"ConsoleLevel": "INFO"|g' $(DIST_PATH)/config/config.json
sed -i'' -e 's|"SiteURL": "http://localhost:8065"|"SiteURL": ""|g' $(DIST_PATH)/config/config.json
@# Reset email sending to original configuration
sed -i'' -e 's|"SendEmailNotifications": true,|"SendEmailNotifications": false,|g' $(DIST_PATH)/config/config.json
sed -i'' -e 's|"FeedbackEmail": "test@example.com",|"FeedbackEmail": "",|g' $(DIST_PATH)/config/config.json
sed -i'' -e 's|"ReplyToAddress": "test@example.com",|"ReplyToAddress": "",|g' $(DIST_PATH)/config/config.json
sed -i'' -e 's|"SMTPServer": "localhost",|"SMTPServer": "",|g' $(DIST_PATH)/config/config.json
sed -i'' -e 's|"SMTPPort": "2500",|"SMTPPort": "",|g' $(DIST_PATH)/config/config.json
chmod 600 $(DIST_PATH)/config/config.json
@# Package web app
mkdir -p $(DIST_PATH)/client
cp -RL $(BUILD_WEBAPP_DIR)/channels/dist/* $(DIST_PATH)/client
@# Help files
ifeq ($(BUILD_ENTERPRISE_READY),true)
cp $(BUILD_ENTERPRISE_DIR)/ENTERPRISE-EDITION-LICENSE.txt $(DIST_PATH)
cp -L $(BUILD_ENTERPRISE_DIR)/cloud/config/cloud_defaults.json $(DIST_PATH)/config
else
cp build/MIT-COMPILED-LICENSE.md $(DIST_PATH)
endif
cp ../NOTICE.txt $(DIST_PATH)
cp ../README.md $(DIST_PATH)
if [ -f bin/manifest.txt ]; then \
cp bin/manifest.txt $(DIST_PATH); \
fi
.PHONY: fetch-prepackaged-plugins
fetch-prepackaged-plugins:
@# Import Mattermost plugin public key, ignoring errors. In FIPS mode, GPG fails to start
@# the gpg-agent, but still imports the key. If it really fails, it will fail validation later.
-gpg --import build/plugin-production-public-key.gpg
@# Download prepackaged plugins
mkdir -p tmpprepackaged
@echo "Downloading prepackaged plugins ... "
@cd tmpprepackaged && for plugin_package in $(PLUGIN_PACKAGES) ; do \
curl -f -O -L https://plugins.releases.mattermost.com/release/$$plugin_package-$(PLUGIN_ARCH).tar.gz; \
curl -f -O -L https://plugins.releases.mattermost.com/release/$$plugin_package-$(PLUGIN_ARCH).tar.gz.sig; \
done
@echo "Done"
.PHONY: package-general
package-general:
@# Create needed directories
mkdir -p $(DIST_PATH_GENERIC)/bin
mkdir -p $(DIST_PATH_GENERIC)/logs
@# Copy binaries
ifeq ($(BUILDER_GOOS_GOARCH),"$(CURRENT_PACKAGE_ARCH)")
cp $(GOBIN)/$(MM_BIN_NAME) $(GOBIN)/$(MMCTL_BIN_NAME) $(DIST_PATH_GENERIC)/bin # from native bin dir, not cross-compiled
else
cp $(GOBIN)/$(CURRENT_PACKAGE_ARCH)/$(MM_BIN_NAME) $(GOBIN)/$(CURRENT_PACKAGE_ARCH)/$(MMCTL_BIN_NAME) $(DIST_PATH_GENERIC)/bin # from cross-compiled bin dir
endif
.PHONY: package-plugins
package-plugins: fetch-prepackaged-plugins
@# Create needed directories
mkdir -p $(DIST_PATH_GENERIC)/prepackaged_plugins
@# Prepackage plugins
@for plugin_package in $(PLUGIN_PACKAGES) ; do \
ARCH=$(PLUGIN_ARCH); \
cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz $(DIST_PATH_GENERIC)/prepackaged_plugins; \
cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz.sig $(DIST_PATH_GENERIC)/prepackaged_plugins; \
gpg --verify $(DIST_PATH_GENERIC)/prepackaged_plugins/$$plugin_package-$$ARCH.tar.gz.sig $(DIST_PATH_GENERIC)/prepackaged_plugins/$$plugin_package-$$ARCH.tar.gz; \
if [ $$? -ne 0 ]; then \
echo "Failed to verify $$plugin_package-$$ARCH.tar.gz|$$plugin_package-$$ARCH.tar.gz.sig"; \
exit 1; \
fi; \
done
.PHONY: package-osx-amd64
package-osx-amd64: package-prep
DIST_PATH_GENERIC=$(DIST_PATH_OSX_AMD64) CURRENT_PACKAGE_ARCH=darwin_amd64 MM_BIN_NAME=mattermost MMCTL_BIN_NAME=mmctl $(MAKE) package-general
@# Package
tar -C $(DIST_PATH_OSX_AMD64)/.. -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-darwin-amd64.tar.gz mattermost ../mattermost
@# Cleanup
rm -rf $(DIST_ROOT)/darwin_amd64
.PHONY: package-osx-arm64
package-osx-arm64: package-prep
DIST_PATH_GENERIC=$(DIST_PATH_OSX_ARM64) CURRENT_PACKAGE_ARCH=darwin_arm64 MM_BIN_NAME=mattermost MMCTL_BIN_NAME=mmctl $(MAKE) package-general
@# Package
tar -C $(DIST_PATH_OSX_ARM64)/.. -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-darwin-arm64.tar.gz mattermost ../mattermost
@# Cleanup
rm -rf $(DIST_ROOT)/darwin_arm64
.PHONY: package-osx
package-osx: package-osx-amd64 package-osx-arm64
.PHONY: package-freebsd-amd64
package-freebsd-amd64: package-prep
DIST_PATH_GENERIC=$(DIST_PATH_FREEBSD_AMD64) CURRENT_PACKAGE_ARCH=freebsd_amd64 MM_BIN_NAME=mattermost MMCTL_BIN_NAME=mmctl $(MAKE) package-general
@# Package
tar -C $(DIST_PATH_FREEBSD_AMD64)/.. -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-freebsd-amd64.tar.gz mattermost ../mattermost
@# Cleanup
rm -rf $(DIST_ROOT)/freebsd_amd64
.PHONY: package-freebsd-arm64
package-freebsd-arm64: package-prep
DIST_PATH_GENERIC=$(DIST_PATH_FREEBSD_ARM64) CURRENT_PACKAGE_ARCH=freebsd_arm64 MM_BIN_NAME=mattermost MMCTL_BIN_NAME=mmctl $(MAKE) package-general
@# Package
tar -C $(DIST_PATH_FREEBSD_ARM64)/.. -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-freebsd-arm64.tar.gz mattermost ../mattermost
@# Cleanup
rm -rf $(DIST_ROOT)/freebsd_arm64
.PHONY: package-freebsd
package-freebsd: package-freebsd-amd64 package-freebsd-arm64
.PHONY: package-linux-amd64
package-linux-amd64: package-prep
DIST_PATH_GENERIC=$(DIST_PATH_LIN_AMD64) PLUGIN_ARCH=linux-amd64 $(MAKE) package-plugins
DIST_PATH_GENERIC=$(DIST_PATH_LIN_AMD64) CURRENT_PACKAGE_ARCH=linux_amd64 MM_BIN_NAME=mattermost MMCTL_BIN_NAME=mmctl $(MAKE) package-general
@# Package
tar -C $(DIST_PATH_LIN_AMD64)/.. -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-linux-amd64.tar.gz mattermost ../mattermost
@# Cleanup
rm -rf $(DIST_ROOT)/linux_amd64
.PHONY: package-linux-arm64
package-linux-arm64: package-prep
ifeq ($(FIPS_ENABLED),true)
@echo Skipping package linux arm64 for FIPS
else
DIST_PATH_GENERIC=$(DIST_PATH_LIN_ARM64) CURRENT_PACKAGE_ARCH=linux_arm64 MM_BIN_NAME=mattermost MMCTL_BIN_NAME=mmctl $(MAKE) package-general
@# Package
tar -C $(DIST_PATH_LIN_ARM64)/.. -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-linux-arm64.tar.gz mattermost ../mattermost
@# Cleanup
rm -rf $(DIST_ROOT)/linux_arm64
endif
.PHONY: package-linux
package-linux: package-linux-amd64 package-linux-arm64
.PHONY: package-windows
package-windows: package-prep
DIST_PATH_GENERIC=$(DIST_PATH_WIN) CURRENT_PACKAGE_ARCH=windows_amd64 MM_BIN_NAME=mattermost.exe MMCTL_BIN_NAME=mmctl.exe $(MAKE) package-general
@# Package
cd $(DIST_PATH_WIN)/.. && zip -9 -r -q -l ../mattermost-$(BUILD_TYPE_NAME)-windows-amd64.zip mattermost ../mattermost && cd ../..
@# Cleanup
rm -rf $(DIST_ROOT)/windows
# Only package linux by default. Other platforms can be packaged by specifying the platform.
.PHONY: package
package: package-linux
rm -rf tmpprepackaged
rm -rf $(DIST_PATH)