GitLab-CE Mattermost with Apache

Hello,
I installed GitLab-CE v10.1.0 on my Ubuntu 16.04 LTS server using apache with the following VirtualHost config:

<VirtualHost *:80>
    ServerName www.gitlab.domain.com
    ServerSignature Off

    RedirectMatch permanent ^(.*)$ https://gitlab.domain.com$1

    ErrorLog /var/log/apache2/gitlab.domain.com_error.log
    CustomLog /var/log/apache2/gitlab.domain.com_access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName www.gitlab.domain.com
    ServerSignature Off

    RedirectMatch permanent ^(.*)$ https://gitlab.domain.com$1

    SSLEngine on
    SSLProtocol All -SSLv2 -SSLv3
    SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    SSLHonorCipherOrder     on
    SSLCompression          off
    SSLCertificateFile      /etc/letsencrypt/live/www.gitlab.domain.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/www.gitlab.domain.com/privkey.pem

    ErrorLog /var/log/apache2/gitlab.domain.com_error.log
    CustomLog /var/log/apache2/gitlab.domain.com_access.log combined
</VirtualHost>


<VirtualHost *:80>
    ServerName gitlab.domain.com
    ServerSignature Off

    RedirectMatch permanent ^(.*)$ https://gitlab.domain.com$1

    ErrorLog /var/log/apache2/gitlab.domain.com_error.log
    CustomLog /var/log/apache2/gitlab.domain.com_access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName gitlab.domain.com
    ServerSignature Off

    DocumentRoot /opt/gitlab/embedded/service/gitlab-rails/public
    ProxyPreserveHost On
    AllowEncodedSlashes NoDecode
    <Location />
        Require all granted
        ProxyPassReverse http://127.0.0.1:8181
        ProxyPassReverse http://gitlab.domain.com/
    </Location>
    
    <IfModule mod_expires.c>
        <FilesMatch "\.(jpe?g|png|gif|js|css|ico|php|html|txt|log|xml)$">
            ExpiresActive On
            ExpiresDefault "access plus 1 day"
        </FilesMatch>
    </IfModule>

    <IfModule mod_deflate.c>
        <IfModule mod_filter.c>
            SetOutputFilter DEFLATE
            SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|ico)$ no-gzip dont-vary
            SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
            SetEnvIfNoCase Request_URI .pdf$ no-gzip dont-vary
            BrowserMatch ^Mozilla/4 gzip-only-text/html
            BrowserMatch ^Mozilla/4.0[678] no-gzip
            BrowserMatch bMSIE !no-gzip !gzip-only-text/html
        </IfModule>
    </IfModule>

    <IfModule mod_headers.c>
        Header always set X-FRAME-OPTIONS "SAMEORIGIN"
        Header always set X-Content-Type-Options "nosniff"
        Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
        Header always set Content-Security-Policy "default-src 'self' 'unsafe-eval' 'unsafe-inline' https://www.gstatic.com https://www.google.com *.gitlab.com *.gravatar.com data:;"
        Header always set X-Content-Security-Policy "default-src 'self' 'unsafe-eval' 'unsafe-inline' https://www.gstatic.com https://www.google.com *.gitlab.com *.gravatar.com data:;"
        Header always set X-Webkit-CSP "default-src 'self' 'unsafe-eval' 'unsafe-inline' https://www.gstatic.com https://www.google.com *.gitlab.com *.gravatar.com data:;"
    </IfModule>

    SSLEngine on
    SSLProtocol All -SSLv2 -SSLv3
    SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    SSLHonorCipherOrder     on
    SSLCompression          off
    SSLCertificateFile      /etc/letsencrypt/live/gitlab.domain.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/gitlab.domain.com/privkey.pem
    
    RewriteEngine On
    RewriteCond %{REQUEST_URI} ^/api/v3/.*
    RewriteRule .* http://127.0.0.1:8181%{REQUEST_URI} [P,QSA,NE]
    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR]
    RewriteCond %{REQUEST_URI} ^/uploads/.*
    RewriteRule .* http://127.0.0.1:8181%{REQUEST_URI} [P,QSA]
    
    RequestHeader set X_FORWARDED_PROTO 'https'
    RequestHeader set X-Forwarded-Ssl on
        
    ErrorDocument 404 /404.html
    ErrorDocument 422 /422.html
    ErrorDocument 500 /500.html
    ErrorDocument 503 /deploy.html
        
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded
    ErrorLog /var/log/apache2/gitlab.domain.com_error.log
    CustomLog /var/log/apache2/gitlab.domain.com_forwarded.log common_forwarded
    CustomLog /var/log/apache2/gitlab.domain.com_access.log combined env=!dontlog
    CustomLog /var/log/apache2/gitlab.domain.com.log combined
</VirtualHost>

Then I activated Mattermost in the /etc/gitlab/gitlab.rb:

mattermost_external_url 'https://mattermost.domain.com'
mattermost['enable'] = true
mattermost['gitlab_enable'] = true
mattermost['gitlab_secret'] = "<SecretGeneratedByGitLab>"
mattermost['gitlab_id'] = "<AppIDGeneratedByGitLab>"
mattermost['gitlab_auth_endpoint'] = "https://gitlab.domain.com/oauth/authorize"
mattermost['gitlab_token_endpoint'] = "https://gitlab.domain.com/oauth/token"
mattermost['gitlab_user_api_endpoint'] = "https://gitlab.domain.com/api/v4/user"
mattermost_nginx['enable'] = false

Also I setup an virtualhost for this domain:

<VirtualHost *:80>
    ServerName www.mattermost.domain.com
    ServerSignature Off

    RedirectMatch permanent ^(.*)$ https://mattermost.domain.com$1

    ErrorLog /var/log/apache2/mattermost.domain.com_error.log
    CustomLog /var/log/apache2/mattermost.domain.com_access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName www.mattermost.domain.com
    ServerSignature Off

    RedirectMatch permanent ^(.*)$ https://mattermost.domain.com$1

    SSLEngine on
    SSLProtocol All -SSLv2 -SSLv3
    SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    SSLHonorCipherOrder     on
    SSLCompression          off
    SSLCertificateFile      /etc/letsencrypt/live/www.mattermost.domain.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/www.mattermost.domain.com/privkey.pem

    ErrorLog /var/log/apache2/mattermost.domain.com_error.log
    CustomLog /var/log/apache2/mattermost.domain.com_access.log combined
</VirtualHost>

<VirtualHost *:80>
    ServerName mattermost.domain.com
    ServerSignature Off

    RedirectMatch permanent ^(.*)$ https://mattermost.domain.com$1

    ErrorLog /var/log/apache2/mattermost.domain.com_error.log
    CustomLog /var/log/apache2/mattermost.domain.com_access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName mattermost.domain.com
    ServerSignature Off

    DocumentRoot /var/opt/gitlab/mattermost

    # setup the proxy
    ProxyPreserveHost On
    <Proxy *>
      Order allow,deny
      Allow from all
    </Proxy>

    RewriteEngine On
    RewriteCond %{REQUEST_URI} ^/api/v4/users/websocket [NC,OR]
    RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
    RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
    RewriteRule .* ws://127.0.0.1:8065%{REQUEST_URI} [P,QSA,L]
    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
    RewriteRule .* http://127.0.0.1:8065%{REQUEST_URI} [P,QSA,L]

    <Location /api/v4/users/websocket>
      Require all granted
      ProxyPass ws://127.0.0.1:8065/api/v4/users/websocket
      ProxyPassReverse ws://127.0.0.1:8065/api/v4/users/websocket
      ProxyPassReverseCookieDomain 127.0.0.1 mattermost.domain.com
    </Location>

    <Location />
      Require all granted
      ProxyPass http://127.0.0.1:8065/
      ProxyPassReverse http://127.0.0.1:8065/
      ProxyPassReverseCookieDomain 127.0.0.1 mattermost.domain.com
    </Location>
    
    SSLEngine on
    SSLProtocol All -SSLv2 -SSLv3
    SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    SSLHonorCipherOrder     on
    SSLCompression          off
    SSLCertificateFile      /etc/letsencrypt/live/mattermost.domain.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/mattermost.domain.com/privkey.pem
        
    ErrorLog /var/log/apache2/mattermost.domain.com_error.log
    CustomLog /var/log/apache2/mattermost.domain.com_access.log combined
</VirtualHost>

Now, when I go to https://mattermost.domain.com I will get the login page with the signin button using GitLab. When I click on it it redirects me to the GitLab signin page where I enter my username and password just to get redirected to https://mattermost.domain.com/error?message=Bad%20token%20type saying :

Error
Bad token type

Back to Mattermost

The apache log states that:

AuthorizeOAuthUser: Bad token type, token_type=, response_body={“error”:“invalid_grant”,“error_description”:“The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.”}

Any ideas or hints what might go wrong here? I installed mod_proxy_wstunnel and activated it already. Not sure what else might be missing here.

Best,
Marc

1 Like

I have a same problem. GitLab returned a 401 error.

==> /var/log/gitlab/gitlab-rails/production.log <==
Started POST "/oauth/token" for 127.0.0.1 at 2017-11-01 13:21:49 +0900
Processing by Doorkeeper::TokensController#create as JSON
  Parameters: {"client_id"=>"32e72037ef9b6259028e163d46f86217fb50b1a0d3c2643279b199036586a50b", "client_secret"=>"[FILTERED]", "code"=>"[FILTERED]", "grant_type"=>"authorization_code", "redirect_uri"=>"http://mattermost.example.com/signup/gitlab/complete"}
Completed 401 Unauthorized in 3ms

I set up GitLab and Mattermost with HTTPS (via reverse proxy of Apache), but Mattermost seems to request a redirect URL in HTTP scheme. Is this related to this problem?

Yes, that’s what I see in the log as well:

Started GET "/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fmattermost.domain.com%2Fsignup%2Fgitlab%2Fcomplete&state=STATE" for CLIENT_IP at DATE
Processing by Oauth::AuthorizationsController#new as HTML
  Parameters: {"response_type"=>"code", "client_id"=>"CLIENT_ID", "redirect_uri"=>"https://mattermost.domain.com/signup/gitlab/complete", "state"=>"STATE"}
Redirected to https://gitlab.domain.com/users/sign_in
Filter chain halted as :authenticate_resource_owner! rendered or redirected
Completed 302 Found in 2ms (ActiveRecord: 0.3ms)
Started GET "/users/sign_in" for CLIENT_IP at DATE
Processing by SessionsController#new as HTML
Completed 200 OK in 20ms (Views: 11.0ms | ActiveRecord: 0.5ms)
Started GET "/uploads/-/system/appearance/header_logo/1/apple-touch-icon.png" for CLIENT_IP at DATE
Processing by UploadsController#show as HTML
  Parameters: {"model"=>"appearance", "mounted_as"=>"header_logo", "id"=>"1", "filename"=>"apple-touch-icon.png"}
Sent file /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/system/appearance/header_logo/1/apple-touch-icon.png (0.1ms)
Completed 200 OK in 5ms (ActiveRecord: 0.3ms)
Started POST "/users/sign_in" for CLIENT_IP at DATE
Processing by SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "user"=>{"login"=>"USERNAME", "password"=>"[FILTERED]", "remember_me"=>"0"}}
Redirected to https://gitlab.domain.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fmattermost.domain.com%2Fsignup%2Fgitlab%2Fcomplete&state=STATE
Completed 302 Found in 190ms (ActiveRecord: 11.9ms)
Started GET "/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fmattermost.domain.com%2Fsignup%2Fgitlab%2Fcomplete&state=STATE" for CLIENT_IP at DATE
Processing by Oauth::AuthorizationsController#new as HTML
  Parameters: {"response_type"=>"code", "client_id"=>"CLIENT_ID", "redirect_uri"=>"https://mattermost.domain.com/signup/gitlab/complete", "state"=>"STATE"}
Redirected to https://mattermost.domain.com/signup/gitlab/complete?code=CODE&state=STATE
Completed 302 Found in 16ms (ActiveRecord: 3.1ms)
Started POST "/oauth/token" for SERVER_IP at DATE
Processing by Doorkeeper::TokensController#create as JSON
  Parameters: {"client_id"=>"CLIENT_ID", "client_secret"=>"[FILTERED]", "code"=>"[FILTERED]", "grant_type"=>"authorization_code", "redirect_uri"=>"http://mattermost.domain.com/signup/gitlab/complete"}
Completed 401 Unauthorized in 3ms

Hey, I am done !!
Add the following settings to Apache configuration file of Mattermost reverse proxy to solve this problem.

RequestHeader set X-Forwarded-Proto 'https'
RequestHeader set X-Forwarded-Ssl 'on'

Try it. :wink:

1 Like

Where did you added the request header ?