[nginx] Default avatar for missing images after migration

  • I'll make this as simple as it can be, after importing your forum it might come a problem when you see some of your users avatars broken, here's a simple method to set a placeholder image for missing images.

    • First you have to upload your default image anywhere on the public directory, I would suggest in public/uploads/default.png, the full path should be /path/to/nodebb/public/uploads/default.png.

    • Now you have to get the default avatar directory for your imported forum, to get this path right click on the avatar of your broken user and click copy image location, paste it in a text file, in my case it was example.com/assets/uploads/xenforo/data/avatars/m/0/84.jpg so the path should be the folder containing all avatars /uploads/xenforo/data/avatars you have to lose the assets folder from the path.

    • In your nginx conf add this block under the main block /:

      location /uploads/xenforo/data/avatars {
        try_files $uri /uploads/xenforo/data/avatars/default.png;

      Full nginx conf should look something like this:

      upstream nodebb {
      server {
        server_name example.com www.example.com;
        root /path/to/nodebb/public;
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;
            proxy_pass http://nodebb;
            proxy_redirect off;
            # Socket.IO Support
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            location /uploads/xenforo/data/avatars {
              try_files $uri /uploads/xenforo/data/avatars/default.png;

    Hope this helps someone. 🙂

Suggested Topics

  • 5 Votes
    1 Posts

    Hi everybody 🌴

    Today I show you how to make a sticky brand header and avatars in Harmony.



    We need modify 6 files: library.js, harmony.json, theme.tpl, harmony.tpl, brand.tpl, post.tpl to add 3 new settings:

    Sticky avatars (user avatars in the posts) Sticky header (brand header) Setting to show sticky header on mobile devices

    First we add a new settings in library.js

    Paste this code after this line stickyAvatars: 'on', stickyHeader: 'off', stickyHeaderMobile: 'off', Paste this code after this line config.stickyAvatars = config.stickyAvatars === 'on'; config.stickyHeader = config.stickyHeader === 'on'; config.stickyHeaderMobile = config.stickyHeaderMobile === 'on';

    Now we need add translation for the new settings in harmony.json

    Paste this code after this line "settings.stickyAvatars": "Sticky user avatars in posts", "settings.stickyHeader": "Sticky header on desktop", "settings.stickyHeaderMobile": "Show sticky header on mobile",

    Next step, create controls of new settings in ACP and user profile in harmony.tpl and theme.tpl

    Paste this code after this line in harmony.tpl <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" id="stickyAvatars" name="stickyAvatars" /> <label for="stickyAvatars" class="form-check-label">settings.stickyAvatars</label> </div> <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" id="stickyHeader" name="stickyHeader" /> <label for="stickyHeader" class="form-check-label">settings.stickyHeader</label> </div> <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" id="stickyHeaderMobile" name="stickyHeaderMobile" /> <label for="stickyHeaderMobile" class="form-check-label">settings.stickyHeaderMobile</label> </div> Paste this code after this line in theme.tpl <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" id="stickyAvatars" name="stickyAvatars" {{{ if config.theme.stickyAvatars }}}checked{{{ end }}}> <label class="form-check-label" for="stickyAvatars">settings.stickyAvatars</label> </div> <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" id="stickyHeader" name="stickyHeader" {{{ if config.theme.stickyHeader }}}checked{{{ end }}}> <label class="form-check-label" for="stickyHeader">settings.stickyHeader</label> </div> <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" id="stickyHeaderMobile" name="stickyHeaderMobile" {{{ if config.theme.stickyHeaderMobile }}}checked{{{ end }}}> <label class="form-check-label" for="stickyHeaderMobile">settings.stickyHeaderMobile</label> </div>

    The finally we modify a theme files post.tpl and brand.tpl

    Replace the code in this line with a new code in post.tpl <div class="icon py-1 bg-body d-none d-sm-block {{{ if config.theme.stickyAvatars }}}position-sticky{{{end}}}" {{{ if config.theme.stickyAvatars }}}style="top:7.5rem;"{{{end}}}> Replace the code in this line with a new code in brand.tpl <div class="container px-md-4 brand-container {{{ if config.theme.stickyHeaderMobile }}}sticky-top{{{end}}} {{{ if config.theme.stickyHeader }}}sticky-lg-top bg-body pt-3{{{end}}}" {{{ if config.theme.stickyHeader }}}style="margin-top:-1rem;"{{{end}}}>

    /.nodebb build

    🖖 Happy Dev

  • 0 Votes
    1 Posts

    I have nginx proxying to nodebb, from a /forum/ location.

    I wanted to serve up static contents with nginx - the example here - https://docs.nodebb.org/en/latest/scaling/#use-a-proxy-server-to-serve-static-assets assumes you have the forum running off the root. If running from a subfolder, it can be simplified to this (the public folder is tried first, followed by the proxy if no file exists).

    Here's my config using nginx to serve up the static content (just the locations/configs for nodebb included, I have a wordpress site running of the htdocs root)

    upstream io_nodes { ip_hash; server; # upstream nodebb servers here } server { listen 443 default_server ssl; listen [::]:443 default_server ssl; server_name your.site; root /webroot/of/site; index index.html index.php; location /forum { alias /path/to/nodebb/public; try_files $uri @nodebb; } location @nodebb { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_redirect off; # Socket.IO Support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://io_nodes; } }
  • 0 Votes
    3 Posts

    Nice tutorial! Good to know iptables can be used to forward ports like this.

    I do believe NodeBB can be configured to terminate SSL certificates, but it hasn't been done in awhile because we much prefer nginx 😄

  • 3 Votes
    6 Posts

    Bringing an old thread to life again, sorry!

    I'd also love some help with the instructions for running this in a Docker image. It would make life a bit easier for deploying this in DigitalOcean.

  • 7 Votes
    12 Posts

    @alphagao link me whatever guide you're using. If you don't know what to do, use this guide:

    Ubuntu (Recommended) - NodeBB Documentation