How to protect your account, your work, and the cluster.
The defenses are mostly small habits. This section covers the ones that matter most.
Strong, unique passwords are impossible to remember. A password manager generates and stores them, locked behind a single master password.
Why it matters for HPC:
Reasonable choices:
A manager also holds your SSH key passphrases, 2FA backup codes, and secure notes. Useful for everything else in this section.
The shipped defaults are good. The mistake is weakening them.
Windows
Linux
sshd; most laptops never need to accept SSHsudo ss -tlnp (shows TCP,
listening sockets, numeric ports, owning processes)systemctl disable --now <service>sshd (shared PC): enable
fail2banA key pair has two halves with opposite jobs:
Why the private key never travels: At login,
your machine signs a challenge and the cluster verifies it with
your public key. The cluster only stores the public
half (authorized_keys), so copying your private key to
Hunter isn’t just risky, it’s pointless.
Required:
chmod 600 ~/.ssh/id_* (OpenSSH refuses world-readable
keys)Never:
If a private key is ever exposed, assume it’s compromised and replace it.
Same rule as the last slide: keep the private key private, as enforced by the OS.
Linux / macOS / WSL (from previous slide)
OpenSSH refuses to use a private key that others can read.
$ ls -ld ~/.ssh # the directory
drwx------ ... /home/you/.ssh # 700, only you
$ ls -l ~/.ssh/id_ed25519* # the key pair
-rw------- ... id_ed25519 # private: 600, only you
-rw-r--r-- ... id_ed25519.pub # public: 644, readable
$ chmod 700 ~/.ssh # directory: 700
$ chmod 600 ~/.ssh/id_ed25519 # private key: 600The public key is meant to be shared, so 644 is
correct.
Windows — where keys live
%USERPROFILE%\.ssh\Windows OpenSSH also refuses keys readable by others:
icacls <keyfile> /inheritance:r # drop inherited access
icacls <keyfile> /grant:r "%USERNAME%:F" # grant only yourself (Full)
GUI: right-click key → Properties → Security → Edit → remove everyone but yourself.
Back up the private key somewhere safe (e.g. your password manager).
The first time you connect, SSH shows you the host’s fingerprint and asks if you trust it:
The authenticity of host 'hunter.hww.hlrs.de' can't be established.
ED25519 key fingerprint is SHA256:dJnEmGknqP1RBiZoiKV5x6Kbg/L2z2jMYeHiyTaxYYI
Are you sure you want to continue connecting (yes/no/[fingerprint])?This is not a formality. The fingerprint identifies the server you are about to send your credentials to. If an attacker has redirected the connection (compromised DNS, wrong network, evil twin), the fingerprint will not match.
What to do:
yesOnce accepted, the fingerprint is stored in
~/.ssh/known_hosts. SSH will silently use it on future
connections, and warn loudly if it ever changes:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
A legitimate change, server reinstall, key rotation, is announced by HLRS in advance. An unexpected warning should be reported, not dismissed.
The most common credential leak: a secret committed to git, then pushed.
Never commit to scripts or repositories:
Commit a secret by accident? Rotate it immediately. Deleting it in a later commit is not enough. Once pushed, the history is permanent.
umask decides the permissions of files you create. The
default on our clusters is 0077: new files
are not group-readable, even when they sit inside a
“shared” directory.
So a freshly written output file is private by default. Sharing is always a deliberate act, never automatic.
Sharing inside a workspace? See this slide from day 1:
ws_share: per-person but persistent;
new files shared automatically (Hunter). Best when your team works in
the workspace over time.chgrp / chmod: shares the
folder once; new files will not be shared.Usually you find out because HLRS contacts you. Admins watch for resource-abuse patterns and reach out before you’d notice anything yourself.
What you can check yourself:
If something looks off, submit a Trouble Ticket with the details.
Do not investigate by running unfamiliar commands. That can destroy evidence if you are right.
Ongoing habits worth maintaining:
~/.ssh/ is 700, private keys are
600If anything is unclear, the answer is: ask before doing.

Two node types:
| APU nodes | CPU nodes (industry only) |
|
|---|---|---|
| Count | 188 | 256 |
| Processors | 4× AMD MI300A per node | 2× AMD EPYC 9374F per node |
| Cores | 24 Zen4 CPU + 228 GPU CUs per APU | 32 CPU cores per socket (64/node) |
| Memory | 128 GB HBM3 per APU (512 GB/node) | 768 GB DDR5-4800 per node |
| Network | 4× Slingshot 200 Gbps per node | 1× Slingshot 200 Gbps per node |
Key insight: The MI300A is an APU (CPU, GPU, and HBM on a single chip). No PCIe bottleneck between CPU and GPU.
Interconnect: HPE Slingshot 11, dragonfly topology, 5 groups

Image source: amd-cdna-3-white-paper.pdf
Using the GPUs/APUs
Theoretical maximum (per APU): 228 × 32 × 64 = 466,944 threads (assuming minimal register usage).
To saturate a single APU, aim for at least ~200,000 elements — so roughly 800,000–1,000,000 for a full node of 4 APUs.
APUs are programmed like ordinary GPUs: code written for CPUs must be ported to the GPU architecture.

Image source: instinct.docs.amd.com
Why pin? A node has 4 MI300A chips, each with its own 24 cores, GPU, and HBM.
Crossing the inter-chip link wastes bandwidth, so each rank should drive only the GPU on its own chip, using that chip’s local HBM.
Natural layout in the default (SPX) mode: 4 ranks per node,
one per chip, which is why the jobscript uses
mpiprocs=4. The --cpu-bind /
--gpu-bind lines are this layout;
mpiexec enforces what you write, so wrong lines pile ranks
onto one GPU and idle the rest.
See also: https://kb.hlrs.de/platforms/index.php/Affinity_and_Pinning

https://kb.hlrs.de/platforms/index.php/Storage_(Hunter)
+ https://kb.hlrs.de/platforms/index.php/Storage_usage_policy
Where should I put my data?
| Storage | Speed | Persistence | Capacity | Use for |
|---|---|---|---|---|
| RAM / tmpfs | Fastest | Job only | 512GB HBM3 (per APU node) 768GB DDR5 (per CPU node) |
Temporary scratch, /dev/shm |
| /localscratch/$JOBID (NVMe, only some nodes) |
Very fast | Job only | 3.5TB (per NVMe node) | Fast local I/O |
| Workspace (Lustre) | Fast | Max 60 days (3 Extensions) Has quota on the number of files/folders |
25 PB (shared) A few TB per project |
Large project data Job input/output |
| HPSS (tape) | Slow | Archive | 500TB (shared) | Long term storage |
| $HOME or $PROJECT (NFS) |
Slow | Permanent | 50GB or 200GB | Configs, scripts, small files |
Vulcan is a heterogeneous computing platform providing specialized
resources for pre-/postprocessing, visualization, GPU computing, and
data analytics.
Access requires a separate allocation, so ask your
project manager.
node_type |
# | CPU | Cores | RAM | GPU / Accelerator | /localscratch |
/tmp |
|---|---|---|---|---|---|---|---|
clx |
96 | 2× Xeon Gold 6248 | 40 | 384 GB | - | - | - |
skl |
72 | 2× Xeon Gold 6138 | 40 | 192 GB | - | - | - |
genoa |
60+96(vulcan2) | 2× EPYC 9334 | 64 | 768 GB | - | - | - |
genoa-a30 |
24 | 2× EPYC 9124 | 32 | 768 GB | 1× Nvidia A30 (24 GB) | 3.8 TB NVMe | - |
a100-40gb |
19 | 2× EPYC 7702 | 128 | 1024 GB | 8× Nvidia A100 (40 GB) | 14.6 TB NVMe | 3.5 TB NVMe |
a100-80gb |
4 | 2× EPYC 7702 | 128 | 1024 GB | 8× Nvidia A100 (80 GB) | 14.6 TB NVMe | 3.5 TB NVMe |
rome1tb |
4 | 2× EPYC 7702 | 128 | 1024 GB | - | 21.5 TB | 850 GB |
rome2tb |
4 | 2× EPYC 7702 | 128 | 2048 GB | - | 21.5 TB | 850 GB |
rome4tb |
1 | 2× EPYC 7702 | 128 | 4096 GB | - | 21.5 TB | 850 GB |
genoa-smp |
2 | 2× EPYC 9334 | 64 | 3072 GB | - | - | - |
visamd |
6 | 2× Xeon Silver 4112 | 8 | 96 GB | 1× AMD Radeon WX8200 | - | - |
visnv |
2+1 (vulcan2) | 2× Xeon Silver 4112 | 8 | 96 GB | 1× Nvidia Quadro RTX 4000 | - | - |
Hunter Nutzer bekommen nicht automatisch Zugriff auf Vulcan. Je nachdem über welches Projekt sie kommen kann die Vorgehensweise hier unterschiedlich sein. GCS Projekte: über Projektleiter HLRS Industriekunden: über Projektleiter Uni Projekte: über Uni Instituts Admin HLRS Projekte: über Accounting Team

AI optimized HPC system HammerHAI (late 2026)
| Platform | NVIDIA GB200 NVL4 by HPE |
| GPU Accelerator | NVIDIA B200 Blackwell |
| Host CPU | NVIDIA Grace |
| Storage | VAST Data DASE |
| Network | NVIDIA Quantum-X800 InfiniBand |
| Cooling | Liquid cooling |

Exascale-System Herder (2027)
| Platform | HPE Cray GX5000 |
| GPU Accelerator | AMD Instinct MI430X |
| Host CPU | AMD EPYC Venice |
| Storage | HPE Cray Storage System E2000 |
| Network | HPE Slingshot 400 |
| Cooling | 100% direct liquid cooling |
Dos and don’ts on an HPC system
The login node is shared by all users. Heavy CPU or memory work makes it sluggish for everyone.
Avoid on login nodes:
make -j)find / du -sh on huge directory trees
(your own files are fine; avoid /, /lustre,
system paths)Generally fine on login nodes:
make -j 8)rsync, scp)ls, find,
du -sh, grep)For testing/prototyping: request an interactive job
(qsub -I ...)
Each process on the login node has a CPU-time limit of 2 hours. A single process that exceeds it is killed without warning:
Killed
$
Reference: kb.hlrs.de/platforms/index.php/10_minutes_before_the_first_job
Three things have quotas on Hunter:
When you or your group exceed a quota, no new jobs start in the batch queues, you and your group get an email about it. Existing data isn’t deleted, but you’re blocked from running until usage drops.
$ quota -s # disk + inode usage in home directory
$ ws_quota # disk + inode usage in workspace
$ ws_list # your workspaces + their sizes
$ qstat -f -u $USER # running jobsWatch the file count, not just the size. Compiling a large project in a workspace can exhaust your inode quota long before you fill the disk.
HLRS does not back up any user data on any cluster filesystem.
This applies to:
$HOME (small, but still not backed up)RAID protects against hardware failures, but nothing else. It does not recover from:
rm -rf mistakesYou are responsible for backing up your own data.
rsync or scpYour $HOME is small (50 GB) and slow for HPC I/O. For
working data, use a workspace on the parallel
filesystem (Lustre).
Workspaces are:
Set an expiry reminder so you don’t lose data:
ws_allocate -r 7 -m you@hlrs.de ...
(or set
mail: / reminder: in
~/.ws_user.conf)
$ ws_allocate myproject 60 # allocate for 60 days
$ ws_list # workspaces + remaining time
$ ws_find myproject # print the path
$ ws_extend myproject 60 # extend to 60 days (can be used 3 times)
$ ws_release myproject # release (with grace period for: ws_restore)Symlink a workspace into $HOME for convenience:
umask decides the permissions of files you create. The
default on our clusters is 0077: new files
are not group-readable, even when they sit inside a
“shared” directory.
So a freshly written output file is private by default. Sharing is always a deliberate act, never automatic.
Sharing inside a workspace? See this slide from day 1:
ws_share: per-person but persistent;
new files shared automatically (Hunter). Best when your team works in
the workspace over time.chgrp / chmod: shares the
folder once; new files will not be shared.Lustre and other parallel filesystems are optimized for few large files, not many small ones.
A directory with 100,000 files will:
ls, even with ls -ffind, tar, rsync
dramaticallyMitigations:
tar, HDF5, NetCDF) when
possibleA directory with 100,000+ files is a shared-resource (polite-society) violation, not just a personal problem.
Before contacting support, gather:
$ qstat -f <jobid> # state + resources (running jobs)
$ qstat -xf <jobid> # finished jobs (exit status, history)Open a ticket at hlrs.de/for-users/trouble-ticket-submission with these details. Vague descriptions (“my job did not work”) cost everyone time, including yours.
Hunter’s outgoing firewall blocks direct access, so
git clone, pip install, and curl
time out. A reverse SSH tunnel (ssh -R)
lets Hunter’s outbound traffic reach a SOCKS5 proxy on
Hunter, then ride the tunnel out through your
laptop’s connection.
Use a dedicated SSH connection for the tunnel, and close it when no longer needed.
Reference: kb.hlrs.de/platforms/index.php/SSH_Tunnel_with_Proxy
1. Open it on your local machine
Pick a port (10000–60000, unique to you):
Opens a normal SSH session and a reverse SOCKS5 proxy on Hunter. It lives only as long as this session.
The proxy is reachable by all users on the login node. Keep it open only while needed.
MobaXterm configures tunnels through its GUI, not command-line flags. The reverse tunnel also needs a local SSH daemon, which MobaXterm won’t start for you.
Once, in a local MobaXterm terminal:
Each session:
sshdDetailed guide: kb.hlrs.de/platforms/index.php/Secure_Shell_ssh

If the SOCKS side “just doesn’t work,” the missing sshd
is the usual cause.
Why, on a cluster:
Track: source code, job scripts, configs, small inputs, plotting scripts
Don’t track: simulation output, large data,
binaries, build dirs; those belong in a workspace or
HPSS (use a .gitignore)
With the proxy variables set, HTTPS git operations just work:
For push, use a personal access token, not your password. Create a dedicated token and paste it when git prompts:
Make it read-only if you only clone/pull, and scope
it to the repos Hunter needs (GitHub: fine-grained
tokens).
Otherwise a leaked token with write access would let an attacker push malicious code to your repositories. A dedicated token can be revoked without touching your other access.
For SSH-protocol URLs (git@github.com:user/project.git),
the proxy variables aren’t enough, SSH itself must route through the
tunnel.
Setup, once:
ssh-keygen -t ed25519 -f ~/.ssh/repo_from_hunter)~/.ssh/configAdd the key as a Deploy key on the hosting platform
(with read-only rights) and/or add a passphrase. Otherwise, a leaked key
with full git authorization would allow an attacker to push malicious
code to your git repositories.
pip honors the proxy variables, but only if PySocks is installed.
One-time: ensure PySocks
Check whether SOCKS5 is supported:
If not, install it from the local copy on Hunter:
| Step | Where | Command |
|---|---|---|
| 1. Open tunnel | local | ssh -R localhost:XXXXX hunter |
| 2. Set proxy | Hunter | export https_proxy=socks5://localhost:XXXXX |
| 3. Use git/pip/… | Hunter | git clone ... / pip install ... |
| 4. Close tunnel | local | Close the SSH session |
Remember:
~/.ssh/config with
ncat ProxyCommandFull guide (SSH): kb.hlrs.de/platforms/index.php/SSH_Tunnel_with_Proxy
Full guide(MobaXterm): kb.hlrs.de/platforms/index.php/Secure_Shell_ssh#SOCKS_Proxy_under_Windows_with_MobaXterm
What we have shown here is a Reverse tunnel
(-R).
For running Jupyter Notebooks, you need a
Forward tunnel (-L) which is explained
here: kb.hlrs.de/platforms/index.php/How_to_use_Web_Based_Services_on_HLRS_Compute_Platforms
How the system decides which version of a tool to run
When you type python or gcc, the shell
finds an executable somewhere on $PATH and runs
it. Different choices on $PATH give you different versions
of the same tool, with different libraries and different compatibility
constraints.
An environment is a coordinated set of these choices: a PATH, a library search path, environment variables, and possibly a Python or software stack, all loaded together.
Three problems environments solve:
Reproducibility. Your code today depends on specific versions of NumPy, PyTorch, MPI, and CUDA. In six months those versions will have changed. An environment lets you pin the exact versions, so the code that worked today still works later.
Isolation. Project A needs PyTorch 2.0; project B needs PyTorch 2.5. Without environments, installing one breaks the other. With environments, each project gets its own.
Sharing. Handing your work to a colleague becomes “activate this environment” instead of “good luck installing 30 packages in the right order.”
Environments are the mechanism that lets a single user run many projects on a shared system without conflicts. Without them, every install is a small bet that you are not breaking something else.
Hunter provides two Python convenience modules with HPC-optimized packages (NumPy, SciPy, mpi4py, dask):
cray-python: vendor-provided, tuned for Hunterpython: cray-python plus common
extrasFor project packages, make a venv with
--system-site-packages so you inherit the
optimized builds.
Order matters: module first, then activate. Every new shell or job script must do both.
The cray-python and python modules cover
common cases. They become limiting when:
For these cases, install micromamba in your home directory (needs internet: open the tunnel and set the proxy variables first):
$ curl -L https://micro.mamba.pm/api/micromamba/linux-64/latest \
-o micromamba.tar.bz2 # needs the SSH tunnel + proxy vars
$ tar -xvjf micromamba.tar.bz2 bin/micromamba
$ export MAMBA_ROOT_PREFIX=$HOME/micromamba
$ eval "$(./bin/micromamba shell hook -s posix)"
$ micromamba create -n myproject python=3.11 -c conda-forge
$ micromamba activate myproject
$ pip install -r requirements.txtStep-by-step instructions: kb.hlrs.de/platforms/index.php/Using_micromamba_on_Vulcan
A container bundles software with its dependencies into a portable image that runs the same regardless of the host’s libraries.
Good for:
Caveat: portability holds for userspace-only software. GPU and high-performance MPI need the container’s libraries to match the host’s driver and interconnect — which limits it.
At HLRS:
Build locally, run on the cluster: build with Docker
on your own machine, then scp the image to your workspace.
You don’t build on the cluster.
See the wiki on containers on Vulcan
You may skip exercises depending on your available time or tools that you need on the cluster
High-Performance
Computing Center
Stuttgart
Lucas Jordan
Introduction to the HLRS Systems