Deployment guide

Note Mark

Overview

Note Mark is a fast, minimal, multi-user, self-hosted Markdown notes server. A Go backend API and a SolidJS single-page web app ship together in one official container image.

Every note is stored as portable Markdown, organised into books. Individuals and teams get a private place to write, organise and share notes, with optional OIDC single sign-on, instead of relying on a hosted service.

The SecureAnyCloud image runs the pinned official Note Mark container behind nginx over HTTPS. The container is published on the loopback interface only, and nginx terminates TLS in front of it.

What you get:

  • Note Mark 1.0.3 (AGPL-3.0) from the official pinned container image ghcr.io/enchant97/note-mark:1.0.3, baked into the image and published on loopback 127.0.0.1:8080
  • nginx terminating TLS on :443 in front of Note Mark, with :80 redirecting to HTTPS
  • A per-VM administrator account and a per-VM token signing secret, created on first boot. No default or shared credential ships in the image.
  • Open self-registration disabled by default, so a stranger cannot sign up on a fresh public VM
  • docker.service, note-mark.service and nginx.service as systemd units, enabled and active
  • 24/7 SecureAnyCloud support

Secure by default: a per-VM administrator credential

This image ships with no default or shared login. No user accounts and no token signing secret ship in the image.

On first boot, a one-shot service does the following:

  • Creates a unique AUTH_TOKEN__SECRET (the JWT signing key) for your VM
  • Resolves your public URL
  • Regenerates a per-VM TLS certificate
  • Seeds exactly one administrator account, named admin, with a unique random password, which it writes to a root-only file

Note Mark is deliberately held back until that account exists, so a fresh VM is never reachable without an administrator. Retrieve the password over SSH and change it after your first login.

Prerequisites

Before you deploy, make sure you have:

  • An active Azure subscription
  • An SSH key pair
  • A VNet and subnet in the target region
  • A Standard_B2s VM size (2 vCPU / 4 GiB RAM), which is a comfortable starting point. Scale up for large teams or note volumes.
  • NSG inbound rules that allow 22/tcp from your management network, and 80/tcp and 443/tcp from wherever you browse Note Mark. Port :80 only redirects to :443.

Step 1 - Deploy from the Azure Marketplace

  1. Sign in to the Azure Portal, choose Create a resource, and search the Marketplace for Note Mark by SecureAnyCloud.
  2. Select Create.
  3. On Basics, pick your subscription, resource group, region and size.
  4. Under Administrator account, choose SSH public key and paste your key.
  5. Under Inbound port rules, allow SSH (22), HTTP (80) and HTTPS (443).
  6. Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

Accept the Marketplace terms, create the VM, then open ports 80 and 443.

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:note-mark:default:latest
az vm create \
  --resource-group <your-rg> \
  --name note-mark \
  --image sac1647283583153:note-mark:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name note-mark --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name note-mark --port 443 --priority 1020

Step 3 - Connect to your VM

Connect over SSH.

ssh azureuser@<vm-public-ip>

The message of the day shows your VM's Note Mark URL and administrator username.

Step 4 - Confirm the services are running

Note Mark runs as three systemd units: the Docker engine, the Note Mark container and nginx. Check that all three are active.

systemctl is-active docker.service note-mark.service nginx.service
active active active

The Note Mark container is published only on the loopback interface. nginx is the only service bound to public ports (:80 and :443). Check the listeners.

sudo ss -tln | grep -E ':(80|443|8080) '
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* LISTEN 0 511 0.0.0.0:80 0.0.0.0:* LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:*

The web UI is served over HTTPS, and plain HTTP redirects to it. Confirm both.

curl -sk -o /dev/null -w 'https:// -> %{http_code}\n' https://127.0.0.1/
curl -s -o /dev/null -w 'http:// -> %{http_code}\n' http://127.0.0.1/
https:// -> 200 http:// -> 301

Step 5 - Read the per-VM administrator credential

On first boot, the VM writes a root-only file with your Note Mark URL, the administrator username and the unique password created for this VM. Read the URL and username.

sudo grep -E '^NOTEMARK_URL=|^NOTEMARK_ADMIN_USERNAME=' /root/note-mark-credentials.txt
NOTEMARK_URL=https://<vm-public-ip> NOTEMARK_ADMIN_USERNAME=admin

The NOTEMARK_ADMIN_PASSWORD line in that file holds your unique password. Only the per-VM password authenticates. A wrong or blank password is rejected. Test both.

U=$(sudo grep '^NOTEMARK_ADMIN_USERNAME=' /root/note-mark-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^NOTEMARK_ADMIN_PASSWORD=' /root/note-mark-credentials.txt | cut -d= -f2-)
curl -sk -o /dev/null -w 'per-VM password -> HTTP %{http_code}\n' -X POST https://127.0.0.1/api/auth/o/token \
  -H 'Content-Type: application/json' --data "{\"grant_type\":\"password\",\"username\":\"$U\",\"password\":\"$P\"}"
curl -sk -o /dev/null -w 'wrong password -> HTTP %{http_code}\n' -X POST https://127.0.0.1/api/auth/o/token \
  -H 'Content-Type: application/json' --data "{\"grant_type\":\"password\",\"username\":\"$U\",\"password\":\"wrong-nope\"}"
per-VM password -> HTTP 200 wrong password -> HTTP 401

Step 6 - First login

Open Note Mark in your browser. Accept the self-signed certificate warning, or install a trusted certificate first (see "Enabling a trusted TLS certificate" below).

https://<vm-public-ip>/

Click Login. Enter the administrator username, admin, and the NOTEMARK_ADMIN_PASSWORD from Step 5, then sign in.

Open your profile and change the password immediately after your first sign-in.

Writing and rendering notes

Notes are organised into books (notebooks). Create a book, then add notes inside it. Your books and notes appear in the sidebar.

Note Mark uses Markdown, so headings, bold, lists, tables, task checklists and fenced code all render as you write. Markdown tables and task lists render inline, so structured notes stay readable.

Every note is plain, portable Markdown, which makes it easy to read, search and export.

Step 7 - The official pinned container image

Note Mark runs from the official upstream container image. The image is pinned to an exact version and baked into the VM image, so there is no runtime pull. It is published on the loopback interface only. Check the running container.

sudo docker ps --format 'table {{.Image}}\t{{.Status}}\t{{.Ports}}'
IMAGE STATUS PORTS ghcr.io/enchant97/note-mark:1.0.3 Up 6 minutes 127.0.0.1:8080->8080/tcp

Adding more users

Note Mark is multi-user, and each user gets their own books. Open self-registration is disabled by default, so you add accounts from the VM with the built-in user add command.

sudo docker run --rm --env-file /etc/note-mark/note-mark.env \
  -v /var/lib/note-mark/data:/data ghcr.io/enchant97/note-mark:1.0.3 \
  user add --username alice --password '<choose-a-strong-password>'

To let users register themselves instead, set ENABLE_INTERNAL_SIGNUP=true in /etc/note-mark/note-mark.env and run sudo systemctl restart note-mark.

Note Mark also supports OIDC single sign-on. Add your provider's settings to the same env file and restart the service.

Security updates

The image is patched at build time, including Ubuntu phased updates. Unattended-upgrades stays enabled, so security patches keep flowing on your VM. There should be no held-back packages. Check.

apt-mark showhold

The note-mark and nginx packages are managed by systemd units. The application itself is the pinned container image described above.

Your data

Note Mark stores its SQLite database and Markdown note files under /var/lib/note-mark/data. Check how much space they use.

sudo du -sh /var/lib/note-mark/data

To back up your notes, snapshot the VM's OS disk in Azure. Alternatively, copy /var/lib/note-mark/data to external storage on a schedule.

Enabling a trusted TLS certificate

The image ships a per-VM self-signed certificate so HTTPS works out of the box. Browsers warn until you install a trusted certificate.

For production, point a DNS A record at the VM's public IP and make sure 443/tcp is open in the NSG. Then install certbot and let it manage the nginx certificate. Replace the example domain and email with your own.

sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com -m you@example.com --agree-tos

certbot configures the HTTPS server block and sets up automatic renewal.

When it completes, set PUBLIC_URL=https://your-domain.example.com in /etc/note-mark/note-mark.env and run sudo systemctl restart note-mark. Note Mark is then available at your domain with a trusted certificate.

Upgrading Note Mark

Note Mark runs from a pinned container image. To upgrade within the 1.x line:

  1. Snapshot the OS disk first, because the schema migrates on start.
  2. Edit the image tag in /etc/systemd/system/note-mark.service.
  3. Run sudo docker pull ghcr.io/enchant97/note-mark:<new-tag>.
  4. Run sudo systemctl daemon-reload.
  5. Run sudo systemctl restart note-mark.

SecureAnyCloud support can help you plan and perform upgrades.

Support

SecureAnyCloud backs this image with 24/7 support covering deployment, upgrades, integrations, TLS termination and user administration. Contact us by email and chat.

Note Mark is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Note Mark on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure