Comentario 3.19.0 on AWS User Guide
Overview
This guide covers launching and using the Comentario 3.19.0 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg forums and social networks listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Comentario is a fast, privacy-focused open source comment server for web pages: a self-hosted alternative to hosted commenting services. You add a short HTML snippet to your site, and Comentario renders a comment thread on every page, with local accounts, moderation, voting, Markdown, RSS feeds, live updates, page view statistics, outbound webhooks, an audit log and a full REST API. One Go service serves the embeddable widget, its API and an Administration UI, and keeps everything in PostgreSQL.
What the cloudimg image adds:
- No default login. Comentario makes the first account that signs up the instance superuser. On this image that account is created on your instance's first boot, before anything is served, with a password generated on the instance and written to
/root/comentario-credentials.txt(root only). The PostgreSQL password and Comentario's server signing key are generated at the same time. The image ships an empty database and no known password. - Sign-up closed. Registration of new users in the Administration UI is switched off and users who are not domain owners cannot add domains, so nobody who reaches the instance can create an account on it. You invite users or switch sign-up on yourself. Commenter registration on your own sites is a per-domain setting you control.
- HTTPS from the first boot. nginx serves Comentario on port 443 with a certificate generated on your instance, port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped. Comentario itself listens on
127.0.0.1:8080only. - Fail closed. Comentario and nginx start only after first boot has finished. If it cannot finish, nothing is served.
- Hardened defaults. Comentario, nginx, PostgreSQL and the first boot service are blocked from the instance metadata service (Comentario fetches page titles, avatars and spam checks from the internet), the AMI requires IMDSv2, Comentario is handed the configured host name and the real client address from the connection (never values a client sends), Comentario refuses state-changing requests from other origins, and nginx also refuses them from a plain
http://origin in front of the Administration UI. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Comentario 3.19.0 (the official package, checksum verified), nginx 1.24 and PostgreSQL 16 (from Ubuntu 24.04), cloud-init and the AWS Systems Manager agent.
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) from your admin network, and TCP 443 (Comentario) and TCP 80 (redirects to HTTPS) from the internet, because the comment widget on your sites loads from this instance. Never open 5432 or 8080: PostgreSQL and Comentario listen on the loopback address only.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Comentario 3.19.0 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair and a security group as above.
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=comentario}]'
First boot takes well under a minute after the instance is running.
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Comentario 3.19.0 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot sets the passwords, the signing key and the certificate and creates the owner account, then Comentario and nginx start:
systemctl is-active nginx comentario postgresql@16-main comentario-firstboot
sudo test -f /var/lib/cloudimg/comentario-firstboot.done && echo FIRSTBOOT_DONE
All four units are active and the first boot marker is present:
active
active
active
active
FIRSTBOOT_DONE
Only SSH and nginx listen on network ports; Comentario and PostgreSQL listen on the loopback address:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | grep -v '127.0.0.5' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort
0.0.0.0:22 users:(("sshd"),("systemd"))
0.0.0.0:443 users:(("nginx"),("nginx"),("nginx"))
0.0.0.0:80 users:(("nginx"),("nginx"),("nginx"))
127.0.0.1:5432 users:(("postgres"))
127.0.0.1:8080 users:(("comentario"))
[::]:22 users:(("sshd"),("systemd"))
[::]:443 users:(("nginx"),("nginx"),("nginx"))
[::]:80 users:(("nginx"),("nginx"),("nginx"))
Step 4: Get your URL and password
sudo cat /root/comentario-credentials.txt
The file is readable by root only:
# Comentario 3.19.0 - generated on first boot by comentario-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.
comentario.url=https://<public-ip>/
comentario.owner.email=admin@comentario.local
comentario.owner.pass=<COMENTARIO_OWNER_PASSWORD>
comentario.db.name=comentario
comentario.db.user=comentario
comentario.db.pass=<COMENTARIO_DB_PASSWORD>
# Sign in at https://<public-ip>/en/auth/login with the owner email and password above. The owner is the
# instance superuser. The certificate is self signed (minted on this instance): accept the browser warning
# once, or install your own. Port 80 redirects to https. Change the name Comentario is served as:
# sudo comentario-set-hostname <your-dns-name>
# Sign-up in the Administration UI is OFF; turn it on under Administration > Configuration if you want it.
# PostgreSQL listens on 127.0.0.1:5432 only. User guide: https://www.cloudimg.co.uk/guides/comentario-3-19-0-on-ubuntu-24-04-aws/
The URL uses the instance's public IP address from the EC2 instance metadata. The certificate also names the public DNS name and the private IP address. If you stop and start the instance without an Elastic IP, the boot service picks up the new address, issues a new certificate for it and updates Comentario's base URL. To serve Comentario under your own DNS name, which you should do before you embed it in a site, see Step 7.
Step 5: Sign in
Browse to the URL from the credentials file. Your browser warns once about the self signed certificate; accept it (or install your own certificate, Step 7). Sign in with the owner email admin@comentario.local and the password from the credentials file. The Sign up here link on the sign in page leads to a Sign-up closed page until you switch registration on.

You land on the dashboard, which summarises users, page views and comments over the last 30 days. The navigation on the left gives you Domains, Users, the Audit log, Configuration and your account. Open your account (Instance Owner) to set your own email address and display name and to change the password.

Step 6: Add your site and embed the comments
Choose Domains > New domain, enter the host of the website you want comments on (for example blog.example.com) and a name, and select Create. The domain page shows the snippet to paste into every page that should carry a comment thread:
<script defer src="https://<your-comentario-host>/comentario.js"></script>
<comentario-comments></comentario-comments>
Comentario renders a thread per page URL. Under the domain you moderate Comments, see Pages and Statistics, manage Domain users (moderators) and decide which commenter registration methods are allowed (Edit settings > Authentication): anonymous comments, local accounts or single sign-on. Webhooks on the domain page post comment events to a URL you choose; by default Comentario accepts only https:// targets on public addresses. Federated sign in (GitHub, GitLab, Google and others) needs the provider's keys in /etc/comentario/secrets.yaml; none is configured on this image.
Administration > Configuration > Dynamic holds the instance settings. Enable registration of new users is off on this image; switch it on only if you want anyone to be able to create an account in the Administration UI.

The Audit log records sign ins (including failed ones), domain and user changes and other administrative actions, with who did them and when; use Filter to narrow it down.

Set up outbound email (an smtpServer block in /etc/comentario/secrets.yaml, then sudo systemctl restart comentario) so that password resets and reply notifications reach your users.
Step 7: Your own DNS name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address stable), then set the name Comentario is served as. This mints a new self signed certificate for the name, updates nginx and Comentario's base URL (used in the embed snippet, in links and for its origin checks), the URL in /root/comentario-credentials.txt, and keeps the name across reboots:
sudo comentario-set-hostname <your-domain>
Your sites load the widget from this name, so browsers must trust its certificate: install one from a public certificate authority (for example one issued by Let's Encrypt for <your-domain>) over the generated pair and reload nginx (running comentario-set-hostname again replaces it with a self signed one):
sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/comentario.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/comentario.key
sudo nginx -t && sudo systemctl reload nginx
Step 8: Security checks
The shipped round trip signs in as the owner with this instance's password over HTTPS, proves a wrong, blank and common password are refused, reads the signed in user, proves the Administration UI refuses a sign-up and that a sign in from another site's origin is refused, and checks that PostgreSQL accepts the application user's password and refuses a wrong one. Credentials are handed to curl and psql in root only temporary files, never on a command line:
sudo bash /usr/local/sbin/comentario-cred-roundtrip.sh
OK per-instance owner signs in over HTTPS (200, superuser); wrong/blank/default passwords refused (401 invalid-credentials); GET /api/user; UI sign-up refused (403 signups-forbidden); cross-origin login refused (403 by the cross-origin check); PostgreSQL app user: right password in, wrong refused
The running instance reports its version, its configured base URL and the closed sign-up settings:
curl -s -H 'Host: localhost' http://127.0.0.1:8080/api/config | jq -c '{version: .staticConfig.version, baseUrl: .staticConfig.baseUrl, signup: (.dynamicConfig | map(select(.key=="auth.signup.enabled" or .key=="operation.newOwner.enabled")) | sort_by(.key) | map({(.key): .value}) | add)}'
{"version":"3.19.0","baseUrl":"https://<public-ip>/","signup":{"auth.signup.enabled":"false","operation.newOwner.enabled":"false"}}
Every service is denied the instance metadata service (and Azure's equivalent address), so a URL Comentario is asked to fetch can never reach your instance credentials:
for u in comentario nginx postgresql@16-main comentario-firstboot; do printf '%s: %s\n' "$u" "$(systemctl show -p IPAddressDeny --value $u.service | tr ' ' '\n' | sort | xargs)"; done
comentario: 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
nginx: 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
postgresql@16-main: 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
comentario-firstboot: 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
The block holds inside the running service. This joins a shell to Comentario's control group and tries to reach the metadata service from there (000 means the connection was refused):
CG=$(systemctl show -p ControlGroup --value comentario.service)
sudo bash -c "echo \$\$ > /sys/fs/cgroup$CG/cgroup.procs; curl -s -m 5 -o /dev/null -w 'metadata from the comentario service: %{http_code}\n' -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 60' http://169.254.169.254/latest/api/token; true"
metadata from the comentario service: 000
Comentario 3.19.0 checks every state-changing request against its own origin (https:// plus the configured host) and refuses requests from other sites; this replaced the cross-site request forgery library of Comentario 3.17 and earlier (CVE-2025-47909). In front of it, nginx also refuses any state-changing request from a plain http:// or null origin before it reaches the Administration UI's API, and accepts WebSocket upgrades only on the embed live-update channel. The first request below comes from another site and is refused by Comentario, the second comes from the plain http:// form of the instance's own host and is refused by nginx:
H=$(sudo sed -n 's#^comentario.url=https://\([^/]*\)/#\1#p' /root/comentario-credentials.txt)
curl -sk --resolve "$H:443:127.0.0.1" -H 'Origin: https://other-site.example' -H 'Content-Type: application/json' -d '{}' "https://$H/api/auth/login" | jq -r .id
curl -sk --resolve "$H:443:127.0.0.1" -H "Origin: http://$H" -H 'Content-Type: application/json' -d '{}' "https://$H/api/auth/login"
xsrf-check-failed
cloudimg: state-changing request from a plain-http origin refused
Step 9: Versions and the command line
dpkg-query -W -f='${Package} ${Version}\n' comentario nginx postgresql-16
id comentario
cat /etc/cloudimg/comentario-release.txt
comentario 3.19.0
nginx 1.24.0-2ubuntu7.18
postgresql-16 16.15-0ubuntu0.24.04.1
uid=997(comentario) gid=987(comentario) groups=987(comentario)
cloudimg: Comentario 3.19.0 (MIT) from gitlab.com/comentario/comentario (package registry), .deb sha256 455b501078da9207d3b8cfa7fae6d4159dc687c312431c9511ac35720e37f9ec; LICENSE sha256 ce3b8dc149745f4095607f25888dd7dd6cd1e585d8761208469bb88ec97cfed9.
Package versions move as Ubuntu publishes security updates. The files that matter:
/etc/comentario/comentario.conf: listen address (127.0.0.1:8080),BASE_URL(set bycomentario-set-hostname) and other static settings; see the static configuration reference./etc/comentario/secrets.yaml(ownercomentario, mode 0600): the PostgreSQL connection, the server signing key (serverSigningKey), SMTP and identity provider keys./etc/nginx/sites-available/cloudimg-comentarioand/etc/nginx/ssl/: the HTTPS front end and its certificate.journalctl -u comentarioshows Comentario's log; restart it withsudo systemctl restart comentario.
Step 10: Changing passwords
Change the owner password in the Administration UI on your account page (Instance Owner), and give each person who manages domains their own account under Users.
To change the PostgreSQL password of the application user, set it in PostgreSQL (you are prompted for it, so it never appears on a command line), put the same value in the password: line of /etc/comentario/secrets.yaml, then restart Comentario:
sudo -u postgres psql -c '\password comentario'
sudo nano /etc/comentario/secrets.yaml
sudo systemctl restart comentario
Step 11: Backup and maintenance
All of Comentario's state (domains, pages, users, comments and settings) is in the comentario PostgreSQL database. Back it up regularly and copy the dump off the instance (for example to Amazon S3):
sudo -u postgres pg_dump -Fc comentario > <backup-dir>/comentario-$(date +%F).dump
Also keep a copy of /etc/comentario/secrets.yaml: the server signing key in it signs email-change confirmations. Ubuntu security updates install automatically. To upgrade Comentario, install a newer release package from the Comentario releases after taking a backup, and restart the service; database migrations run on start. The Administration UI shows a notice when a newer release is available.
Step 12: Security recommendations
- Serve Comentario under your own DNS name with a publicly trusted certificate before embedding it (Step 7), and keep the security group to 22 from your admin network plus 80 and 443.
- Set your own email address on the owner account and configure outbound email, so password resets work.
- Leave Enable registration of new users off unless you need open registration, and choose the commenter sign up methods per domain.
- Take regular database backups and test a restore.
Support and licensing
Comentario is open source software released under the MIT License (copyright Dmitry Kann and Commento, Inc.); the licence text is installed at /usr/share/doc/comentario/LICENSE. cloudimg provides 24/7 technical support for this image by email and live chat: support@cloudimg.co.uk. For Comentario itself, see the documentation.
Comentario is a trademark of its respective owner. cloudimg is not affiliated with or endorsed by the Comentario project. All other product names are trademarks of their respective owners.