-version: '2.2'
+version: "3.3"
+
+networks:
+ # communication to web and clients
+ lemmyexternalproxy:
+ # communication between lemmy services
+ lemmyinternal:
+ driver: bridge
+ internal: true
services:
- postgres:
- image: postgres:14-alpine
- environment:
- - POSTGRES_USER=lemmy
- - POSTGRES_PASSWORD=password
- - POSTGRES_DB=lemmy
+ proxy:
+ image: nginx:1-alpine
+ networks:
+ - lemmyinternal
+ - lemmyexternalproxy
+ ports:
+ # only ports facing any connection from outside
+ - 80:80
+ - 443:443
volumes:
- - ./volumes/postgres:/var/lib/postgresql/data
+ - ./nginx.conf:/etc/nginx/nginx.conf:ro
+ # setup your certbot and letsencrypt config
+ - ./certbot:/var/www/certbot
+ - ./letsencrypt:/etc/letsencrypt/live
restart: always
+ depends_on:
+ - pictrs
+ - lemmy-ui
lemmy:
- image: dessalines/lemmy:0.16.6
- ports:
- - "127.0.0.1:8536:8536"
- - "127.0.0.1:6669:6669"
+ image: dessalines/lemmy:0.16.7
+ hostname: lemmy
+ networks:
+ - lemmyinternal
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"
volumes:
- ./lemmy.hjson:/config/config.hjson
- pictrs
lemmy-ui:
- image: dessalines/lemmy-ui:0.16.6
- ports:
- - "127.0.0.1:1235:1234"
- restart: always
+ image: dessalines/lemmy-ui:0.16.7
+ networks:
+ - lemmyinternal
environment:
+ # this needs to match the hostname defined in the lemmy service
- LEMMY_INTERNAL_HOST=lemmy:8536
- - LEMMY_EXTERNAL_HOST=localhost:8536
+ # set the outside hostname here
+ - LEMMY_EXTERNAL_HOST=localhost:1236
- LEMMY_HTTPS=true
- depends_on:
+ depends_on:
- lemmy
+ restart: always
pictrs:
image: asonix/pictrs:0.3.1
- ports:
- - "127.0.0.1:8537:8080"
- - "127.0.0.1:6670:6669"
+ # 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
+ networks:
+ - lemmyinternal
+ environment:
+ - PICTRS__API_KEY=API_KEY
user: 991:991
volumes:
- ./volumes/pictrs:/mnt
restart: always
+ postgres:
+ image: postgres:14-alpine
+ # this needs to match the database host in lemmy.hson
+ hostname: postgres
+ networks:
+ - lemmyinternal
+ environment:
+ - POSTGRES_USER=lemmy
+ - POSTGRES_PASSWORD=password
+ - POSTGRES_DB=lemmy
+ volumes:
+ - ./volumes/postgres:/var/lib/postgresql/data
+ restart: always
{
# 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
# password for the admin user
admin_password: "lemmylemmy"
# name of the site (can be changed later)
- site_name: "lemmy-test"
+ site_name: "mylemmyinstance"
}
- opentelemetry_url: "http://otel:4137"
-
# the domain name of your instance (eg "lemmy.ml")
hostname: "mydomain.ml"
# 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"
+
# settings related to the postgresql database
- pictrs_config: {
- url: "http://pictrs:8080"
- api_key: "API_KEY"
- }
database: {
# name of the postgres database for lemmy
database: "lemmy"
# maximum number of active sql connections
pool_size: 5
}
- slur_filter:
- '''
- (fag(g|got|tard)?\b|cock\s?sucker(s|ing)?|ni((g{2,}|q)+|[gq]{2,})[e3r]+(s|z)?|mudslime?s?|kikes?|\bspi(c|k)s?\b|\bchinks?|gooks?|bitch(es|ing|y)?|whor(es?|ing)|\btr(a|@)nn?(y|ies?)|\b(b|re|r)tard(ed)?s?)
- '''
-# # optional: email sending configuration
-# email: {
-# # hostname and port of the smtp server
-# smtp_server: ""
-# # login name for smtp server
-# smtp_login: ""
-# # password to login to the smtp server
-# smtp_password: ""
-# # address to send emails from, eg "noreply@your-instance.com"
-# smtp_from_address: ""
-# # whether or not smtp connections should use tls
-# use_tls: true
-# }
}
--- /dev/null
+# nginx example config
+# replace {{yourdomain}} and review the certbot/letsencrypt config
+worker_processes 1;
+events {
+ worker_connections 1024;
+}
+http {
+ limit_req_zone $binary_remote_addr zone={{yourdomain}}_ratelimit:10m rate=1r/s;
+
+ upstream lemmy {
+ # this needs to map to the lemmy (server) docker service hostname
+ server "lemmy:8536";
+ }
+ upstream lemmy-ui {
+ # this needs to map to the lemmy-ui docker service hostname
+ server "lemmy-ui:1234";
+ }
+
+ server {
+ # allow letsencrypt challenge
+ # redirect everything else to 443
+ listen 80;
+ listen [::]:80;
+ server_name {{yourdomain}};
+ location /.well-known/acme-challenge/ {
+ root /var/www/certbot;
+ }
+ location / {
+ return 301 https://$host$request_uri;
+ }
+ }
+
+ server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name {{yourdomain}};
+
+ ssl_certificate /etc/letsencrypt/live/{{yourdomain}}/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/{{yourdomain}}/privkey.pem;
+
+ # Various TLS hardening settings
+ # https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_prefer_server_ciphers on;
+ ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
+ ssl_session_timeout 10m;
+ ssl_session_cache shared:SSL:10m;
+ ssl_session_tickets on;
+ ssl_stapling on;
+ ssl_stapling_verify on;
+
+ # Hide nginx version
+ server_tokens off;
+
+ # Enable compression for JS/CSS/HTML bundle, for improved client load times.
+ # It might be nice to compress JSON, but leaving that out to protect against potential
+ # compression+encryption information leak attacks like BREACH.
+ gzip on;
+ gzip_types text/css application/javascript image/svg+xml;
+ gzip_vary on;
+
+ # Only connect to this site via HTTPS for the two years
+ add_header Strict-Transport-Security "max-age=63072000";
+
+ # Various content security headers
+ add_header Referrer-Policy "same-origin";
+ add_header X-Content-Type-Options "nosniff";
+ add_header X-Frame-Options "DENY";
+ add_header X-XSS-Protection "1; mode=block";
+
+ # Upload limit for pictrs
+ client_max_body_size 20M;
+
+ # frontend
+ location / {
+ # distinguish between ui requests and backend
+ # don't change lemmy-ui or lemmy here, they refer to the upstream definitions on top
+ set $proxpass "http://lemmy-ui";
+
+ if ($http_accept = "application/activity+json") {
+ set $proxpass "http://lemmy";
+ }
+ if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
+ set $proxpass "http://lemmy";
+ }
+ if ($request_method = POST) {
+ set $proxpass "http://lemmy";
+ }
+ 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;
+ }
+
+ # backend
+ location ~ ^/(api|feeds|nodeinfo|.well-known) {
+ proxy_pass "http://lemmy";
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+
+ # Rate limit
+ limit_req zone={{yourdomain}}_ratelimit burst=30 nodelay;
+
+ # Add IP forwarding headers
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+
+ # pictrs only - for adding browser cache control.
+ location ~ ^/(pictrs) {
+ # allow browser cache, images never update, we can apply long term cache
+ expires 120d;
+ add_header Pragma "public";
+ add_header Cache-Control "public";
+
+ proxy_pass "http://lemmy";
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+
+ # Rate limit
+ limit_req zone={{yourdomain}}_ratelimit burst=30 nodelay;
+
+ # Add IP forwarding headers
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+
+ # Redirect pictshare images to pictrs
+ location ~ /pictshare/(.*)$ {
+ return 301 /pictrs/image/$1;
+ }
+ }
+
+ # Anonymize IP addresses
+ # https://www.supertechcrew.com/anonymizing-logs-nginx-apache/
+ map $remote_addr $remote_addr_anon {
+ ~(?P<ip>\d+\.\d+\.\d+)\. $ip.0;
+ ~(?P<ip>[^:]+:[^:]+): $ip::;
+ 127.0.0.1 $remote_addr;
+ ::1 $remote_addr;
+ default 0.0.0.0;
+ }
+ access_log /var/log/nginx/access.log combined;
+}
\ No newline at end of file