Nm
Applications Azure

Note Mark on Ubuntu 24.04 on Azure User Guide

| Product: Note Mark on Ubuntu 24.04 LTS on Azure

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 are shipped together in one official container image; every note is stored as portable Markdown organised into books, so 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 cloudimg 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. Backed by 24/7 cloudimg support.

What is included:

  • 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 generated on first boot - no default or shared credential ships in the image
  • Open self-registration disabled by default, so a fresh public VM cannot be signed up by a stranger
  • docker.service, note-mark.service and nginx.service as systemd units, enabled and active
  • 24/7 cloudimg support

Secure by default - a per-VM administrator credential

This image ships with no default or shared login: no user accounts and a blank token signing secret ship in the image. On first boot a one-shot service generates a unique AUTH_TOKEN__SECRET (the JWT signing key) for your VM, resolves your public URL, regenerates a per-VM TLS certificate, and seeds exactly one administrator account (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 there is never a window in which a fresh VM is reachable without an administrator. You retrieve the password over SSH and change it after your first login.

Note Mark login page served over HTTPS

Prerequisites

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

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Note Mark by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22), HTTP (80) and HTTPS (443). Then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name note-mark \
  --image <marketplace-image-urn> \
  --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

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:

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):

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:

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

Note Mark services, loopback + nginx binding, and HTTPS health on the VM

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 generated for this VM:

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:

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

Secure by default: the per-VM info file and a live login round-trip

Step 6 - First login

Open Note Mark in your browser (accept the self-signed certificate warning, or install a trusted certificate first - see 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 to 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. Note Mark uses Markdown, so headings, bold, lists, tables, task checklists and fenced code all render as you write, with your books and notes in the sidebar.

The Note Mark area with the notebooks sidebar

Markdown tables and task lists render inline, so structured notes stay readable:

A Note Mark note rendering a Markdown table and a task list

Every note is plain, portable Markdown - easy to read, search and export:

A Note Mark note rendering headings, body text and a task list

Step 7 - The official pinned container image

Note Mark runs from the official upstream container image, pinned to an exact version and baked into the VM image (no runtime pull), published on the loopback interface only:

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

The pinned Note Mark container image and the loopback-published service

Adding more users

Note Mark is multi-user. Because open self-registration is disabled by default, you add accounts from the VM with the built-in user add command (each user gets their own books):

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 captured fully patched (including Ubuntu phased updates) and unattended-upgrades stays enabled, so security patches keep flowing on your VM. There should be no held-back packages:

apt-mark showhold

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

The per-VM token signing secret and the OS security baseline

Your data

Note Mark stores its SQLite database and Markdown note files under /var/lib/note-mark/data:

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

Snapshot the VM's OS disk in Azure to back up your notes, or 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 will warn until you install a trusted certificate. For production, point a DNS A record at the VM's public IP, ensure 443/tcp is open in the NSG, then install certbot and let it manage the nginx certificate. Replace the placeholders with your own domain and email:

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. After it completes, set PUBLIC_URL=https://your-domain.example.com in /etc/note-mark/note-mark.env and run sudo systemctl restart note-mark, and Note Mark is 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, edit the image tag in /etc/systemd/system/note-mark.service, then sudo docker pull ghcr.io/enchant97/note-mark:<new-tag>, sudo systemctl daemon-reload and sudo systemctl restart note-mark. Always snapshot the OS disk first, as the schema migrates on start. cloudimg support can assist with planning and performing upgrades.

Support

This image is backed by 24/7 cloudimg 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.