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.
Update your apt
repositories and upgrade any out-of-date packages:
sudo apt update -y && sudo apt upgrade -y
Install Docker Engine:
# Remove any old Docker installations.
sudo apt-get remove docker docker-engine docker.io 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 https://download.docker.com/linux/ubuntu/gpg | 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] https://download.docker.com/linux/ubuntu $(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 containerd.io docker-compose-plugin -y
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.
...
Verify that Docker Compose is correctly installed:
docker compose version
This should output something like:
Docker Compose version v2.6.0
Enable the ufw
firewall:
sudo ufw enable
Enter y
when prompted.
Enable SSH connections:
sudo ufw allow ssh
This should output something like:
Skipping adding existing rule
Skipping adding existing rule (v6)
Allow incoming TPC connections on ports 80
and 443
:
sudo ufw allow http
sudo ufw allow https
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)
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.
Clone the self-hosted
repo:
cd ~
git clone --single-branch --branch main https://github.com/standardnotes/self-hosted.git
cd self-hosted
Initialize default configuration files:
./server.sh 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.
Generate random values for the necessary environment variables:
./server.sh generate-keys
Customize ports and endpoints:
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.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 10.0.1.2, set this value to http://10.0.1.2:3125. Read more about configuring your setup for files.Start the Standard Notes server process:
./server.sh 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.
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 './server.sh logs' command to see details.
Check the status of your server:
./server.sh status
This will output something like:
Services State:
NAME COMMAND SERVICE STATUS PORTS
api-gateway-standalone "./wait-for.sh auth …" api-gateway running 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp
auth-standalone "./wait-for.sh db 33…" auth running
auth-worker-standalone "./wait-for.sh 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 "./wait-for.sh db 33…" files running 0.0.0.0:3125->3000/tcp, :::3125->3000/tcp
syncing-server-js-standalone "./wait-for.sh db 33…" syncing-server-js running
syncing-server-js-worker-standalone "./wait-for.sh 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 ./server.sh wait-for-startup
.
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
OK
If you changed the EXPOSED_PORT
variable, check http://localhost:{EXPOSED_PORT}/healthcheck
.
You're done!
To start using your new server with the Standard Notes app at app.standardnotes.com,
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.
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!
Learn more about how to unlock subscription benefits on your self-hosted server.