zadam / trilium

Build your personal knowledge base with Trilium Notes
GNU Affero General Public License v3.0
27.2k stars 1.9k forks source link

Sync doesn't work with domain name. it works with IP. #1376

Closed n-andreev closed 2 years ago

n-andreev commented 3 years ago

Hey. I have 0.44.5 on my laptop (Ubuntu 20.04) and the same version on "server".

My schema: Cloudflare [https] -> nginx [https/let's encypt] -> trilium [http] Things work except sync.

Everythink is ok with sync, but only when I use http://public_IP_or_local_IP/trilium in settings. Once I set it to http[s]://domain/trilium - sync doesn't work

I will try to attach a lot of logs/configs: server side:

[Network] host=127.0.0.1 port=8080 https=false certPath= keyPath=

- nginx virtualhost

server {

server_name mydomain 192.168.1.222;

listen 80;

listen 443 ssl; # managed by Certbot

# RSA certificate
ssl_certificate /etc/letsencrypt/live/mydomain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain/privkey.pem; # managed by Certbot

include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

location /.well-known { root /tmp; auth_basic off; }

client_max_body_size 100M;

location /trilium/ { auth_basic off; proxy_pass http://127.0.0.1:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }

}

- nginx log

[02/Nov/2020:23:49:45 +0200] "GET /trilium/api/setup/status HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) TriliumNotes/0.44.5 Chrome/83.0.4103.122 Electron/9.3.1 Safari/537.36" ip- - [02/Nov/2020:23:49:45 +0200] "POST /trilium/api/login/sync HTTP/1.1" 200 52 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) TriliumNotes/0.44.5 Chrome/83.0.4103.122 Electron/9.3.1 Safari/537.36" ip - - [02/Nov/2020:23:49:45 +0200] "GET /trilium/api/sync/changed?lastEntityChangeId=1418 HTTP/1.1" 401 14 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) TriliumNotes/0.44.5 Chrome/83.0.4103.122 Electron/9.3.1 Safari/537.36"

- trilium log

21:33:13.080 DB size: 2052 KB 21:33:20.787 App HTTP server starting up at port 8080 21:33:20.788 { "appVersion": "0.44.5", "dbVersion": 170, "syncVersion": 16, "buildDate": "2020-10-01T23:45:09+02:00", "buildRevision": "8f018cc7c69257bbd11590e41e267872e19d7bb6", "dataDirectory": "/some/path/trilium-data", "clipperProtocolVersion": "1.0" } 21:33:20.792 CPU model: ARMv7 Processor rev 4 (v7l), logical cores: 3 freq: 988 Mhz 21:33:20.893 Listening on port 8080 21:34:47.020 Notes deleted: 14, not deleted 154 21:34:47.031 Note revisions deleted: 0, not deleted 12 21:34:47.034 Branches deleted: 21, not deleted 176 21:34:47.036 Attributes deleted: 2, not deleted 231 21:34:47.038 API tokens deleted: 0, not deleted 0 21:34:47.097 Slow query took 37ms: SELECT noteId FROM notes JOIN note_contents USING (noteId) WHERE isDeleted = 0 AND isProtected = 0 AND content IS NULL 21:34:47.151 All consistency checks passed (took 135ms) 21:38:30.105 Generated CSRF token KQfBpNM1-mavpzoXF9G9OnsLEhcdBcOBik18 with secret undefined 21:38:33.119 Slow GET / took 3026ms 21:38:34.822 Slow GET /api/options took 12ms 21:38:34.905 Slow GET /api/tree took 44ms 21:38:34.955 GET /api/keyboard-shortcuts-for-notes took 6ms 21:38:34.987 Slow GET /api/keyboard-actions took 19ms 21:38:35.006 Slow GET /api/notes/download/MwAkWACPN28p took 14ms 21:38:35.025 Slow GET /api/script/widgets took 16ms 21:38:35.118 Slow GET /api/notes/download/RvNAtbVelWEx took 11ms 21:38:36.671 Slow GET /api/notes/iEombNwnY0r7 took 15ms 21:38:38.072 Slow GET /api/notes/iEombNwnY0r7/revisions took 22ms 21:38:38.126 Slow GET /api/script/startup took 14ms 21:38:41.449 Slow GET /api/similar-notes/iEombNwnY0r7 took 3315ms 21:38:47.187 GET /api/setup/status took 5ms 21:38:47.388 Slow POST /api/login/sync took 16ms 21:38:47.510 PUT /api/sync/update rejected with 401 Not authorized 21:39:44.067 GET /api/setup/status took 6ms 21:39:44.123 POST /api/login/sync took 6ms 21:39:44.182 PUT /api/sync/update rejected with 401 Not authorized 21:40:44.706 GET /api/setup/status took 5ms 21:40:45.834 POST /api/login/sync took 5ms 21:40:45.896 PUT /api/sync/update rejected with 401 Not authorized ...

CHANGED to IP

22:14:35.027 GET /api/setup/status took 6ms 22:14:35.059 POST /api/login/sync took 5ms 22:14:35.069 GET /api/setup/status took 4ms 22:14:35.099 Slow POST /api/login/sync took 10ms 22:14:35.185 Slow PUT /api/sync/update took 43ms 22:14:35.234 Returning 21 entity changes in 9ms 22:14:35.238 Slow GET /api/sync/changed?lastEntityChangeId=1396 took 14ms 22:14:35.279 GET /api/sync/changed?lastEntityChangeId=1418 took 4ms 22:14:35.319 POST /api/sync/finished took 4ms 22:14:35.395 Content hash computation took 40ms 22:14:35.399 Slow GET /api/sync/check took 46ms 22:14:44.029 GET /api/setup/status took 4ms 22:14:44.210 POST /api/login/sync took 5ms 22:14:44.247 GET /api/sync/changed?lastEntityChangeId=1418 took 6ms 22:14:44.414 POST /api/sync/finished took 4ms 22:14:44.653 Content hash computation took 37ms


**client side:**
- trilium logs

1:38:43.168 DB size: 2068 KB 21:38:44.820 App HTTP server starting up at port 37840 21:38:44.820 { "appVersion": "0.44.5", "dbVersion": 170, "syncVersion": 16, "buildDate": "2020-10-01T23:45:09+02:00", "buildRevision": "8f018cc7c69257bbd11590e41e267872e19d7bb6", "dataDirectory": "/some/path/.local/share/trilium-data", "clipperProtocolVersion": "1.0" } 21:38:44.837 CPU model: Intel(R) Core(TM) i3-8130U CPU @ 2.20GHz, logical cores: 4 freq: 1999 Mhz 21:38:44.842 Listening on port 37840 21:38:44.957 Registered global shortcut Ctrl+Alt+P for action createNoteIntoDayNote 21:38:45.056 Generated CSRF token J0Jc9xoJ-rUMwmmUYktC9tXwBNbTKQTFnafg with secret _csrf=PPSWha2dt9Ij6CGH0msXm7AA; Path=/ 21:38:45.086 Slow GET / took 32ms 21:38:45.350 GET /api/options took 2ms 21:38:45.356 GET /api/tree took 5ms 21:38:45.362 GET /api/keyboard-actions took 2ms 21:38:45.365 GET /api/keyboard-shortcuts-for-notes took 0ms 21:38:45.369 GET /api/notes/download/MwAkWACPN28p took 2ms 21:38:45.372 GET /api/script/widgets took 2ms 21:38:45.374 GET /api/notes/download/RvNAtbVelWEx took 1ms 21:38:45.984 GET /api/notes/mpNtgHi9LoGT took 6ms 21:38:47.339 Slow GET /api/similar-notes/mpNtgHi9LoGT took 357ms 21:38:47.346 GET /api/notes/mpNtgHi9LoGT/revisions took 3ms 21:38:47.462 GET /api/script/startup took 3ms 21:38:47.468 POST /api/tree/load took 2ms 21:38:47.478 POST /api/tree/load took 3ms 21:38:47.490 POST /api/tree/load took 4ms 21:38:47.501 POST /api/tree/load took 3ms 21:38:48.249 sync failed: Request to PUT https://domain/trilium/api/sync/update failed, error: 401 stack: Error: Request to PUT https://domain/trilium/api/sync/update failed, error: 401 at generateError (/usr/lib/trilium/resources/app.asar/src/services/request.js:174:12) at ClientRequest. (/usr/lib/trilium/resources/app.asar/src/services/request.js:53:28) at ClientRequest.emit (events.js:223:5) at SimpleURLLoaderWrapper. (electron/js2c/browser_init.js:93:6152) at SimpleURLLoaderWrapper.emit (events.js:223:5) 21:38:48.252 ERROR: Failed to deserialize sync response: Not authorized 21:38:50.975 POST /api/recent-notes took 9ms 21:38:53.521 GET /api/backend-log took 3ms 21:39:04.598 Notes deleted: 14, not deleted 154 21:39:04.599 Note revisions deleted: 0, not deleted 12 21:39:04.600 Branches deleted: 21, not deleted 176 21:39:04.600 Attributes deleted: 2, not deleted 231 21:39:04.601 API tokens deleted: 0, not deleted 0 21:39:04.630 All consistency checks passed (took 32ms) 21:39:45.390 sync failed: Request to PUT https://domain/trilium/api/sync/update failed, error: 401 stack: Error: Request to PUT https://domain/trilium/api/sync/update failed, error: 401 at generateError (/usr/lib/trilium/resources/app.asar/src/services/request.js:174:12) at ClientRequest. (/usr/lib/trilium/resources/app.asar/src/services/request.js:53:28) at ClientRequest.emit (events.js:223:5) at SimpleURLLoaderWrapper. (electron/js2c/browser_init.js:93:6152) at SimpleURLLoaderWrapper.emit (events.js:223:5) 21:39:45.393 ERROR: Failed to deserialize sync response: Not authorized 21:40:46.431 sync failed: Request to PUT https://domain/trilium/api/sync/update failed, error: 401 stack: Error: Request to PUT https://domain/trilium/api/sync/update failed, error: 401 at generateError (/usr/lib/trilium/resources/app.asar/src/services/request.js:174:12) at ClientRequest. (/usr/lib/trilium/resources/app.asar/src/services/request.js:53:28) at ClientRequest.emit (events.js:223:5) at SimpleURLLoaderWrapper. (electron/js2c/browser_init.js:93:6152) at SimpleURLLoaderWrapper.emit (events.js:223:5) 21:40:46.434 ERROR: Failed to deserialize sync response: Not authorized ...

CHANGED to IP

2:14:34.230 Updating option syncServerHost to http://public_IP/trilium 22:14:34.231 Updating option syncServerTimeout to 60000 22:14:34.231 Updating option syncProxy to 22:14:34.233 PUT /api/options took 4ms 22:14:35.326 POST /api/sync/test took 2ms 22:14:35.975 Pushing 20 sync changes in 82ms 22:14:35.977 Nothing to push 22:14:36.027 Sending message to all clients: {"type":"sync-pull-in-progress"} 22:14:36.031 Pulled 21 changes starting at entityChangeId=1396 in 48ms and applied them in 5ms, 0 outstanding pulls 22:14:36.072 Sending message to all clients: {"type":"sync-pull-finished"} 22:14:36.073 Finished pull 22:14:36.077 Nothing to push 22:14:36.210 Content hash computation took 18ms 22:14:36.211 Content hash checks PASSED 22:14:40.031 GET /api/backend-log took 5ms 22:14:45.424 Nothing to push 22:14:45.594 Finished pull 22:14:45.594 Nothing to push 22:14:46.017 Content hash computation took 12ms 22:14:46.018 Content hash checks PASSED 22:15:45.432 Nothing to push 22:15:45.601 Finished pull 22:15:45.601 Nothing to push 22:15:46.020 Content hash computation took 9ms 22:15:46.021 Content hash checks PASSED



@zadam Please let me know if you need any extra info
Thanks
zadam commented 3 years ago

If IP works but host name doesn't then it's probably something with DNS resolution. I don't think the problem lies in Trilium since DNS resolution is not handled on the application level ...

n-andreev commented 3 years ago

I agree. But DNS is ok, since client can reach the server. The problem that exactly trilium returns back 401 error. Any ideas where can be a problem? Is there any super debug switch? I've tried almost everything.

elementc commented 3 years ago

I can't point to any one particular directive, and none seem auth-related, but your nginx config is missing some items that I'm using successfully on mine.

    location <snip> {
        proxy_http_version        1.1;
        proxy_pass                <snip>;
        proxy_set_header          Host                     $http_host;
        proxy_set_header          X-Real-IP                $remote_addr;
        proxy_set_header          X-Forwarded-For          $proxy_add_x_forwarded_for;
        proxy_set_header          Upgrade                  $http_upgrade;
        proxy_set_header          Connection               "upgrade";
        proxy_connect_timeout     60s;
        proxy_send_timeout        60s;
        proxy_read_timeout        60s;
        client_max_body_size      5M;
    }
n-andreev commented 3 years ago

Hey @elementc, I've already tried these directives, just tried it one more time (X-Real-IP and X-Forwarded_for headers), but it didn't help.

liamzdenek commented 3 years ago

I am having the same issue as OP @n-andreev, but with a slightly different server error as this is occuring for me during client setup. I am using cloudflare as well, but the issue appears to be independent of whether cloudflare proxying is used. I am not using a nginx proxy, and I am using SSL on with a client certificate from cloudflare.

My error:

GET /api/sync/changed rejected with 401 Not authorized  

Op's error:

21:40:45.896 PUT /api/sync/update rejected with 401 Not authorized

I did some debugging, and I see that in routes/routes.js, both of these routes are protected with auth.checkApiAuth, which causes me to believe they are the same root cause.

    route(GET, '/api/sync/changed', [auth.checkApiAuth], syncApiRoute.getChanged, apiResultHandler);
    route(PUT, '/api/sync/update', [auth.checkApiAuth], syncApiRoute.update, apiResultHandler);

I modified checkApiAuth with some debug at the top...

function checkApiAuth(req, res, next) {                    
    console.log('req.session', req.session);               
    console.log('cookies', req.headers.cookie.split('; '));
    console.log('host header', req.headers.host);          
    console.log('logged in', req.session.loggedIn);        
    if (!req.session.loggedIn && !noAuthentication) {      
        reject(req, res, "Not authorized");                
    }                                                      
    else {                                                 
        next();                                            
    }                                                      
}                                                          

... and i see the following output (mydomain.com replaced with example.com):

req.session Session {                                                                                             
  cookie: {                                                                                                       
    path: '/',                                                                                                    
    _expires: 2020-12-18T04:37:26.598Z,                                                                           
    originalMaxAge: 86400000,                                                                                     
    httpOnly: true                                                                                                
  }                                                                                                               
}                                                                                                                 
cookies [                                                                                                         
  '__cfduid=debc2f3bdedc93f33568f8b8db70b89f71608179846',                                                         
  'expires=Sat, 16-Jan-21 04:37:26 GMT',                                                                          
  'path=/',                                                                                                       
  'domain=.example.com',                                                                                         
  'HttpOnly',                                                                                                     
  'SameSite=Lax,connect.sid=s%3AN243BzaRxntQ_A3V0IhnOJS-MRzpLPht.68gKePru6kxo8x%2BUoJvSV9SwIcXyShBECC%2FlSX927Lk',
  'Path=/',                                                                                                       
  'Expires=Fri, 18 Dec 2020 04:37:26 GMT',                                                                        
  'HttpOnly'                                                                                                      
]                                                                                                                 
host header trillium.example.com:8443                                                                            
logged in undefined                                                                                               
GET /api/sync/changed rejected with 401 Not authorized                                                            

I conclude from this that Trilium believes this user is not logged in despite receiving a cookie header. This is unusual because I did nothing out of the ordinary to generate this session. The session was generated only a short time before the call to the API endpoint, so it could not be expired.

I see that the cookie header contains the SID N243BzaRxntQ_A3V0IhnOJS-MRzpLPht. In the data directory, in the sessions folder (~/.local/share/trilium-data/sessions), I see a file named N243BzaRxntQ_A3V0IhnOJS-MRzpLPht.json, with the following contents:

{"cookie":{"originalMaxAge":86400000,"expires":"2020-12-18T04:37:26.339Z","httpOnly":true,"path":"/"},"loggedIn":true,"__lastAccess":1608179846339}

So, this cookie is logged in. So, I tried to figure out why the session wasn't being loaded. I see that you are using express-session. I am not very familiar with this library, but I see that it uses the debug library, so I turned that on by launching Trilium with the command: DEBUG="*" ./node/bin/node src/www

I see the following additional output (among other, redacted/irrelevant output). This appears just prior to the log modifications I made to checkApiAuth:

express-session no SID sent, generating session +256ms   

I read through the express session documentation at a surface level, and then read through the source code a bit, but I can't find a place to check if the session loading/cookie parsing is occurring properly, or if some validation is silently failing, so I'm a bit stuck on debugging this further. Further insight would be appreciated.

zadam commented 3 years ago

Hi @liamzdenek, thanks for detailed report.

I think the problem lies in SameSite=Lax,connect.sid, I don't think comma is a valid cookie separator so cookie parser is not able to read the SID and does not use existing session.