So, here's something that might work. I tested it on my local machine, up to Caddy but without HTTPS, but I'm confident it'll work once deployed on a server.
Prerequisites:
- Server with Docker and docker-compose installed
- Ports 80 and 443 open and directed at your server
- A domain name pointing to your server
Setup
First, create a folder and download the following files:
Then, generate passwords for PostgreSQL and your admin user, store them somewhere safe.
Config changes
lemmy.hjson
You'll want to change the admin_username
, admin_password
and site_name
to match your primary user's credentials and the name you want to give your instance.
Then, change hostname
to match your domain name: if it is sub.domain.tld
then it should read hostname: "sub.domain.tld"
.
The base config file does not have proper configuration for the database, so you'll have to edit the database
field as follows with the password you previously created:
database: {
host: postgres
database: "lemmy"
user: "lemmy"
password: "POSTGRES_PWD" # Change for your password
}
Additionally, if you want to send emails for registration confirmation and password resets, add the following before the closing }
and change to match your email provider configuration.
email: {
# Hostname and port of the smtp server
smtp_server: "SMTP_SERVER"
# Login name for smtp server
smtp_login: "SMTP_LOGIN"
# Password to login to the smtp server
smtp_password: "SMTP_PASSWORD"
# Address to send emails from, eg "noreply@your-instance.com"
smtp_from_address: "SMTP_LOGIN"
# Whether or not smtp connections should use tls. Can be none, tls, or starttls
tls_type: "starttls"
}
docker-compose.yml
By default the compose file is meant to build a development version of Lemmy, we will change this by removing the blocks with build
and uncomment those with image
. Note: think to update the images to 0.18.2
since it fixes some vulnerabilities.
Also, since we will use a reverse proxy and I don't now if your server has a firewall, we should remove the ports
blocks which are used to expose the services' ports on the host.
Finally, make sure to change the POSTGRES_PASSWORD
field to match the PostgreSQL password you set in lemmy.hjson
.
It should look something like that:
version: "3.7"
x-logging: &default-logging
driver: "json-file"
options:
max-size: "50m"
max-file: "4"
services:
proxy:
image: nginx:1-alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro,Z
restart: always
depends_on:
- pictrs
- lemmy-ui
logging: *default-logging
lemmy:
# use "image" to pull down an already compiled lemmy. make sure to comment out "build".
image: dessalines/lemmy:0.18.2
# platform: linux/x86_64 # no arm64 support. uncomment platform if using m1.
# use "build" to build your local lemmy server image for development. make sure to comment out "image".
# run: docker compose up --build
# this hostname is used in nginx reverse proxy and also for lemmy ui to connect to the backend, do not change
hostname: lemmy
restart: always
environment:
- RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
- RUST_BACKTRACE=full
volumes:
- ./lemmy.hjson:/config/config.hjson:Z
depends_on:
- postgres
- pictrs
logging: *default-logging
lemmy-ui:
# use "image" to pull down an already compiled lemmy-ui. make sure to comment out "build".
image: dessalines/lemmy-ui:0.18.2
# platform: linux/x86_64 # no arm64 support. uncomment platform if using m1.
# use "build" to build your local lemmy ui image for development. make sure to comment out "image".
# run: docker compose up --build
# build:
# context: ../../lemmy-ui # assuming lemmy-ui is cloned besides lemmy directory
# dockerfile: dev.dockerfile
environment:
# this needs to match the hostname defined in the lemmy service
- LEMMY_UI_LEMMY_INTERNAL_HOST=lemmy:8536
# set the outside hostname here
- LEMMY_UI_LEMMY_EXTERNAL_HOST=localhost:1236
- LEMMY_UI_HTTPS=false
- LEMMY_UI_DEBUG=true
depends_on:
- lemmy
restart: always
logging: *default-logging
init: true
pictrs:
image: asonix/pictrs:0.4.0-beta.19
# this needs to match the pictrs url in lemmy.hjson
hostname: pictrs
# we can set options to pictrs like this, here we set max. image size and forced format for conversion
# entrypoint: /sbin/tini -- /usr/local/bin/pict-rs -p /mnt -m 4 --image-format webp
environment:
- PICTRS_OPENTELEMETRY_URL=http://otel:4137
- PICTRS__API_KEY=API_KEY
- RUST_LOG=debug
- RUST_BACKTRACE=full
- PICTRS__MEDIA__VIDEO_CODEC=vp9
- PICTRS__MEDIA__GIF__MAX_WIDTH=256
- PICTRS__MEDIA__GIF__MAX_HEIGHT=256
- PICTRS__MEDIA__GIF__MAX_AREA=65536
- PICTRS__MEDIA__GIF__MAX_FRAME_COUNT=400
user: 991:991
volumes:
- ./volumes/pictrs:/mnt:Z
restart: always
logging: *default-logging
postgres:
image: postgres:15-alpine
# this needs to match the database host in lemmy.hson
# Tune your settings via
# https://pgtune.leopard.in.ua/#/
# You can use this technique to add them here
# https://stackoverflow.com/a/30850095/1655478
hostname: postgres
command:
[
"postgres",
"-c",
"session_preload_libraries=auto_explain",
"-c",
"auto_explain.log_min_duration=5ms",
"-c",
"auto_explain.log_analyze=true",
"-c",
"track_activity_query_size=1048576",
]
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password # Change with your password
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres:/var/lib/postgresql/data:Z
restart: always
logging: *default-logging
Reverse-proxy
For the final touch, we are going to setup Caddy, a reverse proxy with HTTPS support out of the box. You could use pretty much any reverse proxy you want, but I chose Caddy for its easy setup.
First, create a file nammed Caddyfile
and write the following in it:
sub.domain.tld {
reverse_proxy http://proxy:1236
}
Make sure to match your actual domain name.
Finally, update the docker-compose.yml
file to add the following at the end (make sure that it's correctly tabulated)
caddy:
image: caddy:2.6.4
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
depends_on:
- proxy
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Launching the instance
Before starting the stack, we have a few things left to do:
- Create the folders for pictrs and postgres to store their data:
mkdir -p volumes/postgres volumes/pictrs
- Change the owner of
volumes/pictrs
: sudo chown -R 991:991 pictrs
Finally, to start everything: docker compose up -d