pull down to refresh

This guide outlines the foundational setup for a robust, headless Ubuntu 24.04 LTS server. We are building this server to be managed entirely over SSH, with Tailscale providing both the secure network overlay and the SSH authentication mechanism.
This is the foundation for mission-critical applications like a Bitcoin node stack.
I will assume you already have your hardware. However if not, follow my guide at https://expatriotic.me/hardware.
TL;DR, go to https://xmrbazaar.com/user/MGold/ and find an Optiplex, then upgrade the NVMe SSD to at least 2TB. Then proceed with the guide.

Part 1: Preparation (Your Main Computer)

Before we touch the server hardware, we must prepare the installer and verify its integrity. These steps are performed on your primary Linux, macOS, or Windows workstation.
Before you begin, you may want to check out these two guides:
  1. https://expatriotic.me/terminal
  2. https://expatriotic.me/nano

Download Files

First, create a dedicated directory and download the necessary Ubuntu files.
# Navigate to your Downloads folder
cd ~/Downloads

# Create and enter a new directory
mkdir ubuntu-server
cd ubuntu-server
Now, use curl to download the four files for installation and verification.
# 1. The Ubuntu Server ISO (the installer itself)
curl -LO https://releases.ubuntu.com/noble/ubuntu-24.04.3-live-server-amd64.iso

# 2. The list of official fingerprints
curl -LO https://releases.ubuntu.com/noble/SHA256SUMS

# 3. The GPG signature ("wax seal") for that list
curl -LO https://releases.ubuntu.com/noble/SHA256SUMS.gpg

# 4. The official Ubuntu keyring (our "set of keys")
curl -o ubuntu-keyring.gpg "https://archive.ubuntu.com/ubuntu/project/ubuntu-archive-keyring.gpg"
Command Flags Explained:
  • curl: A tool to transfer data from a URL.
  • -L: (Location) Follows any redirects if the file has moved.
  • -O: (Output) Saves the file with its original name from the URL.
  • -o <filename>: (output) Saves the file with the specific name we provide (e.s., ubuntu-keyring.gpg).

Verify Files

See https://expatriotic.me/verifying-software as well Never trust a downloaded file. We must verify it. This is a two-step process.
  1. Verify Authenticity: We check that the SHA256SUMS list is authentic by checking its "wax seal" (.gpg file) against the official keyring.
    gpgv --keyring ./ubuntu-keyring.gpg SHA256SUMS.gpg SHA256SUMS
    
    You are looking for the Good signature from "Ubuntu CD Image Automatic Signing Key..." output. This confirms the list is from Ubuntu.
  2. Verify Integrity: Now that we trust the list, we check our .iso file's "fingerprint" against it.
    # On Linux / Git Bash on Windows
    sha256sum -c SHA256SUMS 2>&1 | grep ubuntu-24.04.3-live-server-amd64.iso
    
    # On macOS (with Homebrew coreutils)
    gsha256sum -c SHA256SUMS 2>&1 | grep ubuntu-24.04.3-live-server-amd64.iso
    
    The only output you should see is: ubuntu-24.04.3-live-server-amd64.iso: OK.
If both checks pass, you can proceed. If either fails, stop and re-download the files.

Create Bootable USB

You must now write this verified ISO to a USB drive. The process differs by operating system.

For macOS

  1. Identify your USB drive. Be extremely careful; selecting the wrong disk will erase your data.
    diskutil list
    
    Look for your USB drive (e.g., /dev/disk3 or /dev/disk4).
  2. Unmount the drive (replace X with your disk number).
    diskutil unmountDisk /dev/diskX
    
  3. Write the ISO. We use rdisk for "raw" mode, which is faster.
    sudo dd if=./ubuntu-24.04.3-live-server-amd64.iso of=/dev/rdiskX bs=1m status=progress
    

For Linux

  1. Identify your USB drive. Again, be careful.
    lsblk
    
    Look for your drive (e.g., /dev/sdc).
  2. Unmount all partitions on the drive (replace sdc with your drive).
    umount /dev/sdc*
    
  3. Write the ISO.
    sudo dd if=./ubuntu-24.04.3-live-server-amd64.iso of=/dev/sdc bs=1M status=progress
    

For Windows

The dd command is not natively available. The most reliable method is to use a free tool called Rufus.
  1. Open Rufus.
  2. Select your USB drive under "Device."
  3. Click "SELECT" and choose your downloaded ubuntu-24.04.3-live-server-amd64.iso file.
  4. Ensure the "Partition scheme" is set to GPT and "Target system" is UEFI.
  5. Click "START" and accept the warning that the drive will be erased.

Part 2: Server Installation (Bare Metal)

Connect the Optiplex to a monitor, keyboard, mouse, and Ethernet cable. Plug in your newly created USB drive.

BIOS/UEFI Configuration

  1. Power on the machine and immediately press the key to enter BIOS/UEFI setup (often F2, F12, or Del).
  2. Set Boot Order:
    • Move your USB Drive to be the first boot device.
    • After installation, you will change this back so the internal NVMe/SSD is first.
  3. UEFI Settings:
    • Ensure UEFI Boot is enabled.
    • Disable Secure Boot. Ubuntu supports it, but it can complicate things with custom hardware or modules. It's simpler to disable it for a dedicated server.
  4. Power Settings:
    • Look for AC Recovery or After Power Loss.
    • Set this to Power On. This is a critical sysadmin setting that ensures your server automatically reboots after a power outage.
Save changes and exit. The machine will restart and boot from your USB drive into the Ubuntu Server installer.

Ubuntu Installer Walkthrough

Follow the on-screen prompts, paying close attention to these key steps: (Any menu that I don't mention, leave blank and hit enter.)
  1. Installation Type: Choose Ubuntu Server (Minimized). We are building a headless server; a GUI (Graphical User Interface) is unnecessary overhead and a larger attack surface.
  2. Network Configuration: (Check out my guide on using a GL.iNet router https://expatriotic.me/router)
    • Your Ethernet (e.g., eth0) should show an IP from your router (DHCP).
    • Select it, go to "Edit IPv4," and change it from "Automatic (DHCP)" to "Manual."
    • We want to switch from DHCP to a static IP as this ensures your server is always at the same address on your local network. This also makes certain that your initial SSH connection for setup will work.
    • Enter the following network details. This example assumes your router is like mine, the GL.iNet Flint 2, and is using the default address: 192.168.8.1.
      • Subnet: 192.168.8.0/24
      • Address: 192.168.8.50
      • Gateway: 192.168.8.1
      • Name servers: 9.9.9.9, 149.112.112.112
  3. Storage: Use the default "Use an entire disk" option, selecting your internal NVMe/SSD. If you only have the one drive.\
    If you have multiple drives when you first reach the "Storage configuration" screen, the Ubuntu installer will likely select your largest drive (the 4TB HDD in my case) for a simple "guided" install. This is the opposite of what we want.
    For a high-performance crypto node, the entire operating system and all I/O-intensive applications (Bitcoin Core, Fulcrum, Dojo, etc.) must live on our fastest drive, the NVMe SSD. The large HDD will be used as a separate volume for backups.
    To do this, we must use a Custom storage layout.
    • On the "Storage configuration" screen, select ( ) Custom storage layout and press Done.
    • This brings you to the main partitioning screen (seen in the image above), which shows all your available drives.
    • First, navigate to the NVMe drive (e.g., WD_Blue...), press Enter, and select "Use as boot device". It will automatically allocate a 1GB (fat32) EFI partition for the Bootloader (Mount = /boot/efi).
    • Select the remaining free space on the NVMe drive.
      • Choose "Add GPT Partition".
      • Leave Size blank (this will use all remaining space).
      • Leave Format: as ext4.
      • Mount = /
      • Select Create.
    • Now we'll format our large HDD (the ST4000... drive) and tell the OS where to mount it, so it's ready to receive backups.
      • Navigate to the HDD (ST4000...).
      • Press Enter and select "Edit".
      • Format: ext4 (You can choose to re-format or keep the existing data if the option is available).
      • Mount = /mnt/bigdata (You can use any name you like, I went with "big data").
      • Select Save.
    • Navigate to Done. The installer will show a final summary of changes before it formats the drives. Confirm this.
  4. Profile Setup: This will determine what is displayed in the terminal! E.g., the setup below results in: "satoshis@node".
    • Your name: Satoshi
    • Your server's name: node
    • Pick a username: satoshis
    • Choose a password: Choose a strong, unique password. You will only need this password for sudo commands and the initial login.
  5. Upgrade to Ubuntu Pro: Default option is, "Skip for now". Use default. Hit enter.
  6. SSH Setup: Select "Install OpenSSH Server." This is mandatory. Tailscale SSH works by intercepting traffic to the standard OpenSSH server, so it must be present.
  7. Server Snaps: Skip all of them. We will install software manually.
  8. Reboot: Wait for the installation to finish. Hit Enter to reboot. Follow dialogue and remove USB. Hit Enter again to reboot.

Part 3: First Boot and Configuration

Your server will reboot. For this initial setup, we will log in using the password you just created. This is the only time we will rely on password SSH.

Initial Login

From your main computer's terminal, SSH into the new server using its static IP.
ssh satoshis@192.168.8.50
You will be asked to accept the server's host key and then enter your password.

Edge Case: Fixing the "REMOTE HOST IDENTIFICATION HAS CHANGED" Error

If you're reinstalling Ubuntu on a server that you've connected to via SSH in the past, you are 100% going to run into this warning:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
...
Host key verification failed.
Don't panic. This is the SSH security model working perfectly.

What's Happening?

The first time you connect to any server, your computer saves a unique cryptographic signature, or "host key," for that server's IP address. This is stored in a file on your local machine (at ~/.ssh/known_hosts).
When you re-flashed your server with a fresh Ubuntu install, the new operating system generated a brand new host key.
Now, your computer is seeing this new, unknown key from an IP it thought it already knew. It's correctly throwing an error, warning you that the server's identity has changed and it could be a "man-in-the-middle" attack.
Since we are the ones who made this change, we just need to tell our local machine to forget the old key and accept the new one.

The Solution

The cleanest and fastest way to fix this is to remove the old key from your known_hosts file. While the error message tells you the exact line to edit, there's a much easier command.
On your local computer (the one you are SSH-ing from), run the following command, replacing the IP with your server's:
ssh-keygen -R 192.168.8.50
This command automatically finds and removes all outdated keys for that host.
The next time you connect, you'll be greeted with the "first time" connection prompt. Just type yes to accept the new host key, and you'll be logged in.
$ ssh satoshis@192.168.8.50
The authenticity of host '192.168.8.50 (192.168.8.50)' can't be established.
ED25519 key fingerprint is SHA256:dV2KVvlp/xCJ1tvpmHoLr28lB04tbds36RkhtwnAyWQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

System Updates

First, update your system's package list and apply all upgrades.
# -y flag automatically answers "yes" to prompts
sudo apt update -y && sudo apt full-upgrade -y
Set up unattended-upgrades for "set it and forget it" security patches.
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
This will configure your system to automatically install security updates every night.
Install a few quality-of-life tools.
  • btop: A modern, comprehensive resource monitor.
  • tmux: A terminal multiplexer. It allows you to run long-running processes (like a blockchain sync) in a session that stays active even after you disconnect your SSH.
<!-- end list -->
sudo apt install -y btop tmux

Configure Tailscale SSH

This is the core of our remote access. We will install Tailscale and configure it to manage our SSH access, eliminating the need for manual SSH keys.
  1. Install Tailscale:
    # Add Tailscale's package repository and install
    curl -fsSL https://tailscale.com/install.sh | sh
    
  2. Authenticate and Enable SSH: Run the tailscale up command with the --ssh flag.
    sudo tailscale up --ssh
    
    • This command will present a URL. Copy it and paste it into your browser.
    • Log in to your Tailscale account to authorize the new server.
    • The --ssh flag tells the server to advertise itself as an SSH destination, allowing Tailscale to intercept and manage authentication.
  3. Test Tailscale SSH: From your main computer, find your server's Tailscale hostname (e.g., node) in the admin console. Now, SSH to it.
    # Note: no IP address, just the Tailscale machine name
    ssh satoshis@node
    
    • Your terminal will pause and print a URL.
    • Open this URL in your browser, complete the authentication.
    • Your terminal will then connect instantly, without asking for a password or key.

Final Server Hardening

  • Now that our secure Tailscale SSH is working, we can disable the password-based login on the local network as a final hardening step.
  1. Edit the SSH daemon's configuration file.
    # This edit only affects the standard ssh server, not Tailscale's
    sudo nano /etc/ssh/sshd_config
    
  2. Find the line PasswordAuthentication yes and change it to:
    PasswordAuthentication no
    
  3. Exit (Ctrl+X), save (y), Enter
  4. Apply the changes.
    sudo systemctl reload ssh
    
  • This change only affects connections to the server's local IP (192.168.8.50). Your Tailscale access remains managed by your identity provider. This provides layered security: your server is now inaccessible via password from the local network, and remotely accessible only via your authenticated Tailscale identity.
10 sats \ 5 replies \ @Scoresby 9h
Nice tutorial, thanks!
reply
102 sats \ 3 replies \ @DarthCoin 8h
yes is nice, except that he tried to sneak monero garbage, playing with noobs minds.
reply
Point to one command that has to do with Monero? I'll wait.
reply
4 sats \ 1 reply \ @DarthCoin 8h
it's in the title. Maybe you can fool noobs but not Darth.
reply
You got me
reply
reply
0 sats \ 1 reply \ @nout 2h
My tendency would be to run this on top of Debian rather than Ubuntu, but it's not a major difference.
reply
0 sats \ 0 replies \ @nout 1h
Btw, another relevant option is to do something like
reply
Monero always seemed like the least bad of all the shitcoins. Is it even Dino? Long live Linux and Bitcoin. Great to see good informative tech posts like this from sources other than grumpy @DarthCoin.
reply