Server Basic Configuration

Posted on 6 2026

The source material covers basic Ubuntu Server configuration: hostname, domain, resolver, timezone, and locale. In this network, these settings apply in two places: the Proxmox host itself, and the base Ubuntu 24.04 container template that every service container is built from.

This page covers both. The Proxmox host configuration is done first, then the container template configuration which is applied once and inherited by every container provisioned from it.

Proxmox host: basic configuration

Connect to the Proxmox host via SSH or use the shell in the web interface (node > Shell).

Hostname

The hostname was set during installation. Verify it:

hostname -f

Expected output: server.yourdomain.net

If it needs changing:

hostnamectl set-hostname server.yourdomain.net

Hosts file

Ensure the /etc/hosts file is correctly configured for reliable FQDN resolution without depending on DNS:

sudo tee /etc/hosts << 'EOF'
127.0.0.1       localhost
127.0.1.1       server.yourdomain.net server

10.1.0.10       server.yourdomain.net server

::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters
EOF

Replace 10.1.0.10 with the actual static IP address assigned to the server on the Core VLAN.

Verify FQDN resolution:

hostname -f
# Expected: server.yourdomain.net

getent hosts server
# Expected: 10.1.0.10 server.yourdomain.net server

Timezone

timedatectl set-timezone Europe/London
timedatectl status

Verify the output shows Time zone: Europe/London (BST, +0100) (or GMT during winter) and NTP service: active.

Locale

The Proxmox host and all containers should use British English with UTF-8 encoding:

# Generate the required locales
locale-gen en_GB.UTF-8 en_US.UTF-8

# Set system-wide locale defaults
tee /etc/default/locale << 'EOF'
LANG=en_GB.UTF-8
LANGUAGE=en_GB:en
LC_ALL=en_GB.UTF-8
EOF

# Apply immediately
localectl set-locale LANG=en_GB.UTF-8

Verify:

locale

DNS resolver on the Proxmox host

The Proxmox host uses systemd-resolved for DNS. Configure it to use the internal Unbound resolver:

tee /etc/systemd/resolved.conf.d/internal-dns.conf << 'EOF'
[Resolve]
DNS=10.1.0.x
FallbackDNS=1.1.1.1
Domains=yourdomain.net
EOF

systemctl restart systemd-resolved

Replace 10.1.0.x with the internal Unbound resolver address. While Unbound is still being configured, use 1.1.1.1 as the primary DNS temporarily.

Verify resolution:

resolvectl status
resolvectl query google.com

Container template: base configuration

The container template is a configured Ubuntu 24.04 LXC container that serves as the starting point for every service container. Creating and configuring it once means every new container inherits the correct baseline configuration without manual repetition.

Download the Ubuntu 24.04 template

In the Proxmox web interface, navigate to node > local storage > CT Templates. Click Download from URL and select the Ubuntu 24.04 LXC template, or use the command line:

pveam update
pveam download local ubuntu-24.04-standard_24.04-2_amd64.tar.zst

Create the base container

In the web interface, click Create CT. Configure:

SettingValue
CT ID100 (or your preferred numbering scheme)
Hostnamebase-template
TemplateUbuntu 24.04 standard
Root disk8GB on the SSD storage
CPU cores1
RAM512MB
Networkvmbr0, VLAN tag 14 (Core VLAN), DHCP
DNS domainyourdomain.net
DNS servers10.1.0.x

Do not start the container yet.

Configure the base container

Start the container from the Proxmox web interface and open a console, or connect via SSH once it has an IP address.

Update packages

apt update && apt upgrade -y
apt autoremove -y

Hostname and hosts file

hostnamectl set-hostname base-template.yourdomain.net

tee /etc/hosts << 'EOF'
127.0.0.1       localhost
127.0.1.1       base-template.yourdomain.net base-template

::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters
EOF

Individual containers will update /etc/hostname and /etc/hosts with their own names after provisioning.

Timezone

timedatectl set-timezone Europe/London

Locale

apt install -y locales
locale-gen en_GB.UTF-8

tee /etc/default/locale << 'EOF'
LANG=en_GB.UTF-8
LANGUAGE=en_GB:en
LC_ALL=en_GB.UTF-8
EOF

Essential packages

Install a base set of packages that every container will need:

apt install -y \
    curl \
    wget \
    gnupg \
    ca-certificates \
    apt-transport-https \
    software-properties-common \
    unattended-upgrades \
    nano \
    htop \
    net-tools \
    dnsutils \
    mtr-tiny \
    rsync \
    postfix \
    mailutils

The Postfix installation will ask for configuration type. Select Satellite system and set the relay host to [mail.yourdomain.net]:submission. The full Postfix null client configuration from the desktop section applies identically here.

Configure unattended upgrades

Enable automatic security updates:

tee /etc/apt/apt.conf.d/50unattended-upgrades << 'EOF'
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}";
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";
};

Unattended-Upgrade::Package-Blacklist {};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Mail "root";
EOF

tee /etc/apt/apt.conf.d/20auto-upgrades << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
EOF

NTP configuration

tee /etc/systemd/timesyncd.conf.d/local.conf << 'EOF'
[Time]
NTP=10.1.0.1
FallbackNTP=0.uk.pool.ntp.org 1.uk.pool.ntp.org
EOF

systemctl restart systemd-timesyncd
timedatectl status

Disable IPv6 if not in use

For containers that do not need IPv6:

tee /etc/sysctl.d/99-disable-ipv6.conf << 'EOF'
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF

sysctl --system

Remove this from containers that need IPv6.

Clean up before converting to template

Remove any temporary files, logs, and SSH host keys that should be unique per container:

# Clear logs
find /var/log -type f -exec truncate -s 0 {} \;

# Remove SSH host keys (generated fresh for each container)
rm -f /etc/ssh/ssh_host_*

# Clear bash history
history -c
cat /dev/null > ~/.bash_history

# Remove the machine ID (regenerated per container)
truncate -s 0 /etc/machine-id

# Clean package cache
apt clean

Convert to template

Shut down the container:

poweroff

In the Proxmox web interface, right-click the container and select Convert to Template. The container is now a template that can be cloned to create new containers.

Creating a new container from the template

To provision a new service container from the template:

In the Proxmox web interface, right-click the template and select Clone. Configure:

SettingValue
ModeFull Clone
CT IDNext available (e.g. 101, 102, 103…)
HostnameService-specific name (e.g. dns, mail, nextcloud)
Target StorageSSD storage

After cloning, update the hostname in the new container:

# In the new container
NEW_NAME="dns"
hostnamectl set-hostname ${NEW_NAME}.yourdomain.net

# Update /etc/hosts
sed -i "s/base-template/${NEW_NAME}/g" /etc/hosts

# Generate new SSH host keys
ssh-keygen -A

# Set a unique machine ID
systemd-machine-id-setup

This pattern, clone from template, update hostname, configure the service-specific packages, produces consistent containers with minimal repetition.

Reference: Proxmox container numbering

A consistent numbering scheme makes the container list readable at a glance:

RangePurpose
100Base template
101-109Core network services (DNS, NTP, monitoring)
110-119Mail services
120-129Web and application services
130-139Nextcloud and file services
140-149Media services
150-159IoT and home automation
200-299Virtual machines
900-999Test and development containers

This is a suggestion rather than a requirement. The important thing is consistency within the deployment.

The base template is worth getting right before cloning from it. Every service container inherits its configuration. A missing package or misconfigured timezone in the template means fixing the same issue in every container. Spend the time on the template. It pays back across every service deployment.