A real app is rarely one container. It is a web service, a database, maybe a worker and a cache. Impreza takes a full docker-compose file as a deployment: you own the compose, the agent runs it on your VPS, and the platform’s reverse proxy issues HTTPS for the service you point it at. There is exactly one rule the proxy needs you to follow, and this guide starts with it.
What you get
- Your compose file, unchanged in spirit: services, volumes, networks and limits stay yours
- HTTPS on the service you expose, on your domain or a free imprezaapps.com subdomain
- Private services stay private: the database never gets a public port
- The same lifecycle as any deployment: logs, redeploy in place, a .onion mirror if you want one
The one rule: name the public container
The reverse proxy reaches your container by its name on a shared Docker network called impreza-proxy. Your compose must give the public service a fixed name built from the deployment id, and join that network. Everything else is normal compose.
services:
app:
image: ghcr.io/yourorg/yourapp:1.2.3
container_name: ${DEPLOYMENT_ID}-app
restart: unless-stopped
networks:
- default
- impreza-proxy
environment:
DOMAIN_URL: ${DOMAIN_URL}
networks:
impreza-proxy:
external: true
The matching route in the deployment tells the proxy where to send traffic:
{ "upstream": "{deployment_id}-app:80", "match_var": "domain" }
Without the container_name line, Compose invents a name like project-app-1, the proxy cannot find the container, and every request answers 502. The platform now rejects a manifest that misses it, with a message naming the exact line to add.
Deploy it
Write the compose with the naming rule
Give the public service container_name: ${DEPLOYMENT_ID}-<suffix> and both networks. Leave internal services such as the database on the default network only, with no ports: published. They talk to the app by service name, as usual.
Pass configuration as variables
Reference secrets as ${VAR} in the compose. The variables you pass at deploy time are written to a .env next to the compose, and three are always present: DOMAIN_URL, DEPLOYMENT_ID and HOST_PORT. Nothing sensitive needs to live in the file itself.
Set limits inside the compose
In manifest mode the platform does not apply its CPU and memory defaults; your compose is the source of truth. Use the service-level cpus: and mem_limit: keys so one container cannot starve the host.
Create the deployment
From My Apps in Advanced view, the CLI, or your AI agent, create a custom deployment in manifest mode with the compose content, the route for the public service, and the domain, or leave the domain empty for a free subdomain. The agent brings the stack up with docker compose.
Check it and iterate
When the status turns to running, open the URL. If something is off, read the logs from the card or your agent. To ship a change, redeploy in place: the deployment id, the domain and the URL stay the same.
Only the service that should receive HTTPS traffic joins impreza-proxy. A database on that network, or with a published port, is reachable from the internet. Keep it on the default network and give it a container_name of its own only to avoid collisions.
Two services. wp gets container_name: ${DEPLOYMENT_ID}-wp, both networks and the route {deployment_id}-wp:80. db runs mariadb:11 on the default network with MARIADB_PASSWORD: ${WP_DB_PASS}, and the password arrives as a deploy variable, not in the file. The full example is in the manifest section of the docs.
Declare volumes in the compose as you always do; the platform does not add its own in manifest mode. Any custom deployment can publish a .onion mirror alongside the clearnet hostname, or run onion-only.
Start now
Get an offshore VPS with the agent preselected, read the manifest routing contract at docs.imprezahost.com, or start simpler with deploy a Docker app to an offshore VPS.









