notesnook-sync-server icon indicating copy to clipboard operation
notesnook-sync-server copied to clipboard

Noob-Friendly Setup Tutorial

Open Tiritibambix opened this issue 10 months ago • 10 comments

Hello.

There is no discussion section, so I am posting this here. I wanted to self-host a Notesnook sync server really badly, but I'm a noob. So, I worked hard on it and came up with this noob-proof tutorial on how to set up a Notesnook sync server with local file storage, getting inspiration from the provided docker-compose in the repository.

That's my way of giving back to the self-hosting community. I hope it can help some people.

Devs, please correct me if needed.


Overview

This guide will help you set up a self-hosted instance of Notesnook using Docker Compose.


Prerequisites

  • Linux server with Docker and Docker Compose installed.
  • Domain name with the ability to create subdomains.
  • Basic understanding of terminal commands.
  • Ports 5264, 6264, 7264, 8264, 9090 and 9009 available. Or you can change them but take good note of your changes.

1. Directory Structure Setup

Create the required directories:

# Create data directories
mkdir -p /srv/Files/Notesnook/db
mkdir -p /srv/Files/Notesnook/s3
mkdir -p /srv/Files/Notesnook/setup

2. Configuration Files

2.1. Environment File

Create the .env file:

cd /srv/Files/Notesnook/setup
nano .env

Add the following content (modify the values accordingly):

# Instance Configuration
INSTANCE_NAME=My Notesnook
DISABLE_SIGNUPS=false
NOTESNOOK_API_SECRET=your_secure_api_secret_here

# SMTP Configuration
[email protected]
SMTP_PASSWORD=your_smtp_password
SMTP_HOST=smtp.your-server.com
SMTP_PORT=587

# Public URLs (replace domain.com with your domain)
AUTH_SERVER_PUBLIC_URL=https://auth.domain.com/
NOTESNOOK_APP_PUBLIC_URL=https://notes.domain.com/
MONOGRAPH_PUBLIC_URL=https://mono.domain.com/
ATTACHMENTS_SERVER_PUBLIC_URL=https://files.domain.com/

# MinIO Configuration
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=your_secure_password_here

2.2. Docker Compose File

Create the docker-compose.yml file:

nano docker-compose.yml

Paste the following content:

x-server-discovery: &server-discovery
  NOTESNOOK_SERVER_PORT: 5264
  NOTESNOOK_SERVER_HOST: notesnook-server
  IDENTITY_SERVER_PORT: 8264
  IDENTITY_SERVER_HOST: identity-server
  SSE_SERVER_PORT: 7264
  SSE_SERVER_HOST: sse-server
  SELF_HOSTED: 1
  IDENTITY_SERVER_URL: ${AUTH_SERVER_PUBLIC_URL}
  NOTESNOOK_APP_HOST: ${NOTESNOOK_APP_PUBLIC_URL}

x-env-files: &env-files
  - .env

services:
  validate:
    image: vandot/alpine-bash
    entrypoint: /bin/bash
    env_file: *env-files
    command:
      - -c
      - |
        required_vars=(
          "INSTANCE_NAME"
          "NOTESNOOK_API_SECRET"
          "DISABLE_SIGNUPS"
          "SMTP_USERNAME"
          "SMTP_PASSWORD"
          "SMTP_HOST"
          "SMTP_PORT"
          "AUTH_SERVER_PUBLIC_URL"
          "NOTESNOOK_APP_PUBLIC_URL"
          "MONOGRAPH_PUBLIC_URL"
          "ATTACHMENTS_SERVER_PUBLIC_URL"
        )
        for var in "$${required_vars[@]}"; do
          if [ -z "$${!var}" ]; then
            echo "Error: Required environment variable $$var is not set."
            exit 1
          fi
        done
        echo "All required environment variables are set."
    restart: "no"

  notesnook-db:
    image: mongo:7.0.12
    hostname: notesnook-db
    volumes:
      - /srv/Files/Notesnook/db:/data/db
      - /srv/Files/Notesnook/db:/data/configdb
    networks:
      - notesnook
    command: --replSet rs0 --bind_ip_all
    depends_on:
      validate:
        condition: service_completed_successfully
    healthcheck:
      test: echo 'db.runCommand("ping").ok' | mongosh mongodb://localhost:27017 --quiet
      interval: 40s
      timeout: 30s
      retries: 3
      start_period: 60s

  initiate-rs0:
    image: mongo:7.0.12
    networks:
      - notesnook
    depends_on:
      - notesnook-db
    entrypoint: /bin/sh
    command:
      - -c
      - |
        mongosh mongodb://notesnook-db:27017 <<EOF
          rs.initiate();
          rs.status();
        EOF

  notesnook-s3:
    image: minio/minio:RELEASE.2024-07-29T22-14-52Z
    ports:
      - 9009:9000
      - 9090:9090
    networks:
      - notesnook
    volumes:
      - /srv/Files/Notesnook/s3:/data/s3
    environment:
      MINIO_BROWSER: "on"
    depends_on:
      validate:
        condition: service_completed_successfully
    env_file: *env-files
    command: server /data/s3 --console-address :9090
    healthcheck:
      test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1
      interval: 40s
      timeout: 30s
      retries: 3
      start_period: 60s

  setup-s3:
    image: minio/mc:RELEASE.2024-07-26T13-08-44Z
    depends_on:
      - notesnook-s3
    networks:
      - notesnook
    entrypoint: /bin/bash
    env_file: *env-files
    command:
      - -c
      - |
        until mc alias set minio http://notesnook-s3:9000/ ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin}; do
          sleep 1;
        done;
        mc mb minio/attachments -p

  identity-server:
    image: streetwriters/identity:latest
    ports:
      - 8264:8264
    networks:
      - notesnook
    env_file: *env-files
    depends_on:
      - notesnook-db
    healthcheck:
      test: wget --tries=1 -nv -q  http://localhost:8264/health -O- || exit 1
      interval: 40s
      timeout: 30s
      retries: 3
      start_period: 60s
    environment:
      <<: *server-discovery
      MONGODB_CONNECTION_STRING: mongodb://notesnook-db:27017/identity?replSet=rs0
      MONGODB_DATABASE_NAME: identity

  notesnook-server:
    image: streetwriters/notesnook-sync:latest
    ports:
      - 5264:5264
    networks:
      - notesnook
    env_file: *env-files
    depends_on:
      - notesnook-s3
      - setup-s3
      - identity-server
    healthcheck:
      test: wget --tries=1 -nv -q  http://localhost:5264/health -O- || exit 1
      interval: 40s
      timeout: 30s
      retries: 3
      start_period: 60s
    environment:
      <<: *server-discovery
      MONGODB_CONNECTION_STRING: mongodb://notesnook-db:27017/?replSet=rs0
      MONGODB_DATABASE_NAME: notesnook
      S3_INTERNAL_SERVICE_URL: "http://notesnook-s3:9000/"
      S3_INTERNAL_BUCKET_NAME: "attachments"
      S3_ACCESS_KEY_ID: "${MINIO_ROOT_USER:-minioadmin}"
      S3_ACCESS_KEY: "${MINIO_ROOT_PASSWORD:-minioadmin}"
      S3_SERVICE_URL: "${ATTACHMENTS_SERVER_PUBLIC_URL}"
      S3_REGION: "us-east-1"
      S3_BUCKET_NAME: "attachments"

  sse-server:
    image: streetwriters/sse:latest
    ports:
      - 7264:7264
    env_file: *env-files
    depends_on:
      - identity-server
      - notesnook-server
    networks:
      - notesnook
    healthcheck:
      test: wget --tries=1 -nv -q  http://localhost:7264/health -O- || exit 1
      interval: 40s
      timeout: 30s
      retries: 3
      start_period: 60s
    environment:
      <<: *server-discovery

  monograph-server:
    image: streetwriters/monograph:latest
    ports:
      - 6264:3000
    env_file: *env-files
    depends_on:
      - notesnook-server
    networks:
      - notesnook
    healthcheck:
      test: wget --tries=1 -nv -q  http://localhost:3000/api/health -O- || exit 1
      interval: 40s
      timeout: 30s
      retries: 3
      start_period: 60s
    environment:
      <<: *server-discovery
      API_HOST: http://notesnook-server:5264/
      PUBLIC_URL: ${MONOGRAPH_PUBLIC_URL}

networks:
  notesnook:

3. Docker Images Preparation

Pull all required images to avoid timeout issues:

cd /srv/Files/Notesnook/setup
docker pull mongo:7.0.12
docker pull minio/minio:RELEASE.2024-07-29T22-14-52Z
docker pull streetwriters/identity:latest
docker pull streetwriters/notesnook-sync:latest
docker pull streetwriters/sse:latest
docker pull streetwriters/monograph:latest
docker pull vandot/alpine-bash

or just

cd /srv/Files/Notesnook/setup
docker compose pull

4. Deployment

Start the services:

cd /srv/Files/Notesnook/setup
docker compose up -d

5. Service Verification

5.1. Check Container Status

docker compose ps

Expected status:

  • Running containers:
    • notesnook-db
    • notesnook-s3
    • identity-server
    • notesnook-server
    • sse-server
    • monograph-server
  • Completed containers (should show Exit 0):
    • validate
    • initiate-rs0
    • setup-s3

5.2. Check Logs

docker compose logs

5.3. Test MinIO Access

Visit: http://your-server:9009/


6. Reverse Proxy Configuration with Nginx and SSL

Enable WebSockets Support for: notes.domain.com (port 5264) - For real-time synchronization
events.domain.com (port 7264) - For real-time notifications

Enable Cache Assets for: mono.domain.com (port 6264) - For optimizing public notes loading

Step 1: Install Certbot

sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx

Step 2: Obtain SSL Certificates

sudo certbot --nginx -d auth.domain.com -d notes.domain.com -d events.domain.com -d mono.domain.com

Step 3: Modify Nginx Configuration

Use the following example configurations for each subdomain:

# Auth Server - Basic (no cache/websocket needed)
server {
    listen 80;
    server_name auth.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name auth.domain.com;

    ssl_certificate /etc/letsencrypt/live/auth.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:8264/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Notes Server - With WebSocket
server {
    listen 80;
    server_name notes.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name notes.domain.com;

    ssl_certificate /etc/letsencrypt/live/notes.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/notes.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:5264/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

# Events Server - With WebSocket
server {
    listen 80;
    server_name events.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name events.domain.com;

    ssl_certificate /etc/letsencrypt/live/events.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/events.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:7264/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

# Monograph Server - With Cache
server {
    listen 80;
    server_name mono.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name mono.domain.com;

    ssl_certificate /etc/letsencrypt/live/mono.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mono.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:6264/;
        proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
        proxy_cache_valid 200 60m;
        add_header X-Cache-Status $upstream_cache_status;
        expires 1h;
        add_header Cache-Control "public, no-transform";
    }
}

7. Useful Commands

Service Management

# View real-time logs
docker compose logs -f

# View logs for specific service
docker compose logs [service-name]

# Restart specific service
docker compose restart [service-name]

# Stop all services
docker compose down

# Update services
docker compose pull
docker compose up -d

8. Maintenance

8.1. Backup

Regularly backup these directories:

  • /srv/Files/Notesnook/db/ (MongoDB data)
  • /srv/Files/Notesnook/s3/ (MinIO data)
  • /srv/Files/Notesnook/setup/.env (Configuration)

8.2. Updates

To update all services:

cd /srv/Files/Notesnook/setup
docker compose pull
docker compose down
docker compose up -d

9. Troubleshooting

Common Issues:

Service won't start

  • Check logs: docker compose logs [service-name]
  • Verify port availability.
  • Check directory permissions.
  • Verify environment variables.

Database Connection Issues

  • Ensure MongoDB replica set is initialized.
  • Check MongoDB logs: docker compose logs notesnook-db.

Storage Issues

  • Verify MinIO credentials.
  • Check MinIO logs: docker compose logs notesnook-s3.

Email Not Working

  • Verify SMTP settings in .env.
  • Check identity-server logs.

Security Notes

  • Change default passwords in .env.
  • Use strong passwords for MinIO and API secret.
  • Keep your .env file secure.
  • Regularly update all services.
  • Enable HTTPS on your reverse proxy.
  • Consider implementing fail2ban.
  • Regularly monitor logs for suspicious activity.

Support

If you encounter issues:

Tiritibambix avatar Jan 20 '25 19:01 Tiritibambix

Nginx is missing HTTPS configuration.

dyw770 avatar Jan 21 '25 02:01 dyw770

I use nginx proxy manager, so I might have overlooked this step. I recycled and old guide I tried to use a couple years ago. So please, correct any error.

Step 1: Install Certbot

sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx

Step 2: Obtain SSL Certificates

sudo certbot --nginx -d auth.domain.com -d notes.domain.com -d events.domain.com -d mono.domain.com

Step 3: Modify Nginx Configuration

Add SSL directives to your Nginx configuration. Here is an example of the updated configuration:

# Auth Server - Basic (no cache/websocket needed)
server {
    listen 80;
    server_name auth.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name auth.domain.com;

    ssl_certificate /etc/letsencrypt/live/auth.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:8264;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Notes Server - With WebSocket
server {
    listen 80;
    server_name notes.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name notes.domain.com;

    ssl_certificate /etc/letsencrypt/live/notes.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/notes.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:5264;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

# Events Server - With WebSocket
server {
    listen 80;
    server_name events.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name events.domain.com;

    ssl_certificate /etc/letsencrypt/live/events.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/events.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:7264;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

# Monograph Server - With Cache
server {
    listen 80;
    server_name mono.domain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name mono.domain.com;

    ssl_certificate /etc/letsencrypt/live/mono.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mono.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:6264;
        proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
        proxy_cache_valid 200 60m;
        add_header X-Cache-Status $upstream_cache_status;
        expires 1h;
        add_header Cache-Control "public, no-transform";
    }
}

Step 4: Test the Configuration

Before reloading Nginx, test the configuration to ensure there are no errors.

sudo nginx -t

Step 5: Reload Nginx

If the configuration is correct, reload Nginx to apply the changes.

sudo systemctl reload nginx

Step 6: Configure Automatic Renewal

sudo certbot renew --dry-run

Tiritibambix avatar Jan 21 '25 07:01 Tiritibambix

Very Nice work, thanks a lot! I would test setting up w/ caddy and post back my caddy config here (so that the https part becomes easier)

devkamiki avatar Mar 28 '25 04:03 devkamiki

minimum compose.yml+ Caddyfile to get things work, and block ip:port access ~~(in this case, minio exposure is unnecessary since all i/o happens localhost. so i didn't assign a domain or reverse proxy for it):~~ Issues of attachment not working is reported so I would adjust this to make sure S3 endpoint is exposed: In compose.yml, change:5264:5264 to 127.0.0.1:5264:5264 and same for 6264:6264, 7264:7264, 8264:8264 , 9000:9000 and 9090:9090. Caddyfile:

notes.example.io {
        reverse_proxy localhost:5264
}

mono.example.io {
        reverse_proxy localhost:6264
}

events.example.io {
        reverse_proxy localhost:7264
}

auth.example.io {
        reverse_proxy localhost:8264
}

file.example.io {
        reverse_proxy localhost:9000
}

And only monograph + minio are expected to return something in browser

devkamiki avatar Mar 29 '25 09:03 devkamiki

Do attachments work for you in this setup? I found the only way to get that to work was to also include the minio/s3 endpoint (files.domain.com)

wraeuk avatar Apr 14 '25 06:04 wraeuk

Do attachments work for you in this setup? I found the only way to get that to work was to also include the minio/s3 endpoint (files.domain.com)

Yes, I could reproduce the error

Error: Failed to connect to localhost/127.0.0.1:9000
    at anonymous (address at index.android.bundle:1:782163)
    at apply (native)
    at __invokeCallback (address at index.android.bundle:1:1578551)
    at anonymous (address at index.android.bundle:1:1576842)
    at __guard (address at index.android.bundle:1:1577715)
    at invokeCallbackAndReturnFlushedQueue (address at index.android.bundle:1:1576804)

Apologies and Thanks for telling this, I will adjust the Caddyfile to prevent further issues

devkamiki avatar Apr 14 '25 06:04 devkamiki

I dont have an email server setup on my homelab, I cant run the validate without the email settings in the .env, anyway around this?

Giraffes19 avatar Sep 27 '25 09:09 Giraffes19

I dont have an email server setup on my homelab, I cant run the validate without the email settings in the .env, anyway around this?

You don't have to set up your own mail server to use this. Technically, your personal mail provider would do. For example, I use mailbox.org:

[email protected]
SMTP_PASSWORD=your_password
SMTP_HOST=smtp.mailbox.org
SMTP_PORT=465

You can also use resend or brevo, and there will be an extra step #23

devkamiki avatar Sep 27 '25 10:09 devkamiki

minimum compose.yml+ Caddyfile to get things work, and block ip:port access ~(in this case, minio exposure is unnecessary since all i/o happens localhost. so i didn't assign a domain or reverse proxy for it):~ Issues of attachment not working is reported so I would adjust this to make sure S3 endpoint is exposed: In compose.yml, change:5264:5264 to 127.0.0.1:5264:5264 and same for 6264:6264, 7264:7264, 8264:8264 , 9000:9000 and 9090:9090. Caddyfile:

notes.example.io {
        reverse_proxy localhost:5264
}

mono.example.io {
        reverse_proxy localhost:6264
}

events.example.io {
        reverse_proxy localhost:7264
}

auth.example.io {
        reverse_proxy localhost:8264
}

file.example.io {
        reverse_proxy localhost:9000
}

And only monograph + minio are expected to return something in browser

I cant get the events reverse proxy to get working. getting error in caddy saying connection refused

update: nvm i made a mistake in the caddyfile. Its working now

RazzoR023 avatar Oct 15 '25 13:10 RazzoR023

I'have had many troubles to keep running upload service. I had configured in my .env file:

# With my domain data
ATTACHMENTS_SERVER_PUBLIC_URL=https://files.domain.com/

but I always get error:

Error: 400, name: 3647157171094f55, length: 1066337, info: {"respType":"","headers":{"Pragma":"no-cache","Cache-Control":"no-store,no-cache","Server":"nginx/1.24.0 (Ubuntu)","Connection":"keep-alive","Transfer-Encoding":"chunked","Vary":"Accept-Encoding","Date":"Sat, 18 Oct 2025 19:36:01 GMT","Content-Type":"text/plain; charset=utf-8"},"redirects":["https://notes.domain.com/s3?name=3647157171094f55"],"timeout":false,"taskId":"726ae4jo3hy2lqjy1fgx1h","state":"2",
"status":400,"rnfbEncode":"utf8"}
at ?anon_0_ (address at index.android.bundle:1:3556642)
at next (native) at asyncGeneratorStep (address at index.android.bundle:1:893710)
at _next (address at index.android.bundle:1:893966)
at tryCallOne (address at InternalBytecode.js:1:1180)
at anonymous (address at InternalBytecode.js:1:1874)
at apply (native) at anonymous (address at index.android.bundle:1:3117421)
at _callTimer (address at index.android.bundle:1:3116633)
at _callReactNativeMicrotasksPass (address at index.android.bundle:1:3116782)
at callReactNativeMicrotasks (address at index.android.bundle:1:3118486)
at __callReactNativeMicrotasks (address at index.android.bundle:1:3043772)
at anonymous (address at index.android.bundle:1:3042892)
at __guard (address at index.android.bundle:1:3043646)
at flushedQueue (address at index.android.bundle:1:3042803)
at invokeCallbackAndReturnFlushedQueue (address at index.android.bundle:1:3042746)

I have solved it changing this to nginx:

# Notesnook web client.
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name https://files.domain.com/;

    # SSL certs (replace with your real paths or use certbot)
    ssl_certificate /etc/letsencrypt/live/files.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/files.domain.com/privkey.pem;

    error_log /var/log/nginx/notesnook.orencio.org_443_error.log;
    access_log /var/log/nginx/notesnook.orencio.org_443_access.log;

    location / {
        proxy_pass http://127.0.0.1:9009;
        proxy_http_version 1.1;

        # Required for WebSocket (Notesnook sync uses it)
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $host;
        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;
    }
}

orencio avatar Oct 18 '25 20:10 orencio