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?
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/*
- 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.
- 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
- 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.
- 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.
-
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?
-
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
- 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.
- 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
- Enable serial console access (especially if this is going to be a virtual machine):
$ sudo systemctl enable [email protected]
$ sudo systemctl start [email protected]
- 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.
-
After a major version upgrade you may need to remove and reinstall
ubuntu-release-upgrader-core
. -
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.
-
Other helpful software and services. These are not essential, but make life a lot easier (package names are for Ubuntu):
- needrestart tool
- bind9utils
- nmap
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.
"Netplan configuration examples". Netplan.io, https://netplan.io/examples/. Retrieved 22 July 2022.
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:
Not exactly happy about having our access point key in the clear there. Definitely need to find another way.