Skip to content

Instantly share code, notes, and snippets.

@plembo
Last active June 1, 2024 19:40
Show Gist options
  • Save plembo/52aa4e442943f68d86ec0ce31de8e0b0 to your computer and use it in GitHub Desktop.
Save plembo/52aa4e442943f68d86ec0ce31de8e0b0 to your computer and use it in GitHub Desktop.
Ubuntu Server Setup - with netplan

Ubuntu Server Setup - with netplan

Introduction

The assumption here is that you're now starting with a Ubuntu 22.04 LTS Server or newer, rather than Desktop, base (Ubuntu Desktop deploys NetworkManager rather than systemd-networkd by default). This box has an AMD Ryzen CPU.

The goal is networking configured for static addressing using systemd-networkd and netplan. Note that punctuation (including hypens, '-') and indentation are significant when working with netplan YAML files.

There are a lot good arguments against using netplan. I have tried NetworkManager (packages named "network-manager", but the service is "NetworkManager.service" -- go figure) on Ubuntu Server, and was disappointed in the result (in contrast to its solid performance on Ubuntu Desktop). An alternative is to use ifupdown (i.e. Debian's "/etc/network/interfaces") instead. See this gist on how to do that.

The physical network device name for the test machine was "ens3", it will be something else on different hardware.

You will notice this is a fairly involved "personalization". That was not my preference, but frankly, Canonical has made some poor choices in the design of their server distro (i.e. force-feeding us systemd-resolved when it clearly has not reached stable maturity) that made it necessary.

Please do not perform this procedure on a virtual machine hosted in the cloud. You will probably annoy your vendor and almost certainly have to re-create the vm (or restore from a snapshot -- you do take snapshots, don't you?

Security

Every Ubuntu Server and Desktop shares one glaring security flaw: user home directories (other than root) are permissioned with read and execute rights for "other". Before going any further (and from this point forward until Canonical fixes this), be sure to reset these permissions on all user home directories:

$ sudo chmod o-rx /home/*

Configuration

  1. Make vi(m) the default editor, because I don't like nano.
$ sudo apt install vim
$ sudo update-alternatives --config editor 

Pick "vim.basic" from the list.

  1. Completely remove cloud-init and its associated files under /etc/cloud-init, unless you enjoy watching it fail and delay the completion of every reboot.
$ sudo apt remove --purge cloud-init
$ sudo rm -rf /etc/cloud-init

Also mask the systemd-networkd-wait-online service, because it depends on cloud-init and will drag out system recovery after reboot:

$ sudo systemctl mask systemd-networkd-wait-online
  1. Make sure systemd-networkd is enabled and running.
$ sudo systemctl enable systemd-networkd
$ sudo systemctl status systemd-networkd

Add nomodeset and loglevel modifying /etc/default/grub so it looks something like this:

GRUB_CMDLINE_LINUX_DEFAULT=quiet splash nomodeset loglevel=3"

NOTE: To work, the loglevel option must come last.

Then run sudo update-grub and reboot.

  1. Set up a /etc/netplan/01-netcfg.yaml to specify your network config. Note this config sets up a network bridge, which is useful for making virtual machines available from other hosts on a local network (a macvtap bridge will normally not allow connection to a guest, but a real network bridge will). It can also provides a bridge alias with a second IP for the system (see below).
$ sudo vi /etc/netplan/01-netcfg.yaml

The resulting file should look like this:

# /etc/netplan/01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    ens3:
      dhcp4: false
      dhcp6: false
  bridges:
    br0:
      interfaces: [ens3]
      dhcp4: false
      dhcp6: true
      addresses:
        - 10.0.1.11/24
        - 10.0.1.9/24
      nameservers:
        addresses: [10.0.1.1, 8.8.8.8, 8.8.4.4]
        search: [example.com]
      routes:
        - to: default
          via: 10.0.1.1

OR, for a simpler config without a bridge:

network:
  version: 2
  renderer: networkd
  ethernets:
    ens3:
      dhcp4: false
      dhcp6: true
      addresses:
        - 10.0.1.11/24
      gateway4: 10.0.1.1
      nameservers:
        addresses: [10.0.1.1, 8.8.8.8, 8.8.4.4]
        search: [example.com]   
      routes:
        - to: default
          via: 10.0.1.1

Remember: indentation and hyphens are significant. If your config throws an error, it is usually became one of those if off somehow (or you're missing something important: like the network mask for a host IP address assigment).

The "gateway4" configuration item has been deprecated. The latest documentation specifies the use of the "routes" statement given above, where the "via" item is the IP address of what would have been "gateway4".

Setting dhcp6: true on the primary interface will allow the machine to grab a global IPv6 address if SLAAC (or DHCP6) is running on the gateway side. It will also get the IPv6 name servers. If it isn't, networking may hang. IPv6 may not work in KVM virtual machines.

  1. Rename any /etc/netplan/50-cloud-init.yaml to 50-cloud-init.yaml.disabled or delete. Did I mention you should probably just uninstall cloud-init and delete all its associated files?

  2. If using the default systemd-resolved DNS cache, make sure /etc/resolv.conf is linked to /run/systemd/resolve/resolv.conf and not stub-resolv.conf:

$ sudo rm /etc/resolv.conf
$ sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

After your netplan has been applied and both systemd-networkd and systemd-resolved have been cycled, resolv.conf should reflect the name server order specified in netplan (important if you have an internal name server that queries should go to first).

Disable the systemd-resolved listener (and free up its hold on local port 53) by editing /etc/systemd/resolved.conf, modifying the following lines (if "DNS=" is uncommented, comment it):

#DNS=
DNSStubListener=no
  1. Apply the configuration and reboot the server.
$ sudo netplan generate
$ sudo netplan apply
$ sudo reboot

If you get an error when applying your netplan, go back over the .yaml file with a fine-toothed comb. On one iteration it kept barking at me because I had failed to indent my "bridges:" statement in line with "ethernets:", in another I forgot to add the network component to an ethernet addreess.

  1. If you haven't done so already, edit /etc/hosts to add the host's static ip.
$ sudo vi /etc/hosts
# /etc/hosts
127.0.0.1 localhost
10.0.1.11 myhost.example.com myhost
  1. Enable serial console access (especially if this is going to be a virtual machine):
$ sudo systemctl enable serial-getty@ttyS0.service
$ sudo systemctl start serial-getty@ttyS0.service
  1. Install and configure chrony, which will disable systemd-timesyncd. The reasons for doing this on an Internet-connected workstation or server are laid out here.
$ sudo apt install chrony
$ sudo vi /etc/chrony/chrony.conf

The defaults will work fine for a desktop worksation that doesn't need a local time server. My preference, being located in the continental US, is to use the n.us.pool.ntp.org servers (see the code block below).

To set up the machine as a local time server, add the "allow" directive and specify the local network to be served.

# pool ntp.ubuntu.com        iburst maxsources 4
# pool 0.ubuntu.pool.ntp.org iburst maxsources 1
# pool 1.ubuntu.pool.ntp.org iburst maxsources 1
# pool 2.ubuntu.pool.ntp.org iburst maxsources 2
server 0.us.pool.ntp.org iburst
server 1.us.pool.ntp.org iburst
server 2.us.pool.ntp.org iburst
server 3.us.pool.ntp.org iburst

allow 10.0.1.0/24

Where 10.0.1.0/24 is your local network.

  1. After a major version upgrade you may need to remove and reinstall ubuntu-release-upgrader-core.

  2. Postfix is my go to when I need to send mail over the Internet or my local network, or receive mail from services like cron (in the last case the server would be configured as Local only). Hanif Jetha and Mark Drake, "How to Install and Configure Postfix on Ubuntu 20.04" is a good place to start, https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-on-ubuntu-20-04. I use the s-nail mail client with postfix.

  3. Other helpful software and services. These are not essential, but make life a lot easier (package names are for Ubuntu):

  • needrestart tool
  • bind9utils
  • nmap

Postgame

Do some basic tests to make sure the system state is now consistent with your netplan, like running hostnamectl, networkctl and resolvectl:

$ hostnamectl status # show hostname
$ networkctl # to get list of interfaces
$ networkctl status br0 # details on interface br0
$ resolvectl status # show resolvers per interface

Also verify that resolv.conf is consistent with your netplan. If it isn't, there's either a problem with your netplan config or with systemd-resolved.

References

"Netplan configuration examples". Netplan.io, https://netplan.io/examples/. Retrieved 22 July 2022.

@plembo
Copy link
Author

plembo commented Mar 11, 2020

Recently installed Ubuntu Server 18.04 LTS for the Raspberry Pi 3, which meant that I had to configure networking for DHCP through both the ethernet port and wifi (this device will eventually live outside, away from my wired network). Basically followed the guide above except for the contents of /etc/netplan/01-netcfg.yaml:

# /etc/netplan/01-netcfg.yaml
network:
    ethernets:
        eth0:
            dhcp4: true
            optional: true
    version: 2

    wifis:
        wlan0:
            optional: true
            dhcp4: true
            access-points:
               "helios-home":
                  password: "oursecretkey"

Not exactly happy about having our access point key in the clear there. Definitely need to find another way.

@plembo
Copy link
Author

plembo commented Mar 16, 2020

NetworkManager is usually not installed on Ubuntu Server, but if it did get installed somehow the appropriate action is to stop and then mask it and related services:

$ sudo systemctl stop NetworkManager
$ sudo systemctl mask NetworkManager
$ sudo systemctl stop NetworkManager-wait-online
$ sudo systemctl mask NetworkManager-wait-online

"Masking" a systemd service ensures it can't be called up by another service (like systemd-networkd.socket is called by systemd-networkd).

NOTE: If you're running a variant of the Gnome Shell (like ubuntu-desktop), do not try removing the network-manager package unless you really want Gnome gone as well. The NetworkManager package is a dependency for the Gnome packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment