Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Most Kamal failures on a Hetzner server behind Cloudflare happen outside Rails. The usual order is local provisioning, SSH and firewalls, Docker and image delivery, then Kamal secrets and Rails boot; only after those layers work should you troubleshoot DNS, TLS, proxy headers or assets. This runbook follows that order. Each error includes the layer responsible, a practical fix and a command that proves whether the fix worked. Test the Hetzner origin directly before changing Cloudflare settings: otherwise an edge error can hide a stopped container, wrong port or invalid certificate.

What must be working before Kamal touches Rails?

Kamal needs three first dependencies: a reachable Linux host, SSH access for the configured user and a working Docker engine. A failure in any of these occurs before Rails code, migrations or Active Storage are involved.

  • A supported host such as Ubuntu 22.04 or newer, or Debian 11 or newer.
  • An SSH key whose public half is installed in the target account’s authorized_keys.
  • Inbound TCP 22, 80 and 443 allowed in both the Hetzner firewall and the host firewall (for example, UFW).
  • A deployment registry, image name and tag that the build environment can push and the server can pull.
  • Production secrets for the registry, database, Rails credentials and any required service integrations.
  • Correct DNS for the public hostname and a clear decision about whether Cloudflare will proxy it.

Keep the server clock synchronized. Incorrect time can make certificate validation, log correlation and short-lived credentials appear randomly broken.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Why does hcloud: command not found appear, or why was no server created?

Layer: local provisioning. Kamal cannot repair a VPS that was never created. The error means the Hetzner command-line client is absent or unauthenticated, or that provisioning was done in the wrong project.

#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter | 4Pack Type C Female to A Male Cable Converter for Apple Duo 17 16 15 14 Plus,iWatch Watch 12 11 10,iPad 9 8 Air,Airpods 5 4
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Fix

  1. Install the Hetzner CLI, authenticate it with a token that can create servers, and select the intended project.
  2. Alternatively, create the VPS in the Hetzner Cloud Console.
  3. Record the server’s public IPv4 address and add the deployment public key during creation or afterward.
  4. Use that address consistently in your Kamal destination and DNS records.

Do not proceed with Kamal until the server exists and responds on the network.

Verify

hcloud server list
ping -c 3 SERVER_IP

If the CLI is not part of your workflow, verify the same address in the Cloud Console and continue with the SSH test in the next section.

2. Why does SSH return Permission denied (publickey)?

Layer: SSH authentication. Kamal uses SSH to install Docker, upload configuration and control containers. A registry login or Rails fix cannot help while the server rejects the key.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix

  1. Confirm that the public key matching your local private key is present in the target account’s ~/.ssh/authorized_keys.
  2. Set the same private-key path in config/deploy.yml; do not assume Kamal will choose the key you intended.
  3. Use the correct account, commonly root for an initial tutorial-style setup, or the non-root account configured on your host.
  4. Correct file permissions if you manually copied the key: the SSH directory should not be writable by other users.

Verify

ssh -i ~/.ssh/your_deploy_key root@SERVER_IP 'id && hostname && uptime'

Run this exact connection before kamal setup. If it fails, increase SSH verbosity with -vvv and check which key the client actually offers.

3. Why does port 22, 80 or 443 time out?

Layer: network firewalls. A timeout normally means packets are being dropped, not that Rails returned an error. Hetzner’s cloud firewall and the host firewall are separate controls, so opening only one is insufficient.

Fix

  • Allow TCP 22 for administration and Kamal.
  • Allow TCP 80 for HTTP redirects or an origin that Cloudflare reaches over HTTP.
  • Allow TCP 443 for HTTPS origin traffic.
  • Check Hetzner firewall rules attached to the correct server and the host’s UFW or equivalent rules.
  • Keep any temporary diagnostic rule narrow and remove it after testing.

Verify

nc -vz SERVER_IP 22
nc -vz SERVER_IP 80
nc -vz SERVER_IP 443
sudo ufw status verbose

A refused connection is different from a timeout: refusal proves the path is open but no process is listening, which points to Docker, Nginx, Rails or the TLS listener rather than the firewall.

4. Why does Kamal report an unsupported OS or docker: command not found?

Layer: host and Docker. Kamal’s setup routine expects a supported Linux distribution and a usable Docker engine. On Ubuntu 22.04+ or Debian 11+, Kamal can install Docker when it is absent; an unsupported image, restricted package source or partial installation can stop that process.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter | USB C Dongle with 90W Max Power Delivery, 3×5Gbps USB A Data Ports, for MacBook, Dell, and More (Charger Not Included)
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Fix

  1. Use a supported Ubuntu or Debian image and update its package metadata.
  2. Let kamal setup install Docker, or install and start Docker yourself before retrying.
  3. Ensure the configured deployment user can run Docker, either as root or through the Docker group as appropriate.
  4. Do not mix a stale Docker package with a second installation method unless you understand which service owns the socket.

Verify

cat /etc/os-release
docker version
sudo systemctl is-active docker
docker run --rm hello-world

The final command proves that the daemon can create a container, not merely that a Docker binary exists.

5. Why does the Docker build fail in Bundler or Bootsnap with a libyaml or native-extension error?

Layer: image build dependencies. Bundler compiles native gems during the image build. If a gem or Bootsnap cannot find its system library, the build stops before Kamal can push an image.

Fix

  1. Read the first missing header or library in the build log; that name identifies the package to install.
  2. For the documented YAML failure, add libyaml-dev to the builder image before bundle install.
  3. Add any other development package named by the failing extension, then rebuild without relying on a cached broken layer.
  4. Keep runtime-only images smaller by installing compiler and development packages only in the build stage when your Dockerfile uses multi-stage builds.

Verify

docker build --no-cache -t your-image:test .
docker run --rm your-image:test bundle exec bootsnap precompile --gemfile app/

If the second command is not part of your application, run the image’s normal boot command instead and confirm Bundler loads every gem.

6. Why can Kamal not push or pull the image?

Layer: registry authentication and naming. Kamal builds locally, pushes to the registry configured in the deployment file, and instructs the server to fetch the exact image tag. A typo in any of those values produces an image-not-found or authentication error.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix

  • Compare the registry hostname, repository path and tag character for character between config/deploy.yml and the image you built.
  • Authenticate from the build environment with the registry’s login command.
  • Authenticate the server or provide Kamal’s registry credentials so Docker can pull privately.
  • Use an immutable tag for a release rather than silently reusing a mutable tag while debugging.

Verify

docker pull REGISTRY_HOST/OWNER/APP:TAG
ssh root@SERVER_IP 'docker pull REGISTRY_HOST/OWNER/APP:TAG'
ssh root@SERVER_IP 'docker image inspect REGISTRY_HOST/OWNER/APP:TAG --format "{{.Id}}"'

The digest or image ID should correspond to the release you intended to deploy.

7. Why is KAMAL_REGISTRY_PASSWORD empty or a secret interpolation missing?

Layer: deployment environment. Kamal substitutes variables when it reads the deployment configuration. If the shell that launched the command did not export a variable, or the name in .kamal/secrets differs from the name referenced by config/deploy.yml, the resulting credential is blank.

Fix

  1. Put deploy-time credentials in .kamal/secrets using the variable names expected by your deployment file.
  2. Keep that file out of version control and restrict its permissions.
  3. Check that your current shell exports any variables the secrets file reads; a value defined in another terminal is not available here.
  4. Remove accidental quotes, spaces or line breaks from tokens.

Verify

grep -E '^[A-Z0-9_]+=' .kamal/secrets
KAMAL_REGISTRY_PASSWORD='redacted' kamal env push

Never print the password itself. The useful result is that Kamal accepts the environment and can authenticate to the registry without an interpolation warning.

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter | 85W Max PD, 2 USB 3.0 & 1 USBC Data Ports, SD/TF Card Reader, for Laptops/Mac and Other Type C Devices (Charger Not Included)
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

8. Why does the container start and then exit, or become unhealthy?

Layer: container process and application boot. Docker reporting a created container does not mean a web process is listening. Common causes are a crash on boot, missing production variables, a failed database connection, a wrong internal port or Rails binding only to loopback.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix

  1. Read the application and release logs before restarting repeatedly.
  2. Set the Rails server to bind to 0.0.0.0 inside the container, not only 127.0.0.1.
  3. Make the exposed and internal ports agree with the Kamal service definition and health check.
  4. Supply every required production environment variable and verify database reachability from the container network.
  5. Make the health check test the actual listening endpoint and an appropriate response, rather than a path that requires an unavailable dependency.

Verify

kamal app logs
kamal app details
ssh root@SERVER_IP 'docker ps --format "table {{.Names}}t{{.Status}}t{{.Ports}}"'
curl -sv http://SERVER_IP:INTERNAL_OR_PUBLISHED_PORT/health

If the container exits too quickly for an interactive check, inspect its exit code and the last log lines with docker ps -a and docker logs CONTAINER.

9. Why do migrations fail with ActiveRecord, DATABASE_URL or a missing master key?

Layer: Rails release and persistence. The web image can be valid while the release step cannot connect to the database or decrypt credentials. A deployment that skips migrations may also leave the new code incompatible with the existing schema.

Fix

  • Provide the production DATABASE_URL or equivalent database settings through Kamal secrets.
  • Provide the Rails master key and any credentials required to boot the environment; do not bake them into the image.
  • Run migrations in the release flow and inspect the release container logs, not just the web container logs.
  • Use a persistent volume or managed database for production data. Replacing an ephemeral database container during a redeploy can erase state.
  • For a failed migration, restore the previous application version only after determining whether the schema change is backward compatible.

Verify

kamal app logs --roles=web
kamal app exec 'bin/rails db:migrate:status'
kamal app exec 'bin/rails runner "puts ActiveRecord::Base.connection.active?"'

Run the status command against the release that is actually serving traffic, and confirm that the expected migration is marked up.

10. Why does DNS return NXDOMAIN, the wrong host or an exposed origin IP?

Layer: DNS. Cloudflare cannot proxy a hostname that has no authoritative record, and a record aimed at an old address sends users to the wrong server. A direct origin address exposed in public DNS also lets traffic bypass edge controls.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix

  1. Create the intended A record for the hostname and the current Hetzner IPv4 address; add an AAAA record only when IPv6 is configured and reachable.
  2. Use a CNAME where your architecture requires one, and remove stale records that conflict with the desired hostname.
  3. Check that the record is in the correct Cloudflare zone and that the proxy state matches your test plan.
  4. Wait for resolver caches to expire; changing records repeatedly can make different networks appear inconsistent.

Verify

dig +short app.example.com A
dig +short app.example.com AAAA
curl -sv --resolve app.example.com:80:SERVER_IP http://app.example.com/

The --resolve request tests the intended hostname against the origin without depending on public DNS, which separates an application problem from propagation.

11. Why does Cloudflare show ERR_TOO_MANY_REDIRECTS?

Layer: Cloudflare-to-origin HTTPS policy and Rails proxy trust. A loop occurs when Cloudflare connects to the origin over HTTP while the origin insists on HTTPS, or when Rails does not recognize the forwarded HTTPS request and redirects it again.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray | Data transfer & Fast charging for MacBook, iPhone 17/16/15, iPad, Samsung Galaxy, Apple Watch
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

Fix

  1. Make the origin serve HTTPS when the edge is configured to require an encrypted origin connection.
  2. Use Cloudflare’s Full mode for an encrypted origin; use Full (strict) when the origin certificate is valid, trusted and matches the hostname.
  3. Avoid Flexible mode with an origin that force-redirects HTTP to HTTPS; that combination creates the classic loop.
  4. Configure Rails to trust the proxy and, where appropriate for your production setup, set config.assume_ssl = true.
  5. Ensure the canonical host and redirect rules do not point between two hostnames.

Verify

curl -sSIL https://app.example.com/
curl -sv -H 'Host: app.example.com' http://ORIGIN_IP/

Record every Location header. If the origin response redirects to HTTPS while Cloudflare is using HTTP to reach it, change the mode or origin listener rather than adding another redirect rule.

12. What causes Cloudflare errors 525 and 526?

Layer: origin TLS. Error 525 means the TLS handshake between Cloudflare and the origin failed. Error 526 means Cloudflare could connect but rejected the origin certificate under the selected validation policy. Retrying the deployment does not repair either condition.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix a 525

  • Confirm that a process listens on origin port 443 and that the firewall permits it.
  • Check that the certificate and private key match and that the server presents the required certificate chain.
  • Enable a protocol and cipher set supported by Cloudflare and your origin server.

Fix a 526

  • Install a valid certificate whose name covers the hostname Cloudflare uses.
  • Include the intermediate chain and verify that the private key belongs to that certificate.
  • Use a temporary SSL mode consistent with the installed certificate only while repairing the underlying trust issue; do not treat a weaker mode as the final fix.

Verify

openssl s_client -connect ORIGIN_IP:443 -servername app.example.com -showcerts
ss -tlnp | grep ':443'

Inspect the certificate dates, subject names and chain in the output, then repeat an external request and retain its Cloudflare request identifier for correlation.

13. Why does Cloudflare return 502 Bad Gateway, 1033 or “connection refused”?

Layer: origin reachability, protocol or tunnel connectivity. A 502 commonly means the service is down, Cloudflare is using the wrong protocol or the route points to a closed port. A 1033 indicates that Cloudflare cannot associate a tunnel request with a healthy connector.

Fix

  1. Bypass Cloudflare and request the origin directly with the correct Host header.
  2. Check the container logs and listening sockets; confirm that the port in the Cloudflare route matches the port exposed by the service.
  3. Use HTTP to an HTTP origin and HTTPS to an HTTPS origin; do not assume changing only the public URL changes the backend protocol.
  4. For a tunnel, restart or reconnect the connector, verify its DNS association and confirm that it can reach the local service.
  5. Remove stale routes that point at a retired container or old port.

Verify

curl -sv -H 'Host: app.example.com' http://ORIGIN_IP:ORIGIN_PORT/
ssh root@SERVER_IP 'ss -tlnp; docker ps'
curl -sv https://app.example.com/

Compare the direct response with the proxied response. The first status line, protocol, port and application headers usually reveal which side is failing.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

14. Why are Rails URLs, cookies, WebSockets, assets or Active Storage wrong after deployment?

Layer: proxy-aware Rails configuration and release assets. A page can load while Rails still believes the request is HTTP, the wrong host is canonical, WebSockets are blocked or a new container cannot find files generated by an older release.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix the request and host information

  • Preserve Cloudflare’s forwarded protocol and client headers through the origin proxy.
  • Set the canonical production host and allow it in Rails.
  • Use config.assume_ssl = true where the application receives HTTPS at the edge and the proxy terminates or forwards TLS in a way Rails must understand.
  • Check secure cookie behavior, redirect rules and URL generation with the forwarded scheme, not only with a direct HTTP test.

Fix WebSockets and uploads

  • Verify that the proxy route supports WebSocket upgrade requests and that the application endpoint is reachable on the expected path.
  • Confirm that Active Storage’s service, bucket credentials and public URL are production values rather than development defaults.
  • Test upload, download and signed URL expiry through the public hostname.

Fix release assets

Fingerprinting makes each release’s asset names unique, but an old container can remain live while the new container serves a different asset set. Use Kamal asset bridging or a shared asset path so every container serving traffic can read the required compiled files during the transition.

Best Value
Sale
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display | 85W Max PD, 1 Powered USB-C 5Gbps & 2 Powered USB-A 3.0 5Gbps Data Ports, for MacBook Pro, MacBook Air, Dell and More (Black)
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

Verify

curl -sv https://app.example.com/ | sed -n '1,20p'
curl -sv -H 'Upgrade: websocket' -H 'Connection: Upgrade' https://app.example.com/cable
curl -sv https://app.example.com/assets/application- FINGERPRINT.css

Check the response’s Location, Set-Cookie, cache and upgrade headers. Compare those results with a direct-origin request to determine whether Rails or the proxy altered them.

What is the fastest verification sequence after a fix?

Work from the inside out. This prevents changing DNS or TLS settings when the application is simply not listening.

  1. SSH and Docker: connect to the Hetzner IP and run docker version, docker ps and systemctl is-active docker.
  2. Application logs: run kamal app logs and confirm the Rails process remains alive after boot.
  3. Origin HTTP: run curl -sv http://ORIGIN_IP/, adding the production Host header when routing depends on it.
  4. DNS: run dig +short app.example.com and confirm the answer and Cloudflare proxy state are intentional.
  5. Public HTTPS: run curl -sv https://app.example.com/; record the status, every Location header and the CF-RAY header.
  6. TLS-specific checks: for 525 or 526, inspect the certificate and origin listener with openssl s_client and ss -tlnp.
  7. 502-specific checks: compare the origin port and protocol with the Cloudflare route, then compare direct and proxied responses.

Keep the outputs from each layer together. A direct-origin success paired with a public 502 points to Cloudflare routing or protocol; a direct-origin failure keeps the investigation on the server and application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Which layer owns each symptom?

Symptom Likely layer First check Security caution
CLI missing or no VPS Local provisioning Hetzner CLI authentication or Cloud Console Use a scoped API token
Public-key denial SSH ssh -vvv with the configured key Do not copy private keys to the server
Timeout on 22, 80 or 443 Cloud and host firewalls nc -vz and firewall rules Open only required ports
Docker or build error Host and image build docker version and build log Keep build secrets out of image layers
Image pull or secret failure Registry and Kamal environment Pull the exact tag on the server Protect registry credentials
Container unhealthy or migration error Rails and database kamal app logs and migration status Keep database data persistent
NXDOMAIN or wrong address DNS dig +short Avoid exposing an origin unnecessarily
Redirect loop or 525/526 Cloudflare TLS and Rails proxy trust Inspect redirects and origin certificate Do not leave TLS weakened as a workaround
502 or 1033 Origin route or tunnel Direct-origin curl and listening sockets Validate route and connector identity
Wrong URLs, cookies or assets Proxy-aware Rails and release files Compare direct and proxied headers Check secure cookies and signed URLs

The blast radius also differs. A bad local key affects one deploy; a DNS, TLS or proxy mistake can affect every visitor; an asset-path mistake may affect only traffic split between old and new containers. Use the narrowest test that can distinguish those cases.

Frequently Asked Questions

Can I deploy Kamal without Cloudflare first?

Yes. Point a temporary hostname or your local hosts file at the Hetzner address and validate SSH, Docker, the Rails process and direct-origin HTTP before enabling proxying. This removes edge TLS and DNS variables while you establish a known-good origin.

Should port 80 stay open when Cloudflare uses HTTPS?

Usually keep it available if you intentionally redirect HTTP to HTTPS or use an HTTP origin mode; otherwise close it after confirming your chosen architecture. Cloudflare still needs the port when its origin protocol is HTTP, even if visitors enter through an HTTPS edge.

How do I roll back a Kamal release safely after a failed migration?

First determine whether the migration changed the schema in a backward-incompatible way. Roll back the application image only when the existing schema supports it, and take a database backup before any destructive reversal; redeploying an older image does not automatically undo a migration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does a direct-origin request work while the browser still fails?

The public request may use a different Host header, TLS SNI name, Cloudflare cache or WebSocket upgrade path. Reproduce the browser’s hostname and protocol with curl, inspect the CF-RAY value and compare response headers before changing application code.

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.