Docker-based development environment for NOPHI with:
- Ubuntu and optional CUDA base images
- Per-user dev container startup/removal scripts
- Shared host data directory setup
- Dedicated Docker bridge network setup
- Docker network egress filtering via
iptables, prevents access to internal networks but Internet is allowed.
The purpose of this project is to provide a sandboxed container for software development with AI coding tools that must not access PHI.
NEVER place PHI in either host-mounted path or copy it to your container:
${HOME}/NOPHI-home(your personal persistent workspace, created for you)${HOME}/NOPHI-tmp(host-backed/tmp, auto-created for you)- Linux:
/srv/NOPHI-shared(shared data directory, created for you) - macOS:
${HOME}/NOPHI-shared(single-user shared data directory, created by./macos-docker-setup.sh)
Network boundary: these containers cannot access internal hosts or internal network resources. They can reach external Internet endpoints and other containers attached to cri-collab-net.
NEVER allow PHI to be accessed by these containers or transferred over any network path, including SSH.
Assumptions:
- Docker is installed and usable by your user.
- All of the installation steps at the bottom of this document were completed by an admin already.
nophi-startandnophi-removewere installed by an admin and are on yourPATH.- Docker network
cri-dev-netwas created during server setup. - Your public key is in
${HOME}/.ssh/authorized_keysfor SSH access (if${HOME}/.sshis missing,nophi-startcreates it as0700; if the file is missing, it creates an empty0600file, and you still need to add a key).
- Start your container.
Auto-select mode (uses CUDA when available, otherwise CPU):
nophi-startForce CPU mode:
nophi-start --cpuPrefer CUDA mode (falls back to CPU if CUDA is unavailable):
nophi-start --cudaStartup behavior:
- Container name:
- CPU:
${USER}-NOPHI-${HOSTNAME} - CUDA:
${USER}-NOPHI-${HOSTNAME}-cuda
- CPU:
- Mounts:
${HOME}/NOPHI-home -> /home/${USER}Personal, persistent workspace (auto-created if missing). Use this for cloning repos and development work. Data here persists across container restarts/removals. NEVER store PHI data here.${HOME}/NOPHI-tmp -> /tmpHost-backed scratch space (auto-created if missing). Use this only when you need/tmpcontents to persist across container restarts/removals. NEVER store PHI data here.- Linux default:
/srv/NOPHI-shared -> /srv/NOPHI-shared - macOS default:
${HOME}/NOPHI-shared -> /srv/NOPHI-sharedShared NOPHI data directory. NEVER store PHI data here. Override with env var:NOPHI_SHARED_DIR=/path/to/shared. ${HOME}/.ssh/authorized_keys -> /home/${USER}/.ssh/authorized_keys(read-only) Used for SSH access to the container user account. If${HOME}/.sshis missing,nophi-startcreates it as0700. If the host file is missing,nophi-startcreates an empty0600file and tells you to copy in a public key before connecting.
- SSH port is derived as
40000 + $(id -u) - Forwarding port is derived as
50000 + $(id -u)and maps to container port3879 - SSH target:
- Linux:
ssh -p <port> ${USER}@$(hostname) - macOS:
ssh -p <port> ${USER}@localhost(hostname may not resolve locally)
- Linux:
- Stop/remove your container.
Auto-select target (prefers CUDA target when available, otherwise CPU; if that container does not exist, it tries the other target):
nophi-removeForce CPU target:
nophi-remove --cpuPrefer CUDA target (falls back to CPU if CUDA is unavailable):
nophi-remove --cuda- Validate egress policy from the running container.
./test-nophi-egress.shOptional container override:
./test-nophi-egress.sh --container <container-name>Use this section for first-time host setup by an admin.
- Clone this Git repo.
git clone <repo-url>- Move into the cloned repository.
cd NOPHI-dev- Configure the shared data directory (requires sudo).
./create-shared-data-dir.shWhat this does:
- Ensures Linux group
cri-sharedexists - Ensures
/srv/NOPHI-sharedexists - Applies group ownership/permissions (
2775) - Adds your user to
cri-sharedif needed
If your user was newly added to cri-shared, log out and back in before continuing.
- Create Docker bridge networks.
./create-docker-networks.shThis creates both networks:
cri-dev-net:192.168.240.0/24, gateway192.168.240.1cri-collab-net:192.168.241.0/24, gateway192.168.241.1
- Optional (CUDA only): Configure NVIDIA Container Toolkit on the host (requires sudo).
./setup-nvidia-container-toolkit.shIf your host already supports docker run --gpus all ..., you can skip this step.
- Optional: Configure Docker egress filtering for
cri-dev-net(requires sudo).
./configure-docker-egress-filtering.shDefault egress policy:
- Applies only to containers attached to
cri-dev-net - Allows established/related return traffic
- Allows same-network container-to-container traffic
- Allows DNS to
172.19.20.19on TCP/UDP 53 - Allows explicit single-IP exceptions before subnet blocks (default:
172.19.21.28) - Blocks internal subnets with
REJECT --reject-with icmp-port-unreachable:172.19.20.0/23172.19.149.0/26
- Allows all other egress
Add more blocked networks as needed:
./configure-docker-egress-filtering.sh \
--allow-ip 172.19.21.28 \
--allow-ip 172.19.21.29 \
--block-subnet 172.19.30.0/24 \
--block-subnet 10.42.0.0/16- If UFW is enabled on the host, allow inbound SSH and forwarded port ranges for remote clients.
sudo ufw allow from 172.19.149.0/24 to any port 42000:43000 proto tcp
sudo ufw allow from 172.19.20.0/24 to any port 42000:43000 proto tcp
sudo ufw allow from 172.19.149.0/24 to any port 52000:53000 proto tcp
sudo ufw allow from 172.19.20.0/24 to any port 52000:53000 proto tcp
sudo ufw status numberedWithout these rules, SSH and forwarded access to container port 3879 from another client may be blocked even when the container is running.
- Build container images.
Build both CPU and CUDA images (default):
./build-NOPHI-dev.shBuild CPU image only:
./build-NOPHI-dev.sh --cpuBuild CUDA image only (if the server has NVIDIA GPUs and developers will use CUDA):
./build-NOPHI-dev.sh --cudaOn non-GPU servers, CUDA build paths are treated as no-ops and skipped.
Custom tag (single-image build only):
./build-NOPHI-dev.sh --cpu --tag my-image:latest- Install global developer commands (requires sudo).
./install-nophi-commands.shCustom install prefix:
./install-nophi-commands.sh --prefix /opt/nophi/binIf you use a custom prefix, ensure it is on each developer's PATH.
This installs:
nophi-startnophi-remove
- Ensure each developer account can run containers and access shared data.
For each developer user:
- Add to
dockergroup - Add to
cri-sharedgroup - Ensure
~/.ssh/authorized_keyscontains their public SSH key
Example:
sudo usermod -aG docker,cri-shared <username>Users added to new groups must log out and back in.
Use this flow on macOS instead of the Linux server-prep steps below.
- Run setup:
./macos-docker-setup.shWhat it does:
- Creates
~/NOPHI-shared(or custom--shared-dir) for/srv/NOPHI-sharedmount - Ensures
cri-dev-netandcri-collab-netDocker networks exist - Builds CPU image only (
nophi-dev:ubuntu24.04) - Installs
nophi-startandnophi-removeinto~/.local/bin - Applies egress filtering inside the macOS Docker VM for
cri-dev-net - Installs a LaunchAgent that reapplies egress rules on Docker socket changes
- Start/remove your dev container:
nophi-start
nophi-remove- Validate egress policy from the running container:
./test-nophi-egress.sh- Uninstall macOS network configuration created by setup:
./macos-docker-setup.sh --uninstallUninstall removes:
- LaunchAgent
com.nophi.docker-egress - Script-managed
DOCKER-USERegress rules/chains (DNET-*) in the macOS Docker VM - Docker networks
cri-dev-netandcri-collab-net(fails if still in use)
macos-docker-setup.sh- macOS 14+ single-user setup for OrbStack or Docker Desktop Linux containers
- Configures
~/NOPHI-shared, networks, CPU image build, command install, VM egress filtering, and LaunchAgent persistence --uninstallremoves script-managed macOS network settings
build-NOPHI-dev.sh- Builds CPU and CUDA images by default, or selected image(s) with
--cpu/--cuda
- Builds CPU and CUDA images by default, or selected image(s) with
start-NOPHI-dev.sh- Starts per-user container on
cri-dev-netwith auto CPU/CUDA selection (--cpu/--cudasupported) - Shared mount defaults: Linux
/srv/NOPHI-shared, macOS${HOME}/NOPHI-shared(override withNOPHI_SHARED_DIR)
- Starts per-user container on
remove-NOPHI-dev.sh- Removes per-user container with auto CPU/CUDA target selection (
--cpu/--cudasupported)
- Removes per-user container with auto CPU/CUDA target selection (
test-nophi-egress.sh- Runs sequential egress tests from inside a running NOPHI container and reports each result
- Defaults to auto-detected current-user container, DNS
172.19.20.19:53allowed, and blocked probes for172.19.20.19:443and172.19.149.1:443
create-shared-data-dir.sh- Prepares
/srv/NOPHI-sharedandcri-sharedmembership
- Prepares
create-docker-networks.sh- Ensures Docker bridge networks with fixed
192.168.x.xsubnets
- Ensures Docker bridge networks with fixed
configure-docker-egress-filtering.sh- Applies per-network Docker egress policy in
DOCKER-USER
- Applies per-network Docker egress policy in
setup-nvidia-container-toolkit.sh- Installs/configures NVIDIA Container Toolkit so Docker can run CUDA containers with
--gpus all
- Installs/configures NVIDIA Container Toolkit so Docker can run CUDA containers with
install-nophi-commands.sh- Installs
nophi-startandnophi-removeinto/usr/local/bin(or a custom prefix)
- Installs