{"id":1038,"date":"2026-09-02T22:37:25","date_gmt":"2026-09-02T22:37:25","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=1038"},"modified":"2026-09-13T22:03:33","modified_gmt":"2026-09-13T22:03:33","slug":"vps-log-management-journald-logrotate-setup-guide","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/","title":{"rendered":"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A VPS disk filling up with logs is one of the most common causes of sudden downtime. The symptom looks dramatic \u2014 services fail to write, databases refuse transactions \u2014 but the cause is mundane: journald is retaining everything forever, or logrotate is configured but never actually trimming a chatty application&#8217;s log. This is a concrete walkthrough for sizing, rotating, and verifying both systems so your disk stays predictable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You need a host with enough headroom to survive a logging incident in the first place. If your current plan is tight on disk, review the storage characteristics of the <a href=\"https:\/\/virtualserversvps.com\/\">VPS hosting plans on our main site<\/a> before tuning retention windows.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Debian\/Ubuntu or RHEL-family VPS with systemd and <code>journald<\/code><\/li><li><code>logrotate<\/code> installed (usually present by default)<\/li><li>Root or sudo access<\/li><li>Knowledge of your total disk size and current free space<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Measure Before You Configure<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Never set a retention window without knowing what logs currently consume.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>df -h \/\njournalctl --disk-usage\ndu -sh \/var\/log \/var\/log\/journal 2>\/dev\/null\ndu -sh \/var\/log\/* 2>\/dev\/null | sort -h | tail -10<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note the journal size and the top consumers. A well-behaved small VPS keeps the journal under a few hundred megabytes; if it is multiple gigabytes, retention is the first thing to fix.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Cap journald by Size and Time<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the journald configuration. Both size and age limits are enforced, and whichever is hit first wins \u2014 which is what you want.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/etc\/systemd\/journald.conf.d\nsudo tee \/etc\/systemd\/journald.conf.d\/99-limits.conf &gt; \/dev\/null &lt;&lt;'EOF'\n[Journal]\nStorage=persistent\nSystemMaxUse=500M\nSystemKeepFree=1G\nSystemMaxFileSize=50M\nMaxRetentionSec=1month\nCompress=yes\nRateLimitIntervalSec=30s\nRateLimitBurst=1000\nEOF\n\nsudo systemctl restart systemd-journald\njournalctl --disk-usage\n\n# Immediately reclaim if the journal is already oversized\nsudo journalctl --vacuum-size=400M\nsudo journalctl --vacuum-time=2weeks<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>SystemKeepFree=1G<\/code> is the safety valve: journald will stop growing before it consumes the last gigabyte of the filesystem, keeping the host alive even under a log flood. <code>RateLimitBurst<\/code> prevents a single crashing service from spamming the journal thousands of times per second.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Configure Application Log Rotation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">journald does not manage plain files under <code>\/var\/log<\/code>. Those are logrotate&#8217;s job. Create a dedicated policy rather than editing the vendor defaults.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tee \/etc\/logrotate.d\/myapp &gt; \/dev\/null &lt;&lt;'EOF'\n\/var\/log\/myapp\/*.log {\n    daily\n    rotate 14\n    size 50M\n    missingok\n    notifempty\n    compress\n    delaycompress\n    copytruncate\n    dateext\n    dateformat -%Y%m%d\n    create 0640 www-data adm\n    sharedscripts\n    postrotate\n        systemctl reload myapp.service &gt; \/dev\/null 2&gt;&amp;1 || true\n    endscript\n}\nEOF\n\nsudo logrotate -d \/etc\/logrotate.d\/myapp   # dry run, shows decisions\nsudo logrotate -f \/etc\/logrotate.d\/myapp   # force once to confirm<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Two details matter. <code>copytruncate<\/code> lets you rotate logs from programs that cannot be told to reopen their file (it copies then truncates in place), at the cost of a tiny window where a few lines can be lost. If your service supports a reload signal, drop <code>copytruncate<\/code> and rely on the <code>postrotate<\/code> reload for zero-loss rotation. <code>size 50M<\/code> combined with <code>daily<\/code> means a log escalates to rotation on either trigger.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Confirm the Timer Is Actually Running<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A common failure is a perfect logrotate config that nothing ever invokes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl status logrotate.timer\nsystemctl list-timers | grep logrotate\ncat \/etc\/logrotate.conf | grep -v '^#' | grep -v '^$'\ncat \/var\/lib\/logrotate\/status | head -20<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The status file records the last rotation date per log. If a log you expect is missing from it, logrotate is not matching the path \u2014 check your globs against the real filenames.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Optional Centralization<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once local retention is sane, forwarding is cheap and preserves history after a host dies. A minimal rsyslog forward:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tee \/etc\/rsyslog.d\/60-forward.conf &gt; \/dev\/null &lt;&lt;'EOF'\n*.* action(type=\"omfwd\" target=\"logs.internal\" port=\"514\" protocol=\"tcp\"\n           action.resumeRetryCount=\"-1\" queue.type=\"linkedList\"\n           queue.size=\"10000\")\nEOF\nsudo systemctl restart rsyslog<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>linkedList<\/code> disk-assisted queue means local logging survives a network outage to the collector instead of blocking. Keep local retention even with forwarding \u2014 the collector is an archive, not a substitute.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verification Step<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Prove the limits are enforced rather than merely configured.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 1. Journal honors the size cap\nsudo dd if=\/dev\/zero bs=1M count=800 | xargs -I{} sh -c   'logger -p user.info \"flood test payload\"'\nsleep 5\njournalctl --disk-usage      # must remain near SystemMaxUse, not climb past it\n\n# 2. logrotate policy parses and rotates\nsudo logrotate -d \/etc\/logrotate.d\/myapp 2&gt;&amp;1 | grep -E 'rotating|skipping'\nls -lh \/var\/log\/myapp\/\n\n# 3. Free space did not collapse\ndf -h \/<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If <code>journalctl --disk-usage<\/code> stays pinned near your cap after the flood, the limit is working. Rotation is confirmed when you see a dated archive alongside the fresh file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Symptom<\/th><th>Cause<\/th><th>Fix<\/th><\/tr><\/thead><tbody><tr><td>Journal grows past SystemMaxUse<\/td><td>Config not in the drop-in dir<\/td><td>Verify with <code>systemd-analyze cat-config systemd\/journald.conf<\/code><\/td><\/tr><tr><td>Rotation runs but files never shrink<\/td><td>Logs outside the configured glob<\/td><td>Match exact paths; check <code>\/var\/lib\/logrotate\/status<\/code><\/td><\/tr><tr><td><code>logrotate -d<\/code> reports no matching logs<\/td><td>Wrong directory or filename pattern<\/td><td>Test the glob with <code>ls<\/code> first<\/td><\/tr><tr><td>Lines lost at rotation<\/td><td><code>copytruncate<\/code> race<\/td><td>Remove it and reload the service in <code>postrotate<\/code><\/td><\/tr><tr><td>Timer never fires<\/td><td>logrotate.timer disabled<\/td><td><code>systemctl enable --now logrotate.timer<\/code><\/td><\/tr><tr><td>Journal restarts lose entries<\/td><td><code>Storage=volatile<\/code><\/td><td>Set <code>Storage=persistent<\/code> and create <code>\/var\/log\/journal<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">With size caps on the journal, an explicit rotation policy for application logs, and a verification pass after the flood test, log growth becomes a bounded, predictable cost instead of a surprise outage.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Step-by-step guide to capping journald with size and time limits, writing a working logrotate policy, confirming the timer runs, and verifying with a log flood test.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":5,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1038","post","type-post","status-publish","format-standard","hentry","category-vps-guides-tutorials"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"Step-by-step guide to capping journald with size and time limits, writing a working logrotate policy, confirming the timer runs, and verifying with a log flood test.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup\" \/>\n<meta property=\"og:description\" content=\"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-02T22:37:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-13T22:03:33+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/\",\"name\":\"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-09-02T22:37:25+00:00\",\"dateModified\":\"2026-09-13T22:03:33+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"Step-by-step guide to capping journald with size and time limits, writing a working logrotate policy, confirming the timer runs, and verifying with a log flood test.\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup - Virtual Servers VPS Blog","description":"Step-by-step guide to capping journald with size and time limits, writing a working logrotate policy, confirming the timer runs, and verifying with a log flood test.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/","og_locale":"en_US","og_type":"article","og_title":"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup","og_description":"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup","og_url":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-09-02T22:37:25+00:00","article_modified_time":"2026-09-13T22:03:33+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/","url":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/","name":"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-09-02T22:37:25+00:00","dateModified":"2026-09-13T22:03:33+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"Step-by-step guide to capping journald with size and time limits, writing a working logrotate policy, confirming the timer runs, and verifying with a log flood test.","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/vps-log-management-journald-logrotate-setup-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Keeping VPS Logs Under Control: A Step-by-Step journald and logrotate Setup"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1038","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=1038"}],"version-history":[{"count":3,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1038\/revisions"}],"predecessor-version":[{"id":1121,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1038\/revisions\/1121"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=1038"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=1038"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=1038"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}