This documents one lab deployment. Read this before adapting any of it.
Every credential in the examples is a placeholder. Generate real ones:
openssl rand -hex 32 > secrets/api-key.txt
chmod 600 secrets/*Never commit real secrets. .env.example files here contain REPLACE_ME values by design.
Decide deliberately, per service, who should reach it:
| Bind | Reachable by |
|---|---|
127.0.0.1:PORT |
the host only |
<bridge-gateway>:PORT |
containers on that bridge |
0.0.0.0:PORT |
anything that can route to the host |
Docker's published ports bypass host firewalls. Docker installs its own iptables rules; a port published as "3000:8080" is reachable from the network regardless of UFW configuration. Write "127.0.0.1:3000:8080" unless you intend exposure.
Assert it in a health check rather than trusting configuration:
ss -tln | awk '{print $4}' | grep -E ':(PORT|PORT)$' | grep -qv '^127\.0\.0\.1' \
&& echo "UNEXPECTED EXPOSURE"An unauthenticated model server is compute anyone can spend and a log of everything anyone asks. Run llama.cpp with --api-key, and prefer binding to a container bridge gateway rather than 0.0.0.0.
If you tunnel it to a VPN or overlay network, the API key becomes the only remaining control — treat it accordingly.
Anything that executes generated code or edits files should see only a directory you chose for it. Mount a dedicated projects path, not a home directory.
Prefer tools that don't require mounting the Docker socket. Access to /var/run/docker.sock is equivalent to root on the host — anyone reaching that service controls the machine.
Web UIs for agent tools frequently ship without authentication. Keep them on loopback, and stop them when not in use.
If others use the box:
- Don't enable a host firewall you don't own — you may cut off their services
- Don't modify shared SSH configuration unilaterally
- Announce services you expose on shared interfaces
- Membership in the
dockergroup is root-equivalent; audit who has it - Plain HTTP means credentials cross the network in cleartext — tell users not to reuse an important password
- Encrypt at rest; restic and similar tools do this by default
- Store the repository password off the machine. A backup you can't decrypt is not a backup
- A backup on the same disk as the data protects against mistakes, not hardware failure
- Test a restore before you need one
Scripts that automate login to institutional portals sit in a grey area even when automating your own authorized access. Publishing working code that encodes a specific site's anti-CSRF tokens and honeypot fields hands anyone a ready-made tool against that site.
Describe the pattern; don't publish the weapon. That's why no such script appears in this repo.
Found something wrong in these notes? Open an issue. This is a lab write-up, not a product — there's no security response process, but corrections are welcome.