Deploying and Routing Dash Applications on Railway with Nginx as reverse Proxy

ibuitronHOBBY

9 months ago

Hi team!

I've developed a web application based on Plotly's Dash in Python.

App1: auth, handles user authentication and registration.
App2: quickbio, is an application for processing biological data.

Each app is a standalone Dash application, meaning it has its own configuration:

app = dash.Dash(...)

I've been able to communicate between both applications using Nginx as follows:

I deploy app1.
I deploy app2.
I route them using a reverse proxy with Nginx under the same domain, communicating both independent applications.

What I'd like to know is the following: Is it possible to do this natively on Railway?

I've seen that you can deploy independent applications from GitHub. By going to "New Project" and adding each repository there, So, from there, I would have to create a third "repository/script" that is responsible for joining the applications in a similar way to the Nginx script I have, or can this be done natively with Railway?

Regarding costs, how different would it be compared to me creating a Docker container that runs everything as a monolith with the routing I already have?

I'm interested in keeping everything separate (as microservices) because if I need to add new features, I would only have to update my GitHub code and Railway would take care of the rest, and I would have a more real separation than having all the code in a single Docker container.

I would like to know if there are other options that you know of, thank you for your help!

There is a code snippet of how i handle the reverse proxy with nginx

def generate_nginx_config(modules: List[ModuleType]) -> str:
    config = """
server {
    listen 80;
    server_name localhost;
    """

    for module in modules:
        module_name = get_module_name(module)
        port = get_app_port(module)
        prefix = get_app_prefix(module)
        if port is None or prefix is None:
            print(f"Error: No se pudo obtener el puerto o prefijo para {module_name}")
            continue

        config += f"""
    location {prefix} {{
        proxy_pass http://localhost:{port};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }}
    """

        print(f"Ruta de Nginx para {module_name}: http://localhost{prefix}")

    config += "}\n"

    config_path = os.path.expanduser("~/dash_apps_nginx.conf")
    with open(config_path, "w") as f:
        f.write(config)

    print(f"Configuración de Nginx generada en {config_path}")
    return config_path

4 Replies

9 months ago

I can not recommend using NGINX on Railway for proxy related stuff, every kind of IP (public and private) is dynamic and NGINX does not refresh the DNS cache by default so lookups can become stale and requests will fail, NGINX is a head ache to deal with imo.

I think this is what you want - https://railway.app/template/7uDSyj

You may need to eject from it and add extra config to the Caddyfile, but its going to be far better than NGINX for use on Railway.

Additionally, Please do not create a new project for every service that relate to one another, you would want them all in the same project if they are going to be used together in any capacity, like this -

https://railway.app/project/35d8d571-4313-4049-9699-4e7db7f02a2f


ibuitronHOBBY

9 months ago

Thanks!

I'll take a look at Caddyfile.

About the projects, I was referring to:

Haute Environmental (Project name)

(2 Repos)

app1: Auth

app2: QuickBio

My question was regarding the difference in resource expenditure of creating/maintaining two separate repositories/instances (two rectangles within a project in the railway dashboard) or dockerizing both as a single "rectangle".

Regarding Caddyfile, I see in the example you gave me that it is Frontend and Backend, can reverse proxy be done with more instances?


9 months ago

If you are new to Railway please check out this page - https://docs.railway.app/overview/the-basics

You would want to have the services separate for ease of use, the only reason you would want to combine them is if they needed access to the same fs.

As for resources used by combining them or having them as separate services, the resource usage between the two options would be negligible, so its better (imo) to go with the more DX friendly approach of two separate services in the same project.

Yes the Caddyfile can be adapted in anyway you would like, the template overview lists some links to Caddy's docs that you would want to read, you don't need to use the dynamic upstream stuff if that doesn't fit your use case.


ibuitronHOBBY

9 months ago

Thanks for the reply!

I'll check it out and if I have any questions, I'll follow this thread.


Deploying and Routing Dash Applications on Railway with Nginx as reverse Proxy - Railway Help Station