Question on selfhosting Mastodon (docker or not, reverse proxy and how to easily update)

Shiimiish@lm.ainyataovi.net to Selfhosted@lemmy.world – 15 points –

I finally managed to selfhost Lemmy and Matrix, now it is time to also get a selfhosted Mastodon instance up. A few questions before I start:

I did some research into the topic and it seems that Mastodon doesn't like to run behind an existing reverse proxy and there are quite a few tweaks necessary to get it running - can someone confirm this? Or is this something easily set up?

I'm currently leaning to run it on a dedicated VPS (due to the issue above and also because it seems to need quite a bit of disk space) - this opens up to do a non-docker installation and follow the official install path. Do you think this will make it easier to keep it updated to new releases in the future?

If going with a docker install there seem to be quite a few problems with updating (at least a lot of threads discussing failed update procedures sprung up when I googles "mastodon docker update") - can someone confirm? Are there easy to follow guides for a docker based update routine?

Right now it seems the easiest would be to run on a dedicated server, follow the native installation procedure and use the templates provided for nginx, certbot, .... thoughts?

9

It's actually not hard to get Mastodon running behind an existing reverse proxy. It's also not hard to run it in a docker container. I run mine in a docker container with no issues. When version 4.1.4 was released, I just ran a docker-compose pull, and voila, my instant was upgraded. I can share my configs with you if you want. What is your existing reverse proxy server?

I run Nginx with Nginx Proxy Manager web-ui, which makes setting up proxy hosts and handling letsencrypt certificates really easy. I also use Portainer to manage my docker containers. This works well for the stuff I mentioned above (Nextcloud, Matrix, Lemmy mostly)

If I can get Mastodon into the same setup, it'd be neat. I just found a lot of discussion with problems, so I thought I'll ask about it before I spend a few hours in vain :)

NGINX Proxy Manager makes things even easier! All you have to do is make certain that you have websockets enabled for the proxy settings to go to your Mastodon instance and don't forward via SSL because NPM is your SSL termination point. On your Mastodon instance's NGINX configuration, change the port to listen on port 80, comment out all of the SSL related options, and in the @proxy section change the proxy_set_header X-Forwarded-Proto $scheme; to proxy_set_header X-Forwarded-Proto https; This is just telling Mastodon a small lie so it thinks the traffic is encrypted. This is necessary to prevent a redirection loop which will break things.

Is there a good guide for Mastodon in Docker? I’ve followed a few but they all get stuck at various points.

You need to actually piece together those few to come up with one cohesive working instance. I can share with you the docker-compose.yml file that worked for me, if that will help.

version: '3'
services:
  db:
    restart: always
    image: postgres:14-alpine
    shm_size: 256mb
    networks:
      - internal_network
    healthcheck:
      test: ['CMD', 'pg_isready', '-U', 'postgres']
    volumes:
      - ./postgres14:/var/lib/postgresql/data
    environment:
      - 'POSTGRES_HOST_AUTH_METHOD=trust'

  redis:
    restart: always
    image: redis:7-alpine
    networks:
      - internal_network
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    volumes:
      - ./redis:/data

  # es:
  #   restart: always
  #   image: docker.elastic.co/elasticsearch/elasticsearch:7.17.4
  #   environment:
  #     - "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
  #     - "xpack.license.self_generated.type=basic"
  #     - "xpack.security.enabled=false"
  #     - "xpack.watcher.enabled=false"
  #     - "xpack.graph.enabled=false"
  #     - "xpack.ml.enabled=false"
  #     - "bootstrap.memory_lock=true"
  #     - "cluster.name=es-mastodon"
  #     - "discovery.type=single-node"
  #     - "thread_pool.write.queue_size=1000"
  #   networks:
  #      - external_network
  #      - internal_network
  #   healthcheck:
  #      test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
  #   volumes:
  #      - ./elasticsearch:/usr/share/elasticsearch/data
  #   ulimits:
  #     memlock:
  #       soft: -1
  #       hard: -1
  #     nofile:
  #       soft: 65536
  #       hard: 65536
  #   ports:
  #     - '127.0.0.1:9200:9200'

  web:
    #build: .
    #image: ghcr.io/mastodon/mastodon
    image: tootsuite/mastodon:latest
    restart: always
    env_file: .env.production
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
    ports:
      - '127.0.0.1:3000:3000'
    depends_on:
      - db
      - redis
      # - es
    volumes:
      - ./public/system:/mastodon/public/system

  streaming:
    #build: .
    #image: ghcr.io/mastodon/mastodon
    image: tootsuite/mastodon:latest
    restart: always
    env_file: .env.production
    command: node ./streaming
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
    ports:
      - '127.0.0.1:4000:4000'
    depends_on:
      - db
      - redis

  sidekiq:
    #build: .
    #image: ghcr.io/mastodon/mastodon
    image: tootsuite/mastodon:latest
    restart: always
    env_file: .env.production
    command: bundle exec sidekiq
    depends_on:
      - db
      - redis
    networks:
      - external_network
      - internal_network
    volumes:
      - ./public/system:/mastodon/public/system
    healthcheck:
      test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]

  ## Uncomment to enable federation with tor instances along with adding the following ENV variables
  ## http_proxy=http://privoxy:8118
  ## ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
  # tor:
  #   image: sirboops/tor
  #   networks:
  #      - external_network
  #      - internal_network
  #
  # privoxy:
  #   image: sirboops/privoxy
  #   volumes:
  #     - ./priv-config:/opt/config
  #   networks:
  #     - external_network
  #     - internal_network

networks:
  external_network:
  internal_network:
    internal: true

If you do use Docker, Mastodon seems to be a prime example of where you shouldn't use the : latest tag and autoupdate with something like Watchtower.

I initially installed with :latest a few days ago and it gave me 4.1.3 (the actual latest version had been 4.1.4 for quite awhile at that point). I saw other people mention that they "updated" to a 3.x release via :latest recently.

That sounds more like improper tagging by the maintainers.

Probably.

Though it was the official Mastodon container, and not a third party.