Parseable 3.2.5 on AWS User Guide
Overview
This guide covers launching and using the Parseable 3.2.5 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg log management listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Parseable is an open source log analytics and observability platform written in Rust. Applications, agents and the OpenTelemetry Collector send logs and events to its HTTP ingest API; Parseable detects the schema, stores the data in a compressed columnar format and lets you explore it in a web console or query it with SQL. On this image it runs in local storage mode: everything is stored on the instance's own disk, with no external object store and no separate database.
Upstream Parseable listens on all interfaces and falls back to the login admin / admin when no password is configured. The cloudimg image changes that:
- HTTPS from the first boot. nginx is the only network entry point and serves the web console and every ingest and query API on port 443 with a certificate generated on your instance's first boot. Port 80 only redirects to HTTPS.
- An admin password unique to your instance. First boot generates the password and writes it to the root only file
/root/parseable-credentials.txt. Theadmin/admindefault is never live, no password is baked into the image and no two instances share one. - Parseable on loopback only. Its HTTP port 8000 and its internal gRPC and Arrow Flight ports 8001 and 8002 are bound to
127.0.0.1and are never reachable from the network, so never open them in a security group. - Fail closed. Parseable and nginx both refuse to start until first boot has written the password and the certificate.
- Fixed host name and real client addresses. Requests for a host name the instance does not serve are dropped, nginx passes the real client address to Parseable (client supplied
X-Forwarded-Forheaders are overwritten), cross site browser requests that change state are refused, and no cross origin browser access is granted. - Instance metadata blocked for the service. An administrator can point Parseable alert targets at any URL, so the Parseable service itself cannot reach the EC2 instance metadata endpoint.
- 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: Parseable 3.2.5 (/usr/local/bin/parseable, the unmodified upstream open source release binary, checksum verified, AGPL-3.0, with the licence text at /usr/local/share/parseable/LICENSE), nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. Parseable runs as its own unprivileged parseable user.
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.
- A security group that allows TCP 22 (SSH) from your own networks and TCP 443 (the web console and the ingest and query APIs) from the networks your users and log agents are in. TCP 80 only redirects to HTTPS and is optional. If your agents run inside the same VPC, allow 443 from the VPC CIDR only.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Parseable 3.2.5 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. Parseable keeps your data on the root volume, so give it room on the launch page: 30 GiB or more for a real workload (the root file system grows to the volume size automatically on first boot).
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> \
--block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=50,VolumeType=gp3}' \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=parseable}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Parseable 3.2.5 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot generates the certificate and the password, then Parseable and nginx start:
systemctl is-active parseable nginx parseable-firstboot
sudo test -f /var/lib/cloudimg/parseable-firstboot.done && echo FIRSTBOOT_DONE
parseable --version
active
active
active
FIRSTBOOT_DONE
parseable 3.2.5
Only SSH and nginx listen on public addresses; Parseable 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' | 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:8000 users:(("parseable"))
127.0.0.1:8001 users:(("parseable"))
127.0.0.1:8002 users:(("parseable"))
[::]:22 users:(("sshd"),("systemd"))
[::]:443 users:(("nginx"),("nginx"),("nginx"))
[::]:80 users:(("nginx"),("nginx"),("nginx"))
Step 4: Get your URL and password
The URL and the user name are in the root only credentials file:
sudo grep -E '^parseable\.(url|admin\.user)=' /root/parseable-credentials.txt
parseable.url=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
parseable.admin.user=admin
The password is the parseable.admin.pass line of the same file: sudo grep '^parseable.admin.pass=' /root/parseable-credentials.txt. Store it in your password manager or secrets store; it is unique to this instance.
The URL uses the instance's public DNS name from EC2 instance metadata (IMDSv2), or its public or private IPv4 address when it has no public name. The certificate names that host plus the instance's public and private IP addresses, so browsers and agents can use any of them:
openssl x509 -in /etc/parseable/tls/cert.pem -noout -subject -ext subjectAltName -enddate
subject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = cloudimg
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>
Step 5: Check the login
Without the password every API is refused, the admin / admin default and a wrong password are refused, and port 80 redirects to HTTPS. With the password the API answers, and the liveness probe answers without a login for load balancer health checks. The commands below read the password from the credentials file into a shell variable and pass it to curl through a file descriptor, so it never appears in the process list or your shell history:
H=$(sudo sed -n 's#^parseable\.url=https://\([^/]*\)/.*#\1#p' /root/parseable-credentials.txt)
PW=$(sudo sed -n 's/^parseable\.admin\.pass=//p' /root/parseable-credentials.txt)
CA=/etc/parseable/tls/cert.pem
curl -s -o /dev/null -w 'http:// -> %{http_code} %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -s -o /dev/null -w 'liveness -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" "https://$H/api/v1/liveness"
curl -s -o /dev/null -w 'no login -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" "https://$H/api/v1/logstream"
curl -s -o /dev/null -w 'admin:admin -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" -K <(printf 'user = "admin:admin"\n') "https://$H/api/v1/logstream"
curl -s -o /dev/null -w 'wrong password -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" -K <(printf 'user = "admin:not-the-password"\n') "https://$H/api/v1/logstream"
curl -s -o /dev/null -w 'admin + password -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" -K <(printf 'user = "admin:%s"\n' "$PW") "https://$H/api/v1/logstream"
http:// -> 301 https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
liveness -> HTTP 200
no login -> HTTP 401
admin:admin -> HTTP 403
wrong password -> HTTP 403
admin + password -> HTTP 200
--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 URL directly.
The image also ships a self test that runs the same checks and prints only OK:
sudo bash /usr/local/sbin/parseable-credcheck.sh
OK
Step 6: Send events and query them with SQL
Parseable organises data into datasets (log streams). Create one, send a JSON array of events to /api/v1/ingest with the dataset named in the X-P-Stream header, then query it with SQL through /api/v1/query:
H=$(sudo sed -n 's#^parseable\.url=https://\([^/]*\)/.*#\1#p' /root/parseable-credentials.txt)
PW=$(sudo sed -n 's/^parseable\.admin\.pass=//p' /root/parseable-credentials.txt)
CA=/etc/parseable/tls/cert.pem
curl -s -o /dev/null -w 'create dataset -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" \
-K <(printf 'user = "admin:%s"\n' "$PW") -X PUT "https://$H/api/v1/logstream/demoapp"
curl -s -o /dev/null -w 'ingest -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" \
-K <(printf 'user = "admin:%s"\n' "$PW") -X POST -H 'X-P-Stream: demoapp' -H 'Content-Type: application/json' --data '[
{"host":"web-01","level":"info","service":"checkout","status":200,"message":"order placed"},
{"host":"web-02","level":"warn","service":"checkout","status":200,"message":"slow response"},
{"host":"api-01","level":"error","service":"payments","status":504,"message":"gateway timeout"}
]' "https://$H/api/v1/ingest"
sleep 3
T0=$(date -u -d '-1 hour' +%Y-%m-%dT%H:%M:%SZ); T1=$(date -u -d '+1 hour' +%Y-%m-%dT%H:%M:%SZ)
curl -s --cacert $CA --resolve "$H:443:127.0.0.1" -K <(printf 'user = "admin:%s"\n' "$PW") -H 'Content-Type: application/json' \
--data "{\"query\":\"SELECT host, level, service, status, message FROM demoapp WHERE level <> 'info' ORDER BY status DESC\",\"startTime\":\"$T0\",\"endTime\":\"$T1\"}" \
"https://$H/api/v1/query" | jq -c '.[]'
create dataset -> HTTP 200
ingest -> HTTP 200
{"host":"api-01","level":"error","service":"payments","status":504.0,"message":"gateway timeout"}
{"host":"web-02","level":"warn","service":"checkout","status":200.0,"message":"slow response"}
Parseable detected the fields from the JSON and added its own p_timestamp, p_src_ip and p_user_agent columns. Every query needs a time window (startTime and endTime).
Parseable also accepts OpenTelemetry logs, metrics and traces over OTLP/HTTP at /v1/logs, /v1/metrics and /v1/traces:
H=$(sudo sed -n 's#^parseable\.url=https://\([^/]*\)/.*#\1#p' /root/parseable-credentials.txt)
PW=$(sudo sed -n 's/^parseable\.admin\.pass=//p' /root/parseable-credentials.txt)
CA=/etc/parseable/tls/cert.pem
curl -s -o /dev/null -w 'otlp logs -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" \
-K <(printf 'user = "admin:%s"\n' "$PW") -X POST -H 'Content-Type: application/json' -H 'X-P-Stream: otel-demo' \
--data '{"resourceLogs":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"guide-test"}}]},"scopeLogs":[{"logRecords":[{"severityText":"INFO","body":{"stringValue":"hello from OTLP/HTTP"}}]}]}]}' \
"https://$H/v1/logs"
otlp logs -> HTTP 200
Step 7: Use the web console
Open the parseable.url from Step 4 (https://<your-host>/) in a browser. The certificate is self signed, so the browser warns once; accept it, or install your own certificate (Step 10). Sign in as admin with the password from the credentials file:

The home page lists your datasets and the console's sections for logs, metrics, traces, dashboards, alerts and the SQL editor:

Logs shows a dataset's events over time with every detected field in the side panel; pick a time range, filter, group and add columns:

The SQL Editor runs the same SQL as the query API and shows the results as a table or a chart:

The console's AI features (Keystone, the AI assistant and MCP) need a model provider you configure yourself; nothing is set up on the image.
Step 8: Send logs from your servers
Any agent that can POST JSON over HTTPS with basic authentication works: Fluent Bit, Vector, Fluentd, Logstash or the OpenTelemetry Collector. Give it the host, the user, the password and the instance's certificate so it can verify the connection. Copy the certificate to each agent host first (it is public, not a secret):
scp -i <your-key.pem> ubuntu@<parseable-host>:/etc/parseable/tls/cert.pem ./parseable.crt
Use a separate user for agents rather than the admin login: create it in the console's user management (or with the /api/v1/user API) and give it a role that can only ingest into the datasets it needs.
Fluent Bit ([OUTPUT] section):
[OUTPUT]
Name http
Match *
Host <parseable-host>
Port 443
URI /api/v1/ingest
Format json
Header X-P-Stream app-logs
tls On
tls.verify On
tls.ca_file /etc/fluent-bit/parseable.crt
http_User <ingest-user>
http_Passwd <ingest-user-password>
Vector (vector.yaml):
sinks:
parseable:
type: http
inputs: [your_source]
uri: https://<parseable-host>/api/v1/ingest
method: post
encoding:
codec: json
request:
headers:
X-P-Stream: app-logs
auth:
strategy: basic
user: <ingest-user>
password: <ingest-user-password>
tls:
ca_file: /etc/vector/parseable.crt
OpenTelemetry Collector: use an otlphttp exporter with endpoint: https://<parseable-host>, the header X-P-Stream: <dataset>, a basicauth extension and tls.ca_file pointing at the copied certificate.
Keep agent passwords in the agent's own secret store or a root only file rather than in a world readable configuration. Agents send no browser Origin header, so the image's cross site request guard does not affect them.
Step 9: Storage and retention
Parseable keeps the data and its staging area on the root volume:
sudo du -sh /var/lib/parseable/data /var/lib/parseable/staging
sudo grep -E '^P_' /etc/parseable/parseable.env
systemctl cat parseable | grep -E '^(ExecStart|EnvironmentFile)='
144K /var/lib/parseable/data
32K /var/lib/parseable/staging
P_ADDR=127.0.0.1:8000
P_FS_DIR=/var/lib/parseable/data
P_STAGING_DIR=/var/lib/parseable/staging
P_CHECK_UPDATE=false
P_SEND_ANONYMOUS_USAGE_DATA=false
EnvironmentFile=/etc/parseable/parseable.env
EnvironmentFile=/etc/parseable/parseable.cred.env
ExecStart=/usr/local/bin/parseable local-store
Parseable keeps data until you delete it. Set a retention period per dataset in the console's dataset settings or with the /api/v1/logstream/<dataset>/retention API. To grow the disk, modify the root volume in the EC2 console (Volumes, Modify volume), then extend the partition and file system online:
sudo growpart /dev/nvme0n1 1 && sudo resize2fs /dev/nvme0n1p1
Take EBS snapshots of the root volume for backups.
Object storage (optional). For larger or distributed deployments Parseable can store data in Amazon S3 instead of the local disk. Change ExecStart in /etc/systemd/system/parseable.service to /usr/local/bin/parseable s3-store, add P_S3_URL, P_S3_REGION and P_S3_BUCKET to /etc/parseable/parseable.env (and P_S3_ACCESS_KEY / P_S3_SECRET_KEY in the root only /etc/parseable/parseable.cred.env, since the service is blocked from the instance metadata endpoint and cannot use an instance role), then run sudo systemctl daemon-reload && sudo systemctl restart parseable. Data already stored locally is not moved. See the Parseable documentation for every storage setting.
Known issue in S3 mode. Parseable 3.2.5 bundles the XML parser quick-xml 0.39.2, which carries two denial of service advisories, RUSTSEC-2026-0194 (quadratic run time on duplicate attribute names) and RUSTSEC-2026-0195 (unbounded namespace allocation), both fixed in quick-xml 0.41.0. Parseable only parses XML when it talks to an object store, so the default local storage mode on this image never reaches that code. In S3 mode, Parseable parses the XML responses of the S3 endpoint you configure, so point it only at an endpoint you trust (Amazon S3 itself). No Parseable release ships the fixed quick-xml yet; cloudimg will publish a new version of this image as soon as one does.
Step 10: Use your own DNS name or certificate
The served host name is fixed by configuration, never taken from a request. To serve Parseable under your own DNS name, point the name at the instance and run the helper, which records the name, regenerates the self signed certificate for it, updates the credentials file and reloads nginx:
sudo parseable-set-hostname <your-dns-name>
Run the same command after a stop and start if the instance's public DNS name changed (an Elastic IP avoids that), because a request for a name the instance does not serve is dropped.
To use a certificate from your own CA or a public CA instead, replace /etc/parseable/tls/cert.pem (full chain) and /etc/parseable/tls/key.pem (mode 0600, owner root), then run sudo nginx -t && sudo systemctl reload nginx. Alternatively, put the instance behind an Application Load Balancer with an AWS Certificate Manager certificate and let the load balancer forward to port 443, with /api/v1/liveness as the health check path.
Step 11: Change the admin password
The admin login is set by P_USERNAME and P_PASSWORD in the root only file /etc/parseable/parseable.cred.env. To rotate the password, edit the P_PASSWORD= line with sudoedit, restart Parseable, and update the parseable.admin.pass line in /root/parseable-credentials.txt:
sudoedit /etc/parseable/parseable.cred.env
sudo systemctl restart parseable
Step 12: Security notes
Parseable runs as its own unprivileged user with a read only system, and cannot reach the instance metadata endpoint:
systemctl show parseable -p User -p NoNewPrivileges -p ProtectSystem -p ProtectHome -p IPAddressDeny
IPAddressDeny=168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
User=parseable
ProtectHome=yes
ProtectSystem=full
NoNewPrivileges=yes
SSH accepts keys only: passwords, root logins and X11 forwarding are switched off in /etc/ssh/sshd_config.d/00-cloudimg.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 no
A state changing request carrying a foreign browser Origin is refused, even with the right password, so a web page cannot change or delete your data through a signed in browser:
H=$(sudo sed -n 's#^parseable\.url=https://\([^/]*\)/.*#\1#p' /root/parseable-credentials.txt)
PW=$(sudo sed -n 's/^parseable\.admin\.pass=//p' /root/parseable-credentials.txt)
CA=/etc/parseable/tls/cert.pem
curl -s -o /dev/null -w 'Origin evil.example delete -> HTTP %{http_code}\n' --cacert $CA --resolve "$H:443:127.0.0.1" -K <(printf 'user = "admin:%s"\n' "$PW") -X DELETE -H 'Origin: https://evil.example' "https://$H/api/v1/logstream/demoapp"
Origin evil.example delete -> HTTP 403
Other points:
- Upstream Parseable grants credentialed cross origin access to
https://cdn.parseable.com; nginx removes those CORS headers, so only the console served by your instance can read your data from a browser. - nginx passes the real client address of every request to Parseable and logs it;
X-Forwarded-Forheaders sent by clients are ignored. - SSH accepts key logins as
ubuntuonly (no passwords, no root login, no X11 forwarding); usesudofor administration. - The AMI requires IMDSv2. Restrict port 443 to the networks your users and agents use, and never open 8000, 8001 or 8002.
- Parseable's own update check and anonymous usage reporting are switched off in
/etc/parseable/parseable.env.
Support and licensing
Parseable is open source under the GNU Affero General Public License v3.0 (AGPL-3.0); the image ships the unmodified upstream open source release binary with its licence text at /usr/local/share/parseable/LICENSE, and the source code for this release is available from the upstream project. 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
Parseable is developed by Parseable, Inc.; for features and the full API, see the upstream Parseable documentation.
Parseable is a trademark of Parseable, Inc. cloudimg is not affiliated with or endorsed by Parseable, Inc.; the name is used only to identify the unmodified upstream software.