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

web

22/tcp

campus/VPN

SSH for deploys (stack.ps1 -Target web), key-only

web

80/tcp

internet

Let’s Encrypt HTTP-01 validation and http-to-https redirect. Only needed for TLS_MODE=letsencrypt; otherwise campus only or closed.

web

443/tcp

internet

Every public Viking name (SNI passthrough)

compute

22/tcp

campus/VPN

SSH for deploys and tunnels

compute

40443/tcp, 40444/tcp, 40445-40447/tcp

web only

viking-segmentation servers (default model and demo on 40443-40444; the models profile’s v3 / v4 / sem-v1 on 40445-40447), reached by the proxy

compute

445/tcp outbound

to the NAS

CIFS mounts for nornir-build

iis

443/tcp

web only

IIS sites behind websvc.<domain>

iis

22/tcp

campus/VPN

Windows OpenSSH for stack.ps1 -Target iis

SQL Server

1433/tcp

web and iis only

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.1 only (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-USER chain, 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

compute

8087:127.0.0.1:8087

Build dashboard at http://127.0.0.1:8087

compute

5678:127.0.0.1:5678

debugpy (Debugging)

web

4024:127.0.0.1:4024

Identity .NET remote debugger

web

1433:<sql-host>:1433

SQL Server as seen from web (for SSMS / Azure Data Studio on the dev box)

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

  1. Install the Remote - SSH and Dev Containers extensions.

  2. Remote-SSH: Connect to Host… deploy@compute.connectomes.pitt.edu (or the alias), open /srv/src/nornir or /srv/docker/Run to edit env files in place.

  3. 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.