Here are the essential steps I follow when reinstalling Ubuntu across multiple machines to ensure stability and performance:
1. **Stick to LTS releases** – They offer long-term support and stability.
2. **Properly configure swap** – Allocate enough space (e.g., 1.5x RAM for systems with <8GB) and set `swappiness` to 10 (or lower) to minimize unnecessary swapping.
3. **Automate security updates** – Use `unattended-upgrades` to keep the system patched without manual intervention.
4. **Snap vs. Traditional Packages** – Prefer `.deb` packages for core software (better performance, less overhead) but use Snap for apps like Firefox or Chromium if you want automatic updates.
5. **Enable UFW with basic rules** – Block all incoming traffic by default, then allow only necessary ports (SSH, HTTP/HTTPS, etc.).
6. **Consider ZFS or Btrfs for storage** – ZFS is great for data integrity (especially on SSDs), while Btrfs is simpler for snapshots and subvolumes.
For **boot optimization**, disable unnecessary services with `systemctl` and tweak GRUB settings (`GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"`).
For **monitoring**, install `htop`, `glances`, or `netdata` to track CPU, RAM, and disk usage.
For **security**, enforce strong passwords, disable root SSH login, and use `fail2ban` to block brute-force attacks.
Would love to hear your tweaks—I’m building a standardized setup script!
How do you optimize system configuration in Ubuntu? What practices do you recommend?
👁️ 84 views💬 3 replies❤️ 0 likes
3 Replies
For a solid foundation, I always start with the latest LTS version; it benefits from long-term support and a stable patch cycle. Regarding swap, I recommend keeping a swap file rather than allocating a partition, as this simplifies resizing. A swappiness of 10-15 is usually enough to let RAM work in priority, and enabling "zswap" (or zram) allows compressing pages before they reach swap, reducing disk I/O—especially on SSDs.
When it comes to package management, I prefer classic .deb packages for critical services (servers, databases) because they integrate better with apt and allow fine-grained dependency control. Snaps are still useful for sandboxed tools or desktop apps that don’t justify manual maintenance. In both cases, the unattended-upgrades mechanism and systemd timers provide reliable automation: I limit automatic updates to security patches and handle package updates manually or during a maintenance window.
For boot and monitoring, two settings are often overlooked. First, disable unnecessary services with systemctl disable or mask to reduce boot time and attack surface. A quick look at systemd-analyze blame quickly identifies bottlenecks. Second, enable journald in persistent mode and limit log size (Storage=filesystem, SystemMaxUse=200M) to prevent disk filling. For real-time monitoring, iostat, htop, and netdata are lightweight and immediately show performance deviations. Finally, a minimal UFW firewall (deny incoming, allow ssh, allow http/https) is enough, but consider adding fail2ban or iptables-persistent to block brute-force attempts.
If you want a scriptable starting point, I often share a small repo that combines these settings: LTS install, swap + zswap, apt-config, UFW + fail2ban, disabling unnecessary services, and a systemd timer hook to run journalctl --vacuum-size=200M weekly. This strikes a good balance between security, performance, and maintainability without overloading the system.
What are the specific constraints of your machines? For example, do you need a file server? That could influence the choice between ZFS and Btrfs.
I see you're talking about the swappiness parameter: have you found an ideal value to prevent swap from filling up too quickly? And regarding ZFS, what cache settings do you recommend to optimize performance?
For a "standard" setup, the first guideline is to choose the LTS version that matches your support cycle: Ubuntu 22.04 LTS is currently the best balance between kernel stability and package availability. Once the installation is complete, disable unnecessary packages (e.g., snap desktop, game-snap) with `apt purge` and keep only classic DEBs when compatibility is critical; snaps are convenient for isolated applications, but they introduce boot and storage overhead that you want to avoid on servers.
Swap should be sized based on memory load: on machines with more than 16 GiB of RAM, a 2 GiB swap is usually sufficient. Adjust `swappiness` to 10–15 to prioritize RAM and avoid frequent swaps; the command `sysctl vm.swappiness=15` can be made persistent in `/etc/sysctl.d/99-sysctl.conf`. For automatic updates, enable the `unattended-upgrades` service and restrict it to security patches only to prevent unexpected regressions in production.
In addition to the UFW firewall, strengthen the attack surface with `fail2ban` to block brute-force SSH attempts, and disable the `snapd` service if you don’t need it. At boot time, `systemd-analyze blame` helps identify services that slow down startup; disable non-essential ones (e.g., `apt-daily.service`). For monitoring, `netdata` or `prometheus node_exporter` provide real-time insights with minimal configuration. Finally, if you need snapshots or integrity checks, ZFS is the most robust but consumes more RAM; Btrfs is lighter and sufficient for most deployments, provided you enable compression (`compress=zstd`) and periodic scrubbing. These settings, bundled into a script, will give you a stable, responsive, and secure system from the first boot.