Note: this is my crosspost from reddit. Hello folks! I’ve been trying to get my own Lemmy instance up and had some problems figuring out how to set it up for realsies in production.
Perhaps you like to play self hosting on hard mode like I do. Perhaps you looked at the ansible playbook for Lemmy and said ‘absolutely not’. Perhaps you saw you could also build it from scratch, and oh nevermind there’s a docker, cool. That’s what Portainer is for, you crazy son of a gun!! Perhaps you then looked at the Docker guide, saw that nginx was part of the deployment and said ‘I could probably move that to my currently existing Nginx Proxy Manager!’
You’d be right, but it might cost you hours of time, tears, sweat, and some sanity. Like me! I hope this helps someone!
To start:
SSH into your docker box. You’ll need to create a few volumes and download some stuff. I elected to create my files at /docker/lemmy.
mkdir /docker/lemmy/
cd /docker/lemmy/
mkdir -p volumes/pictrs
sudo chown -R 991:991 volumes/pictrs
Download the ‘lemmy.hjson’ config file by doing a
wget https://raw.githubusercontent.com/LemmyNet/lemmy/release/v0.17/docker/prod/lemmy.hjson
Change the stuff between < > (and remove the <>s). If there are ""s it’s intentional. Here’s how mine looks. Take note: It starts and ends with { } brackets.
{
# for more info about the config, check out the documentation
# https://join-lemmy.org/docs/en/administration/configuration.html
# only few config options are covered in this example config
setup: {
# username for the admin user
admin_username: <"astronguser">
# password for the admin user
admin_password: <"astrongpassword">
# name of the site (can be changed later)
site_name: <"acoolname">
}
# the domain name of your instance (eg "lemmy.ml" or "fernchat.esotericmonkey.com")
hostname: <"fakelemmy.horse">
# address where lemmy should listen for incoming requests
bind: "0.0.0.0"
# port where lemmy should listen for incoming requests
port: 8536
# Whether the site is available over TLS. Needs to be true for federation to work.
tls_enabled: true
# pictrs host
pictrs: {
url: "http://pictrs:8080/"
# api_key: "API_KEY"
}
# settings related to the postgresql database
database: {
# name of the postgres database for lemmy
database: <"databasename">
# username to connect to postgres
user: <"astronguser">
# password to connect to postgres
password: <"astrongpassword">
# host where postgres is running. This needs to match the postgres hostname in the portainer stack
host: "postgres"
# port where postgres can be accessed
port: 5432
# maximum number of active sql connections
pool_size: 5
}
# See the documentation for available config fields and descriptions:
# https://join-lemmy.org/docs/en/administration/configuration.html
federation: {
hostname: <fakelemmy.horse>
allowed_instances: <lemmy_ml>
}
email: {
# Hostname and port of the smtp server
smtp_server: <"mail.server.com:465">
# Login name for smtp server
smtp_login: <"lemmy@server.com">
# Password to login to the smtp server
smtp_password: <"12345">
# Address to send emails from, eg "noreply@your-instance.com"
smtp_from_address: <"noreply@server.com">
# Whether or not smtp connections should use tls. Can be none, tls, or starttls
tls_type: "tls"
}
}
Download the docker-compose.yml to your computer. Go to Portainer, and create a new stack.
Paste the content of that files into the stack, edit it, and create it.Here’s how my compose file looks. This keeps the database on the lemmyinternal network. It exposes the UI and lemmy to the LAN. My Portainer IP is 172.16.7.20. Update the variables inside < >!
version: "3.3"
networks:
#Keep the database safe, dawg
lemmyinternal:
driver: bridge
internal: true
lemmyexternal:
#Everything else
services:
lemmy:
image: dessalines/lemmy:0.17.3
networks:
- lemmyinternal
- lemmyexternal
ports:
- 8536:8536
restart: always
environment:
- 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"
#Set RUST_BACKTRACE=1 if you have problems, or if you just want to feel clever looking at log files
- RUST_BACKTRACE=1
volumes:
- /docker/lemmy/lemmy.hjson:/config/config.hjson
depends_on:
- postgres
- pictrs
lemmy-ui:
image: dessalines/lemmy-ui:0.17.3
networks:
- lemmyexternal
ports:
#Always keep em guessing
- 1236:1234
environment:
# THIS SHOULD BE 'lemmy'. IT'S THE NAME OF THE DOCKER SEVICE NOT A HOSTNAME
- LEMMY_UI_LEMMY_INTERNAL_HOST=lemmy:8536
# set the outside hostname here. I use 1236 as the port, make sure you have 1236:1234 for your lemmy-ui port if so.
- LEMMY_UI_LEMMY_EXTERNAL_HOST=<172.16.7.20:1236>
#Nginx Proxy Manager will get this.
- LEMMY_HTTPS=false
depends_on:
- lemmy
restart: always
pictrs:
networks:
- lemmyinternal
image: asonix/pictrs:0.3.1
# 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__API_KEY=API_KEY
user: 991:991
volumes:
- /docker/lemmy/volumes/pictrs:/mnt
restart: always
postgres:
networks:
- lemmyinternal
image: postgres:15-alpine
# this needs to match the database host in lemmy.hson
hostname: postgres
ports:
- 5432:5432
environment:
- POSTGRES_USER=<strongusername>
- POSTGRES_PASSWORD=<strongpassword>
- POSTGRES_DB=<databasename>
volumes:
- /docker/lemmy/volumes/postgres:/var/lib/postgresql/data
restart: always
Note: if this fails the first time and you get database errors in postgres, or lemmy won’t shut up about being unable to access the database or settings, you may need to destroy the stack containers, remove all non-persistent volumes, and do a rm -rf on the /docker/lemmy/volumes/postgres folder.
If you check the database logs in Portainer, you should see the database initalizing for the first time, and lemmy should be running a migration process.
Pop over to Nginx Proxy Manager and create a new site. In my case, I’ll be pointing towards http://172.16.7.20:1236.
Under SSL, acquire your Lets Encrypt Certificate
(or install your own, you crazy admin!).
Enable ‘Force SSL’ and ‘HTTPS/2 Support’.
You may enable HSTS if you’d like.
Under Custom Locations, you’ll need a few!
location: /api http://172.16.7.20:8536
location: /pictrs http://172.16.7.20:8536
location: /feeds http://172.16.7.20:8536
location: /nodeinfo http://172.16.7.20:8536
Then, go to the advanced tab, and paste in this block. This makes the federation all federationy.
location / {
# The default ports:
# lemmy_ui_port: 1235(not used here)
# lemmy_port: 8536
# The cooler port:
# lemmy_ui_port: 1236
set $proxpass "http://172.16.7.20:1236";
if ($http_accept ~ "^application/.*$") {
set $proxpass "http://172.16.7.20:8536";
}
if ($request_method = POST) {
set $proxpass "http://172.16.7.20:8536";
}
proxy_pass $proxpass;
rewrite ^(.+)/+$ $1 permanent;
# Send actual client IP upstream
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Hit save. In theory, you should have a working Lemmy instance. See you in the fediverse!