{"id":2544,"date":"2026-09-14T08:00:19","date_gmt":"2026-09-14T08:00:19","guid":{"rendered":"https:\/\/ukspeed.co.uk\/blog\/self-host-grafana-loki-log-management-uk-vps-2026\/"},"modified":"2026-09-14T08:08:11","modified_gmt":"2026-09-14T08:08:11","slug":"self-host-grafana-loki-log-management-uk-vps-2026","status":"publish","type":"post","link":"https:\/\/ukspeed.co.uk\/blog\/self-host-grafana-loki-log-management-uk-vps-2026\/","title":{"rendered":"Self-Host Grafana Loki: Log Management on UK VPS 2026"},"content":{"rendered":"<p>If you want to self-host Grafana Loki, you can turn a single UK VPS into a proper centralised logging platform without paying per-gigabyte SaaS bills. Loki is a lightweight, cost-effective log aggregation system from Grafana Labs, and it pairs perfectly with the metrics stack we covered in our guide to <a href=\"https:\/\/ukspeed.co.uk\/blog\/prometheus-and-grafana-monitoring-uk-vps-metrics-alerting-2026\/\">Prometheus and Grafana monitoring on a UK VPS<\/a>. Think of this as the logs companion to that metrics article: same dashboard, same VPS, all your log management in one place.<\/p>\n\n<h2 class=\"wp-block-heading\">What Is Grafana Loki?<\/h2>\n\n<p>Grafana Loki is an open-source, horizontally scalable log aggregation system built by Grafana Labs. It is frequently described as &#8220;Prometheus, but for logs&#8221; because it borrows the same label-based data model. Rather than indexing the full text of every log line the way Elasticsearch does, Loki indexes only a small set of metadata labels (such as <code>job<\/code>, <code>host<\/code> or <code>app<\/code>) and stores the raw log content as compressed chunks.<\/p>\n\n<p>That single design decision is what makes Loki so cheap to run. Full-text indexing engines like the ELK stack (Elasticsearch, Logstash, Kibana) are powerful but hungry: they consume large amounts of RAM and disk to keep every token searchable. Loki keeps the index tiny and pushes the heavy lifting to query time, so it happily runs alongside your other services on a modest VPS. The trade-off is honest: if your primary need is deep full-text search across huge volumes, an engine such as OpenSearch or ELK may suit you better. For most teams who simply want reliable, affordable centralised logging, Loki hits the sweet spot.<\/p>\n\n<h2 class=\"wp-block-heading\">Why Self-Host Log Management<\/h2>\n\n<p>Hosted log platforms such as Datadog Logs are excellent, but they bill per gigabyte ingested. Logs are noisy and grow relentlessly, so those bills climb fast and unpredictably. Running your own Loki instance turns a variable, volume-based cost into a flat, known cost: the price of the VPS it lives on. If you already run monitoring or <a href=\"https:\/\/ukspeed.co.uk\/blog\/self-host-uptime-monitoring-uk-vps-uptime-kuma-vs-gatus-vs-netdata-2026\/\">self-hosted uptime monitoring on a UK VPS<\/a>, adding Loki to the same box is a small step.<\/p>\n\n<p>There is also a compliance angle that matters for British businesses. Logs routinely contain personal data such as client IP addresses, usernames and request paths. Shipping all of that to a third-party platform, often outside the UK, raises real GDPR and data-residency questions. Self-hosting keeps your log data on infrastructure you control, in the UK, on a <a href=\"https:\/\/ukspeed.co.uk\/blog\/docker-compose-wordpress-production-on-uk-vps-full-stack-setup-guide-2026\/\">UK VPS such as those from UK Speed<\/a>. The trade-off is that you own the operations: you run it, patch it, and back it up yourself.<\/p>\n\n<h3 class=\"wp-block-heading\">What You Need to Self-Host Grafana Loki<\/h3>\n\n<p>The good news is that the requirements are modest. To self-host Grafana Loki comfortably you need:<\/p>\n\n<ul class=\"wp-block-list\"><li>A UK VPS running a modern Linux distribution (Ubuntu 24.04 or Debian 12 are ideal).<\/li><li>2 vCPUs and 2\u20134 GB RAM for a small to medium workload; more if you ingest heavily.<\/li><li>Docker and Docker Compose installed for a clean, reproducible deployment.<\/li><li>Enough disk for your log retention window (start with 20\u201340 GB and monitor it).<\/li><li>A domain or subdomain plus a reverse proxy if you want secure external access.<\/li><\/ul>\n\n<h2 class=\"wp-block-heading\">How Loki, Promtail and Grafana Fit Together<\/h2>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/ukspeed.co.uk\/blog\/wp-content\/uploads\/2026\/09\/lk1-arch.svg\" alt=\"Self-host Grafana Loki architecture: Promtail ships logs to Loki, queried in Grafana with LogQL\" class=\"wp-image-2545\" \/><figcaption class=\"wp-element-caption\">Promtail labels and ships logs to Loki, which indexes by label; Grafana queries them with LogQL &mdash; the same model as Prometheus, for logs.<\/figcaption><\/figure>\n\n\n<p>Self-hosted Loki is really a small stack of three cooperating parts. An agent collects logs and ships them, Loki stores and indexes them, and Grafana lets you query and visualise them. Understanding these roles makes the configuration much clearer.<\/p>\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Component<\/th><th>Role<\/th><th>Default port<\/th><\/tr><\/thead><tbody><tr><td>Promtail \/ Grafana Alloy<\/td><td>Agent that tails log files and the systemd journal, attaches labels, and pushes them to Loki<\/td><td>9080<\/td><\/tr><tr><td>Loki<\/td><td>Receives, indexes by label and stores the log chunks<\/td><td>3100<\/td><\/tr><tr><td>Grafana<\/td><td>Web UI to query logs with LogQL and build dashboards<\/td><td>3000<\/td><\/tr><\/tbody><\/table><\/figure>\n\n<p>Promtail is the classic agent and is still very widely deployed, though Grafana Labs now positions <strong>Grafana Alloy<\/strong> as its successor. Both do the same core job: tail logs, add labels, and forward them to Loki&#8217;s push endpoint. Because Grafana speaks to both Loki and Prometheus, you can view metrics and logs side by side on one dashboard, which is the real payoff of running the whole observability stack together.<\/p>\n\n<h2 class=\"wp-block-heading\">How to Install Loki with Docker Compose<\/h2>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/ukspeed.co.uk\/blog\/wp-content\/uploads\/2026\/09\/lk2-explore.svg\" alt=\"Grafana Explore querying logs from Loki with a LogQL query on a UK VPS\" class=\"wp-image-2547\" \/><figcaption class=\"wp-element-caption\">In Grafana Explore, a LogQL query filters logs by label and line &mdash; drill into an error spike in seconds.<\/figcaption><\/figure>\n\n\n<p>The cleanest way to deploy the stack is with Docker Compose, which keeps all three services and their configs version-controlled in one folder. If Docker is new to you, our <a href=\"https:\/\/ukspeed.co.uk\/blog\/docker-compose-wordpress-production-on-uk-vps-full-stack-setup-guide-2026\/\">Docker Compose on a UK VPS guide<\/a> covers the basics. Always cross-check versions and options against <a href=\"https:\/\/grafana.com\/docs\/loki\/latest\/\" rel=\"noopener\" target=\"_blank\">the official Grafana Loki documentation<\/a>, as flags evolve between releases.<\/p>\n\n<p>Create a project directory and a <code>docker-compose.yml<\/code> like the one below:<\/p>\n\n<pre class=\"wp-block-code\"><code>services:\n  loki:\n    image: grafana\/loki:3.1.1\n    command: -config.file=\/etc\/loki\/loki-config.yaml\n    volumes:\n      - .\/loki-config.yaml:\/etc\/loki\/loki-config.yaml\n      - loki-data:\/loki\n    ports:\n      - \"127.0.0.1:3100:3100\"\n\n  promtail:\n    image: grafana\/promtail:3.1.1\n    command: -config.file=\/etc\/promtail\/promtail-config.yaml\n    volumes:\n      - .\/promtail-config.yaml:\/etc\/promtail\/promtail-config.yaml\n      - \/var\/log:\/var\/log:ro\n    depends_on:\n      - loki\n\n  grafana:\n    image: grafana\/grafana:11.2.0\n    environment:\n      - GF_SECURITY_ADMIN_PASSWORD=change-me-now\n    volumes:\n      - grafana-data:\/var\/lib\/grafana\n    ports:\n      - \"127.0.0.1:3000:3000\"\n\nvolumes:\n  loki-data:\n  grafana-data:<\/code><\/pre>\n\n<p>Notice that Loki and Grafana are bound to <code>127.0.0.1<\/code>, not <code>0.0.0.0<\/code> \u2014 this keeps them off the public internet, which matters because Loki ships with no authentication by default. Next, a minimal <code>loki-config.yaml<\/code> that stores chunks on the local filesystem:<\/p>\n\n<pre class=\"wp-block-code\"><code>auth_enabled: false\nserver:\n  http_listen_port: 3100\ncommon:\n  path_prefix: \/loki\n  storage:\n    filesystem:\n      chunks_directory: \/loki\/chunks\n      rules_directory: \/loki\/rules\n  replication_factor: 1\n  ring:\n    kvstore:\n      store: inmemory\nschema_config:\n  configs:\n    - from: 2024-01-01\n      store: tsdb\n      object_store: filesystem\n      schema: v13\n      index:\n        prefix: index_\n        period: 24h<\/code><\/pre>\n\n<p>Run <code>docker compose up -d<\/code>, then open Grafana on <code>http:\/\/127.0.0.1:3000<\/code> (via an SSH tunnel or reverse proxy), log in, and add a new Loki data source pointing at <code>http:\/\/loki:3100<\/code>. Within the Compose network the services reach each other by service name, so <code>loki<\/code> resolves correctly.<\/p>\n\n<h2 class=\"wp-block-heading\">How to Ship Logs with Promtail<\/h2>\n\n<p>Promtail is the piece that actually reads your logs and forwards them. Its config defines a <code>clients<\/code> block (where to push) and one or more <code>scrape_configs<\/code> (what to read and how to label it). Here is a practical <code>promtail-config.yaml<\/code> that ships everything under <code>\/var\/log<\/code>:<\/p>\n\n<pre class=\"wp-block-code\"><code>server:\n  http_listen_port: 9080\npositions:\n  filename: \/tmp\/positions.yaml\nclients:\n  - url: http:\/\/loki:3100\/loki\/api\/v1\/push\nscrape_configs:\n  - job_name: varlogs\n    static_configs:\n      - targets: [localhost]\n        labels:\n          job: varlogs\n          host: web01\n          __path__: \/var\/log\/*log\n  - job_name: nginx\n    static_configs:\n      - targets: [localhost]\n        labels:\n          job: nginx\n          host: web01\n          __path__: \/var\/log\/nginx\/*.log<\/code><\/pre>\n\n<p>The <code>labels<\/code> you set here are exactly how you will later filter logs, so choose them thoughtfully. Promtail can also read the systemd journal directly with a <code>journal<\/code> scrape config \u2014 handy if you have followed our guide on <a href=\"https:\/\/ukspeed.co.uk\/blog\/how-to-read-server-logs-on-uk-vps-nginx-pm2-systemd-journalctl-2026\/\">reading server logs with journalctl<\/a> and want that same data centralised. Restart the stack and, within seconds, log lines start flowing into Loki.<\/p>\n\n<h2 class=\"wp-block-heading\">Query Logs with LogQL in Grafana<\/h2>\n\n<p>LogQL is Loki&#8217;s query language, and it feels immediately familiar if you know PromQL. Every query starts with a <strong>label selector<\/strong> in curly braces, which narrows down the log streams, followed by optional <strong>line filters<\/strong> that match text within those streams. Open Grafana&#8217;s Explore view, pick the Loki data source, and try:<\/p>\n\n<pre class=\"wp-block-code\"><code># All lines from the varlogs job\n{job=\"varlogs\"}\n\n# Only nginx lines containing the word error\n{job=\"nginx\"} |= \"error\"\n\n# A metric query: rate of nginx errors over 5 minutes\nrate({job=\"nginx\"} |= \"error\" [5m])<\/code><\/pre>\n\n<p>The first query returns raw lines. The second adds the <code>|=<\/code> line filter to keep only matching entries (use <code>!=<\/code> to exclude, or <code>|~<\/code> for a regex). The third is where LogQL shines: it converts matching log lines into a numeric time series you can graph and even alert on, giving you metrics derived straight from logs. This is what lets you build a single Grafana dashboard that blends Prometheus metrics with Loki-derived signals.<\/p>\n\n<h2 class=\"wp-block-heading\">Configure Retention and Storage<\/h2>\n\n<p>Logs never stop arriving, so retention is not optional \u2014 without it your disk will eventually fill. Loki handles deletion through its <strong>compactor<\/strong>, driven by a <code>retention_period<\/code> limit. A minimal addition to your <code>loki-config.yaml<\/code> looks like this:<\/p>\n\n<pre class=\"wp-block-code\"><code>limits_config:\n  retention_period: 720h   # 30 days\ncompactor:\n  working_directory: \/loki\/compactor\n  retention_enabled: true\n  delete_request_store: filesystem<\/code><\/pre>\n\n<p>For small and medium setups the local filesystem is perfectly fine. As volumes grow, Loki can store its chunks in S3-compatible object storage instead \u2014 and you can run that yourself with <strong>MinIO<\/strong>, keeping the data on your own UK infrastructure rather than a public cloud bucket. Whichever you choose, keep an eye on disk usage and set your retention to match both your compliance needs and the space you have.<\/p>\n\n<h2 class=\"wp-block-heading\">Best Practices for Production Loki<\/h2>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/ukspeed.co.uk\/blog\/wp-content\/uploads\/2026\/09\/lk3-vs-elk.svg\" alt=\"Why Loki is cost-effective: it indexes labels only, unlike full-text ELK-style logging\" class=\"wp-image-2549\" \/><figcaption class=\"wp-element-caption\">Loki keeps log management cheap by indexing labels only; choose ELK\/OpenSearch when you need heavy full-text search.<\/figcaption><\/figure>\n\n\n<p>A few habits separate a hobby install from a dependable production log management system:<\/p>\n\n<ul class=\"wp-block-list\"><li><strong>Never expose port 3100 publicly.<\/strong> Loki has no built-in authentication, so keep it on <code>127.0.0.1<\/code> or a private network and place it behind a reverse proxy with HTTPS and auth if it must be reached remotely.<\/li><li><strong>Secure Grafana.<\/strong> Change the default admin password immediately, enable HTTPS, and restrict access.<\/li><li><strong>Label wisely.<\/strong> Avoid high-cardinality labels such as user IDs or request IDs \u2014 they explode the number of streams and hurt performance. Keep labels few and stable, and search detail with line filters instead.<\/li><li><strong>Always set retention.<\/strong> Enable the compactor from day one so disks do not silently fill.<\/li><li><strong>Back up configs and data.<\/strong> Version your compose and YAML files in Git and back up the chunk store.<\/li><li><strong>Harden the host.<\/strong> Keep the VPS patched, lock down SSH, and consider running the agent as a <a href=\"https:\/\/ukspeed.co.uk\/blog\/how-to-create-systemd-services-on-uk-vps-systemctl-2026\/\">systemd service<\/a> on hosts where you are not using Docker.<\/li><\/ul>\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n<p>Self-hosting Grafana Loki gives you cost-effective, GDPR-friendly centralised logging that lives right next to your metrics, all on a single UK VPS you control. It is not a full-text search monster like ELK, and it does not pretend to be \u2014 but for the everyday reality of tailing, filtering and alerting on logs, it is hard to beat on price and simplicity.<\/p>\n\n<p>Pair it with Prometheus and Grafana for a complete observability picture, and you have a professional monitoring platform for a fraction of SaaS costs. Here is what to do next:<\/p>\n\n<ul class=\"wp-block-list\"><li>Spin up the Docker Compose stack on a test UK VPS and add Loki as a Grafana data source.<\/li><li>Point Promtail at <code>\/var\/log<\/code> and confirm lines appear in Grafana&#8217;s Explore view.<\/li><li>Enable the compactor and set a retention period that matches your policy.<\/li><li>Lock everything down behind a reverse proxy before going to production.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-group uks-cta-box has-border-color\" style=\"border-color:#bfdbfe;border-style:solid;border-width:1px;border-radius:14px;background-color:#eff6ff;padding:30px\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n\n<h3 class=\"wp-block-heading has-text-color\" style=\"color:#0f172a\">Run Grafana Loki on a UK Speed VPS<\/h3>\n\n\n<p class=\"has-text-color\" style=\"color:#334155\">Centralise your logs on a fast UK NVMe VPS with full root access and generous storage &#8211; self-host Loki, Promtail and Grafana with your data kept in the UK.<\/p>\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-color has-background wp-element-button\" href=\"https:\/\/ukspeed.co.uk\/vps-nvme\" style=\"border-radius:8px;color:#ffffff;background-color:#2563eb\">Explore UK NVMe VPS plans &rarr;<\/a><\/div>\n<\/div>\n\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>If you want to self-host Grafana Loki, you can turn a single UK VPS into a proper centralised logging platform without paying per-gigabyte SaaS\u2026<\/p>\n","protected":false},"author":3,"featured_media":2553,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[105],"tags":[147,146,113,141,136,140],"class_list":["post-2544","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-docker","tag-linux","tag-performance","tag-security","tag-ssl","tag-vps"],"_links":{"self":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2544","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=2544"}],"version-history":[{"count":4,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2544\/revisions"}],"predecessor-version":[{"id":2551,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2544\/revisions\/2551"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/media\/2553"}],"wp:attachment":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=2544"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=2544"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=2544"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}