Self-hosting with Docker

This guide walks you through the process of installing the self-hosted backend of Standard Notes. In this example, we used a server running Ubuntu 20.04, with 2GB RAM and 1 CPU.

Due to mounted volumes, we recommend running the setup as a root user. If you wish to run it as a non-root user, please see Docker's post-installation steps for Linux.

If you're self-hosting on an OS other than Linux, skip to the installation instructions below.


  1. Update your apt repositories and upgrade any out-of-date packages:

    sudo apt update -y && sudo apt upgrade -y
  2. Install Docker Engine:

    # Remove any old Docker installations.
    sudo apt-get remove docker docker-engine containerd runc
    # Install dependencies.
    sudo apt install git ca-certificates curl gnupg lsb-release -y
    # Add Docker's GPG key.
    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    # Set the Docker repo.
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    # Install Docker Engine.
    sudo apt update -y
    sudo apt install docker-ce docker-ce-cli docker-compose-plugin -y
  3. Verify that Docker is installed:

    sudo docker run hello-world

    This should output something like:

    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    2db29710123e: Pull complete
    Digest: sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651
    Status: Downloaded newer image for hello-world:latest
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
  4. Verify that Docker Compose is correctly installed:

    docker compose version

    This should output something like:

    Docker Compose version v2.6.0
  5. Enable the ufw firewall:

    sudo ufw enable

    Enter y when prompted.

  6. Enable SSH connections:

    sudo ufw allow ssh

    This should output something like:

    Skipping adding existing rule
    Skipping adding existing rule (v6)
  7. Allow incoming TPC connections on ports 80 and 443:

    sudo ufw allow http
    sudo ufw allow https
  8. Check the status of your ufw settings:

    ufw status verbose

    This should output something like:

    Status: active
    Logging: on (low)
    Default: deny (incoming), allow (outgoing), deny (routed)
    New profiles: skip
    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW IN    Anywhere
    80/tcp                     ALLOW IN    Anywhere
    443/tcp                    ALLOW IN    Anywhere
    22/tcp (v6)                ALLOW IN    Anywhere (v6)
    80/tcp (v6)                ALLOW IN    Anywhere (v6)
    443/tcp (v6)               ALLOW IN    Anywhere (v6)
  9. Configure a domain name (or subdomain) to point to your server's IP address. Consult your domain registration provider for how to configure your domain name.

Install Standard Notes

  1. Clone the self-hosted repo:

    cd ~
    git clone --single-branch --branch main
    cd self-hosted
  2. Initialize default configuration files:

    ./ setup

    This will output something like:

    Initializing default configuration
    Default configuration files created as .env and docker/*.env files. Feel free to modify values if needed.
  3. Generate random values for the necessary environment variables:

    ./ generate-keys
  4. Customize ports and endpoints:

    • By default, the server will run on port 3000. If you have a different service running on that port, you can customize the port on which you want to run the infrastructure by editing the EXPOSED_PORT variable in the .env file.
    • Edit FILES_SERVER_URL to the final public-facing URL of your server. For example, if you are self-hosting on a server on your local network which you know has an IP of, set this value to Read more about configuring your setup for files.
  5. Start the Standard Notes server process:

    ./ start

    Docker will start outputting lots of information about the containers it is pulling in and installing. This process took about 8 minutes on a Ubuntu 20.04 server with 2GB RAM and 1 CPU.

  6. Once Docker has finished installing, the Standard Notes install script will output:

    Infrastructure started. Give it a moment to warm up. If you wish, please run the './ logs' command to see details.
  7. Check the status of your server:

    ./ status

    This will output something like:

    Services State:
    NAME                                  COMMAND                  SERVICE                    STATUS              PORTS
    api-gateway-standalone                "./ auth …"   api-gateway                running   >3000/tcp, :::3000->3000/tcp
    auth-standalone                       "./ db 33…"   auth                       running
    auth-worker-standalone                "./ db 33…"   auth-worker                running
    cache-standalone                      "docker-entrypoint.s…"   cache                      running             6379/tcp
    db-standalone                         "docker-entrypoint.s…"   db                         running             3306/tcp
    files-standalone                      "./ db 33…"   files                      running   >3000/tcp, :::3125->3000/tcp
    syncing-server-js-standalone          "./ db 33…"   syncing-server-js          running
    syncing-server-js-worker-standalone   "./ db 33…"   syncing-server-js-worker   running

    Your Standard Notes server is ready once all the services have a STATUS of Up. This process took about 11 minutes on a Ubuntu 20.04 server with 2GB RAM and 1 CPU. If you want to control when this process finishes you can run ./ wait-for-startup.

  8. You should be able now to check that the syncing server is running by checking http://localhost:3000/healthcheck. You must do this on the server:

    curl http://localhost:3000/healthcheck

    If you changed the EXPOSED_PORT variable, check http://localhost:{EXPOSED_PORT}/healthcheck.

  9. You're done!

Securing your server

To start using your new server with the Standard Notes app at, you have to configure an HTTPS reverse proxy. Head over to Securing HTTP traffic of your Sync server for more information on how to set up a reverse proxy.

Using your new server

In the account menu, choose Advanced options and enter the address of your new server in Custom sync server. Then, register for a new account or log in to an existing account and begin using your private new secure Standard Notes server!

Unlock premium features with a subscription

Learn more about how to unlock subscription benefits on your self-hosted server.

Other ways to get help

Browse or post to the forum
Recommended for non-account related issues.
Join the Standard Notes Discord group
Recommended for small talk.
Send an email to
Recommended for account related issues.