Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tutorial: How to properly configure reverse proxy with Nginx Proxy Manager and Trilium(both deployed using docker) #4910

Open
WeskerC opened this issue Feb 18, 2025 · 4 comments

Comments

@WeskerC
Copy link

WeskerC commented Feb 18, 2025

This is a TUTORIAL for setting up reverse proxy for the Trilium Notes application using Nginx(through Nginx Proxy Manager), if you are merely using Nginx you can also benefit from reading this post.

AND This post will make your ONLINE Trilium Note Application more secured, only if you care about safety issues ;)

As a newbie, I tried hundreds of hours trying to figure out the mechanisms between Nginx and Trilium Notes, and I have also failed multiple times using the default Nginx setting provided (because there is a "Express" node-js app issue in the backend). But now I have gained more knowledge about computers and want to share it with you guys so that saves you precious time if you want to secure your Trilium Notes application when deploying online.

The exact problem I faced is that the Note container is not able to recognize the visitor's real IP address after Nginx reverse proxy, it will only show the local IP address of Nginx Proxy Manager(172.x.x.x) instead of the visitor's IP, which makes the rate-limit function not working properly, and the brutal bypass setting will also block normal users.

Solution:

  1. Make sure that your Nginx is correctly forwarding the real IP. In my case, I put the following codes in the "Advanced Setting" in Nginx Proxy Manager host:
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://**[the local IP address of the Trilium app]**:8080;
proxy_redirect off;
}

Image

  1. Access the backend of the Trilium App. In my case, it is deployed using docker so I use docker exec -it trilium sh.
    2.1 add the following command inside the app.js file using vi ./src/app.js and add app.set('trust proxy', true); into the file on line 18:
    (ps if you don't know how to edit using vi, please google it)
    The result looks like:
    Image
    2.2 add the following command in the rate-limit file to suppress /usr/src/app/src/routes/routes.js validation error:
    trustProxy: 1,
    Image

Then basically everything will work smoothly, and the reason why step 1 is not enough for the reverse proxy is that the Note app is also using a JS app called "Express" to provide many functions, and if trust proxy is not enabled, it will only forward the Nginx proxy IP.

Also if you have several layers of reverse proxies, make sure to test and exchange the correct number with x in the command app.set('trust proxy', **x** );

This is the end, hope it helps!

@Makarov3821
Copy link

That's a great help. I'm using trilium from packaged server and nginx from ubuntu, I found changing only in 2.1 can make real ip in trilium log instead of 127.0.0.1, which is enough for my fail2ban setup. Many thanks!

@WeskerC
Copy link
Author

WeskerC commented Feb 20, 2025

That's a great help. I'm using trilium from packaged server and nginx from ubuntu, I found changing only in 2.1 can make real ip in trilium log instead of 127.0.0.1, which is enough for my fail2ban setup. Many thanks!

Glad that it helps! I am also wondering how to protect Trulium notes app from brutal force attacks and Zadam says it already has a 15 minutes rate-limit with a 10-try-per-time rules to block, but it was not enough for me.

Did you output the trilium note log to the system log to enable fail2ban? I am curious about how you set it up.

Cheers

@Makarov3821
Copy link

Glad that it helps! I am also wondering how to protect Trulium notes app from brutal force attacks and Zadam says it already has a 15 minutes rate-limit with a 10-try-per-time rules to block, but it was not enough for me.

Did you output the trilium note log to the system log to enable fail2ban? I am curious about how you set it up.

Cheers

Nope. As for me, I have been switching the setup between package and docker for several times, thus I have a seperate trilium-data dir to mount if I use docker. Trilium itself creates log daily in log:

trilium-data/
├── backup
│   ├── backup-before-migration-v060.db
│   ├── backup-before-migration.db
│   ├── backup-daily.db
│   ├── backup-monthly.db
│   └── backup-weekly.db
├── config.ini
├── document.db
├── document.db-shm
├── document.db-wal
└── log
     ├── trilium-2025-02-19.log
     ├── trilium-2025-02-20.log
     └── trilium.log -> /root/trilium/trilium-data/log/trilium-2025-02-20.log

The symlink is created manually cuz fail2ban won't refresh log files name as it started, but trilium creates logs by date. I have a script to change it:

#!/bin/bash

#get the date
date=$(date +%Y-%m-%d)
#turn the newest log link to it
if [ ! -f /root/trilium/trilium-data/log/trilium-$date.log ]; then
    touch /root/trilium/trilium-data/log/trilium-$date.log
fi
if [ -f /root/trilium/trilium-data/log/trilium.log ]; then
    rm /root/trilium/trilium-data/log/trilium.log;
fi
ln -s /root/trilium/trilium-data/log/trilium-$date.log /root/trilium/trilium-data/log/trilium.log;

and do it regularly by crontab:
5 0 * * * bash /root/trilium/trilium-data/refresh_log_link.sh
can creates suitable log for fail2ban.

When someone put a wrong password, the attacker's ip will be logged in like:
WARNING: Wrong password from xxx.xxx.xxx.xxx, rejecting.
thus you can setup a new filter for fail2ban, I named it trilium-login.conf:

[INCLUDES]
before = common.conf

[Definition]

failregex = ^.*?Wrong password from <ADDR>, rejecting.*$
ignoreregex =

and for my jail.local:

[trilium-login]
enabled = true
backend = pyinotify
port = 80,443
filter = trilium-login
logpath = /root/trilium/trilium-data/log/trilium.log
maxretry = 5
bantime = 5h
findtime = 1h

now for someone failed 5 time in 1hr, fail2ban will ban him for 5hrs, for more failed attempts fail2ban will increase its bantime.

I'm also imitating the way in vaultwarden, you can also referring some setup in official setup, hoping it will help.

@WeskerC
Copy link
Author

WeskerC commented Feb 21, 2025

@Makarov3821 Thank you for providing these details for me Makarov, I just learnt from you that Trilium Notes generates logs using separate dates~ Really helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants