Core answer: the pre-launch four — ① ports: open only 80/443; MySQL 3306, Redis 6379, MongoDB 27017 must never bind 0.0.0.0; ② license: internal projects are free, distributed code splits on MIT (carefree) vs GPL (derivatives must open source); ③ identifiers: UUID v4 carries 122 bits of entropy — a billion IDs a day collides once every ~86 years; ④ download estimate: file MB ÷ (bandwidth Mbps ÷ 8) = theoretical seconds, then ×1.1-1.3 for protocol overhead.

Port security check

Three red lines: ① database ports stay private — bind 127.0.0.1 or internal IPs, whitelist the office network only; ② admin ports get hardened — SSH 22 is scanned 24/7, key-only login plus fail2ban is the floor; ③ debug ports close before launch — Node 9229, Java JDWP 8787, exposed phpMyAdmin — all are backdoors once indexed.

High-frequency port table

PortServiceLaunch posture
22SSHKey login + source IP limit
80/443HTTP/HTTPSPublic
3306MySQLInternal only
5432PostgreSQLInternal only
6379RedisInternal + password
8080App debugClose on launch
27017MongoDBInternal only

All 40 ports with troubleshooting mnemonics: [port lookup](/c/dev/port-list).

Choosing an open-source license

LicenseCommercialClosed derivativesCopyleftOne-liner
MITNoneKeep the notice, done
Apache 2.0NoneMIT + patent grant
BSDNoneMIT family
LGPL✓ (dynamic link)WeakChanges to the library itself must open
GPLStrongDerivatives go GPL wholesale
AGPLStrongestSaaS counts as distribution

Decision tree: maximize adoption → MIT; need patent protection → Apache 2.0; force give-back → GPL; defend SaaS → AGPL. The [license picker](/c/dev/license-picker) recommends one after three questions.

UUID versions compared

VersionSourceNotes
v1Timestamp + MACOrdered but leaks MAC — rare
v4Pure randomThe default, 122 bits of entropy
v7Timestamp + randomOrdered and safe — preferred for new systems

v4 collision math: 2.71×10¹⁸ IDs for a 50% chance — about 7.4 million years at a billion per day. Ship it.

Example: security group debugging

http://1.2.3.4:8080 times out externally: ① local curl localhost:8080 works — the app is fine; ② ss -lptn shows the app bound to 127.0.0.1:8080 — local-only, of course the internet cannot reach it; ③ rebind to 0.0.0.0 — still failing; ④ the cloud security group has no 8080 inbound rule — add it — fixed. Mnemonic: local works → check the bind address; bind is right → check the security group; that is right → check iptables/ufw.

Example: download time estimate

A 500MB installer on a 200Mbps connection: 200÷8 = 25MB/s theoretical → 500÷25 = 20s; ×1.2 for TCP overhead and peak-hour loss → about 24s. The [download time calculator](/c/dev/download-time) includes overhead correction.

Common mistakes

  • "Open 0.0.0.0 for debugging, tighten later": scanners find fresh ports within minutes; weak-password Redis becomes an SSH-key implant every week.
  • "GPL is fine because we are SaaS": GPL cannot reach network services, but AGPL was written exactly for that — check which one your dependency uses.
  • UUID as a credential: a UUID is an identifier, not a secret — once it appears in URLs or logs it is public. Use real tokens for auth.
  • Confusing Mbps with MB/s: ISPs quote bits; downloads show bytes. 1000M fiber peaks at 125MB/s — do not blame the wrong party.