Colanode 0.4.7
Overview
This guide covers launching and using the Colanode 0.4.7 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud office suites and workspaces listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Colanode is an open-source, local-first collaboration workspace. It combines real-time chat channels, collaborative pages and documents, databases (tables, boards and calendars made of pages) and file sharing in one place. It is a self-hosted alternative to tools like Slack and Notion.
The web and desktop clients keep a local copy of your workspaces, so they stay fast and keep working offline. They sync with your server when they reconnect.
What you get:
- HTTPS from the first boot. nginx serves Colanode on port 443 with a certificate generated on your instance's first boot for its public DNS name. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped.
- An administrator unique to your instance, and sign-up closed. First boot creates and verifies one account,
admin@colanode.local, with a random password written to/root/colanode-credentials.txt(root only). nginx answers 403 to every sign-up until you open it, and new accounts need your verification, so a fresh instance is never open for anyone to join. nginx does not start until the administrator exists. - Per-instance database secrets. PostgreSQL and Valkey passwords are generated on first boot and handed to the containers as read-only files, never as environment variables or command line arguments. PostgreSQL accepts
scram-sha-256only, Valkey requires its password, and neither has a port on the host or the network. - The avatar path traversal fenced. Colanode 0.4.7 and earlier let a signed in user read files outside the avatar folder through
GET /client/v1/avatars/<id>(CVE-2026-110766, no fixed release yet). nginx only lets a plain letters-and-digits avatar id through, judged on the raw request, and refuses any request path that carries an encoded dot, slash or backslash, a..or an empty segment. Every build sends 16 bypass attempts and proves none of them reaches Colanode. - Risky entry points closed. Avatar upload (which decodes images with sharp 0.34.5, whose libvips fixes arrive only in sharp 0.35) and Google sign-in are refused at nginx. Accounts show their initials instead of a picture.
- Containers and services blocked from the instance metadata service. A firewall rule drops container traffic to
169.254.169.254and to your VPC's addresses, and nginx, Docker and Colanode's unit carryIPAddressDenyfor the metadata addresses. The AMI requires IMDSv2. - Built from source and pinned. The Colanode server and web app are built from the v0.4.7 source with dependency fixes inside their version ranges, scanned with Trivy at build time, and PostgreSQL (pgvector 0.8.7 on PostgreSQL 17) and Valkey 8.1.11 are pulled by image digest. First boot never pulls an image.
- Workspace data on its own volume. PostgreSQL, Valkey and uploaded files live on a separate 10 GiB EBS volume mounted at
/var/lib/colanode, which you can grow or snapshot on its own. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Colanode 0.4.7 (server and web app, Apache-2.0), PostgreSQL 17 with pgvector 0.8.7, Valkey 8.1.11, Docker Engine with the Compose plugin from Docker's repository, nginx 1.24, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. The build record, Colanode's license and the Trivy reports are in /usr/share/doc/colanode/.
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 public IP or a route from your network.
- A security group that allows TCP 22 (SSH) from your admin network (for example
<your-mgmt-cidr>), and TCP 443 and TCP 80 (the redirect) from the networks your team works from. - A desktop browser. The web app needs a secure (HTTPS) page, which the image provides.
Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Colanode 0.4.7 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose an instance type, your key pair, your subnet and the security group above.
m5.large (2 vCPUs, 8 GiB) suits a team of a few dozen people. The image has two volumes: a 30 GiB root volume and a 10 GiB data volume (/dev/sdf) for /var/lib/colanode. Make the data volume bigger at launch if your team shares many files.
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 \
--block-device-mappings '[{"DeviceName":"/dev/sdf","Ebs":{"VolumeSize":50,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=colanode}]'Connect to your instance
Connect over SSH as the default login user for your AMI. For Colanode 0.4.7 on Ubuntu 24.04, the login user is ubuntu:
ssh -i <your-key.pem> ubuntu@<public-ip>The login message shows where your URL and password are and how to add a teammate.
Check the services
First boot takes about 20 seconds: it names the instance after its public DNS name and makes the certificate, generates the database passwords, starts the containers, creates the administrator and only then starts nginx. Check that everything is running:
systemctl is-active docker colanode-firstboot colanode nginx \
&& sudo test -f /var/lib/sac/data/colanode-firstboot.done && echo FIRSTBOOT_DONEactive active active active FIRSTBOOT_DONEThree containers run, all healthy: the Colanode server, PostgreSQL and Valkey.
sudo docker ps --format '{{.Names}} {{.Image}} {{.Status}}' | sort | tee /dev/stderr \
| grep -c '(healthy)' | grep -qx 3 && echo "3 containers healthy"colanode-postgres sac/pgvector:0.8.7-pg17 Up 2 minutes (healthy) colanode-server sac/colanode-server:0.4.7 Up 2 minutes (healthy) colanode-valkey valkey/valkey:8.1.11 Up 2 minutes (healthy) 3 containers healthyOnly SSH and nginx listen on the network. The Colanode server listens on 127.0.0.1:3000 behind nginx, and PostgreSQL and Valkey have no port on the host at all:
sudo ss -Hlnt | awk '{print $4}' | grep -vE '^(127\.|\[::1\]|\[::ffff:127\.)' \
| sed -E 's/.*:([0-9]+)$/\1/' | sort -un | xargs | tee /dev/stderr | grep -qx '22 80 443' && echo "network listeners: 22 80 443"22 80 443 network listeners: 22 80 443Your workspace data is on the data volume:
findmnt -no FSTYPE,TARGET /var/lib/colanode | head -n 1 | tee /dev/stderr | grep -q '^ext4 ' \
&& sudo ls /var/lib/colanode | xargsext4 /var/lib/colanode lost+found postgres storage valkeyThe data volume holds three folders:
- /var/lib/colanode/postgres holds the PostgreSQL database (accounts, workspaces, pages, messages).
- /var/lib/colanode/storage holds uploaded files.
- /var/lib/colanode/valkey holds the Valkey cache and sync channel.
Get your URL and password
/root/colanode-credentials.txt (root only) holds everything generated on first boot:
sudo grep -o '^colanode\.[a-z.]*' /root/colanode-credentials.txt | tee /dev/stderr \
| grep -qx colanode.admin.pass && echo "credentials present"colanode.url colanode.admin.email colanode.admin.pass colanode.db.name colanode.db.user colanode.db.pass credentials presentShow the values (keep them private):
sudo cat /root/colanode-credentials.txtcolanode.url is the address to open, for example https://ec2-203-0-113-10.compute-1.amazonaws.com/. It uses the instance's public DNS name, and the certificate is made for that name. Use this name rather than the IP address: the server only accepts changes from pages loaded from the name it is configured with (Step 9 changes it to your own domain).
Open Colanode and add your server
In a desktop browser, open the colanode.url address. The certificate is self-signed, so the browser warns once. Choose Advanced and continue, or use your own domain and certificate (Step 9).
Colanode opens on Add a server. Choose Add a new server, enter your server's config URL, which is colanode.url followed by config, for example:
https://ec2-203-0-113-10.compute-1.amazonaws.com/configand choose Create. Your server appears in the list as Colanode:
Sign in
Choose your server, then sign in with admin@colanode.local and the colanode.admin.pass value from Step 4.
Colanode allows 10 sign-in attempts per email address in 10 minutes. After that, wait 10 minutes.
The image has no outgoing email, so Forgot password? cannot send a reset link. Keep the credentials file, and change the password in your account settings once you are in.
Pages, chat and databases
Your workspace opens with a Home space holding a Welcome page and a Discussions channel. Click anywhere on a page and type, or press / to add headings, to-do lists, quotes, subpages and databases. Everything syncs to the server and to every device signed in to the workspace.
Open Discussions to chat in real-time: type in the composer and press Enter.
Add your team
Sign-up is closed. Confirm it:
sudo colanode-signup status | tee /dev/stderr | grep -qx 'sign-up is CLOSED' && echo SIGNUP_CLOSEDsign-up is CLOSED SIGNUP_CLOSEDnginx refuses any sign-up while it is closed (403), and no account is created:
H="$(sudo sed -n 's/^set \$app_host "\(.*\)";$/\1/p' /etc/nginx/colanode-host.conf)" curl -sk -o /dev/null -w '%{http_code}\n' --resolve "$H:443:127.0.0.1" -X POST -H "Origin: https://$H" \
-H 'Content-Type: application/json' --data '{"name":"Test","email":"test@example.com","password":"Not-a-real-1234"}' \
"https://$H/client/v1/auth/email/register" | tee /dev/stderr | grep -qx 403 && echo "sign-up refused"403 sign-up refusedTo add a teammate, open sign-up and let them register in the Colanode app (No account yet? Register on the login screen). Then verify their account and close sign-up again:
sudo colanode-signup open
# they register in the app; their account waits for your verification
sudo colanode-activate --list sudo colanode-activate <their-email>
sudo colanode-signup closeNew accounts always wait for your verification, even while sign-up is open (account.verificationType is manual). Then invite them to your workspace from the workspace settings.
Your own DNS name and certificate
Point a DNS name at the instance (an Elastic IP keeps the address fixed), then:
sudo colanode-set-hostname <your-dns-name>This makes a new self-signed certificate for the name, updates nginx, the cross-site check and Colanode's web domain, and restarts the stack. Your config URL becomes https://<your-dns-name>/config; add it in the app as in Step 5.
For a certificate your browsers trust, replace /etc/ssl/colanode/colanode.crt (the full chain) and /etc/ssl/colanode/colanode.key (mode 0600, root) with your own and run sudo systemctl reload nginx. The certificate is only regenerated when you change the name again.
Security checks
The server's public configuration and the full credential round trip (the web app, anonymous API calls refused, sign-up closed, a wrong password refused, the administrator signs in and opens a sync socket, the database passwords work):
H="$(sudo sed -n 's/^set \$app_host "\(.*\)";$/\1/p' /etc/nginx/colanode-host.conf)" curl -sk --resolve "$H:443:127.0.0.1" "https://$H/config" | jq -c '{name,version}' | tee /dev/stderr \
| grep -qx '{"name":"Colanode","version":"0.4.7"}' && sudo colanode-selftest | tail -n 1 | cut -c1-60{"name":"Colanode","version":"0.4.7"} round-trip OK https://ec2-203-0-113-10.compute-1.amazonaws.The CVE-2026-110766 fence: an encoded traversal is refused before it reaches Colanode (400), and so is an avatar upload (403):
H="$(sudo sed -n 's/^set \$app_host "\(.*\)";$/\1/p' /etc/nginx/colanode-host.conf)" T="$(curl -sk -o /dev/null -w '%{http_code}' --path-as-is --resolve "$H:443:127.0.0.1" "https://$H/client/v1/avatars/..%2f..%2fconfig")" U="$(curl -sk -o /dev/null -w '%{http_code}' --resolve "$H:443:127.0.0.1" -X POST -H "Origin: https://$H" --data-binary x "https://$H/client/v1/avatars")" echo "traversal=$T upload=$U" | tee /dev/stderr | grep -qx 'traversal=400 upload=403' && echo "avatar fences hold"traversal=400 upload=403 avatar fences holdThe containers cannot reach the instance metadata service (and so cannot read the instance role's credentials). The first request is the control: the instance itself reaches the same address (HTTP 200), so a refusal from inside the container is the block at work, not a dead network path:
HOST="$(curl -s -m 5 -o /dev/null -w '%{http_code}' -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 60' http://169.254.169.254/latest/api/token)" CONT="$(sudo docker exec colanode-server node -e "fetch('http://169.254.169.254/latest/api/token',{method:'PUT',headers:{'X-aws-ec2-metadata-token-ttl-seconds':'60'},signal:AbortSignal.timeout(4000)}).then(r=>console.log('REACHED '+r.status)).catch(()=>console.log('BLOCKED'))")" echo "host=$HOST container=$CONT" | tee /dev/stderr | grep -qx 'host=200 container=BLOCKED' && echo "metadata service blocked for the containers"host=200 container=BLOCKED metadata service blocked for the containersWhat else the image does:
- PostgreSQL and Valkey sit on an internal Docker network with no route out, and the server runs as an unprivileged user on a read-only filesystem with every Linux capability dropped.
- nginx pins the host name and the client address it passes to Colanode (it never forwards
X-Forwarded-FororForwardedvalues a client sends) and refuses cross-site state changes and WebSocket upgrades. - SSH accepts keys only, with no root login. No core dumps are written by the services that hold secrets.
- The firmware metadata refresh (
fwupd-refresh) is masked, as there is no firmware it could update on EC2.
Managing the service
sudo systemctl restart colanode
# restart the three containers
sudo docker logs --tail 50 colanode-server
sudo tail -n 20 /var/log/nginx/colanode-upstream.log
# requests that reached ColanodeThe stack is defined in /opt/colanode/docker-compose.yml. Colanode's configuration, including the logging level and the workspace file size limit, is in /etc/colanode/config.json.
Backup and maintenance
Everything your team creates is on the data volume. For a consistent backup, stop the stack, snapshot the volume, and start it again:
sudo systemctl stop colanode aws ec2 create-snapshot --volume-id <data-volume-id> --description "colanode backup"
sudo systemctl start colanodeKeep /root/colanode-credentials.txt and /etc/colanode/ with your backups: the database password in /etc/colanode/pg_password is needed to open a restored database.
Operating system updates install automatically (unattended security upgrades). The Colanode, PostgreSQL and Valkey images are fixed at build time; new Colanode releases arrive as new versions of this listing.
Security recommendations
- Allow port 22 from your admin network only, and ports 80 and 443 only from the networks your team works from.
- Use your own DNS name and a trusted certificate (Step 9).
- Change the administrator password after your first sign-in, and keep sign-up closed except while you add people.
- Snapshot the data volume regularly.
Support and licensing
Colanode is open source under the Apache License 2.0, and there is no per-user license fee. The AMI price covers SecureAnyCloud's hardening, first-boot setup and support. The license, the build notice and the third-party list are in /usr/share/doc/colanode/.
Colanode is a trademark of its respective owner. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by, or sponsored by the Colanode project.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24 hour response SLA
Deploy on AWS
Launch Colanode 0.4.7 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com