From 9d32be52f36372fffd9ad0a8b4e344d4ddefc692 Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Sun, 27 Sep 2020 13:53:43 -0400 Subject: [PATCH] beginning mattermost --- README.md | 4 ++ compose/production/mattermost/Dockerfile | 56 +++++++++++++++ compose/production/mattermost/entrypoint.sh | 74 +++++++++++++++++++ extra/mattermost.yml | 79 +++++++++++++++++++++ scripts/subinstallers/gen_prod_env.sh | 7 ++ 5 files changed, 220 insertions(+) create mode 100644 compose/production/mattermost/Dockerfile create mode 100755 compose/production/mattermost/entrypoint.sh create mode 100644 extra/mattermost.yml diff --git a/README.md b/README.md index 1ad4ed0..7726c50 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ Within Mistborn is a panel to enable and manage these free extra services (off b - [Jellyfin](https://jellyfin.org): The Free Media Software System. - [Tor](https://www.torproject.org): The Onion Router. One tool in the arsenal of online security and privacy. - [Jitsi](https://jitsi.org): Multi-platform open-source video conferencing +- [Mattermost](https://mattermost.com/): A flexible, open source messaging platform that enables secure team collaboration + # Quickstart Tested Operating Systems (in order of thoroughness): @@ -260,6 +262,7 @@ Mistborn uses the following domains (that can be reached by all Wireguard client | Syncthing | syncthing.mistborn | Off | | OnlyOffice | onlyoffice.mistborn | Off | | Jitsi | jitsi.mistborn | Off | +| Mattermost | mattermost.mistborn | Off | # Default Credentials These are the default credentials to use in the services you choose to use: @@ -317,6 +320,7 @@ But wait, there's more! You can: | Jellyfin | [Jellyfin](https://play.google.com/store/apps/details?id=org.jellyfin.mobile) | [Jellyfin](https://apps.apple.com/us/app/jellyfin-mobile/id1480192618) | | Home Assistant | [Home Assistant](https://play.google.com/store/apps/details?id=io.homeassistant.companion.android) | | | Rocket.Chat | [Rocket.Chat](https://play.google.com/store/apps/details?id=chat.rocket.android) | [Rocket.Chat](https://apps.apple.com/us/app/rocket-chat/id1148741252) | +| Mattermost | [Mattermost](https://play.google.com/store/apps/details?id=com.mattermost.rn) | [Mattermost](https://apps.apple.com/us/app/mattermost/id1257222717) | ## TLS Certificate Some apps require TLS (HTTPS). All traffic to Mistborn domains already occurs over Wireguard but to keep apps running, a TLS certificate exists for Mistborn and can be imported into your device's trusted credentials in the security settings. This certificate is checked every day and will be re-generated when expiration is less than 30 days away. diff --git a/compose/production/mattermost/Dockerfile b/compose/production/mattermost/Dockerfile new file mode 100644 index 0000000..0780bf3 --- /dev/null +++ b/compose/production/mattermost/Dockerfile @@ -0,0 +1,56 @@ +FROM alpine:3.10 + +# Some ENV variables +ENV PATH="/mattermost/bin:${PATH}" +ENV MM_VERSION=5.27.0 + +# Build argument to set Mattermost edition +ARG edition=enterprise +ARG PUID=2000 +ARG PGID=2000 +ARG MM_BINARY= + + +# Install some needed packages +RUN apk add --no-cache \ + ca-certificates \ + curl \ + jq \ + libc6-compat \ + libffi-dev \ + libcap \ + linux-headers \ + mailcap \ + netcat-openbsd \ + xmlsec-dev \ + tzdata \ + && rm -rf /tmp/* + +# Get Mattermost +RUN mkdir -p /mattermost/data /mattermost/plugins /mattermost/client/plugins \ + && if [ ! -z "$MM_BINARY" ]; then curl $MM_BINARY | tar -xvz ; \ + elif [ "$edition" = "team" ] ; then curl https://releases.mattermost.com/$MM_VERSION/mattermost-team-$MM_VERSION-linux-amd64.tar.gz?src=docker-app | tar -xvz ; \ + else curl https://releases.mattermost.com/$MM_VERSION/mattermost-$MM_VERSION-linux-amd64.tar.gz?src=docker-app | tar -xvz ; fi \ + && cp /mattermost/config/config.json /config.json.save \ + && rm -rf /mattermost/config/config.json \ + && addgroup -g ${PGID} mattermost \ + && adduser -D -u ${PUID} -G mattermost -h /mattermost -D mattermost \ + && chown -R mattermost:mattermost /mattermost /config.json.save /mattermost/plugins /mattermost/client/plugins \ + && setcap cap_net_bind_service=+ep /mattermost/bin/mattermost + +USER mattermost + +#Healthcheck to make sure container is ready +HEALTHCHECK CMD curl --fail http://localhost:8000 || exit 1 + +# Configure entrypoint and command +COPY entrypoint.sh / +ENTRYPOINT ["/entrypoint.sh"] +WORKDIR /mattermost +CMD ["mattermost"] + +# Expose port 8000 of the container +EXPOSE 8000 + +# Declare volumes for mount point directories +VOLUME ["/mattermost/data", "/mattermost/logs", "/mattermost/config", "/mattermost/plugins", "/mattermost/client/plugins"] diff --git a/compose/production/mattermost/entrypoint.sh b/compose/production/mattermost/entrypoint.sh new file mode 100755 index 0000000..9646229 --- /dev/null +++ b/compose/production/mattermost/entrypoint.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# Function to generate a random salt +generate_salt() { + tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 48 | head -n 1 +} + +# Read environment variables or set default values +DB_HOST=${DB_HOST:-db} +DB_PORT_NUMBER=${DB_PORT_NUMBER:-5432} +MM_DBNAME=${MM_DBNAME:-mattermost} +MM_CONFIG=${MM_CONFIG:-/mattermost/config/config.json} + +if [ "${1:0:1}" = '-' ]; then + set -- mattermost "$@" +fi + +if [ "$1" = 'mattermost' ]; then + # Check CLI args for a -config option + for ARG in $@; + do + case "$ARG" in + -config=*) + MM_CONFIG=${ARG#*=};; + esac + done + + if [ ! -f "$MM_CONFIG" ]; then + # If there is no configuration file, create it with some default values + echo "No configuration file" $MM_CONFIG + echo "Creating a new one" + # Copy default configuration file + cp /config.json.save "$MM_CONFIG" + # Substitute some parameters with jq + jq '.ServiceSettings.ListenAddress = ":8000"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.LogSettings.EnableConsole = true' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.LogSettings.ConsoleLevel = "ERROR"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.FileSettings.Directory = "/mattermost/data/"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.FileSettings.EnablePublicLink = true' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.FileSettings.PublicLinkSalt = "'$(generate_salt)'"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.EmailSettings.SendEmailNotifications = false' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.EmailSettings.FeedbackEmail = ""' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.EmailSettings.SMTPServer = ""' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.EmailSettings.SMTPPort = ""' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.EmailSettings.InviteSalt = "'$(generate_salt)'"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.EmailSettings.PasswordResetSalt = "'$(generate_salt)'"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.RateLimitSettings.Enable = true' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.SqlSettings.DriverName = "postgres"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.SqlSettings.AtRestEncryptKey = "'$(generate_salt)'"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + jq '.PluginSettings.Directory = "/mattermost/plugins/"' $MM_CONFIG > $MM_CONFIG.tmp && mv $MM_CONFIG.tmp $MM_CONFIG + else + echo "Using existing config file $MM_CONFIG" + fi + + # Configure database access + if [[ -z "$MM_SQLSETTINGS_DATASOURCE" && ! -z "$MM_USERNAME" && ! -z "$MM_PASSWORD" ]] + then + echo -ne "Configure database connection..." + # URLEncode the password, allowing for special characters + ENCODED_PASSWORD=$(printf %s $MM_PASSWORD | jq -s -R -r @uri) + export MM_SQLSETTINGS_DATASOURCE="postgres://$MM_USERNAME:$ENCODED_PASSWORD@$DB_HOST:$DB_PORT_NUMBER/$MM_DBNAME?sslmode=disable&connect_timeout=10" + echo "OK" + else + echo "Using existing database connection" + fi + + # Wait another second for the database to be properly started. + # Necessary to avoid "panic: Failed to open sql connection pq: the database system is starting up" + sleep 1 + + echo "Starting mattermost" +fi + +exec "$@" diff --git a/extra/mattermost.yml b/extra/mattermost.yml new file mode 100644 index 0000000..99fdd28 --- /dev/null +++ b/extra/mattermost.yml @@ -0,0 +1,79 @@ +version: "3" + +services: + + db: + build: db + read_only: true + restart: unless-stopped + volumes: + - ../../mistborn_volumes/extra/mattermost/db/var/lib/postgresql/data:/var/lib/postgresql/data + - /etc/localtime:/etc/localtime:ro + env_file: + - ../.envs/.production/.mattermost + #environment: + # - POSTGRES_USER=mmuser + # - POSTGRES_PASSWORD=mmuser_password + # - POSTGRES_DB=mattermost + # uncomment the following to enable backup + # - AWS_ACCESS_KEY_ID=XXXX + # - AWS_SECRET_ACCESS_KEY=XXXX + # - WALE_S3_PREFIX=s3://BUCKET_NAME/PATH + # - AWS_REGION=us-east-1 + + app: + build: + context: compose/production/mattermost #app + # uncomment following lines for team edition or change UID/GID + args: + - edition=team + - PUID=1000 + - PGID=1000 + restart: unless-stopped + volumes: + - ../../mistborn_volumes/extra/mattermost/app/mattermost/config:/mattermost/config:rw + - ../../mistborn_volumes/extra/mattermost/app/mattermost/data:/mattermost/data:rw + - ../../mistborn_volumes/extra/mattermost/app/mattermost/logs:/mattermost/logs:rw + - ../../mistborn_volumes/extra/mattermost/app/mattermost/plugins:/mattermost/plugins:rw + - ../../mistborn_volumes/extra/mattermost/app/mattermost/client-plugins:/mattermost/client/plugins:rw + - /etc/localtime:/etc/localtime:ro + # When you want to use SSO with GitLab, you have to add the cert pki chain of GitLab inside Alpine + # to avoid Token request failed: certificate signed by unknown authority (link: https://github.com/mattermost/mattermost-server/issues/13059) + # - /pki_chain.pem:/etc/ssl/certs/pki_chain.pem:ro + env_file: + - ../.envs/.production/.mattermost + environment: + # set same as db credentials and dbname + #- MM_USERNAME=mmuser + #- MM_PASSWORD=mmuser_password + #- MM_DBNAME=mattermost + + # use the credentials you've set above, in the format: + # MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10 + #- MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:mmuser_password@db:5432/mattermost?sslmode=disable&connect_timeout=10 + - MM_SQLSETTINGS_DATASOURCE=postgres://${MM_USERNAME}:${MM_PASSWORD}@db:5432/${MM_DBNAME}?sslmode=disable&connect_timeout=10 + + # in case your config is not in default location + #- MM_CONFIG=/mattermost/config/config.json + + web: + build: web + #ports: + # - "80:80" + # - "443:443" + labels: + - "traefik.enable=true" + - "traefik.http.routers.mattermost-http.rule=Host(`mattermost.mistborn`)" + - "traefik.http.routers.mattermost-http.entrypoints=web" + - "traefik.http.routers.mattermost-http.middlewares=mistborn_auth@file" + - "traefik.http.routers.mattermost-https.rule=Host(`mattermost.mistborn`)" + - "traefik.http.routers.mattermost-https.entrypoints=websecure" + - "traefik.http.routers.mattermost-https.middlewares=mistborn_auth@file" + - "traefik.http.routers.mattermost-https.tls.certresolver=basic" + - "traefik.http.services.mattermost-service.loadbalancer.server.port=80" + read_only: true + restart: unless-stopped + volumes: + # This directory must have cert files if you want to enable SSL + #- ./volumes/web/cert:/cert:ro + - /etc/localtime:/etc/localtime:ro diff --git a/scripts/subinstallers/gen_prod_env.sh b/scripts/subinstallers/gen_prod_env.sh index f4b9675..a32c2cd 100755 --- a/scripts/subinstallers/gen_prod_env.sh +++ b/scripts/subinstallers/gen_prod_env.sh @@ -78,3 +78,10 @@ sed -i "s/JVB_AUTH_PASSWORD.*/JVB_AUTH_PASSWORD=$(python3 -c "import secrets; im sed -i "s/JIGASI_XMPP_PASSWORD.*/JIGASI_XMPP_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")/" "$JITSI_PROD_FILE" sed -i "s/JIBRI_RECORDER_PASSWORD.*/JIBRI_RECORDER_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")/" "$JITSI_PROD_FILE" sed -i "s/JIBRI_XMPP_PASSWORD.*/JIBRI_XMPP_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(32)]))")/" "$JITSI_PROD_FILE" + +# Mattermost +MATTERMOST_PROD_FILE="./.envs/.production/.mattermost" +echo "MM_USERNAME=mmuser" > $MATTERMOST_PROD_FILE +echo "MM_PASSWORD=$1" >> $MATTERMOST_PROD_FILE +echo "MM_DBNAME=mattermost" >> $MATTERMOST_PROD_FILE +