Running the monitor as a service#
Running monitor in a foreground terminal is fine for trying it out, but
for anything ongoing you want it to survive reboots, restart itself if it
crashes, and log somewhere you can check later. Two straightforward ways to
get that: a systemd unit, or a Docker container. Pick whichever fits how you
already manage the machine it’ll run on.
Either way you’ll need: the monitor binary (or a way to build/pull it),
your server’s URL, and an enrollment token from Monitors → Add a monitor
(see Adding your first monitor
if you haven’t done this yet).
Option A: systemd#
Create a dedicated user and directories for its local state (its SQLite database of mirrored checks and unsent results):
sudo useradd --system --home /var/lib/monitoring --shell /usr/sbin/nologin monitoring
sudo mkdir -p /var/lib/monitoring /etc/monitoring /opt/monitoring
sudo chown monitoring:monitoring /var/lib/monitoring
sudo chmod 750 /var/lib/monitoring
sudo cp monitor /opt/monitoring/monitor && sudo chmod 755 /opt/monitoring/monitorConfiguration file, filled in with your own values:
sudo tee /etc/monitoring/monitor.env <<'EOF'
SERVER_URL=https://your-tenpm-server
ENROLLMENT_TOKEN=<paste from the UI>
MONITOR_NAME=My first monitor
REGION=us
COUNTRY=US
CITY=New York
DB_PATH=/var/lib/monitoring/monitor.db
EOF
sudo chown root:monitoring /etc/monitoring/monitor.env
sudo chmod 640 /etc/monitoring/monitor.envThe token is only needed for the first successful enrollment — after that
the agent holds its own API key in its database, and you can drop
ENROLLMENT_TOKEN from the file if you like.
Service unit, /etc/systemd/system/monitoring-agent.service:
[Unit]
Description=Monitoring agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=monitoring
Group=monitoring
EnvironmentFile=/etc/monitoring/monitor.env
ExecStart=/opt/monitoring/monitor
WorkingDirectory=/var/lib/monitoring
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetThen:
sudo systemctl daemon-reload
sudo systemctl enable --now monitoring-agent.service
sudo journalctl -u monitoring-agent -fRunning more than one monitor on the same host? Give each its own
monitor.env/unit pair (a -shared/-private suffix, say) — it’s the same
setup twice, not a different one.
Option B: Docker#
Build an image from an already-built binary (produced by your own build, or downloaded):
FROM alpine:3.20
RUN adduser -D -h /data monitor
USER monitor
COPY monitor /usr/local/bin/monitor
VOLUME /data
ENV DB_PATH=/data/monitor.db
ENTRYPOINT ["/usr/local/bin/monitor"]docker build -t tenpmuptime-monitor .
docker run -d --name tenpmuptime-monitor \
--restart unless-stopped \
-v tenpmuptime-monitor-data:/data \
-e SERVER_URL=https://your-tenpm-server \
-e ENROLLMENT_TOKEN=<paste from the UI> \
-e MONITOR_NAME="My first monitor" \
-e REGION=us -e COUNTRY=US -e CITY="New York" \
tenpmuptime-monitorA few things worth knowing:
Use a named volume for
/data, not a bind mount — it comes up with the right ownership automatically, where a fresh bind-mounted host directory often doesn’t.The monitor’s identity (its server-assigned id and API key) lives in that volume, not in the container or image. Stopping and recreating the container — to deploy a new version, for instance — keeps the same monitor as long as the volume survives:
docker stop tenpmuptime-monitor && docker rm tenpmuptime-monitor # docker build a new image, then re-run the same `docker run` commandLogs go to stdout/stderr, so
docker logs -f tenpmuptime-monitoris yourjournalctlequivalent.Run a one-off CLI flag (like
-list-checks) against the running container withdocker exec:docker exec tenpmuptime-monitor monitor -list-checks
Either way#
SERVER_URL, MONITOR_NAME, REGION, COUNTRY and CITY are required on
every start, not just the first — don’t drop them from your config once
enrollment succeeds, only ENROLLMENT_TOKEN becomes optional. If you ever
need to move a monitor to new hardware, or its local database is lost,
Reset enrollment on the Monitors page and re-run with a fresh token and
-id <the existing monitor's id> (or MONITOR_ID as an env var) to reclaim
its history rather than enrolling a new one — see
Managing monitors.