Your app works locally. You can create an account, click through it and show a demo. Production work begins when the right people need access to the right data, even when a request fails.
Whether the code came from Codex, Grok or you does not change the questions to ask about the server. Who can administer it? Where are the secrets? How do you return to the previous version? Here is a starting point for a VPS deployment, not a security certification.
Expose the site, not the whole machine
In this example, Caddy runs on the host and receives web traffic. The Docker app is published only on the server’s loopback address. It listens on 0.0.0.0:3000 inside the container. The image must already support running without privileges and without writing outside designated locations.
APP_IMAGE must contain a verified image reference, ideally pinned by digest. User 10001 must match your image’s user. Adjust memory limits after measuring usage. Do not put secrets in this file or bake them into the image.
services:
app:
image: ${APP_IMAGE:?Set a verified image reference}
user: "10001:10001"
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
read_only: true
tmpfs:
- /tmp:size=64m,mode=1777
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
pids_limit: 100
mem_limit: 512m
cpus: 1.0
Connect the domain and check from outside
Replace app.example.com with your domain and point its DNS to the VPS. For Caddy’s standard HTTPS setup, ports 80 and 443 need to be reachable and its data directory must remain persistent. SSH administration stays restricted to the intended access paths.
app.example.com {
reverse_proxy 127.0.0.1:3000
}
Prepare for failure before launch
Use a patched Docker version and test ports from another machine. Its documentation notes a loopback port isolation limitation before version 28.0.0. Published ports can also bypass UFW rules. An “active firewall” status is not enough.
Before opening registration, check authorization with two separate accounts, limits on public endpoints and restoration from an off-server backup. Keep the previous image and plan for migration rollback. Docker and HTTPS do not fix an endpoint that lets someone read another account’s data.