{"id":1557,"date":"2026-09-11T18:49:17","date_gmt":"2026-09-11T21:49:17","guid":{"rendered":"https:\/\/www.linuxpro.com.br\/?p=1557"},"modified":"2026-09-11T18:54:03","modified_gmt":"2026-09-11T21:54:03","slug":"uptime-kuma-no-linux-monitoramento-self-hosted-com-docker-e-nginx","status":"publish","type":"post","link":"https:\/\/www.linuxpro.com.br\/en\/2026\/09\/uptime-kuma-no-linux-monitoramento-self-hosted-com-docker-e-nginx\/","title":{"rendered":"Uptime Kuma on Linux: self-hosted monitoring with Docker and Nginx"},"content":{"rendered":"<p><img fetchpriority=\"high\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/uptime-kuma-linux-monitoramento-v1.webp\" alt=\"Mascote LinuxPro acompanhando o painel do Uptime Kuma em uma sala de servidores\" width=\"1440\" height=\"810\" loading=\"eager\"><\/p>\n<p>When a site, API, or server stops responding, finding out from the user is too late. The <strong>Uptime Kuma<\/strong> is a monitoring tool <em>self-hosted<\/em> with a web interface: it performs checks at regular intervals, records history, and sends alerts when a service changes state. In this guide, we'll install it with Docker Compose, publish it with Nginx, and configure the first monitors securely.<\/p>\n<h2>Why use Uptime Kuma<\/h2>\n<p>Kuma makes sense when you need to quickly know if something the user consumes remains accessible: a website, an API, a TCP port, a DNS resolution, or a job completion. It brings together checking, history, state change, notification, and a status page in a simple interface. How it works <em>self-hosted<\/em>, URLs, notification credentials, and history stay on your infrastructure, instead of in a third-party monitoring account.<\/p>\n<p>This doesn't make it a universal replacement. Uptime is not complete observability: an endpoint can respond and still be slow, out of disk space, or have a backlog. The best choice is to use it as the availability and quick alert layer, alongside metrics and logs when the operation needs deep diagnosis.<\/p>\n<h2>What language is it developed in<\/h2>\n<p>Uptime Kuma is a <strong>Node.js<\/strong>, application, predominantly in JavaScript. The web interface uses <strong>Vue 3<\/strong> and <strong>Vite<\/strong>; the repository also includes TypeScript in the development stack. That's why running without Docker requires Node.js 20.4 or higher, but the container path avoids installing Node and project dependencies directly on the host.<\/p>\n<h2>What Uptime Kuma monitors<\/h2>\n<p>The project is a lightweight alternative for monitoring service availability without outsourcing the dashboard. It supports HTTP(S), TCP, keyword search, and JSON query monitors over HTTP(S), WebSocket, ping, DNS, <em>push<\/em>, Steam servers and Docker containers. It also offers public status pages, latency graphs, certificate information, proxy support, two-factor authentication, and notification integrations.<\/p>\n<p>It doesn't replace detailed metrics: for CPU, memory, disk, and server time series, combine it with <a href=\"\/en\/2026\/09\/monitorando-servidores-linux-com-prometheus\/\">Prometheus and Node Exporter<\/a>. Kuma answers another question: \u201cis this endpoint accessible right now and has someone been notified?\u201d.<\/p>\n<h2>Install Docker, Compose, and Nginx on Ubuntu<\/h2>\n<p>The commands below are for Ubuntu 22.04 LTS, 24.04 LTS or later supported by Docker. They use the official Docker repository, which delivers the Engine and the modern plugin <code data-no-translation=\"\">docker compose<\/code>. On a machine that already runs containers, don't remove or replace packages without reviewing the impact: Docker's documentation lists <code data-no-translation=\"\">docker.io<\/code>, <code data-no-translation=\"\">docker-compose<\/code>, <code data-no-translation=\"\">containerd<\/code> and <code data-no-translation=\"\">runc<\/code> among the packages that can conflict with the official installation.<\/p>\n<p>On a new host, install the prerequisites, Nginx, and the repository key:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">sudo apt update\nsudo apt install -y ca-certificates curl nginx\nsudo install -m 0755 -d \/etc\/apt\/keyrings\nsudo curl -fsSL https:\/\/download.docker.com\/linux\/ubuntu\/gpg \n  -o \/etc\/apt\/keyrings\/docker.asc\nsudo chmod a+r \/etc\/apt\/keyrings\/docker.asc<\/code><\/pre>\n<p>Add the APT source. The command automatically reads the codename and architecture of the current installation:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">sudo tee \/etc\/apt\/sources.list.d\/docker.sources &lt;&lt;EOF\nTypes: deb\nURIs: https:\/\/download.docker.com\/linux\/ubuntu\nSuites: $(. \/etc\/os-release &amp;&amp; echo \"${UBUNTU_CODENAME:-$VERSION_CODENAME}\")\nComponents: stable\nArchitectures: $(dpkg --print-architecture)\nSigned-By: \/etc\/apt\/keyrings\/docker.asc\nEOF\n\nsudo apt update<\/code><\/pre>\n<p>Install Docker Engine, Compose, and enable the services:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">sudo apt install -y docker-ce docker-ce-cli containerd.io \n  docker-buildx-plugin docker-compose-plugin\nsudo systemctl enable --now docker nginx\nsudo docker run hello-world\ndocker compose version<\/code><\/pre>\n<p>The first test command downloads a small image and exits; it confirms the daemon is working. Keep <code data-no-translation=\"\">sudo<\/code> in Docker commands or configure post-installation access thoughtfully: belonging to the group <code data-no-translation=\"\">docker<\/code> is effectively equivalent to having administrative power over the host. Before exposing container ports, also review the firewall: rules published by Docker can bypass UFW rules.<\/p>\n<h2>Before you begin<\/h2>\n<p>You need a Linux host with Docker Engine and the Docker Compose plugin. The example uses a dedicated directory in <code data-no-translation=\"\">\/opt<\/code>, a local volume for the data, and the service port limited to <code data-no-translation=\"\">127.0.0.1<\/code>. so the interface is not directly exposed to the internet; Nginx will be the only entry point.<\/p>\n<p>The Uptime Kuma database lives in the data directory. Do not place this directory on NFS: the project does not support it because file locks required by SQLite are not suitable for this scenario. Include <code data-no-translation=\"\">\/opt\/uptime-kuma\/data<\/code> in the server backup.<\/p>\n<h2>Deploy Uptime Kuma with Docker Compose<\/h2>\n<p>Create the directory and the file <code data-no-translation=\"\">compose.yaml<\/code>:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">sudo install -d -m 0755 \/opt\/uptime-kuma\nsudoedit \/opt\/uptime-kuma\/compose.yaml<\/code><\/pre>\n<p>Use this configuration. The tag <code data-no-translation=\"\">:2<\/code> follows the latest version of the 2 line and is the recommended one by the project. To freeze a specific release, use a tag <code data-no-translation=\"\">2.x.x<\/code>. Do not use <code data-no-translation=\"\">:latest<\/code> as a shortcut for version 2: that name is deprecated and still points to the 1 line.<\/p>\n<pre data-no-translation=\"\"><code class=\"language-yaml\" data-no-translation=\"\">services:\n  uptime-kuma:\n    image: louislam\/uptime-kuma:2\n    container_name: uptime-kuma\n    restart: unless-stopped\n    volumes:\n      - .\/data:\/app\/data\n    ports:\n      - \"127.0.0.1:3001:3001\"<\/code><\/pre>\n<p>Start and confirm the status:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">cd \/opt\/uptime-kuma\nsudo docker compose up -d\nsudo docker compose ps\ncurl -I http:\/\/127.0.0.1:3001<\/code><\/pre>\n<p>On first launch, create the administrative account. Store this password in a password manager and enable 2FA in settings. To monitor the startup, use <code data-no-translation=\"\">sudo docker compose logs -f<\/code>.<\/p>\n<h2>Publish with Nginx and HTTPS<\/h2>\n<p>Choose a subdomain, for example <code data-no-translation=\"\">status-admin.exemplo.com<\/code>, and point the DNS to the server. Uptime Kuma should be at the root of this subdomain; it does not support installation in a subdirectory like <code data-no-translation=\"\">exemplo.com\/kuma\/<\/code>.<\/p>\n<p>First, issue a TLS certificate for the subdomain using the method adopted on your server. <strong>Do not open the interface or create the administrative account before HTTPS is active<\/strong>: HTTP login exposes the credential. Then, create the <em>server block<\/em> final. Adjust the certificate paths to your environment; WebSocket support is important for the interface to update in real time:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-nginx\" data-no-translation=\"\">server {\n    listen 80;\n    server_name status-admin.exemplo.com;\n    return 301 https:\/\/$host$request_uri;\n}\n\nserver {\n    listen 443 ssl;\n    server_name status-admin.exemplo.com;\n\n    ssl_certificate \/etc\/letsencrypt\/live\/status-admin.exemplo.com\/fullchain.pem;\n    ssl_certificate_key \/etc\/letsencrypt\/live\/status-admin.exemplo.com\/privkey.pem;\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:3001;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}<\/code><\/pre>\n<p>Test before reloading:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">sudo nginx -t\nsudo systemctl reload nginx<\/code><\/pre>\n<p>Validate <code data-no-translation=\"\">https:\/\/status-admin.exemplo.com<\/code> and only then perform the first login. When enabling the option <em>Trust Proxy<\/em> on Kuma, do this only if all requests come through a reverse proxy you control; otherwise, forwarded headers can spoof the origin IP. For an Nginx review on Debian or Ubuntu, see our guide on <a href=\"\/en\/2026\/09\/nginx-varias-versoes-php-debian-ubuntu\/\">Nginx and PHP versions<\/a>.<\/p>\n<h2>Create monitors that actually notify you of something useful<\/h2>\n<p>In the dashboard, click on <strong>Add New Monitor<\/strong>. Start with a few checks that represent a real journey:<\/p>\n<ul>\n<li><strong>HTTP(S):<\/strong> the public URL of the site or API. Define the accepted HTTP codes according to the application.<\/li>\n<li><strong>Keyword:<\/strong> a health page that must contain a known marker, such as <code data-no-translation=\"\">ok<\/code>.<\/li>\n<li><strong>TCP:<\/strong> the port of a service that must accept connections, such as SMTP or an internal application.<\/li>\n<li><strong>DNS:<\/strong> a critical record, useful for detecting resolution errors or unexpected changes.<\/li>\n<li><strong>Push:<\/strong> backup, synchronization, or maintenance jobs: the job calls the unique URL provided by Kuma when it finishes. If the signal does not arrive within the configured window, the monitor raises an alert.<\/li>\n<\/ul>\n<p>Avoid aggressive intervals by default. A monitor with too many false positives is quickly ignored. Set the timeout, retries, and interval according to the service's criticality and capacity.<\/p>\n<h2>Configure notifications before failure<\/h2>\n<p>Open <strong>Settings \u2192 Notifications<\/strong>, set up your chosen channel, and use the test button. Uptime Kuma integrates with SMTP, Telegram, Discord, Slack, Gotify, Pushover, and many other services. Then assign the notification to each monitor \u2014 creating the channel alone does not enable alerts.<\/p>\n<p>Start with a channel that someone actually watches. For critical services, use more than one destination and document who responds to each type of alert.<\/p>\n<h2>Public status page, without exposing the admin panel<\/h2>\n<p>Under <strong>Status Pages<\/strong>, create a page with the monitors that can be shown publicly. It is separate from the admin dashboard: publish only information that is appropriate to disclose. A status page helps reduce support requests during an outage, but should not list internal services, private addresses, or infrastructure details.<\/p>\n<h2>Updates and backups<\/h2>\n<p>Back up the data directory before updating. During a maintenance window, the basic workflow is:<\/p>\n<pre data-no-translation=\"\"><code class=\"language-bash\" data-no-translation=\"\">cd \/opt\/uptime-kuma\nsudo docker compose pull\nsudo docker compose up -d --force-recreate\nsudo docker compose logs --tail=100<\/code><\/pre>\n<p>Check the <a href=\"https:\/\/github.com\/louislam\/uptime-kuma\/releases\">official release notes<\/a> before updating, especially when moving to a new major version. The project also provides <a href=\"https:\/\/github.com\/louislam\/uptime-kuma\/wiki\/Migration-From-v1-To-v2\">specific guidance for migrating from v1 to v2<\/a>.<\/p>\n<h2>Security considerations<\/h2>\n<ul>\n<li>Do not expose port <code data-no-translation=\"\">3001<\/code> directly; keep it bound to <code data-no-translation=\"\">127.0.0.1<\/code> behind HTTPS and authentication.<\/li>\n<li>Use a unique password, 2FA, and regular updates.<\/li>\n<li>Protect the backup of <code data-no-translation=\"\">data<\/code>: it may contain URLs, notification tokens, and information about your infrastructure.<\/li>\n<li>Container monitoring may require access to the Docker socket. This socket controls the daemon; do not mount it without understanding the implications, and never treat this instance as a public dashboard.<\/li>\n<\/ul>\n<h2>Alternatives: which to use in each scenario<\/h2>\n<ul>\n<li><strong><a href=\"https:\/\/github.com\/TwiN\/gatus\">Gatus<\/a>:<\/strong> monitoring <em>self-hosted<\/em> written in Go and configured through a configuration file. It is a good option for teams that prefer reviewing checks in Git and applying configuration as code.<\/li>\n<li><strong><a href=\"https:\/\/prometheus.io\/docs\/prometheus\/latest\/configuration\/configuration\/#blackbox_config\">Prometheus with Blackbox Exporter<\/a>:<\/strong> collects metrics from HTTP, TCP, ICMP, and DNS probes and integrates alerts into the Prometheus ecosystem. Choose it when the data needs to feed time series, dashboards, and more sophisticated rules.<\/li>\n<li><strong><a href=\"https:\/\/www.zabbix.com\/\">Zabbix<\/a>:<\/strong> a broader platform for hosts, networking, discovery, and templates. It is suited to larger inventories; for just a few endpoints, it usually requires more operational work than Kuma.<\/li>\n<li><strong><a href=\"https:\/\/cachethq.io\/\">Cachet<\/a>:<\/strong> focuses on incident communication and public status pages. It can complement a monitor, but should not be chosen on its own with the expectation of providing the same set of probes as Kuma.<\/li>\n<\/ul>\n<p>In short: choose Kuma for its quick-to-use interface and ready-made checks; Gatus for version-controlled configuration; Prometheus\/Blackbox for metrics and alerts as code; and Zabbix when you need to monitor the entire infrastructure.<\/p>\n<h2>Where Kuma fits in your operations<\/h2>\n<p>Uptime Kuma is excellent as a simple availability and alerting layer: a dashboard for your endpoints, jobs, and status pages. For in-depth host monitoring, complement your strategy with <a href=\"\/en\/2026\/09\/monitorando-servidores-linux-com-prometheus\/\">Prometheus<\/a>; to explore traditional alternatives, read the histories of <a href=\"\/en\/2026\/09\/a-historia-do-nagios\/\">Nagios<\/a> and <a href=\"\/en\/2026\/09\/a-historia-do-zabbix\/\">Zabbix<\/a>. The official installation instructions, advanced proxy configuration, and source code are available in the <a href=\"https:\/\/github.com\/louislam\/uptime-kuma\">Uptime Kuma repository<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Install Uptime Kuma with Docker Compose, publish it with Nginx and configure alerts, status page and backup with security.<\/p>","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,2,120,3],"tags":[156,126,240,466,203,465,5,464],"class_list":["post-1557","post","type-post","status-publish","format-standard","hentry","category-infra","category-linux","category-servidores","category-ubuntu","tag-docker","tag-monitoramento","tag-nginx","tag-node-js","tag-self-hosted","tag-status-page","tag-ubuntu","tag-uptime-kuma"],"_links":{"self":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts\/1557","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/comments?post=1557"}],"version-history":[{"count":2,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts\/1557\/revisions"}],"predecessor-version":[{"id":1559,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts\/1557\/revisions\/1559"}],"wp:attachment":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/media?parent=1557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/categories?post=1557"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/tags?post=1557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}