Deploying Ring Web Applications to Cloud Platforms

Chapter Author: Youssef Saeed

While the tutorial on deploying with Docker and a reverse proxy covers a traditional, powerful setup, modern Platform-as-a-Service (PaaS) providers like Fly.io and Railway.app offer a dramatically simplified deployment experience. These platforms abstract away the complexity of managing servers, reverse proxies, and SSL certificates, allowing you to go from code to a live, secure URL in minutes.

This tutorial guides you through deploying the same containerized Ring application to both Fly.io, known for its global reach and fine-grained control, and Railway.app, celebrated for its “it just works” simplicity.

1. Introduction: The PaaS Model

This approach differs fundamentally from setting up a reverse proxy on a cloud VM.

Self-Managed VM (Nginx/Traefik/Caddy)

Managed PaaS (Fly.io/Railway)

You manage the server, networking, and firewall rules.

The platform manages the entire underlying infrastructure.

You are responsible for setting up and configuring a reverse proxy (Nginx, etc.).

The platform provides a built-in, auto-configured edge router.

SSL certificate acquisition and renewal is a manual or scripted step (e.g., Certbot).

SSL is provisioned and renewed automatically for your application.

Deployment involves SSH’ing into a server and running docker compose.

Deployment is typically done via a CLI command (flyctl deploy or railway up).

Scaling requires manual intervention (e.g., setting up a load balancer).

Scaling is often a simple command or a setting in a dashboard.

The PaaS model is ideal for developers who want to focus on their code and not on infrastructure management.

Why Fly.io and Railway.app?

This tutorial focuses specifically on Fly.io and Railway.app because they are exceptionally developer-friendly and share a critical feature: both offer a generous free tier that does not require a credit card to get started. This makes them the perfect platforms for learning, prototyping, and deploying personal or small-scale applications without any initial financial commitment.

2. Prerequisites

  • A basic understanding of the Ring programming language.

  • A free account on Fly.io and/or Railway.app.

  • The respective command-line tools installed for the path you choose:

3. The Foundation: Application and Dockerfile

For consistency, we will deploy the exact same application and Dockerfile used in the reverse proxy tutorial. This highlights a key benefit of Docker: the containerized application is portable and does not need to be changed for different hosting environments.

Ensure you have these two files in your project directory.

  1. The app.ring file:

load "httplib.ring"

# Main Execution Block
oServer = new Server {
   # Route for the root path
   route(:Get, "/", :mainRoute)

   # Listen on all available network interfaces on port 8080
   listen("0.0.0.0", 8080)
}

func mainRoute
   # Set content type to HTML
   oServer.setContent("<!DOCTYPE html>
<html>
<head><title>Ring HTTPLib App</title></head>
<body>
<h1>Hello from Ring on a PaaS!</h1>
<p>This is a Ring application running inside a Docker container on a modern cloud platform.</p>
</body>
</html>", "text/html")
  1. The Dockerfile:

# Use a lightweight Ring image as the base
FROM ysdragon/ring:light

# Set the working directory inside the container
WORKDIR /app

# Copy the application source code
COPY . .

# The ysdragon/ring:light image uses the RING_FILE environment variable
# to determine which script to run. We'll set this via the platform UI/config.
# It also automatically exposes port 8080, which the platforms will detect.

4. Deployment Scenarios

Choose the platform you wish to deploy to.

Path A: Deploying to Fly.io

Fly.io launches your application containers on “micro-VMs” across its global network. The deployment is a two-step process: first, you initialize the configuration, and second, you deploy.

1. Log in to Fly.io

Open your terminal and authenticate the flyctl CLI with your Fly.io account.

flyctl auth login

2. Initialize Your Application without Deploying

To set environment variables before the first deployment, we need to create the fly.toml configuration file without immediately starting a build. The --no-deploy flag is perfect for this.

flyctl launch --no-deploy

This command will:

  • Scan your source code and detect the Dockerfile.

  • Ask you for an App Name and to choose a Region.

  • Create the fly.toml file in your project directory.

  • Exit without deploying, returning you to the command line.

3. Configure the Required Environment Variable

Our container image needs the RING_FILE environment variable to know which script to run. We set this using Fly’s secrets management. Secrets are encrypted and become available to your application at runtime.

flyctl secrets set RING_FILE=app.ring

4. Deploy the Application

Now that your fly.toml file is created and the required secret is set, you can run your first deployment. flyctl will build the Docker image, push it to Fly’s registry, and provision a machine to run it.

flyctl deploy

5. Visit Your Application

Once the deployment is complete, the CLI will display your application’s hostname. You can also run the following command at any time to open it in your browser.

flyctl open

Your Ring application is now live with a secure https://<app-name>.fly.dev URL!

Path B: Deploying to Railway.app

Railway offers an incredibly simple deployment experience, allowing you to deploy directly from your local machine with its powerful command-line interface.

1. Log in to Railway

Open your terminal and authenticate the Railway CLI.

railway login

2. Initialize a New Project

This command creates a new project in your Railway account.

railway init --name my_ring_project

4. Add Service and Configure Variables

This command creates a new service and sets its required environment variables.

railway add --service my_ring_project --variables "RING_FILE=app.ring"

5. Deploy the Application

Now, deploy your application. The up command builds your Dockerfile and starts the service. The -c flag streams build logs only, then exits.

railway up -c

6. Generate a Public Domain

By default, a new service on Railway is not exposed to the public internet. You can generate a secure, public domain for it using the railway domain command.

railway domain

The command will return a public URL for your service, which will look something like your-app-name-production.up.railway.app.

7. Visit Your Application

You can now visit the https://...up.railway.app URL that was generated in the previous step to see your live Ring application.

At any time, you can also open your project dashboard in the browser to view logs, settings, and find this domain again.

# This command opens your Railway project dashboard in the browser
railway open

5. Conclusion

This tutorial demonstrated how modern PaaS providers can eliminate nearly all the overhead of infrastructure management.

  • Fly.io is a fantastic choice when you need more control over your deployment’s configuration, want to distribute your application globally, or need to run services other than web apps. It gives you power and flexibility while still automating the hardest parts of deployment.

  • Railway.app is the champion of developer experience and speed. Its direct CLI deployment workflow makes it an incredible tool for rapid prototyping, personal projects, and any scenario where you want to move from code to a live URL with minimal friction.

By leveraging Docker, your Ring application becomes universally portable, allowing you to choose the deployment model—from a self-managed VM with a reverse proxy to a fully managed PaaS—that best fits your project’s needs and your personal workflow.