// blog.guide.ec2
Monitoring EC2 With LogForge, Without Turning Your Afternoon Into an IAM Side Quest
Run LogForge Central on your own machine, enroll each EC2 Docker host as an agent, and keep the monitoring setup simple enough that it does not become the project.
What do you do when you want to monitor your EC2 instances?
Set up CloudWatch, right?
That is the default answer, and it is not a bad answer. CloudWatch is powerful. It is also the kind of powerful where a simple "I want to see what my instance is doing" can turn into IAM roles, agent packages, log groups, JSON config files, retention policies, pricing tabs, and one browser tab you keep open only because you are afraid closing it will break the spell.
There is a simpler way if your goal is: "I have a few EC2 boxes running Docker workloads, and I want one place to watch them."
Run LogForge Central on your personal machine, workstation, home server, or whichever device has the most comfortable amount of CPU, memory, and disk. Then run the LogForge remote agent on each EC2 instance. Central stays yours. The EC2 instances phone home.
No CloudWatch agent ceremony required.
The Shape Of The Setup
The setup has two parts:
- LogForge Central. This is the web UI, API, storage, auth, alerting, notifications, and agent enrollment service. In the public Docker Compose install, it runs as one appliance container.
- LogForge agent. This runs on each EC2 instance you want to monitor. It watches Docker, host metrics, logs, and container inventory, then sends telemetry back to Central over LogForge's mTLS endpoint.
The important network detail for agents is direction:
EC2 agent ---> your LogForge Central mTLS port
Your EC2 instances do not need inbound ports opened for LogForge. They need outbound access to your Central machine. Central must be reachable from those EC2 instances.
The current public install exposes two host ports:
| Setting | Default | Used for |
|---|---|---|
UNICRON_APP_PORT |
8444 |
LogForge web UI and API at https://<your-central-host>:8444/unicron |
UNICRON_AGENT_MTLS_PORT |
9443 |
Agent mTLS enrollment, WebSocket, and telemetry ingress |
If your Central machine is behind a home router, office firewall, or laptop Wi-Fi, you need one of these before EC2 can reach it:
- A DNS name pointing at the Central machine, plus port forwarding for
UNICRON_AGENT_MTLS_PORT. ForwardUNICRON_APP_PORTtoo if you want to open the dashboard from outside that network. - A private network overlay such as WireGuard, Tailscale, or ZeroTier where EC2 can reach the Central host by a stable name.
- A reverse tunnel or proxy that forwards the browser/API port and the mTLS port.
- Or, if you decide your "most powerful device" is actually another cloud VM, run Central there instead.
For the rest of this guide, I will use:
logforge.example.com
Replace it with your real DNS name or reachable tunnel hostname.
Does This Apply To ECS?
It applies to ECS when your ECS tasks run on EC2 container instances that you manage. In that setup, install one LogForge agent per ECS container instance, not one per ECS task. The ECS-specific guide is here: Monitoring ECS On EC2 With LogForge.
It does not apply to pure ECS Fargate, because Fargate does not expose the Docker host boundary that the LogForge remote agent needs. The Fargate boundary guide is here: Monitoring ECS Fargate With LogForge.
Step 0: What You Need
On the Central machine:
- Docker
- Docker Compose
- A reachable hostname, like
logforge.example.com - Browser access to
UNICRON_APP_PORT, default8444, from wherever you administer LogForge - TCP
UNICRON_AGENT_MTLS_PORT, default9443, reachable from your EC2 instances
On each EC2 instance:
- Linux with Docker installed
- Outbound access to Central on
UNICRON_AGENT_MTLS_PORT, default9443 - Permission to run Docker containers
The LogForge agent is built for Docker hosts. If your EC2 instance is not running Docker yet, install and start Docker first. On Amazon Linux 2023, that usually looks like:
sudo dnf update -y
sudo dnf install -y docker
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
After adding your user to the docker group, log out and back in, or use sudo docker for the first run.
Step 1: Start LogForge Central
On the machine where Central will live, run the public installer:
curl -fsSL https://www.logforge.dev/install.sh | sh
The installer clones or updates the public repo, starts LogForge with Docker Compose, and prints the local URL:
https://localhost:8444/unicron
Open that on the Central machine. If you are connecting from another machine, replace localhost with your reachable hostname:
https://logforge.example.com:8444/unicron
If you prefer to run the commands yourself, use the public repo flow:
git clone https://github.com/log-forge/logforge.git
cd logforge
docker compose pull
docker compose up -d
docker compose ps
The public repo includes .env. You do not need to create one by hand for the default install. If the dashboard port conflicts, change UNICRON_APP_PORT. If the agent mTLS port conflicts, change UNICRON_AGENT_MTLS_PORT. Then recreate the container so Docker Compose reads the new values:
docker compose up -d
docker compose ps
If you did not set CENTRAL_ADMIN_PASSWORD, LogForge generates a first-boot admin password and logs it once. Fetch it with:
docker logs unicron-appliance | grep -E "Local admin first-boot generated administrator credential|generatedPassword"
Log in as admin using that generated password.
Step 2: Check Central Reachability From EC2
Before generating agent commands, SSH into one EC2 instance and make sure it can reach Central's agent mTLS port.
nc -vz logforge.example.com 9443
If nc is not installed:
timeout 5 bash -c '</dev/tcp/logforge.example.com/9443' && echo "9443 reachable"
If you changed UNICRON_AGENT_MTLS_PORT, use that value instead of 9443.
If you also want to confirm browser/API reachability from that EC2 instance, test the dashboard port separately:
curl -kI https://logforge.example.com:8444/unicron
If this fails but the mTLS port works, agent enrollment can still work. It just means that EC2 instance cannot reach the dashboard/API port.
If the mTLS test fails, do not keep clicking around in the UI hoping vibes will fix routing. Fix DNS, firewall rules, security groups, port forwarding, or your tunnel first. The agent command will only work if the EC2 instance can reach Central's mTLS endpoint.
Step 3: Generate An Agent Command
In LogForge:
- Go to Settings.
- Open Agents.
- Click Enroll New Agent.
- Choose a clear agent name, for example:
api-prod-i-0123456789abcdef0
- Set the Central URL to:
https://logforge.example.com:8444/unicron
- Keep Memory only queue mode for a first install, unless you specifically want durable local buffering during Central outages.
- Click Generate Enrollment Command.
LogForge will generate a command that looks roughly like this:
# Reinstall is idempotent: remove any old container with this agent name.
# Reset only the agent identity/trust volume for this fresh enrollment.
# Durable telemetry queue volumes are preserved when explicitly enabled.
docker rm -f unicron-agent-api-prod-i-0123456789abcdef0 2>/dev/null || true
docker volume rm unicron-agent-api-prod-i-0123456789abcdef0-data 2>/dev/null || true
docker run -d --name unicron-agent-api-prod-i-0123456789abcdef0 \
--restart unless-stopped \
-p 24224:24224 \
-p 9880:9880 \
-p 4317:4317 \
-p 4318:4318 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host/root:ro \
-v /var/lib/docker/containers:/var/lib/docker/containers:ro \
-v unicron-agent-api-prod-i-0123456789abcdef0-data:/agent-data \
-e AGENT_NAME=api-prod-i-0123456789abcdef0 \
-e CENTRAL_WS_URL=wss://logforge.example.com:9443/unicron/api/agent/ws \
-e CENTRAL_URL=https://logforge.example.com:8444/unicron \
-e CENTRAL_MTLS_URL=https://logforge.example.com:9443 \
-e ENROLL_TOKEN=<one-time-token> \
-e CA_FINGERPRINT=<central-ca-fingerprint> \
-e HOST_ID=api-prod-i-0123456789abcdef0 \
-e HERALD_NAME=api-prod-i-0123456789abcdef0 \
-e HERALD_ID=api-prod-i-0123456789abcdef0 \
-e HERALD_CA_ROOT=/agent-data/certs/root_ca.crt \
-e HERALD_CERT=/agent-data/certs/agent.crt \
-e HERALD_KEY=/agent-data/certs/agent.key \
-e TELEMETRY_MODE=hybrid \
-e TELEMETRY_QUEUE_MODE=memory \
-e TELEMETRY_MEMORY_QUEUE_MB=256 \
-e OTEL_SENDING_QUEUE_SIZE=64000 \
-e FLB_MEM_BUF_LIMIT=256MB \
-e FLB_TAIL_DB_PATH=/dev/shm/flb_monitored.db \
-e UPSTREAM_CRITICAL_QUEUE_SIZE=1024 \
-e UPSTREAM_TELEMETRY_QUEUE_SIZE=4096 \
-e UPSTREAM_CRITICAL_ENQUEUE_TIMEOUT_MS=5000 \
-e ENVIRONMENT=production \
logforge/unicron-agent:latest
Step 4: Run The Agent On EC2
SSH into the EC2 instance:
ssh ec2-user@ec2-203-0-113-25.compute-1.amazonaws.com
Use the right SSH user for your AMI. For Ubuntu images, that is usually ubuntu instead of ec2-user.
Paste the generated command.
Then check that the agent container is running:
docker ps --filter "name=unicron-agent"
Follow the logs for the first boot:
docker logs -f unicron-agent-api-prod-i-0123456789abcdef0
You are looking for the agent to bootstrap its certificate, register with Central, and begin sending heartbeat and telemetry. After a few seconds, return to Settings > Agents in LogForge. The EC2 instance should appear as online. From there, the container inventory and logs should start filling in.
Step 5: Repeat For Each EC2 Instance
Generate a fresh command for each EC2 instance.
This matters because each agent gets its own identity. Do not reuse one enrollment command across five servers unless your plan is to create a tiny identity crisis and then debug it with stale coffee.
Good names:
api-prod-i-0123456789abcdef0
worker-prod-i-0fedcba9876543210
staging-web-i-01112222333344445
Bad names:
server
test
please-work
You will thank yourself later when an alert says exactly which host is angry.
What About EC2 Security Groups?
For the EC2 agent instances, you usually do not need new inbound rules.
The agent connects out to Central and keeps an mTLS WebSocket open. So the EC2 instance needs outbound access to:
tcp/9443 -> logforge.example.com
Use your UNICRON_AGENT_MTLS_PORT value if you changed it from the default.
Central-triggered remediation actions do not require inbound access to the EC2 instance. The alert engine calls Central's internal action API. Central resolves the target host and container, then sends container_command_request or run_script through AgentRegistry.send_command. The agent receives that command over its existing WebSocket and uses the local Docker socket to restart, stop, kill, start, or run the script.
The generated agent command publishes 24224, 9880, 4317, and 4318 on the EC2 host. Those are useful for local Fluent Bit and OTLP inputs. Do not add EC2 inbound security group rules for those ports unless you intentionally want another machine to push logs or telemetry into that agent.
For the Central machine, allow inbound from your EC2 instances to:
tcp/9443
Allow inbound to UNICRON_APP_PORT, default 8444, only from the browsers or proxies that need to use the dashboard/API.
If you can restrict those rules to your VPC, EC2 security group, VPN CIDR, fixed EC2 egress IPs, or admin IPs, do that. "Open to the world because I am just testing" is how "just testing" becomes a calendar event.
Durable Queue Or Memory Queue?
For a first install, use Memory only.
It is simpler and avoids persistent queue volumes on the EC2 host. If Central goes offline, the agent may drop backlog once its memory queue fills or the container restarts, but the setup is clean.
Use Durable output queue when:
- The EC2 instance is chatty.
- Central may go offline for maintenance.
- You would rather spend disk to preserve telemetry backlog.
In durable mode, LogForge adds extra Docker volumes for the OpenTelemetry and Fluent Bit queues. The generated reinstall command intentionally removes the identity volume for a fresh enrollment, but preserves durable queue volumes.
Troubleshooting
The agent never appears in LogForge.
Check the token age. Enrollment tokens are short-lived. Generate a fresh command and run that.
The agent logs mention Central connection failures.
From the EC2 instance, test the required mTLS port:
nc -vz logforge.example.com 9443
If you also want to check the dashboard/API port from that host:
curl -kI https://logforge.example.com:8444/unicron
If the mTLS port fails, it is networking, not LogForge.
The agent says certificate bootstrap or fingerprint validation failed.
Generate a new enrollment command from the UI and run the whole command, including the docker volume rm ...-data line. That clears stale trust material from an older install.
Docker permission denied.
Use sudo docker ..., or add your user to the docker group and log in again:
sudo usermod -aG docker "$USER"
Containers are missing.
The generated command mounts:
/var/run/docker.sock
/var/lib/docker/containers
/
Those mounts are how the agent sees Docker inventory, container logs, and host metrics. If your EC2 host uses a nonstandard Docker data root, adjust the generated /var/lib/docker/containers mount to match that host.
Why This Works
This guide follows the current public LogForge install path:
curl -fsSL https://www.logforge.dev/install.sh | shclones or updateshttps://github.com/log-forge/logforge.git.- The public repo includes
.env, so the default install does not need a hand-written environment file. - The installer starts
docker compose -f docker-compose.yml up -d unicron; the manual fallback usesdocker compose up -dfrom the repo root. - Docker Compose runs the appliance as
logforge/unicron:latest. UNICRON_APP_PORTpublishes the browser/API endpoint, default8444.UNICRON_AGENT_MTLS_PORTpublishes agent mTLS enrollment and traffic, default9443.- The installer prints
https://localhost:${UNICRON_APP_PORT}/unicron, which ishttps://localhost:8444/unicronby default. - The backend enrollment endpoint is
POST /unicron/api/agent/enroll. - The UI at Settings > Agents calls that endpoint and displays the generated
docker runcommand. - The generated command sets
CENTRAL_URL,CENTRAL_WS_URL,CENTRAL_MTLS_URL,ENROLL_TOKEN, andCA_FINGERPRINT. - The agent bootstraps its certificate with the one-time token, then registers and streams telemetry over mTLS.
That is the nice part: once Central is reachable, the EC2 side is mostly one pasted command per host.
CloudWatch is still there when you need the full AWS-native machinery. But for "show me my Docker hosts and containers without making me write another policy document," LogForge is a very pleasant shortcut.