OpenObserve 1.1.2
Overview
OpenObserve is an open-source observability platform for logs, metrics and traces. Agents send data over HTTP (JSON, Elasticsearch bulk or OpenTelemetry OTLP). You search it with SQL or PromQL, build dashboards and set alerts in the built-in web interface. It is a single, self-contained binary that stores everything on local disk, so a single instance needs no external database or object store.
This guide covers launching and using the OpenObserve 1.1.2 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud log management listing on AWS Marketplace. You select it as the software version when you subscribe and launch.
What you get:
- HTTPS from the first boot. nginx is the only network entry point. It serves the web interface and every ingest API on port 443 with a certificate generated on your instance's first boot. Port 80 only redirects to HTTPS.
- A root password unique to your instance. OpenObserve creates its root user on the first start of an empty store. The image ships an empty store and no password. First boot generates the password, writes it to the root-only file
/root/openobserve-credentials.txtand only then starts OpenObserve. No two instances share a password, and OpenObserve will not start before first boot has run. - OpenObserve on loopback only. OpenObserve's HTTP API listens on
127.0.0.1:5080and its gRPC port on127.0.0.1:5081. Neither is reachable from the network. Agents use OTLP over HTTPS on port 443. - Fail closed. nginx refuses to start until first boot has written the certificate and the password.
- Hardened service. OpenObserve runs as an unprivileged
openobserveuser in a systemd sandbox. It cannot reach the EC2 instance metadata service, so an alert webhook or URL import cannot be turned against the instance's credentials. Requests for a host name the instance does not serve are dropped, cross-site requests and WebSocket upgrades are refused, and session cookies are marked Secure. OpenObserve's own metrics endpoint is not exposed, and nginx logs the real client address rather than anyX-Forwarded-Forheader a client sends. - Data on its own volume. Everything OpenObserve stores lives on a separate 20 GiB EBS volume mounted at
/var/lib/openobserve. You can grow it independently of the system disk. - Key-only SSH. Password logins, root logins and X11 forwarding are switched off.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: OpenObserve 1.1.2, the unmodified upstream open-source build (/usr/local/bin/openobserve, GNU AGPL v3.0), nginx, Ubuntu 24.04 LTS, 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), TCP 443 (web interface and ingest) and TCP 80 (redirects to HTTPS) from your own networks and the hosts that send data only. Never open ports 5080 or 5081, because OpenObserve listens on loopback.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Select OpenObserve 1.1.2 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2.
Choose m5.large or larger, your key pair and a security group as described in the prerequisites. OpenObserve caches recent data in memory, so give busy instances more RAM. The AMI includes a 20 GiB data volume. Increase its size on the Configure storage step if you expect to keep a lot of data.
To launch with the AWS CLI instead, 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=openobserve}]'Connect to your instance
Connect over SSH as the ubuntu user. The table below lists the SSH user for this version.
Version SSH user
OpenObserve 1.1.2 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>The login message shows the web address and where to find the password.
Check the services
First boot takes a few seconds. It generates the password and the certificate, starts OpenObserve on an empty store, and then starts nginx in front of it. Run these commands to confirm:
systemctl is-active openobserve-firstboot openobserve nginx
sudo test -f /var/lib/sac/data/openobserve-firstboot.done && echo FIRSTBOOT_DONE /usr/local/bin/openobserve --version curl -s http://127.0.0.1:5080/config | jq -r '"build_type=\(.build_type) commit=\(.commit_hash)"'active active active FIRSTBOOT_DONE openobserve v1.1.2 build_type=opensource commit=d16d693ba99bc20621a58b948ecbcad7ec7fa882build_type=opensource and the commit of the upstream v1.1.2 tag confirm the open source build.
Only SSH and nginx listen on public addresses. OpenObserve listens on loopback:
sudo ss -Hlntp | awk '{print $4, $6}' | grep -v '127.0.0.5' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort0.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:5080 users:(("openobserve")) 127.0.0.1:5081 users:(("openobserve")) [::]:22 users:(("sshd"),("systemd")) [::]:443 users:(("nginx"),("nginx"),("nginx")) [::]:80 users:(("nginx"),("nginx"),("nginx"))The data lives on its own EBS volume:
findmnt -no TARGET,SOURCE,FSTYPE /var/lib/openobserve df -h --output=size,avail,target /var/lib/openobserve/var/lib/openobserve /dev/nvme1n1 ext4 Size Avail Mounted on 20G 19G /var/lib/openobserveSSH accepts keys only. Passwords, root logins and X11 forwarding are switched off in /etc/ssh/sshd_config.d/00-sac.conf, which sorts before every other SSH setting. Check the effective values:
sudo sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin|x11forwarding|pubkeyauthentication) 'permitrootlogin no pubkeyauthentication yes passwordauthentication no kbdinteractiveauthentication no x11forwarding noGet your address and password
The address, user name and ingest URL are in the root-only file /root/openobserve-credentials.txt. Read them with sudo:
sudo grep -E '^OPENOBSERVE_(URL|USERNAME|INGEST_URL)=' /root/openobserve-credentials.txtOPENOBSERVE_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ OPENOBSERVE_USERNAME=admin@openobserve.local OPENOBSERVE_INGEST_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/api/default/<stream>/_jsonThe password is the OPENOBSERVE_PASSWORD line of the same file: sudo grep '^OPENOBSERVE_PASSWORD=' /root/openobserve-credentials.txt. It is unique to this instance, so store it in your password manager.
The address uses the instance's public DNS name from EC2 instance metadata (IMDSv2). If the instance has no public name, it uses the public or private IPv4 address. The certificate names that host plus the instance's public and private IP addresses:
openssl x509 -in /etc/ssl/openobserve/openobserve.crt -noout -subject -ext subjectAltName -enddatesubject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = sac X509v3 Subject Alternative Name: DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost notAfter=<date about 27 months after first boot>Check the login
This check confirms that port 80 redirects to HTTPS and /healthz answers without a login. It also confirms that the API refuses a missing or wrong password and accepts yours, and that a request for a host name the instance does not serve is dropped.
The commands read the password into a shell variable and hand it to curl through a file descriptor, so it never appears in the process list or your shell history:
H=$(sudo sed -n 's#^OPENOBSERVE_URL=https://\([^/]*\)/.*#\1#p' /root/openobserve-credentials.txt)
U=$(sudo sed -n 's/^OPENOBSERVE_USERNAME=//p' /root/openobserve-credentials.txt)
PW=$(sudo sed -n 's/^OPENOBSERVE_PASSWORD=//p' /root/openobserve-credentials.txt) CA=/etc/ssl/openobserve/openobserve.crt curl -s -o /dev/null -w 'http:// -> %{http_code} %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/" curl -s -w ' <- healthz, HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" "https://$H/healthz" curl -s -o /dev/null -w 'no login -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" "https://$H/api/default/streams" curl -s -o /dev/null -w 'wrong password -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" -u "$U:not-the-password" "https://$H/api/default/streams" curl -s -o /dev/null -w 'your password -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" -K <(printf 'user = "%s:%s"\n' "$U" "$PW") "https://$H/api/default/streams" curl -s -o /dev/null -w 'metrics -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" "https://$H/metrics" curl -sk -o /dev/null -w 'other host -> HTTP %{http_code} (000 = connection dropped)\n' -H 'Host: evil.example' https://127.0.0.1/ || truehttp:// -> 301 https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ {"status":"ok"} <- healthz, HTTP 200 no login -> HTTP 401 wrong password -> HTTP 401 your password -> HTTP 200 metrics -> HTTP 404 other host -> HTTP 000 (000 = connection dropped)--resolve sends the request to this instance while keeping the real host name, so the certificate check passes. From another machine, drop --resolve and use the address directly.
Sign in to the web interface
Open the OPENOBSERVE_URL address from Step 4 in your browser. The certificate is self-signed and made on your instance, so your browser asks you to accept it once. Step 10 shows how to use your own name and certificate.
Sign in with the email admin@openobserve.local and your password.
Logs lists your log streams. Pick a stream and a time range to see a histogram of events by level and the matching records. Click a field on the left to add it to the view.
Type a filter such as level='error' in the query bar and choose Run query. Or switch on SQL mode to run full SQL over the stream.
Send your first logs and query them
Every ingest and search API is under https://<your-host>/api/<organisation>/... and uses HTTP Basic Auth over HTTPS. The instance starts with the organisation default.
This example sends two JSON log lines to a stream called app_logs, which OpenObserve creates on first write. It then searches the stream with SQL:
H=$(sudo sed -n 's#^OPENOBSERVE_URL=https://\([^/]*\)/.*#\1#p' /root/openobserve-credentials.txt)
U=$(sudo sed -n 's/^OPENOBSERVE_USERNAME=//p' /root/openobserve-credentials.txt)
PW=$(sudo sed -n 's/^OPENOBSERVE_PASSWORD=//p' /root/openobserve-credentials.txt) CA=/etc/ssl/openobserve/openobserve.crt AUTH() { printf 'user = "%s:%s"\n' "$U" "$PW"; } curl -s --cacert $CA --resolve "$H:443:127.0.0.1" -K <(AUTH) -H 'Content-Type: application/json' \
-d '[{"level":"info","service":"checkout","message":"order placed","order_id":1001}, {"level":"error","service":"payments","message":"card declined","order_id":1002}]' \
"https://$H/api/default/app_logs/_json"; echo sleep 3
NOW=$(date +%s%6N);
FROM=$((NOW - 3600000000)) curl -s --cacert $CA --resolve "$H:443:127.0.0.1" -K <(AUTH) -H 'Content-Type: application/json' \
-d "{\"query\":{\"sql\":\"SELECT level, service, message FROM \\\"app_logs\\\" WHERE level = 'error'\",\"start_time\":$FROM,\"end_time\":$NOW,\"from\":0,\"size\":10}}" \
"https://$H/api/default/_search" | jq -c '{total, hits: [.hits[] | {level, service, message}]}'{"code":200,"status":[{"name":"app_logs","successful":2,"failed":0}]} {"total":1,"hits":[{"level":"error","service":"payments","message":"card declined"}]}Search times are in microseconds since the epoch. The same data appears under the app_logs stream in Logs in the web interface.
Connect your agents
Point log shippers and OpenTelemetry collectors at the instance's HTTPS address. These are the useful endpoints for the organisation default:
Data Endpoint
JSON logs https://<your-host>/api/default/<stream>/_json
Elasticsearch bulk (Fluent Bit, Vector, Logstash) https://<your-host>/api/default/_bulk
OTLP over HTTP: logs, traces, metrics https://<your-host>/api/default/v1/logs, /v1/traces, /v1/metrics
Prometheus remote write https://<your-host>/api/default/prometheus/api/v1/write
This example configures an OpenTelemetry Collector exporter:
exporters: otlphttp/openobserve: endpoint: https://<your-host>/api/default headers: Authorization: Basic <base64 of user-email:password> tls: ca_file: /etc/otel/openobserve.crt
# or insecure_skip_verify: true while you testOTLP over gRPC (port 5081) is not exposed, so use OTLP over HTTPS as shown above.
Do not give agents the root login. In the web interface, open IAM > Users and add a user with a role limited to ingestion. Use that user's email and password, or its token from Data sources, in your agents.
Copy /etc/ssl/openobserve/openobserve.crt to your agents so they can verify the self-signed certificate. Alternatively, install a certificate from your own authority (Step 10). Open port 443 in the security group to the agents' addresses.
Check the security settings
OpenObserve cannot reach the EC2 instance metadata service, so an alert destination or URL import cannot be used to read instance credentials. The root password exists only in root-only files:
systemctl show -p IPAddressDeny --value openobserve
sudo stat -c '%a %U %n' /etc/openobserve/root-user.env /root/openobserve-credentials.txt /etc/ssl/openobserve/openobserve.key cat /etc/openobserve/web-url.env169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 600 root /etc/openobserve/root-user.env 600 root /root/openobserve-credentials.txt 600 root /etc/ssl/openobserve/openobserve.key ZO_WEB_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.comZO_WEB_URL is the address OpenObserve uses in links, for example in alert messages. It comes from the configured host name, never from a request.
Use your own DNS name, certificate or password
The served host name comes from configuration, never from a request. To serve OpenObserve under your own DNS name, point the name at the instance and run the helper. The helper records the name and makes a new self-signed certificate for it. It also updates ZO_WEB_URL and /root/openobserve-credentials.txt, reloads nginx and restarts OpenObserve:
sudo openobserve-set-hostname logs.example.comTo use a certificate from your own certificate authority instead, put the full chain in /etc/ssl/openobserve/openobserve.crt and the private key in /etc/ssl/openobserve/openobserve.key (owner root, mode 0600). Then run sudo nginx -t && sudo systemctl reload nginx. Running openobserve-set-hostname again replaces them with a self-signed pair.
To change the root password, sign in, open IAM > Users, edit admin@openobserve.local and set a new password. Store it in your password manager and update /root/openobserve-credentials.txt.
The ZO_ROOT_USER_PASSWORD value in /etc/openobserve/root-user.env is used only when OpenObserve creates the root user on an empty store. Changing it later has no effect on an existing instance.
Storage, backups and operations
- Storage. All data is under
/var/lib/openobserveon its own EBS volume. That includes ingested logs, metrics and traces, plus the metadata database with users, dashboards and alerts. Grow the volume with Modify volume in the EC2 console, then runsudo resize2fs <device>. Find the device withfindmnt /var/lib/openobserve. - Backups. Back up with EBS snapshots of the data volume. For a consistent copy, stop OpenObserve first (
sudo systemctl stop openobserve) or snapshot both volumes together. - Retention. Data is kept for 3,650 days by default. To keep the volume from filling, set a shorter retention per stream in its settings under Data > Streams. For the whole instance, set
ZO_COMPACT_DATA_RETENTION_DAYS=<days>in/etc/openobserve/openobserve.env, then runsudo systemctl restart openobserve. - Operations. Manage the services with
systemctl status openobserve nginxand read their logs withjournalctl -u openobserve -u nginx. Unattended upgrades keep Ubuntu and nginx patched. Check the listing for newer OpenObserve versions.
Security notes
- Restrict ports 443 and 80 to the networks your team and your agents use. Ports 5080 and 5081 are never exposed.
- Give each agent or team its own user with the least access it needs, instead of sharing the root login.
- SSH accepts key logins as
ubuntuonly, with no passwords, no root login and no X11 forwarding. Usesudofor administration. - The AMI requires IMDSv2. nginx logs the real client address of every request and ignores
X-Forwarded-Forheaders sent by clients. - The web interface shows an offer for OpenObserve's commercial edition. This image runs the open-source edition and works without it.
Support and licensing
OpenObserve is open source under the GNU Affero General Public License v3.0. The image runs the unmodified upstream v1.1.2 release. The licence, a note with the release checksums and a link to the corresponding source code are in /usr/share/doc/openobserve/.
There is no per-user or per-CPU licence fee. The AMI price covers SecureAnyCloud's hardening, first-boot setup and support.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
OpenObserve is developed by OpenObserve Inc. For features, see the upstream documentation at https://openobserve.ai/docs/.
OpenObserve is a trademark of OpenObserve Inc. SecureAnyCloud is not affiliated with or endorsed by OpenObserve Inc. The name is used only to identify the upstream software.
Deploy on AWS
Launch OpenObserve 1.1.2 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