Install Kamal on your laptop or CI runner—not on the VPS—then let it connect over SSH, build and push your Docker image, install or use Docker on the server, and route traffic through kamal-proxy. The practical flow is: create a Dockerfile, run kamal init, configure config/deploy.yml and .kamal/secrets, point DNS at the VPS, run kamal setup once, and use kamal deploy for subsequent releases.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
What Kamal does on a VPS
Kamal is a deployment tool that you run from a development computer or CI runner. It uses SSH to control Docker on one or more servers, rather than requiring a Kamal installation on the VPS itself. Your checked-out application is built into a container image, the image is pushed to a registry, and the server pulls and runs it.
As an Amazon Associate I earn from qualifying purchases.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
A kamal-proxy process sits in front of the application container. It listens on ports 80 and 443, performs a health check, and changes the active route from the old container to the new one only after the new container is ready. That is the mechanism behind Kamal’s normal zero-downtime release behavior.
Read the official Kamal documentation for the release-specific syntax. Kamal and kamal-proxy defaults can change, and the available version was not established here.
#1 Best Overall
- HP ProLiant DL360 G7 Business Server, the perfect enterprise server or small business server!
- Processors: Dual (2) Xeon X5675 6-Core 3.06 GHz 12MB CPUs Max Turbo 3.46 GHz
- Memory: 72GB (4 x 16GB) DDR3 PC3-10600R Memory; Storage: 3.6TB (4 x 900GB) 10K 12Gb/s SAS 2.5" HDDs
- Power: Redundant Power Supplies; RAID: HP Smart Array P410i-a 12Gb/s with 4×GigaBit NIC
- Hard drives and memory upgrades included separately NOT installed, installation required.
Prerequisites and decisions
Complete these items before writing the deployment file. Skipping one usually produces an avoidable failure during setup.
- A deployment machine: your laptop, a dedicated build host, or a CI runner with Ruby, Git, Docker build capability, and an SSH client. Current third-party installation guides describe Ruby 2.7 or newer, but that requirement was not confirmed against the official installation page; check the documentation for the Kamal version you install.
- A VPS: a public IPv4 address, an SSH account, enough CPU, memory, disk, and bandwidth for your application and its image layers, and a firewall that permits SSH plus HTTP (80) and HTTPS (443).
- An SSH key: the deployment account must be able to log in non-interactively. A separate non-root account is preferable; grant it the Docker permissions required by your server’s operating system instead of routinely deploying as root.
- A Dockerfile: it must build a production image and start the web process on the port you will expose through the proxy.
- A container registry: Docker Hub, GHCR, or a private registry all work. The registry hostname, username, and password or token are needed by Kamal.
- A DNS name: create an A record such as
app.example.compointing to the VPS public IPv4 address. Add an AAAA record only when IPv6 is correctly configured and reachable on that server. - A health endpoint: the application should answer
GET /upwith HTTP 200 when it is ready to receive production traffic. If your framework uses another path, configure that path explicitly.
DNS must resolve publicly before automatic HTTPS can succeed. A local hosts-file entry is not sufficient for a public certificate challenge.
Install Kamal and create its configuration
Run these commands from the application repository on the deployment machine:
gem install kamal
kamal version
kamal init
kamal version confirms which client you installed. kamal init scaffolds config/deploy.yml and .kamal/secrets. Commit the deployment configuration, but keep secret values out of version control. Add .kamal/secrets to the repository’s ignore rules if the scaffold has not already done so.
Write a deploy.yml that matches your application
The following is a minimal single-VPS example. Replace every example value with your own service name, image, host, registry, and port.
service: myapp
image: registry.example.com/acme/myapp
servers:
web:
- 203.0.113.10
proxy:
host: app.example.com
app_port: 3000
ssl: true
env:
clear:
RAILS_ENV: production
secret:
- DATABASE_URL
- SECRET_KEY_BASE
registry:
server: registry.example.com
username: deployer
password:
- KAMAL_REGISTRY_PASSWORD
Service and image
service names the running application and is also used by Kamal when it creates containers and proxy routes. image is the full registry path that Kamal builds and pushes. The server must be able to pull that exact image, so the registry hostname in the image and the registry.server value should agree.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Servers and roles
The web role lists the VPS address. You can list more hosts when you need redundancy, but a one-host deployment remains a single point of failure. Kamal command flags allow you to target selected roles or hosts during an operation.
Rank #2
- [CPU] AMD Ryzen 7 5700G Processor (8 Cores, 16 Threads, 3.8 GHz Base Clock Speed up to 4.6 GHz Max Boost Clock Speed) for Gaming and Content Creation with 7nm Leading Edge Technology | [STORAGE] 2TB PCIe NVMe M.2 SSD - Experience Hyper-Fast Bootup and Data Transfer thats up to 30x Faster Performance than a Traditional Hard Drive.
- Graphics: Integrated AMD Radeon Graphics | [RAM] 32GB DDR4 RAM 3200 Gaming Memory for Seamless Multitasking from Multiple Web Pages to Playing Games Online Simultaneously | [OS] Windows 11 Pro x64
- 2x 3.5" Drive Bays | 4x Expansion Slots | mATX Motherboard | ATX PSU
- [BUY WITH CONFIDENCE] Empowered PCs are Assembled in the USA, Rigorously Stress-Tested Before Shipping, and Supported with Lifetime Technical and Diagnostic Support and 3-Year Limited Hardware Warranty.
Proxy and application port
proxy.host is the public hostname used for routing and certificate issuance. Set app_port to the port on which the container listens; if you omit it, the proxy default is 80. Kamal-proxy forwards requests from ports 80 and 443 to that internal application port.
With ssl: true on a single host, kamal-proxy can obtain and renew a Let’s Encrypt certificate automatically. Port 443 must be reachable from the internet for the ACME challenge. SSL redirect is enabled when SSL is enabled. Forwarded headers are disabled by default in that mode unless you turn them on explicitly, so enable the setting if your framework needs the original protocol or client headers.
Environment values
Put non-sensitive, deployment-wide values under env.clear. List sensitive variable names under env.secret; their values come from the secrets file and are injected during deployment. Do not place database passwords, signing keys, API tokens, or registry credentials directly in the committed YAML file.
Unless you change it, the proxy checks GET /up. Configure your application so that this endpoint does not depend on a browser session and returns 200 only when the process is ready. The default proxy response timeout is 30 seconds; a slow startup or a health handler that waits on an unavailable dependency can therefore prevent activation.
Path and timeout behavior
The proxy strips path prefixes by default. If your application must receive the original prefix, set strip_path_prefix: false. Set a larger response_timeout only when your workload genuinely needs it; increasing the timeout can hide a hung application rather than fix it.
Store registry and application secrets safely
Populate .kamal/secrets on the deployment machine with the variables named in your configuration. A typical file contains entries like:
KAMAL_REGISTRY_PASSWORD=replace-with-a-registry-token
DATABASE_URL=postgres://user:[email protected]:5432/myapp
SECRET_KEY_BASE=replace-with-a-long-random-value
Protect the file with restrictive permissions and provide equivalent variables in the CI runner’s secret store when deploying automatically. The registry credential must have permission to push the image from the deployment machine and to pull it from the VPS. If the registry is private, a failed login or expired token stops setup before the application can start.
Recommended Free Tools
Rank #3
- Dell PowerEdge R730xd 24B SFF 2U Server
- 2x Intel Xeon E5-2690 v4 2.6Ghz 14-Core (28-cores Total)
- 128GB DDR4 RAM – 4x 1.2TB 10K SAS 2.5” 12Gb/s
- Dell H730P mini 2GB 12Gb/s RAID
- 2x 750W PSU - 2x 10Gb SFP+ 2x 1Gb (RJ45) NIC
kamal env push is available when you need to push updated environment values to the server. Treat an environment change as an operational change: review it, deploy it through the same controlled process, and restart or redeploy the service when the application needs to read the new value.
Point DNS and open the VPS firewall
- Create an A record for the exact hostname in
proxy.host, for exampleapp.example.com, with the VPS public IPv4 address. - Wait until public DNS resolvers return that address. Query the record from outside your local network if possible.
- Allow inbound TCP 22 for SSH from the addresses that administer the server, TCP 80 for HTTP and the certificate challenge, and TCP 443 for HTTPS.
- If you publish an AAAA record, verify that the VPS, firewall, Docker host, and application all support IPv6. An incorrect AAAA record can make some visitors fail even while IPv4 appears healthy.
Do not enable automatic HTTPS until the hostname resolves to this VPS and port 443 is reachable. Kamal cannot complete the certificate challenge against a private address, stale DNS target, or blocked port.
Run the first bootstrap with kamal setup
From the repository revision you intend to release, run:
kamal setup
This is the one-time bootstrap for each newly prepared server. The operation normally performs the following sequence:
- Connects to the listed server over SSH.
- Installs Docker when it is missing or prepares the host to run Docker.
- Logs in to the configured container registry.
- Builds the checked-out application image and pushes it to the registry.
- Pulls the image onto the VPS and starts the application container.
- Starts kamal-proxy and configures the host and port route.
- Waits for the health check, normally
GET /up, to return HTTP 200. - Switches traffic to the new container only after that check succeeds.
- Stops the old container, when one exists, and prunes unused images according to Kamal’s cleanup behavior.
Watch the command output for the first failing stage. A successful image build does not prove that the application is reachable: the container must start, the port must be correct, and the health endpoint must respond through the proxy.
Deploy later releases without downtime
Commit your application and Dockerfile changes, check out the exact revision to release, and run:
kamal deploy
Kamal builds that checked-out version, pushes the image, starts a new container, waits for the health check, and asks kamal-proxy to move traffic from the old container to the new one. Existing requests can finish on the old container while new requests are directed to the healthy replacement.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #4
- Spacious Chassis: This huge 4U server case comes with 15 internal 3.5" HDD bays.
- Expandable & E-ATX Compatible: 7 PCI expansion slots and E-ATX compatibility gives you growth options for all of your needs.
- Exceptional Cooling: 8 pre-installed cooling fans provide excellent airflow and heat protection. 3 front 120mm PWM fans, 3 middle 120mm fans and 2 rear 80mm fans ensure your drives and chassis avoid overheating.
- Desired Features: Front panel LED indicators for power, HDD, and LAN status monitoring allow quick, easy visual assessment. Additional utility with 2 USB 3.0 port and built-in front panel lock.
Useful deployment options include:
| Option | Purpose |
|---|---|
--skip-push |
Skip pushing the image when the required image is already available in the registry. |
--roles |
Limit the operation to selected configured roles. |
--hosts |
Limit the operation to specific hosts. |
--destination |
Override the deployment destination for the command. |
--config-file |
Use another configuration file; the default is config/deploy.yml. |
Use kamal redeploy when the server is already bootstrapped and you need a deployment without repeating bootstrap-only work such as initial proxy startup, registry login, and pruning. It is not a substitute for the first kamal setup.
How kamal-proxy decides whether to switch traffic
The proxy keeps the old route in place while the replacement container starts. It calls the configured health path on the application port. A 200 response from /up indicates readiness; connection failures, a wrong port, non-200 responses, or a timeout leave the old route active instead of sending users to a broken container.
That check should be cheap and deterministic. If it performs a database migration, waits on an external API, or requires authentication, a deploy can time out even though the web process itself is running. Keep readiness checks focused on the dependencies required to serve requests and perform heavier diagnostics separately.
For advanced use, kamal-proxy also has a standalone command shape such as kamal-proxy deploy <service> --target host:port, with optional host and TLS flags. Normal Kamal deployments invoke the proxy for you, so use the standalone interface only when you have a deliberate reason to manage proxy operations separately.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesTroubleshoot the failures that stop most VPS deployments
| Symptom | Likely cause | What to check or fix |
|---|---|---|
| Certificate issuance fails | DNS still points elsewhere, the hostname is not public, or TCP 443 is blocked. | Confirm the public A/AAAA answers, open 443, and retry after DNS has propagated. |
| Proxy reports an unhealthy container | No /up endpoint, a non-200 response, wrong app_port, or startup longer than the timeout. |
Request the endpoint locally inside the container, verify the listening port, inspect logs, and adjust the health path or timeout only when justified. |
| Registry login or pull fails | Wrong server name, username, token, expired credential, or missing secret variable. | Check the names in registry and .kamal/secrets; verify that the token can push and the VPS can pull. |
| SSH connection fails | Incorrect host, key, account, firewall rule, or server-side SSH configuration. | Test a direct SSH connection using the same account and key, then correct the server entry or firewall. |
| Old code keeps serving | The new image was not pushed, the wrong revision was checked out, or the command targeted another host or role. | Confirm the Git revision, image tag output, destination, and selected roles; rerun without --skip-push when the registry lacks the image. |
| Setup stops partway through | A bootstrap component such as the proxy or an accessory did not restart cleanly. | Use kamal proxy reboot or kamal accessory reboot for the affected component, then run kamal deploy again. |
When investigating, start with the first error in the command output rather than the final cascade of failures. Inspect the container logs on the VPS, confirm that the process is listening on the configured port, and test the health endpoint from the same network path used by the proxy.
Operational practices for a safer Kamal host
- Use a dedicated deployment account and SSH key, and remove access when a person or CI runner no longer needs it.
- Restrict registry tokens to the permissions required for image push and pull. Rotate them in the registry and in
.kamal/secretstogether. - Keep the VPS operating system, Docker engine, and application base image patched. Kamal deploys your container; it does not replace host maintenance.
- Back up databases and persistent uploads independently of the application container. Replacing a container must not delete irreplaceable data.
- Monitor disk usage because each release creates image layers. Pruning helps, but set an alert before the filesystem fills and blocks both Docker and SSH operations.
- Test a rollback procedure before an incident: identify the last known-good revision, check it out, and run
kamal deployso the proxy can return traffic to a healthy image. - Pin and review dependency versions in the application image. Kamal’s zero-downtime switch cannot correct a migration that is incompatible with both the old and new application versions.
What this single-VPS design does—and does not—provide
A one-host Kamal deployment gives you repeatable image-based releases, an automated proxy, health-gated traffic switching, and optional automatic certificates without requiring a separate orchestration cluster. It does not make the VPS highly available: a host outage, a full disk, a broken kernel, or a network failure still takes the application offline. Multiple hosts, external databases, backups, monitoring, and a tested disaster-recovery plan are separate design decisions.
Kamal also does not infer your application’s runtime requirements. You remain responsible for Dockerfile correctness, migrations, persistent storage, background workers, cron jobs, firewall policy, and observability. Configure those as explicit services, roles, or accessories only after you understand their failure and restart behavior.
Quick Recap
Release checklist
- Dockerfile builds locally and starts the production web process.
- Deployment machine has the supported Ruby/Kamal installation and SSH access.
config/deploy.ymlnames the correct image, host, role, proxy hostname, and application port.- Secrets exist locally or in CI and are not committed.
- Registry credentials can push and pull the image.
- DNS resolves the proxy hostname to the VPS; IPv6 is published only when tested.
- Ports 22, 80, and 443 are permitted according to your access policy.
GET /upreturns 200 from a ready container.- You have run
kamal setupfor a new host, or selectedkamal deploy/kamal redeployappropriately for an existing one. - Backups, logs, disk alerts, and a rollback revision are available before exposing the service to users.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




