JustToThePoint English Website Version
JustToThePoint en español

Arch Linux Post-Installation: Locale, Timezone, and SSH Configuration

Do, or do not. There is no try, Yoda.

image info

Introduction

After establishing the graphical environment and optimizing package management, the focus shifts to localizing the system and enabling remote access. This phase ensures that your Arch Linux installation conforms to regional standards for dates, currency, and language while securing the necessary tools for remote administration. The following scripts cover these essential configurations: 07-locale.sh sets up a hybrid locale strategy—keeping the system language in English for easier troubleshooting while applying Spanish formats for regional data—and synchronizes the system clock. 08-ssh.sh then hardens the OpenSSH server, enabling features like X11 forwarding for remote GUI applications and generating modern Ed25519 cryptographic keys for secure, passwordless login.

System Locale Configuration

#!/usr/bin/env bash
# ── 07-locale.sh ──────────────────────────────────────────────────────────────
#
# DESCRIPTION
#   Configures system locale settings with English UI language but Spanish
#   regional formats. This is the standard Unix way to achieve localized
#   formats while keeping error messages and documentation in English.
# Strategy: English UI + Spanish regional formats
#   LANG=en_US.UTF-8        → menus, error messages, man pages in English
#   LC_TIME=es_ES.UTF-8     → dates: lunes, 10 de marzo de 2026
#   LC_NUMERIC=es_ES.UTF-8  → numbers: 1.234,56 (comma as decimal)
#   LC_MONETARY=es_ES.UTF-8 → currency: 1.234,56 €
#   LC_MEASUREMENT=es_ES.UTF-8 → metric system (km, kg, ℃)
#   LC_ADDRESS=es_ES.UTF-8  → Spanish address format conventions
#   LC_TELEPHONE=es_ES.UTF-8 → Spanish phone format (+34)
#   LC_PAPER=es_ES.UTF-8    → A4 paper (not US Letter)
#
# Why split LANG and LC_*:
#   Most non-US users want English error messages (easier to Google solutions)
#   but regional formats matching their country. Separating LANG from the
#   format variables is the correct, standards-compliant way to achieve this.
#
# Run: bash 07-locale.sh
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail

echo "── 07-locale: configuring locale..."

# ── 1. Uncomment required locales in /etc/locale.gen ─────────────────────────
# /etc/locale.gen lists all available locales, most commented out.
# locale-gen reads this file and generates the binary locale data.
echo "  Uncommenting en_US.UTF-8 and es_ES.UTF-8 in /etc/locale.gen..."

sudo sed -i 's/^#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
sudo sed -i 's/^#es_ES.UTF-8 UTF-8/es_ES.UTF-8 UTF-8/' /etc/locale.gen

# ── 2. Generate the locale data ───────────────────────────────────────────────
echo "  Running locale-gen..."
sudo locale-gen

# ── 3. Write /etc/locale.conf ─────────────────────────────────────────────────
# This file is read by systemd at boot and sets the environment for all
# sessions  (including display managers, TTYs, and system services).
# Individual users can override these settings in ~/.config/locale.conf (systemd).
echo "  Writing /etc/locale.conf..."
sudo tee /etc/locale.conf > /dev/null << 'LOCALE'
# System locale configuration
# ────────────────────────────────────────────────────────
# LANG: primary locale — controls UI language (English)
LANG=en_US.UTF-8

# LC_TIME: date and time format — "lunes, 10 de marzo de 2026, 15:30:45"
LC_TIME=es_ES.UTF-8

# LC_NUMERIC: number format — "1.234,56" (European style, period for thousands, comma for decimal)
LC_NUMERIC=es_ES.UTF-8

# LC_MONETARY: currency format — "1.234,56 €"  (space between amount and symbol)
LC_MONETARY=es_ES.UTF-8

# LC_MEASUREMENT: measurement system — metric (kilometers, kilograms, Celsius)
LC_MEASUREMENT=es_ES.UTF-8

# LC_ADDRESS: Spanish conventions (calle, ciudad, código postal)
LC_ADDRESS=es_ES.UTF-8

# LC_TELEPHONE: Spanish format (+34 912 345 678, +34 prefix)
LC_TELEPHONE=es_ES.UTF-8

# LC_PAPER: paper size — A4 (210×297mm, not US Letter, standard in Europe)
LC_PAPER=es_ES.UTF-8

# LC_MESSAGES intentionally NOT set — stays as en_US.UTF-8 (inherits from LANG=en_US.UTF-8)
# This keeps all error messages and software UI in English
LOCALE

echo "  ✅  /etc/locale.conf written"

# ── 4. Set system hostname and timezone ───────────────────────────────────────
# Timezone: Europe/Madrid covers mainland Spain (CET/CEST)
echo "  Setting timezone to Europe/Madrid..."
sudo timedatectl set-timezone Europe/Madrid

# Enable NTP (network time synchronisation) for accurate system clock
sudo timedatectl set-ntp true

echo "  ✅  Timezone: $(timedatectl show --property=Timezone --value)"
echo "  ✅  NTP: $(timedatectl show --property=NTP --value)"

# ── 5. Set keyboard layout system-wide ───────────────────────────────────────
# This sets the console (TTY) keyboard layout.
# The Niri config handles the Wayland keyboard layout separately.
echo "  Setting console keymap to us..."
sudo localectl set-keymap us

echo
echo "── Current locale settings:"
locale 2>/dev/null || true

echo
echo "✅  07-locale: done"
echo "    Next: bash 08-ssh.sh"

Some checks: Check current locale settings (locale); date formatting (date); number formatting (python3 -c "print(f'{1234567.89:,.2f}')". It should show 1.234.567,89); timezone (timedatectl status).

SSH Server Configuration & Client Setup

#!/usr/bin/env bash
# ── 08-ssh.sh ─────────────────────────────────────────────────────────────────
# Configure the OpenSSH server and generate client keys.
#
# Server settings enabled:
#   AllowTcpForwarding yes  — lets SSH act as a tunnel
#   X11Forwarding yes       — Enable X11 forwarding (GUI apps over SSH)
#   X11DisplayOffset 10     — first X11 display number assigned to forwarded
#                             sessions (avoids conflicts with display :0, :1...)
#   X11UseLocalhost yes     — binds the X11 forwarding socket to localhost
#                             only (more secure than binding to 0.0.0.0)
#
#
# Run: bash 08-ssh.sh
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail

USERNAME="${SUDO_USER:-$(whoami)}"

echo "── 08-ssh: configuring OpenSSH..."

# ── Install OpenSSH if not present ───────────────────────────────────────────
sudo pacman -S --needed --noconfirm openssh

# ── Backup existing configuration sshd_config ──────────────────────────────────────────────
SSHD_CONFIG="/etc/ssh/sshd_config"
if [[ ! -f "${SSHD_CONFIG}.orig" ]]; then
  sudo cp "$SSHD_CONFIG" "${SSHD_CONFIG}.orig"
  echo "  📦  Original sshd_config backed up to ${SSHD_CONFIG}.orig"
fi

# ── Apply server settings ─────────────────────────────────────────────────────
# We use sed to uncomment and set specific directives.
# Pattern: find the line (commented or not), replace the whole line with
# our desired value. This is idempotent — safe to run multiple times.

echo "  Applying sshd_config settings..."

# Core settings for X11 forwarding and tunneling
# AllowTcpForwarding: enables -L (local), -R (remote), -D (dynamic SOCKS) tunnels
sudo sed -i 's/^#\?AllowTcpForwarding.*/AllowTcpForwarding yes/' "$SSHD_CONFIG"

# X11Forwarding: allows forwarding of GUI application windows to the client
sudo sed -i 's/^#\?X11Forwarding.*/X11Forwarding yes/' "$SSHD_CONFIG"

# X11DisplayOffset: the first display number available for X11 forwarding.
# Set to 10 so forwarded displays start at :10, leaving :0-:9 for local use.
sudo sed -i 's/^#\?X11DisplayOffset.*/X11DisplayOffset 10/' "$SSHD_CONFIG"

# X11UseLocalhost: bind the X11 forwarding socket to localhost only (more secure)
sudo sed -i 's/^#\?X11UseLocalhost.*/X11UseLocalhost yes/' "$SSHD_CONFIG"

# MaxAuthTries: limit brute-force attempts. Maximum authentication attempts per connection.
sudo sed -i 's/^#\?MaxAuthTries.*/MaxAuthTries 3/' "$SSHD_CONFIG"

# ClientAliveInterval: server pings client every 60s; disconnect after 3 missed pings
# This prevents zombie SSH sessions from accumulating
sudo sed -i 's/^#\?ClientAliveInterval.*/ClientAliveInterval 60/' "$SSHD_CONFIG"
sudo sed -i 's/^#\?ClientAliveCountMax.*/ClientAliveCountMax 3/' "$SSHD_CONFIG"

echo "  ✅  sshd_config configured"

# ── Enable and start SSH server ───────────────────────────────────────────────
sudo systemctl enable --now sshd
echo "  ✅  sshd enabled and started"

# ── Generate SSH client keys ──────────────────────────────────────────────────
# Create an Ed25519 key pair for the user if one doesn't already exist.
# Ed25519 is faster, smaller, and more secure than RSA 4096 for new keys.
SSH_DIR="/home/${USERNAME}/.ssh"
ED25519_KEY="${SSH_DIR}/id_ed25519"
RSA_KEY="${SSH_DIR}/id_rsa"

mkdir -p "$SSH_DIR"
# Set proper permissions
chmod 700 "$SSH_DIR"

# Generate Ed25519 key (modern, secure)
if [[ ! -f "$ED25519_KEY" ]]; then
  echo "  Generating Ed25519 SSH key pair..."
  ssh-keygen -t ed25519 -C "${USERNAME}@arch-$(hostname)" -f "$ED25519_KEY" -N ""
  echo "  ✅  Ed25519 key generated: $ED25519_KEY"
  echo "  📋  Public key:"
  cat "${ED25519_KEY}.pub"
else
  echo "  ✅  Ed25519 key already exists: $ED25519_KEY"
fi

# Generate RSA key for legacy compatibility
if [[ ! -f "$RSA_KEY" ]]; then
  echo "  Generating RSA 4096 key for legacy server compatibility..."
  ssh-keygen -t rsa -b 4096 -C "${USERNAME}@arch-$(hostname)-rsa" -f "$RSA_KEY" -N ""
  echo "  ✅  RSA key generated: $RSA_KEY"
  echo "  Copy your public key to remote hosts. "
  echo "  📋  To authorise this key on your server:"
  echo "      ssh-copy-id -i ${RSA_KEY}.pub nmaximo7@dirIPServerSSH"
fi

echo "  Firewall configuration (if applicable):"
echo "   sudo ufw allow 22/tcp"

# ── Verify settings ───────────────────────────────────────────────────────────
echo
echo "── Verifying sshd_config settings:"
for setting in AllowTcpForwarding X11Forwarding X11DisplayOffset X11UseLocalhost MaxAuthTries ClientAliveInterval; do
  value=$(grep -E "^${setting}" "$SSHD_CONFIG" | head -1 || echo "  (not found)")
  echo "  $value"
done

echo
echo "✅  08-ssh: done"
echo "    Next: bash 09-audio.sh"

After configuration, test with: ssh -X nmaximo7@192.168.1.46, then xclock or xeye.

Bitcoin donation

JustToThePoint Copyright © 2011 - 2026 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.