Applications AWS

TiddlyWiki 5.4.1 on AWS User Guide

| Product: TiddlyWiki 5.4.1 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the TiddlyWiki 5.4.1 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg BookStack, CMS, Blogs and Wikis listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

TiddlyWiki is an open source personal wiki and non linear notebook. Instead of rigid pages, everything you write is a small, individually addressable note called a tiddler, and tiddlers link, tag and transclude each other freely, so a knowledge base grows the way you think. This image runs TiddlyWiki's own Node.js server, which stores every tiddler as a file on the instance and saves your edits back to it as you work.

The cloudimg image adds:

  • HTTPS from the first boot. nginx serves TiddlyWiki on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
  • An admin password unique to your instance, for every read and every write. TiddlyWiki's built in authentication asks for the user admin and a password generated on first boot; without it the wiki is neither readable nor writable. The password is written to /root/tiddlywiki-credentials.txt and to a credentials file that TiddlyWiki reads, never to its command line. No password is baked into the image.
  • Fail closed. TiddlyWiki refuses to start until first boot has written that password, and nginx refuses to start until first boot has finished.
  • Loopback only. TiddlyWiki listens on 127.0.0.1:8080 behind nginx. The only open ports are 22, 80 and 443.
  • Hardened defaults. TiddlyWiki runs as its own unprivileged user in a systemd sandbox that can write only its wiki folder. TiddlyWiki and nginx are blocked from the instance metadata service; the AMI requires IMDSv2; requests for a host name the instance does not serve are dropped; and cross site requests that would change your wiki are refused.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: TiddlyWiki 5.4.1 (the tiddlywiki npm package, checksum verified), Node.js 22 LTS from the NodeSource repository, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. The wiki starts empty apart from TiddlyWiki's GettingStarted note.

Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
  • A security group that allows TCP 22 (SSH), TCP 443 (the wiki) and TCP 80 (redirects to HTTPS) from your own networks only.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick TiddlyWiki 5.4.1 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (TiddlyWiki is light; a smaller instance is fine for one person), your key pair and a security group as above. The wiki lives under /var/lib/tiddlywiki on the root volume.

With the AWS CLI (replace the values in angle brackets):

aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
  --instance-type m5.large --key-name <your-key-pair> \
  --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=tiddlywiki}]'

Step 2: Connect to your instance

Version SSH user
TiddlyWiki 5.4.1 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

First boot takes a few seconds. Then the three units are active:

systemctl is-active tiddlywiki nginx tiddlywiki-firstboot
active
active
active

TiddlyWiki (a Node.js process) listens on loopback only; nginx serves ports 80 and 443:

sudo ss -tlnp | awk 'NR==1 || /node|nginx|sshd/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'
State Local Peer
LISTEN 0.0.0.0:22 users:(("sshd"),("systemd"))
LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx"))
LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx"))
LISTEN 127.0.0.1:8080 users:(("node"))
LISTEN [::]:22 users:(("sshd"),("systemd"))
LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx"))
LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx"))
tiddlywiki --version
node --version
5.4.1
v22.23.3

Step 4: Get your URL and password

sudo cat /root/tiddlywiki-credentials.txt

The file holds the address the wiki is served as (your instance's public DNS name by default), the user and the password generated on this instance:

TIDDLYWIKI_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
TIDDLYWIKI_USERNAME=admin
TIDDLYWIKI_PASSWORD=<24 letters and digits>

Step 5: Sign in from your browser

Open TIDDLYWIKI_URL in your browser. The certificate is self signed (generated on your instance), so accept the browser warning once, or install your own certificate (Step 10). Your browser then asks for a user name and password: enter admin and the password from Step 4. TiddlyWiki loads its notebook view: the story river on the left shows your open tiddlers, starting with GettingStarted, and the sidebar on the right holds the new tiddler, control panel and sync buttons, the search box and the Open, Recent, Tools and More tabs.

The TiddlyWiki notebook view with the GettingStarted tiddler in the story river and the sidebar with the new tiddler, control panel and sync buttons, search box and tabs

Step 6: Create and edit a note

Click + (new tiddler) at the top of the sidebar. TiddlyWiki opens an edit view: give the note a title, add tags and type the body, using the toolbar for headings, lists, links, images and more. Click the check mark to save. The server writes the change to a file on your instance straight away.

Editing a new tiddler titled Project kickoff notes, tagged meetings, with the formatting toolbar and an agenda list in the body

Step 7: Search your wiki

Type in the search box at the top of the sidebar. TiddlyWiki matches titles and full text as you type and lists the results in a dropdown, which is how you find your way around a growing wiki without folders.

Searching for kickoff: the dropdown lists the Project kickoff notes tiddler under title matches and all matches

Step 8: Settings in the Control Panel

Open the Control Panel (the gear icon in the sidebar) to set the wiki's title and subtitle, choose which tiddlers open at startup, and manage appearance, themes, plugins and keyboard shortcuts. The Info tab shows the running TiddlyWiki version and the user name your edits are signed with.

The TiddlyWiki Control Panel Info tab showing version 5.4.1, the title, subtitle, signing user admin and the default tiddlers

Step 9: Security checks

Port 80 sends browsers to HTTPS, the health endpoint answers without a password (for load balancer checks), and the wiki itself does not:

H=$(sudo grep '^TIDDLYWIKI_URL=' /root/tiddlywiki-credentials.txt | sed -E 's#^TIDDLYWIKI_URL=https://([^/]+)/.*#\1#')
curl -s -o /dev/null -w 'port 80: %{http_code} -> %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -w '\n' --resolve "$H:443:127.0.0.1" "https://$H/healthz"
curl -sk -o /dev/null -w 'wiki without a password: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/"
port 80: 301 -> https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/
ok
wiki without a password: 401

With the password (read from the credentials file and passed to curl on stdin, so it never appears on a command line), TiddlyWiki's status endpoint confirms who you are signed in as:

H=$(sudo grep '^TIDDLYWIKI_URL=' /root/tiddlywiki-credentials.txt | sed -E 's#^TIDDLYWIKI_URL=https://([^/]+)/.*#\1#')
sudo sed -n 's/^TIDDLYWIKI_PASSWORD=\(.*\)$/user = "admin:\1"/p' /root/tiddlywiki-credentials.txt \
  | curl -sk -K - --resolve "$H:443:127.0.0.1" "https://$H/status" \
  | jq '{username, anonymous, read_only, tiddlywiki_version}'
{
  "username": "admin",
  "anonymous": false,
  "read_only": false,
  "tiddlywiki_version": "5.4.1"
}

The password is in a credentials file that only root can change and the TiddlyWiki user can read; the server is started with the file's path, not the password:

sudo stat -c '%a %U:%G %n' /etc/tiddlywiki/users.csv /root/tiddlywiki-credentials.txt
systemctl show tiddlywiki -p ExecStart | grep -o 'credentials=[^ ]*'
640 root:tiddlywiki /etc/tiddlywiki/users.csv
600 root:root /root/tiddlywiki-credentials.txt
credentials=/etc/tiddlywiki/users.csv

The certificate was generated on this instance and names its own addresses:

H=$(sudo grep '^TIDDLYWIKI_URL=' /root/tiddlywiki-credentials.txt | sed -E 's#^TIDDLYWIKI_URL=https://([^/]+)/.*#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
    DNS:ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost

TiddlyWiki runs unprivileged in a sandbox, and neither TiddlyWiki nor nginx can reach the instance metadata service:

systemctl show tiddlywiki -p User -p ProtectSystem -p NoNewPrivileges -p IPAddressDeny
systemctl show nginx -p IPAddressDeny
IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
User=tiddlywiki
ProtectSystem=strict
NoNewPrivileges=yes
IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32

nginx passes TiddlyWiki a fixed host name and the real client address from the connection, never values a client sends, and closes the connection for any host name the instance does not serve:

grep -E 'proxy_set_header (Host|X-Forwarded-For|X-Real-IP)' /etc/nginx/sites-available/cloudimg-tiddlywiki
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: example.com' http://127.0.0.1/ || true
        proxy_set_header Host 127.0.0.1:8080;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
unknown host name: 000

(000 means nginx closed the connection without an answer.) Every change to the wiki also needs TiddlyWiki's X-Requested-With: TiddlyWiki header, which a browser cannot add to a cross site form, and nginx refuses a change whose Origin is another web site (HTTP 403), because browsers resend Basic Auth credentials on cross site requests.

Step 10: Your own DNS name and certificate

Point a DNS record at the instance, then set the name TiddlyWiki is served as. This mints a new self signed certificate for the name, updates nginx and the URL in /root/tiddlywiki-credentials.txt, and keeps the name across reboots:

sudo tiddlywiki-set-hostname <your-domain>

To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx (running tiddlywiki-set-hostname again replaces it with a self signed one):

sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/tiddlywiki.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/tiddlywiki.key
sudo nginx -t && sudo systemctl reload nginx

Step 11: Password, wiki data and upgrades

tiddlywiki-set-password sets a new admin password in TiddlyWiki's credentials file, records it in /root/tiddlywiki-credentials.txt and restarts TiddlyWiki. Run it without arguments for a new random password, or pass your own (24 to 64 letters and digits) on stdin:

sudo tiddlywiki-set-password
printf '%s\n' '<your-new-password>' | sudo tiddlywiki-set-password --stdin

Your wiki is a folder with one file per tiddler. Every change you make in the browser is saved there:

sudo ls /var/lib/tiddlywiki/mywiki /var/lib/tiddlywiki/mywiki/tiddlers
/var/lib/tiddlywiki/mywiki:
tiddlers
tiddlywiki.info

/var/lib/tiddlywiki/mywiki/tiddlers:
$__StoryList.tid

Back up /var/lib/tiddlywiki/mywiki (or snapshot the root volume) to keep your notes. You can also save the whole wiki as a single standalone HTML file from the browser: in the sidebar choose Tools, then export all.

TiddlyWiki is installed as a global npm package. To move to a newer release later, snapshot the instance, then run sudo npm install -g tiddlywiki@<version> and sudo systemctl restart tiddlywiki. The image ships the version named in the listing.

The server reads its settings from the tiddlywiki.service unit:

Setting Meaning Image default
host / port Bind address and port 127.0.0.1 / 8080 (nginx fronts it)
credentials File of users and passwords /etc/tiddlywiki/users.csv (user admin)
readers / writers Who may read and change the wiki (authenticated): only a signed in user

Step 12: Server components

Component Path
TiddlyWiki /usr/lib/node_modules/tiddlywiki (command /usr/bin/tiddlywiki)
Wiki folder /var/lib/tiddlywiki/mywiki
Credentials file read by TiddlyWiki /etc/tiddlywiki/users.csv (root:tiddlywiki, 0640)
Service unit /etc/systemd/system/tiddlywiki.service
nginx site /etc/nginx/sites-available/cloudimg-tiddlywiki
Certificate and key /etc/nginx/ssl/
First boot script /usr/local/sbin/tiddlywiki-firstboot.sh
Host name and password helpers /usr/local/sbin/tiddlywiki-set-hostname, /usr/local/sbin/tiddlywiki-set-password
Credentials /root/tiddlywiki-credentials.txt (mode 0600)

Step 13: Security recommendations

  • Allow ports 22, 80 and 443 in the security group from your own networks only.
  • Keep the admin password secret, and rotate it if it may have been shared (Step 11).
  • Use your own DNS name and a certificate your browsers trust (Step 10).
  • Keep the operating system patched; unattended security upgrades are on, and sudo apt-get update && sudo apt-get upgrade applies everything else, including Node.js updates from the NodeSource repository.
  • Back up the wiki folder regularly (Step 11).

Support and licensing

TiddlyWiki is open source under the BSD 3-Clause licence (a copy is at /usr/share/doc/tiddlywiki/LICENSE); there is no per user or per CPU licence fee. The AMI price covers cloudimg's hardening, first boot setup and support.

  • Email: support@cloudimg.co.uk
  • Website: https://www.cloudimg.co.uk
  • Support: 24/7, with a 24 hour response SLA