diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/lemmy-ansible.iml b/.idea/lemmy-ansible.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/lemmy-ansible.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..bf9a031
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/lemmy-ansible.iml" filepath="$PROJECT_DIR$/.idea/lemmy-ansible.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.woodpecker.yml b/.woodpecker.yml
index 796fa8a..678e0fe 100644
--- a/.woodpecker.yml
+++ b/.woodpecker.yml
@@ -1,4 +1,8 @@
 pipeline:
+  prettier_markdown_check:
+    image: tmknom/prettier
+    commands:
+      - prettier -c "*.md" "*.yml"
   check_ansible_format:
     image: alpine:3
     commands:
diff --git a/README.md b/README.md
index c25350c..fdcbafe 100644
--- a/README.md
+++ b/README.md
@@ -6,61 +6,63 @@ This provides an easy way to install [Lemmy](https://github.com/LemmyNet/lemmy)
 
 To run this ansible playbook, you need to:
 
-- Have a server / VPS where lemmy will run.
+- Have a Debian-based server / VPS where lemmy will run.
 - Configure a DNS `A` Record to point at your server's IP address.
 - Make sure you can ssh to it, with a sudo user: `ssh <your-user>@<your-domain>`
 - Install [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) on your **local** machine (do not install it on your destination server).
 
 ## Install
 
-Clone this repo:
+1. Clone this repo:
 
-```
-git clone https://github.com/LemmyNet/lemmy-ansible.git
-cd lemmy-ansible
-```
+   ```
+   git clone https://github.com/LemmyNet/lemmy-ansible.git
+   cd lemmy-ansible
+   ```
 
-Make a directory to hold your config:
+2. Make a directory to hold your config:
 
-`mkdir -p inventory/host_vars/<your-domain>`
+   `mkdir -p inventory/host_vars/<your-domain>`
 
-Copy the sample configuration file:
+3. Copy the sample configuration file:
 
-`cp examples/config.hjson inventory/host_vars/<your-domain>/config.hjson`
+   `cp examples/config.hjson inventory/host_vars/<your-domain>/config.hjson`
 
-Edit that file and change the config to your liking. Note: **Do not edit anything inside the {{ }} braces.**
+   Edit that file and change the config to your liking. Note: **Do not edit anything inside the {{ }} braces.**
 
-[Here are all the config options.](https://join-lemmy.org/docs/en/administration/configuration.html#full-config-with-default-values)
+   [Here are all the config options.](https://join-lemmy.org/docs/en/administration/configuration.html#full-config-with-default-values)
 
-Copy the sample inventory hosts file:
+4. Copy the sample inventory hosts file:
 
-`cp examples/hosts inventory/hosts`
+   `cp examples/hosts inventory/hosts`
 
-Edit the inventory hosts file (inventory/hosts) to your liking.
+   Edit the inventory hosts file (inventory/hosts) to your liking.
 
-Copy the sample postgresql.conf
+5. Copy the sample postgresql.conf
 
-`cp examples/customPostgresql.conf inventory/host_vars/<your-domain>/customPostgresql.conf`
+   `cp examples/customPostgresql.conf inventory/host_vars/<your-domain>/customPostgresql.conf`
 
-You can use [the PGTune tool](https://pgtune.leopard.in.ua) to tune your postgres to meet your server memory and CPU.
+   You can use [the PGTune tool](https://pgtune.leopard.in.ua) to tune your postgres to meet your server memory and CPU.
 
-Run the playbook:
+6. Run the playbook:
 
-`ansible-playbook -i inventory/hosts lemmy.yml`
+   `ansible-playbook -i inventory/hosts lemmy.yml`
 
-_Note_: if you are not the root user or don't have password-less sudo, use this command:
+   _Note_: if you are not the root user or don't have password-less sudo, use this command:
 
-`ansible-playbook -i inventory/hosts lemmy.yml --become --ask-become-pass`
+   `ansible-playbook -i inventory/hosts lemmy.yml --become --ask-become-pass`
 
-_Note_: if you haven't set up ssh keys, and ssh using a password, use the command:
+   _Note_: if you haven't set up ssh keys[^1], and ssh using a password, use the command:
 
-`ansible-playbook -i inventory/hosts lemmy.yml --become --ask-pass --ask-become-pass`
+   `ansible-playbook -i inventory/hosts lemmy.yml --become --ask-pass --ask-become-pass`
 
-[Full ansible command-line docs](https://docs.ansible.com/ansible/latest/cli/ansible-playbook.html)
+   [Full ansible command-line docs](https://docs.ansible.com/ansible/latest/cli/ansible-playbook.html)
 
-If the command above fails, you may need to comment out this line In the ansible.cfg file:
+   If the command above fails, you may need to comment out this line In the ansible.cfg file:
 
-`interpreter_python=/usr/bin/python3`
+   `interpreter_python=/usr/bin/python3`
+
+[^1]: To create an ssh key pair with your host environment, you can follow the [instructions here](https://www.ssh.com/academy/ssh/keygen#copying-the-public-key-to-the-server), and then copy the key to your host server.
 
 ## Upgrading
 
diff --git a/VERSION b/VERSION
index 884e960..6633391 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.17.3
+0.18.0
diff --git a/lemmy.yml b/lemmy.yml
index 67da53a..37f4009 100644
--- a/lemmy.yml
+++ b/lemmy.yml
@@ -21,157 +21,158 @@
     - setup: # gather facts
 
   tasks:
-  - name: Install aptitude
-    apt:
-      name: aptitude
-      state: latest
-      update_cache: true
-
-  - name: install dependencies
-    apt:
-      state: latest
-      update_cache: true
-      pkg:
-        - 'nginx'
-        - 'certbot'
-        - 'python3-certbot-nginx'
-        - 'apt-transport-https'
-        - 'ca-certificates'
-        - 'curl'
-        - 'software-properties-common'
-        - 'python3-pip'
-        - 'virtualenv'
-        - 'python3-setuptools'
-
-  - name: Add Docker GPG apt Key
-    apt_key:
-      url: https://download.docker.com/linux/ubuntu/gpg
-      state: present
-
-  - name: Add Docker Repository
-    apt_repository:
-      repo: deb https://download.docker.com/linux/ubuntu focal stable
-      state: present
-
-  - name: Update apt and install docker-ce
-    apt:
-      name: docker-ce
-      state: latest
-      update_cache: true
-
-  - name: Install Docker Module and docker-compose for Python
-    pip:
-      name:
-        - docker
-        - docker-compose
-      state: latest
-
-  - name: copy docker config
-    copy: src='../files/docker-daemon.json' dest='/etc/docker/daemon.json' mode='0644'
-
-  - name: request initial letsencrypt certificate
-    command: certbot certonly --nginx --agree-tos --cert-name '{{ domain }}' -d '{{ domain }}' -m '{{ letsencrypt_contact_email }}'
-    args:
-      creates: '/etc/letsencrypt/live/{{domain}}/privkey.pem'
-
-  - name: create lemmy folder
-    file:
-      path: '{{item.path}}'
-      owner: '{{item.owner}}'
-      state: directory
-    with_items:
-      - path: '{{lemmy_base_dir}}/{{domain}}/'
-        owner: 'root'
-      - path: '{{lemmy_base_dir}}/{{domain}}/volumes/'
-        owner: 'root'
-      - path: '{{lemmy_base_dir}}/{{domain}}/volumes/pictrs/'
-        owner: '991'
-
-  - block:
-    - set_fact:
-        lemmy_port: "{{ 32767 |random(start=1024) }}"
-        lemmy_ui_port: "{{ 32767 |random(start=1024) }}"
-        pictrs_port: "{{ 32767 |random(start=1024) }}"
-
-    - name: add template files
-      template:
-        src: '{{item.src}}'
-        dest: '{{item.dest}}'
-        mode: '{{item.mode}}'
+    - name: Install aptitude
+      apt:
+        name: aptitude
+        state: latest
+        update_cache: true
+
+    - name: install dependencies
+      apt:
+        state: latest
+        update_cache: true
+        pkg:
+          - "nginx"
+          - "certbot"
+          - "python3-certbot-nginx"
+          - "apt-transport-https"
+          - "ca-certificates"
+          - "curl"
+          - "software-properties-common"
+          - "python3-pip"
+          - "virtualenv"
+          - "python3-setuptools"
+
+    - name: Add Docker GPG apt Key
+      apt_key:
+        url: https://download.docker.com/linux/ubuntu/gpg
+        state: present
+
+    - name: Add Docker Repository
+      apt_repository:
+        repo: deb https://download.docker.com/linux/ubuntu focal stable
+        state: present
+
+    - name: Update apt and install docker-ce
+      apt:
+        name: docker-ce
+        state: latest
+        update_cache: true
+
+    - name: Install Docker Module and docker-compose for Python
+      pip:
+        name:
+          - docker
+          - docker-compose
+        state: latest
+
+    - name: copy docker config
+      copy: src='../files/docker-daemon.json' dest='/etc/docker/daemon.json' mode='0644'
+
+    - name: request initial letsencrypt certificate
+      command: certbot certonly --nginx --agree-tos --cert-name '{{ domain }}' -d '{{ domain }}' -m '{{ letsencrypt_contact_email }}'
+      args:
+        creates: "/etc/letsencrypt/live/{{domain}}/privkey.pem"
+
+    - name: create lemmy folder
+      file:
+        path: "{{item.path}}"
+        owner: "{{item.owner}}"
+        state: directory
       with_items:
-        - src: 'templates/docker-compose.yml'
-          dest: '{{lemmy_base_dir}}/{{domain}}/docker-compose.yml'
-          mode: '0600'
-        - src: 'templates/nginx.conf'
-          dest: '/etc/nginx/sites-available/{{domain}}.conf'
-          mode: '0644'
-      vars:
-        lemmy_docker_image: "dessalines/lemmy:{{ lemmy_version | default( lookup('file', 'VERSION') )}}"
-        lemmy_docker_ui_image: "dessalines/lemmy-ui:{{ lemmy_ui_version | default(lemmy_version | default(lookup('file', 'VERSION')))}}"
+        - path: "{{lemmy_base_dir}}/{{domain}}/"
+          owner: "root"
+        - path: "{{lemmy_base_dir}}/{{domain}}/volumes/"
+          owner: "root"
+        - path: "{{lemmy_base_dir}}/{{domain}}/volumes/pictrs/"
+          owner: "991"
 
     - block:
-      - name: gather stats on site enabled config
-        stat:
-          path: "/etc/nginx/sites-enabled/{{domain}}.conf"
-        register: reg_enabled
-
-      - name: remove if regular file (legacy) instead of symlink
-        file:
-          path: "/etc/nginx/sites-enabled/{{domain}}.conf"
-          state: absent
-        when: reg_enabled.stat.exists and reg_enabled.stat.isreg
-
-      - name: enable nginx site
-        file:
-          src: '../sites-available/{{domain}}.conf'
-          dest: "/etc/nginx/sites-enabled/{{domain}}.conf"
-          state: link
-          
-    - name: add the config.hjson
-      template:
-        src: 'inventory/host_vars/{{domain}}/config.hjson'
-        dest: '{{lemmy_base_dir}}/{{domain}}/lemmy.hjson'
-        mode: '0600'
-        owner: '1000'
-        group: '1000'
-
-    - name: add the customPostgresql.conf
-      template:
-        src: 'inventory/host_vars/{{domain}}/customPostgresql.conf'
-        dest: '{{lemmy_base_dir}}/{{domain}}/customPostgresql.conf'
-        mode: '0600'
-        owner: '1000'
-        group: '1000'
-
-    vars:
-      postgres_password: "{{ lookup('password', 'inventory/host_vars/{{domain}}/passwords/postgres chars=ascii_letters,digits') }}"
-
-  - name: enable and start docker service
-    systemd:
-      name: docker
-      enabled: yes
-      state: started
-
-  # - name: Change the working directory to /opt
-  #   ansible.builtin.shell:
-  #     cmd: find .                    # To list files under /opt directory
-  #     chdir: /opt                    # changes to /opt directory
-  #     register: shell_output
-  # - debug: var=shell_output     
-
-  - name: start docker-compose
-    docker_compose:
-      project_src: '{{lemmy_base_dir}}/{{domain}}'
-      state: present
-      pull: yes
-      remove_orphans: yes
-
-  - name: reload nginx with new config
-    shell: nginx -s reload
-
-  - name: certbot renewal cronjob
-    cron:
-      special_time: daily
-      name: certbot-renew-lemmy
-      user: root
-      job: "certbot certonly --nginx --cert-name '{{ domain }}' -d '{{ domain }}' --deploy-hook 'nginx -s reload'"
+        - set_fact:
+            lemmy_port: "{{ 32767 |random(start=1024) }}"
+
+        - name: add template files
+          template:
+            src: "{{item.src}}"
+            dest: "{{item.dest}}"
+            mode: "{{item.mode}}"
+          with_items:
+            - src: "templates/docker-compose.yml"
+              dest: "{{lemmy_base_dir}}/{{domain}}/docker-compose.yml"
+              mode: "0600"
+            - src: "templates/nginx_internal.conf"
+              dest: "{{lemmy_base_dir}}/{{domain}}/nginx_internal.conf"
+              mode: "0644"
+            - src: "templates/nginx.conf"
+              dest: "/etc/nginx/sites-available/{{domain}}.conf"
+              mode: "0644"
+          vars:
+            lemmy_docker_image: "dessalines/lemmy:{{ lemmy_version | default( lookup('file', 'VERSION') )}}"
+            lemmy_docker_ui_image: "dessalines/lemmy-ui:{{ lemmy_ui_version | default(lemmy_version | default(lookup('file', 'VERSION')))}}"
+
+        - block:
+            - name: gather stats on site enabled config
+              stat:
+                path: "/etc/nginx/sites-enabled/{{domain}}.conf"
+              register: reg_enabled
+
+            - name: remove if regular file (legacy) instead of symlink
+              file:
+                path: "/etc/nginx/sites-enabled/{{domain}}.conf"
+                state: absent
+              when: reg_enabled.stat.exists and reg_enabled.stat.isreg
+
+            - name: enable nginx site
+              file:
+                src: "../sites-available/{{domain}}.conf"
+                dest: "/etc/nginx/sites-enabled/{{domain}}.conf"
+                state: link
+
+        - name: add the config.hjson
+          template:
+            src: "inventory/host_vars/{{domain}}/config.hjson"
+            dest: "{{lemmy_base_dir}}/{{domain}}/lemmy.hjson"
+            mode: "0600"
+            owner: "1000"
+            group: "1000"
+
+        - name: add the customPostgresql.conf
+          template:
+            src: "inventory/host_vars/{{domain}}/customPostgresql.conf"
+            dest: "{{lemmy_base_dir}}/{{domain}}/customPostgresql.conf"
+            mode: "0600"
+            owner: "1000"
+            group: "1000"
+
+      vars:
+        postgres_password: "{{ lookup('password', 'inventory/host_vars/{{domain}}/passwords/postgres chars=ascii_letters,digits') }}"
+
+    - name: enable and start docker service
+      systemd:
+        name: docker
+        enabled: yes
+        state: started
+
+    # - name: Change the working directory to /opt
+    #   ansible.builtin.shell:
+    #     cmd: find .                    # To list files under /opt directory
+    #     chdir: /opt                    # changes to /opt directory
+    #     register: shell_output
+    # - debug: var=shell_output
+
+    - name: start docker-compose
+      docker_compose:
+        project_src: "{{lemmy_base_dir}}/{{domain}}"
+        state: present
+        pull: yes
+        remove_orphans: yes
+
+    - name: reload nginx with new config
+      shell: nginx -s reload
+
+    - name: certbot renewal cronjob
+      cron:
+        special_time: daily
+        name: certbot-renew-lemmy
+        user: root
+        job: "certbot certonly --nginx --cert-name '{{ domain }}' -d '{{ domain }}' --deploy-hook 'nginx -s reload'"
diff --git a/templates/docker-compose.yml b/templates/docker-compose.yml
index 358056d..dbc8b82 100644
--- a/templates/docker-compose.yml
+++ b/templates/docker-compose.yml
@@ -1,56 +1,95 @@
-version: '2'
+version: "3.7"
+
+x-logging: &default-logging
+  driver: "json-file"
+  options:
+    max-size: "50m"
+    max-file: "4"
 
 services:
+  proxy:
+    image: nginx:1-alpine
+    ports:
+      # actual and only port facing any connection from outside
+      # Note, change the left number if port 1236 is already in use on your system
+      # You could use port 80 if you won't use a reverse proxy
+      - "{{ lemmy_port }}:8536"
+    volumes:
+      - ./nginx_internal.conf:/etc/nginx/nginx.conf:ro,Z
+    restart: always
+    logging: *default-logging
+    depends_on:
+      - pictrs
+      - lemmy-ui
+
   lemmy:
     image: {{ lemmy_docker_image }}
-    ports:
-      - "127.0.0.1:{{ lemmy_port }}:8536"
+    hostname: lemmy
     restart: always
+    logging: *default-logging
     environment:
-      - RUST_LOG="warn,lemmy_server=info,lemmy_api=info,lemmy_api_common=info,lemmy_api_crud=info,lemmy_apub=info,lemmy_db_queries=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"
+      - RUST_LOG="warn"
     volumes:
-      - ./lemmy.hjson:/config/config.hjson
+      - ./lemmy.hjson:/config/config.hjson:Z
     depends_on:
       - postgres
       - pictrs
 
   lemmy-ui:
     image: {{ lemmy_docker_ui_image }}
-    ports:
-      - "127.0.0.1:{{ lemmy_ui_port }}:1234"
-    restart: always
     environment:
       - LEMMY_UI_LEMMY_INTERNAL_HOST=lemmy:8536
       - LEMMY_UI_LEMMY_EXTERNAL_HOST={{ domain }}
       - LEMMY_UI_HTTPS=true
     volumes:
       - ./volumes/lemmy-ui/extra_themes:/app/extra_themes
-    depends_on: 
+    depends_on:
       - lemmy
+    restart: always
+    logging: *default-logging
+
+  pictrs:
+    image: asonix/pictrs:0.4.0-rc.7
+    # 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={{ postgres_password }}
+      - 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
+    deploy:
+      resources:
+        limits:
+          memory: 690m
 
   postgres:
     image: postgres:15-alpine
+    hostname: postgres
     environment:
       - POSTGRES_USER=lemmy
       - POSTGRES_PASSWORD={{ postgres_password }}
       - POSTGRES_DB=lemmy
     volumes:
-      - ./volumes/postgres:/var/lib/postgresql/data
+      - ./volumes/postgres:/var/lib/postgresql/data:Z
       - ./customPostgresql.conf:/etc/postgresql.conf
     restart: always
-
-  pictrs:
-    image: asonix/pictrs:0.3.1
-    user: 991:991
-    ports:
-      - "127.0.0.1:{{ pictrs_port }}:8080"
-    volumes:
-      - ./volumes/pictrs:/mnt
-    restart: always
-    mem_limit: 200m
+    logging: *default-logging
 
   postfix:
     image: mwader/postfix-relay
     environment:
       - POSTFIX_myhostname={{ domain }}
     restart: "always"
+    logging: *default-logging
diff --git a/templates/nginx.conf b/templates/nginx.conf
index feac4be..935266b 100644
--- a/templates/nginx.conf
+++ b/templates/nginx.conf
@@ -21,8 +21,7 @@ server {
     ssl_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem;
     ssl_certificate_key /etc/letsencrypt/live/{{domain}}/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';
@@ -42,59 +41,18 @@ server {
     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 / {
-      # The default ports:
-      # lemmy_ui_port: 1235
-      # lemmy_port: 8536
-
-      set $proxpass "http://0.0.0.0:{{lemmy_ui_port}}";
-      if ($http_accept ~ "^application/.*$") {
-        set $proxpass "http://0.0.0.0:{{lemmy_port}}";
-      }
-      if ($request_method = POST) {
-        set $proxpass "http://0.0.0.0:{{lemmy_port}}";
-      }
-      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;
-
-      # Response cache for unauthenticated users
-      proxy_cache lemmy_cache_{{domain}};
-      proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
-      proxy_cache_valid 1m;
-      proxy_no_cache $cookie_jwt;
-      #add_header x-cache-status $upstream_cache_status;
-    }
-
-    # backend
-    location ~ ^/(api|pictrs|feeds|nodeinfo|.well-known) {
       proxy_pass http://0.0.0.0:{{lemmy_port}};
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
-
-      # Rate limit
-      limit_req zone={{domain}}_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;
@@ -104,15 +62,9 @@ server {
       proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
       proxy_cache_valid 1m;
       proxy_no_cache $arg_auth $cookie_jwt;
+      # for debugging add `x-cache-status` header to responses
       #add_header x-cache-status $upstream_cache_status;
     }
-
-
-    # Redirect pictshare images to pictrs
-    location ~ /pictshare/(.*)$ {
-      return 301 /pictrs/image/$1;
-    }
-
 }
 
 access_log /var/log/nginx/access.log combined;
diff --git a/templates/nginx_internal.conf b/templates/nginx_internal.conf
new file mode 100644
index 0000000..02e7345
--- /dev/null
+++ b/templates/nginx_internal.conf
@@ -0,0 +1,72 @@
+worker_processes auto;
+events {
+    worker_connections 1024;
+}
+http {
+    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 {
+        # this is the port inside docker, not the public one yet
+        listen 1236;
+        listen 8536;
+        # change if needed, this is facing the public web
+        server_name localhost;
+        server_tokens off;
+
+        gzip on;
+        gzip_types text/css application/javascript image/svg+xml;
+        gzip_vary on;
+
+        # Upload limit, relevant for pictrs
+        client_max_body_size 20M;
+
+        add_header X-Frame-Options SAMEORIGIN;
+        add_header X-Content-Type-Options nosniff;
+        add_header X-XSS-Protection "1; mode=block";
+
+        # frontend general requests
+        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|pictrs|feeds|nodeinfo|.well-known) {
+            proxy_pass "http://lemmy";
+            # proxy common stuff
+            proxy_http_version 1.1;
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection "upgrade";
+
+            # 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;
+        }
+    }
+}
diff --git a/uninstall.yml b/uninstall.yml
index 58b727d..1779c0c 100644
--- a/uninstall.yml
+++ b/uninstall.yml
@@ -2,7 +2,6 @@
 - hosts: all
 
   vars_prompt:
-
     - name: confirm_uninstall
       prompt: "Do you really want to uninstall Lemmy? This will delete all data and can not be reverted [yes/no]"
       private: no
@@ -12,29 +11,28 @@
       private: no
 
   tasks:
-  - name: end play if no confirmation was given
-    debug:
-      msg: "Uninstall cancelled, doing nothing"
-    when: not confirm_uninstall|bool
-
-  - meta: end_play
-    when: not confirm_uninstall|bool
-
-  - name: stop docker-compose
-    docker_compose:
-      project_src: '{{lemmy_base_dir}}/{{domain}}'
-      state: absent
-
-  - name: delete data
-    file:
-      path: '{{item.path}}'
-      state: absent
-    with_items:
-      - path: '{{lemmy_base_dir}}/{{domain}}'
-      - path: '/etc/nginx/sites-enabled/{{domain}}.conf'
-
-  - name: remove certbot cronjob
-    cron:
-      name: certbot-renew-lemmy
-      state: absent
-
+    - name: end play if no confirmation was given
+      debug:
+        msg: "Uninstall cancelled, doing nothing"
+      when: not confirm_uninstall|bool
+
+    - meta: end_play
+      when: not confirm_uninstall|bool
+
+    - name: stop docker-compose
+      docker_compose:
+        project_src: "{{lemmy_base_dir}}/{{domain}}"
+        state: absent
+
+    - name: delete data
+      file:
+        path: "{{item.path}}"
+        state: absent
+      with_items:
+        - path: "{{lemmy_base_dir}}/{{domain}}"
+        - path: "/etc/nginx/sites-enabled/{{domain}}.conf"
+
+    - name: remove certbot cronjob
+      cron:
+        name: certbot-renew-lemmy
+        state: absent