Hosting Lemmy with Traefik as a reverse proxy

cross-posted from: lmmy.tvdl.dev/post/259

In light of the ongoing Reddit blackout, many users are seeking alternative platforms to host their communities. One popular option is Lemmy, a self-hosted federated link aggregator. However, most of the available documentation on running Lemmy involves using Nginx or Caddy as a reverse proxy. If you’re utilizing Traefik with docker-compose and docker labels on your server, this guide will walk you through the process of setting up a working Lemmy instance without the need for Nginx or Caddy.

Step-by-Step Guide:

  1. Docker Compose Configuration: To begin, create a new docker-compose.yml file and include the necessary services for running Lemmy. Here’s a sample configuration to get you started:

    <pre style="background-color:#ffffff;">
    <span style="color:#63a35c;">version</span><span style="color:#323232;">: </span><span style="color:#183691;">"3.7"
    </span><span style="color:#323232;">
    </span><span style="color:#63a35c;">services</span><span style="color:#323232;">:
    </span><span style="color:#323232;">  </span><span style="color:#63a35c;">web</span><span style="color:#323232;">:
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">image</span><span style="color:#323232;">: </span><span style="color:#183691;">dessalines/lemmy:0.17.4
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">restart</span><span style="color:#323232;">: </span><span style="color:#183691;">always
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">logging</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      </span><span style="color:#63a35c;">driver</span><span style="color:#323232;">: </span><span style="color:#183691;">journald
    </span><span style="color:#323232;">      </span><span style="color:#63a35c;">options</span><span style="color:#323232;">:
    </span><span style="color:#323232;">        </span><span style="color:#63a35c;">tag</span><span style="color:#323232;">: </span><span style="color:#183691;">"{{.Name}}[{{.ID}}]"
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">environment</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">RUST_LOG="warn,lemmy_server=info,lemmy_api=info,lemmy_api_common=info,lemmy_api_crud=info,lemmy_apub=info,lemmy_db_schema=info,lemmy_db_views=info,lemmy_db_views_actor=info,lemmy_db_views_moderator=info,lemmy_routes=info,lemmy_utils=info,lemmy_websocket=info"
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">volumes</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">./lemmy.hjson:/config/config.hjson
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">depends_on</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">db
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">networks</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">default
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">reverse_proxy
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">labels</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.enable=true
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.http_lemmyexamplecom.rule=Host(`lemmy.example.com`) && (PathPrefix(`/api`, `/pictrs`, `/feeds`, `/nodeinfo`, `/.well-known`) || Method(`POST`) || HeadersRegexp(`Accept`, `^[Aa]pplication/.*`))
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.https_lemmyexamplecom.rule=Host(`lemmy.example.com`) && (PathPrefix(`/api`, `/pictrs`, `/feeds`, `/nodeinfo`, `/.well-known`) || Method(`POST`) || HeadersRegexp(`Accept`, `^[Aa]pplication/.*`))
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.http_lemmyexamplecom.entrypoints=http
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.https_lemmyexamplecom.entrypoints=https
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.http_lemmyexamplecom.middlewares=https_redirect@file
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.https_lemmyexamplecom.tls.certresolver=letsencrypt
    </span><span style="color:#323232;">  </span><span style="color:#63a35c;">web-frontend</span><span style="color:#323232;">:
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">image</span><span style="color:#323232;">: </span><span style="color:#183691;">dessalines/lemmy-ui:0.17.4
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">environment</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">LEMMY_UI_LEMMY_INTERNAL_HOST=web:8536
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">LEMMY_UI_LEMMY_EXTERNAL_HOST=localhost:1236
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">LEMMY_HTTPS=true
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">depends_on</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">web
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">restart</span><span style="color:#323232;">: </span><span style="color:#183691;">always
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">logging</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      </span><span style="color:#63a35c;">driver</span><span style="color:#323232;">: </span><span style="color:#183691;">journald
    </span><span style="color:#323232;">      </span><span style="color:#63a35c;">options</span><span style="color:#323232;">:
    </span><span style="color:#323232;">        </span><span style="color:#63a35c;">tag</span><span style="color:#323232;">: </span><span style="color:#183691;">"{{.Name}}[{{.ID}}]"
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">networks</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">default
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">reverse_proxy
    </span><span style="color:#63a35c;">labels</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.enable=true
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.http_lemmyexamplecom_static.rule=Host(`lemmy.example.com`)
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.https_lemmyexamplecom_static.rule=Host(`lemmy.example.com`)
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.http_lemmyexamplecom_static.entrypoints=http
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.https_lemmyexamplecom_static.entrypoints=https
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.http_lemmyexamplecom_static.middlewares=https_redirect@file
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">traefik.http.routers.https_lemmyexamplecom_static.tls.certresolver=letsencrypt
    </span><span style="color:#323232;">  </span><span style="color:#63a35c;">db</span><span style="color:#323232;">:
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">image</span><span style="color:#323232;">: </span><span style="color:#183691;">postgres:15-alpine
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">hostname</span><span style="color:#323232;">: </span><span style="color:#183691;">db
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">environment</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">POSTGRES_USER=lemmy
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">POSTGRES_PASSWORD=password
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">volumes</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">db:/var/lib/postgresql/data
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">restart</span><span style="color:#323232;">: </span><span style="color:#183691;">always
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">logging</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      </span><span style="color:#63a35c;">driver</span><span style="color:#323232;">: </span><span style="color:#183691;">journald
    </span><span style="color:#323232;">      </span><span style="color:#63a35c;">options</span><span style="color:#323232;">:
    </span><span style="color:#323232;">        </span><span style="color:#63a35c;">tag</span><span style="color:#323232;">: </span><span style="color:#183691;">"{{.Name}}[{{.ID}}]"
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">networks</span><span style="color:#323232;">:
    </span><span style="color:#323232;">      - </span><span style="color:#183691;">default
    </span><span style="color:#323232;">
    </span><span style="color:#63a35c;">networks</span><span style="color:#323232;">:
    </span><span style="color:#323232;">  </span><span style="color:#63a35c;">reverse_proxy</span><span style="color:#323232;">:
    </span><span style="color:#323232;">    </span><span style="color:#63a35c;">external</span><span style="color:#323232;">: </span><span style="color:#0086b3;">true
    </span><span style="color:#323232;">
    </span><span style="color:#63a35c;">volumes</span><span style="color:#323232;">:
    </span><span style="color:#323232;">  </span><span style="color:#63a35c;">db</span><span style="color:#323232;">:
    </span>
    
  2. Adjust Hostname: Remember to replace the placeholder hostname in the configuration with the actual hostname of your server. This ensures that Lemmy is accessible via the correct URL. Start Lemmy: Save the changes to your docker-compose.yml file and execute the following command in the terminal to start Lemmy:

    <pre style="background-color:#ffffff;">
    <span style="color:#323232;">docker-compose up -d
    </span>
    
  3. Verify Lemmy’s Availability: Once the containers are up and running, access your Lemmy instance by navigating to the URL associated with your server’s hostname.

Please note that the instructions provided here assume a basic understanding of Docker, Traefik, and server administration. Adjustments may be necessary based on your specific setup and requirements.

edit: Also note that this is for version 0.17.4. In case a new version releases you need to change the tag for both lemmy and lemmy-ui

theRealBassist,

Figured I’d ask to see if you know if this method is still working? I have mine setup very nearly identically to what you have here, and I have corrected my lemmy.hjson to have the correct hostname and password for the database. The only changes I have made thus far is to remove the HTTP redirection, and to change things like me cert resolver, the Lemmy version, and other small corrections.

However, all I am getting is a gateway timeout when I try to visit the url I have setup. Do you have any idea why this might be? I’ll provide my docker-compose below.

<pre style="background-color:#ffffff;">
<span style="color:#323232;">version: "3.7"
</span><span style="color:#323232;">
</span><span style="color:#323232;">services:
</span><span style="color:#323232;">  web:
</span><span style="color:#323232;">    image: dessalines/lemmy:latest
</span><span style="color:#323232;">    restart: always
</span><span style="color:#323232;">    logging:
</span><span style="color:#323232;">      driver: journald
</span><span style="color:#323232;">      options:
</span><span style="color:#323232;">        tag: "{{.Name}}[{{.ID}}]"
</span><span style="color:#323232;">    environment:
</span><span style="color:#323232;">      - RUST_LOG="warn,lemmy_server=info,lemmy_api=info,lemmy_api_common=info,lemmy_api_crud=info,lemmy_apub=info,lemmy_db_schema=info,lemmy_db_views=info,lemmy_db_views_actor=info,lemmy_db_views_moderator=info,lemmy_routes=info,lemmy_utils=info,lemmy_websocket=info"
</span><span style="color:#323232;">    volumes:
</span><span style="color:#323232;">      - /mnt/lemmy/lemmy.hjson:/config/config.hjson
</span><span style="color:#323232;">    depends_on:
</span><span style="color:#323232;">      - db
</span><span style="color:#323232;">    networks:
</span><span style="color:#323232;">      - lemmy
</span><span style="color:#323232;">      - traefik_default
</span><span style="color:#323232;">    labels:
</span><span style="color:#323232;">      - traefik.enable=true
</span><span style="color:#323232;">      - traefik.http.routers.https_lemmy.rule=Host(`lem.domain.tld`) && (PathPrefix(`/api`, `/pictrs`, `/feeds`, `/nodeinfo`, `/.well-known`) || Method(`POST`) || HeadersRegexp(`Accept`, `^[Aa]pplication/.*`))
</span><span style="color:#323232;">      - traefik.http.routers.https_lemmy.entrypoints=https
</span><span style="color:#323232;">      - traefik.http.routers.https_lemmy.tls.certresolver=myresolver
</span><span style="color:#323232;">  web-frontend:
</span><span style="color:#323232;">    image: dessalines/lemmy-ui:latest
</span><span style="color:#323232;">    environment:
</span><span style="color:#323232;">      - LEMMY_UI_LEMMY_INTERNAL_HOST=web:8536
</span><span style="color:#323232;">      - LEMMY_UI_LEMMY_EXTERNAL_HOST=localhost:1236
</span><span style="color:#323232;">      - LEMMY_HTTPS=true
</span><span style="color:#323232;">    depends_on:
</span><span style="color:#323232;">      - web
</span><span style="color:#323232;">    restart: always
</span><span style="color:#323232;">    logging:
</span><span style="color:#323232;">      driver: journald
</span><span style="color:#323232;">      options:
</span><span style="color:#323232;">        tag: "{{.Name}}[{{.ID}}]"
</span><span style="color:#323232;">    networks:
</span><span style="color:#323232;">      - lemmy
</span><span style="color:#323232;">      - traefik_default
</span><span style="color:#323232;">    labels:
</span><span style="color:#323232;">      - traefik.enable=true
</span><span style="color:#323232;">      - traefik.http.routers.https_lemmy_static.rule=Host(`lem.domain.tld`)
</span><span style="color:#323232;">      - traefik.http.routers.https_lemmy_static.entrypoints=https
</span><span style="color:#323232;">      - traefik.http.routers.https_lemmy_static.tls.certresolver=myresolver
</span><span style="color:#323232;">  db:
</span><span style="color:#323232;">    image: postgres:15-alpine
</span><span style="color:#323232;">    hostname: db
</span><span style="color:#323232;">    environment:
</span><span style="color:#323232;">      - POSTGRES_USER=lemmy
</span><span style="color:#323232;">      - POSTGRES_PASSWORD=LONGstringOFcharacters
</span><span style="color:#323232;">    volumes:
</span><span style="color:#323232;">      - /mnt/lemmy/db:/var/lib/postgresql/data
</span><span style="color:#323232;">      - ./customPostgresql.conf:/etc/postgresql.conf
</span><span style="color:#323232;">    restart: always
</span><span style="color:#323232;">    logging:
</span><span style="color:#323232;">      driver: journald
</span><span style="color:#323232;">      options:
</span><span style="color:#323232;">        tag: "{{.Name}}[{{.ID}}]"
</span><span style="color:#323232;">    networks:
</span><span style="color:#323232;">      - lemmy
</span><span style="color:#323232;">
</span><span style="color:#323232;">networks:
</span><span style="color:#323232;">  traefik_default:
</span><span style="color:#323232;">    external: true
</span><span style="color:#323232;">  lemmy:
</span><span style="color:#323232;">    driver: bridge
</span><span style="color:#323232;">volumes:
</span><span style="color:#323232;">  db:
</span><span style="color:#323232;">
</span>
  • All
  • Subscribed
  • Moderated
  • Favorites
  • wartaberita
  • random
  • uselessserver093
  • Food
  • aaaaaaacccccccce
  • [email protected]
  • test
  • CafeMeta
  • testmag
  • MUD
  • RhythmGameZone
  • RSS
  • dabs
  • TheResearchGuardian
  • Ask_kbincafe
  • KbinCafe
  • Testmaggi
  • Socialism
  • feritale
  • oklahoma
  • SuperSentai
  • KamenRider
  • All magazines