Curriculum previewThis is not your assigned passport. No identity, answers, or completion progress are stored here.How to start your passport
Handbook / reference

reference

Euler Access And Safe SSH Key Setup

Goal: connect to Euler and configure a dedicated SSH key without replacing existing keys or rewriting an existing SSH configuration.

Goal: connect to Euler and configure a dedicated SSH key without replacing existing keys or rewriting an existing SSH configuration.

Prerequisites: a valid personal ETH account. Outside the ETH network, connect to the ETH VPN first.

Execution context: commands alternate between your local Windows PowerShell/macOS/Linux terminal and an Euler login-node Bash prompt. Every step labels its context. If the label does not match the prompt in front of you, stop; never paste a PowerShell block into Euler Bash.

The private key remains on your local computer. Never create or copy your local private key on Euler.

1. Confirm Password Login First#

Enter the short ETH username when prompted, not an email address.

Windows laptop - PowerShell#

$User = Read-Host "ETH username"
if ($User -notmatch '^[A-Za-z0-9._-]+$') { throw "Invalid ETH username" }
ssh "$User@euler.ethz.ch"

macOS or Linux laptop - zsh/Bash#

read -r -p "ETH username: " eth_user
case "$eth_user" in
  ''|*[!A-Za-z0-9._-]*) printf 'STOP: invalid ETH username\n' >&2 ;;
  *) ssh "$eth_user@euler.ethz.ch" ;;
esac

On first access, Euler may require acceptance of its usage rules and an access code sent to the registered ETH email address. An ETH password prompt is normal at this stage.

Expected result: the prompt changes to an Euler login node such as eu-login-36:~$.

Run this on the Euler login node - Bash, then disconnect:

hostname
exit

If login fails, stop and use Euler troubleshooting. Do not generate a new key to solve an account, VPN, or password problem.

2. Generate A Dedicated Key Without Overwriting Anything#

The canonical filename is id_ed25519_euler. The following commands preserve an existing file with that name.

Windows laptop - PowerShell#

$SshDir = Join-Path $env:USERPROFILE ".ssh"
$KeyPath = Join-Path $SshDir "id_ed25519_euler"
New-Item -ItemType Directory -Force $SshDir | Out-Null

if ((Test-Path $KeyPath) -or (Test-Path "$KeyPath.pub")) {
    Write-Host "STOP: $KeyPath or its public key already exists. Nothing was overwritten."
} else {
    ssh-keygen -t ed25519 -f $KeyPath -C "$env:USERNAME@euler"
}

Set a passphrase when prompted. If the command printed STOP, inspect the existing pair or ask for help; do not choose overwrite.

Restrict the private key to the current Windows user:

$KeyPath = Join-Path $env:USERPROFILE ".ssh\id_ed25519_euler"
icacls $KeyPath /inheritance:r
icacls $KeyPath /grant:r "$($env:USERNAME):(R)"

Expected result: both id_ed25519_euler and id_ed25519_euler.pub exist. The file ending in .pub is the public key.

macOS or Linux laptop - zsh/Bash#

(
  set -eu
  key="$HOME/.ssh/id_ed25519_euler"
  mkdir -p "$HOME/.ssh"
  chmod 700 "$HOME/.ssh"
  if [ -e "$key" ] || [ -e "$key.pub" ]; then
    printf 'STOP: %s or its public key already exists. Nothing was overwritten.\n' "$key"
  else
    ssh-keygen -t ed25519 -f "$key" -C "$USER@euler"
  fi
)

Set a passphrase. If the command printed STOP, inspect the existing pair or ask for help.

3. Install Only The Public Key On Euler#

Windows laptop - PowerShell#

Run this in a new local PowerShell session if necessary; it defines its own variables.

$User = Read-Host "ETH username"
$PublicKey = Join-Path $env:USERPROFILE ".ssh\id_ed25519_euler.pub"
if (-not (Test-Path $PublicKey)) { throw "Missing public key: $PublicKey" }
Get-Content $PublicKey | ssh "$User@euler.ethz.ch" 'umask 077; mkdir -p ~/.ssh; chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; key="$(cat)"; if ! grep -Fqx "$key" ~/.ssh/authorized_keys; then if [ -s ~/.ssh/authorized_keys ] && [ "$(tail -c 1 ~/.ssh/authorized_keys | wc -l | tr -d " ")" -eq 0 ]; then printf "\n" >> ~/.ssh/authorized_keys; fi; printf "%s\n" "$key" >> ~/.ssh/authorized_keys; fi'

Enter the ETH password when prompted. Only the .pub file is sent.

macOS or Linux laptop - zsh/Bash#

(
  set -eu
  printf 'ETH username: '
  read -r eth_user
  public_key="$HOME/.ssh/id_ed25519_euler.pub"
  test -f "$public_key"
  cat "$public_key" | ssh "$eth_user@euler.ethz.ch" \
    'umask 077; mkdir -p ~/.ssh; chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; key="$(cat)"; if ! grep -Fqx "$key" ~/.ssh/authorized_keys; then if [ -s ~/.ssh/authorized_keys ] && [ "$(tail -c 1 ~/.ssh/authorized_keys | wc -l | tr -d " ")" -eq 0 ]; then printf "\n" >> ~/.ssh/authorized_keys; fi; printf "%s\n" "$key" >> ~/.ssh/authorized_keys; fi'
)

Repeated installation does not add a duplicate exact public-key line. Ask for help before manually editing authorized_keys.

4. Prove Public-Key Authentication Works#

This test disables password and keyboard-interactive fallback. A key passphrase prompt is expected; an ETH password prompt is not.

Windows laptop - PowerShell#

$User = Read-Host "ETH username"
$KeyPath = Join-Path $env:USERPROFILE ".ssh\id_ed25519_euler"
ssh -i $KeyPath -o IdentitiesOnly=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no "$User@euler.ethz.ch" "echo key-ok"

macOS or Linux laptop - zsh/Bash#

read -r -p "ETH username: " eth_user
ssh -i "$HOME/.ssh/id_ed25519_euler" \
  -o IdentitiesOnly=yes \
  -o PreferredAuthentications=publickey \
  -o PasswordAuthentication=no \
  -o KbdInteractiveAuthentication=no \
  "$eth_user@euler.ethz.ch" "echo key-ok"

Expected output: key-ok.

Do not continue to euler-tunnel until this test passes.

5. Add A Safe euler Alias#

The procedure validates and backs up an existing config, writes the Euler host to a separate include file, and does not replace unrelated host blocks.

Windows laptop - PowerShell#

& {
    $User = Read-Host "ETH username"
    $SshDir = Join-Path $env:USERPROFILE ".ssh"
    $Config = Join-Path $SshDir "config"
    $IncludeDir = Join-Path $SshDir "config.d"
    $EulerConfig = Join-Path $IncludeDir "euler.conf"

    New-Item -ItemType Directory -Force $IncludeDir | Out-Null
    if (Test-Path $Config) {
        ssh -G euler.ethz.ch | Out-Null
        if ($LASTEXITCODE -ne 0) { throw "Existing SSH config is invalid. Stop and repair it before continuing." }
        Copy-Item $Config "$Config.backup.$(Get-Date -Format yyyyMMdd-HHmmss)"
    }
    if (Test-Path $EulerConfig) {
        Copy-Item $EulerConfig "$EulerConfig.backup.$(Get-Date -Format yyyyMMdd-HHmmss)"
    }

    @"
Host euler
  HostName euler.ethz.ch
  User $User
  IdentityFile ~/.ssh/id_ed25519_euler
  IdentitiesOnly yes
  ForwardAgent no
"@ | Set-Content $EulerConfig -Encoding ascii

    $Include = "Include ~/.ssh/config.d/*"
    if (-not (Test-Path $Config)) {
        Set-Content $Config $Include -Encoding ascii
    } elseif (-not (Select-String -Path $Config -SimpleMatch $Include -Quiet)) {
        $OldConfig = Get-Content $Config -Raw
        Set-Content $Config "$Include`r`n$OldConfig" -Encoding ascii
    }

    ssh -G euler | Select-String '^(hostname|user|identityfile|identitiesonly) '
}

macOS or Linux laptop - zsh/Bash#

(
  set -eu
  printf 'ETH username: '
  read -r eth_user
  ssh_dir="$HOME/.ssh"
  config="$ssh_dir/config"
  include_dir="$ssh_dir/config.d"

  mkdir -p "$include_dir"
  chmod 700 "$ssh_dir" "$include_dir"
  if [ -f "$config" ]; then
    ssh -G euler.ethz.ch >/dev/null
    cp -p "$config" "$config.backup.$(date +%Y%m%d-%H%M%S)"
  fi
  if [ -f "$include_dir/euler.conf" ]; then
    cp -p "$include_dir/euler.conf" \
      "$include_dir/euler.conf.backup.$(date +%Y%m%d-%H%M%S)"
  fi

  cat > "$include_dir/euler.conf" <<EOF
Host euler
  HostName euler.ethz.ch
  User $eth_user
  IdentityFile ~/.ssh/id_ed25519_euler
  IdentitiesOnly yes
  ForwardAgent no
EOF
  chmod 600 "$include_dir/euler.conf"

  include='Include ~/.ssh/config.d/*'
  if [ ! -f "$config" ]; then
    printf '%s\n' "$include" > "$config"
  elif ! grep -Fqx "$include" "$config"; then
    temporary="$config.passport-new"
    { printf '%s\n' "$include"; cat "$config"; } > "$temporary"
    mv "$temporary" "$config"
  fi
  chmod 600 "$config"
  ssh -G euler | grep -E '^(hostname|user|identityfile|identitiesonly) '
)

Final Verification#

Run on your local computer:

ssh euler "echo config-ok"

Expected output: config-ok, after at most the SSH key passphrase prompt.

Common Failures And Safe Recovery#

  • Bad configuration option or extra arguments at end of line: stop. Use the backup created above and inspect the line named in the error. Do not append another host block to the broken line.
  • Warning names a file ending in .pub as a private key: IdentityFile is wrong. It must point to id_ed25519_euler, never .pub.
  • Public-key-only test says Permission denied: the public key is not installed correctly, the username is wrong, or permissions are wrong. Do not regenerate another key yet.
  • Timeout: connect to ETH VPN and retry.

Ask For Help When#

The password login works but the public-key-only test does not, the existing SSH config fails validation, or the private key permissions cannot be restricted. Share only sanitized output from ssh -v; never share the private key.

Primary Sources#

Verified: 2026-08-04. Review by: 2026-11-04. Owner: IDEAL Lab IT.