Ports and remote access
Firewall request
Send this table to Pitt IT. “Campus/VPN” means the Pitt campus network and the Pitt VPN (GlobalProtect); Pitt typically requires the VPN for SSH from off campus (confirm with Pitt IT).
Host |
Port |
Allow from |
Why |
|---|---|---|---|
|
22/tcp |
campus/VPN |
SSH for deploys ( |
|
80/tcp |
internet |
Let’s Encrypt HTTP-01 validation and http-to-https redirect. Only needed for
|
|
443/tcp |
internet |
Every public Viking name (SNI passthrough) |
|
22/tcp |
campus/VPN |
SSH for deploys and tunnels |
|
40443/tcp, 40444/tcp, 40445-40447/tcp |
|
|
|
445/tcp outbound |
to the NAS |
CIFS mounts for |
|
443/tcp |
|
IIS sites behind |
|
22/tcp |
campus/VPN |
Windows OpenSSH for |
SQL Server |
1433/tcp |
|
Identity, annotation, and IIS databases |
Never open these to the network; reach them through an SSH tunnel:
Port |
Service |
|---|---|
1883 |
Mosquitto (dashboard broker; unauthenticated) |
8087 |
Build dashboard |
4024 |
.NET remote debugger (vsdbg) |
5678 |
debugpy |
81 |
Nginx Proxy Manager admin UI (old layout; removed) |
2375 / 2376 |
Docker daemon API |
5985 / 5986 |
WinRM |
3389 |
Remote Desktop (use it over the VPN or an SSH tunnel if at all) |
The service ports on web (Identity 5001/6001/4001, annotation 5010/5011, corrections
41080/41443, the Sam2Trainer annotation gallery 8442) are internal: the proxy reaches them on the
host. They are not part of the firewall request. Viking’s per-port table is
Viking ports and remote access.
Docker and ufw on Linux
Ports published by Docker (ports: in compose, -p in docker run) are inserted into
iptables ahead of ufw’s rules, so ufw does not filter them. Two rules follow:
Internal ports are published on
127.0.0.1only (the dashboard and broker templates do this:NORNIR_DASHBOARD_BIND_HOST=127.0.0.1,NORNIR_MQTT_BIND_HOST=127.0.0.1). Do not widen them.Ports another host must reach are filtered in the
DOCKER-USERchain, which Docker evaluates before its own rules and never rewrites.
On compute, allow only web to reach the segmentation ports. Replace the interface name
(ip -br link) and the address of web:
EXT_IF=eno1
WEB_IP=203.0.113.10
# Inserted in reverse order: the ACCEPT ends up above the DROP.
sudo iptables -I DOCKER-USER -i "$EXT_IF" -p tcp -m conntrack --ctorigdstport 40443:40447 --ctdir ORIGINAL -j DROP
sudo iptables -I DOCKER-USER -i "$EXT_IF" -p tcp -s "$WEB_IP" -m conntrack --ctorigdstport 40443:40447 --ctdir ORIGINAL -j ACCEPT
sudo iptables -L DOCKER-USER -n -v --line-numbers
# Keep the rules across reboots
sudo apt-get install -y iptables-persistent
sudo netfilter-persistent save
--ctorigdstport matches the port the client connected to, before Docker’s DNAT, so the rule
holds even if the container port differs from the host port. stack.ps1 doctor prints a
reminder when ufw is installed.
SSH keys
On the dev box (Windows OpenSSH client, PowerShell):
ssh-keygen -t ed25519 -C "deploy from <your name>"
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@compute.connectomes.pitt.edu "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
ssh deploy@compute.connectomes.pitt.edu true # must not prompt for a password
Then turn off password login on each Ubuntu server (the script refuses if authorized_keys is
empty):
sudo bash bootstrap-ubuntu.sh --harden-ssh
Optional ~/.ssh/config aliases make targets.psd1 shorter and work for VS Code too:
Host compute
HostName compute.connectomes.pitt.edu
User deploy
IdentityFile ~/.ssh/id_ed25519
Host web
HostName web.connectomes.pitt.edu
User deploy
The servers do not need keys on each other: stack.ps1 certs push -From web runs on the dev
box. Only if you run certs push on web itself (for example from cron) does web need a
key on compute and iis and its own targets.psd1.
Windows OpenSSH (iis)
In an elevated PowerShell on the IIS host (PowerShell 7 must already be installed):
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Set-Service sshd -StartupType Automatic
Start-Service sshd
New-ItemProperty -Path 'HKLM:\SOFTWARE\OpenSSH' -Name DefaultShell -Value 'C:\Program Files\PowerShell\7\pwsh.exe' -PropertyType String -Force
stack.ps1 sends PowerShell syntax to Windows targets, so DefaultShell must be pwsh.
For an account in the Administrators group, keys go in
C:\ProgramData\ssh\administrators_authorized_keys (not the user profile), with an ACL that
only Administrators and SYSTEM can read:
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
Set PasswordAuthentication no in C:\ProgramData\ssh\sshd_config and
Restart-Service sshd once key login works.
Tunnels
stack.ps1 tunnel -Target <name> opens every forward in that target’s Tunnels list and
holds it until Ctrl+C. The template defines:
Target |
Forward |
Use |
|---|---|---|
|
|
Build dashboard at http://127.0.0.1:8087 |
|
|
debugpy (Debugging) |
|
|
Identity .NET remote debugger |
|
|
SQL Server as seen from |
Plain ssh -L works the same way: ssh -N -L 8087:127.0.0.1:8087 deploy@compute.connectomes.pitt.edu.
VS Code Remote-SSH
Install the Remote - SSH and Dev Containers extensions.
Remote-SSH: Connect to Host…
deploy@compute.connectomes.pitt.edu(or the alias), open/srv/src/norniror/srv/docker/Runto edit env files in place.To work inside a running container (for example
nornir-build): Dev Containers: Attach to Running Container… from the Remote-SSH window.
Docker contexts
For quick inspection from the dev box without a shell on the server:
docker context create compute --docker "host=ssh://deploy@compute.connectomes.pitt.edu"
docker context create web --docker "host=ssh://deploy@web.connectomes.pitt.edu"
docker --context compute ps
docker --context web logs --tail 100 <container>
Use stack.ps1 -Target for anything that starts or changes a stack: compose bind paths and env
files must resolve on the target, which a context does not do for you.
Tailscale (optional)
A Tailscale tailnet gives the dev box a stable private route to compute and web without
opening SSH beyond campus. It is a third-party service on university hardware: get Pitt IT’s
approval first. With it, point Ssh in targets.psd1 at the Tailscale host names; nothing
else changes.