Cannot connect wo my web app hosted on Fly machine (VUE3 & VITE)

I have a medium sized web application. A mobile single page application. Build with VUE3 and vite. It runs perfectly local. But when I deploy it to a fly container I cannot connect to it.

Obviously this is a port mapping issue. Here is what I already tried. And none worked so far.

  • configured server.port = 8080 in vite.config.js
  • confugured host: true in vite.config.jsto allow access from any IP (localhost, 127.0.0.1 or any other intranet IP)
  • checked configuration in fly.toml
  • Read all the (very nice) Fly troubleshout documentation
  • Deleted my containers and restarted them from scratch
  • … no luck so far.

Here are the details:

My VUE app running locally with the command npx vite:

VITE v7.1.7  ready in 262 ms

    ➜  Local:   http://localhost:8080/
    ➜  Network: http://192.168.178.134:8080/
    ➜  press h + enter to show help

Works like a charm locally. Mind: Here I have no HTTPS.

vite.config.js

Vite.dev is VUE’s builder, packager and server/runner.

export default defineConfig({
	server: {
		host: true, // listen on all adresses, incl. LAN and public adresses
		port: 8080,		
	},
  plugins: [
    vue(),
  ]
})

fly launch

Then I build the app with fly launch. This creates the following

Dockerfile

FROM debian:bullseye as builder

ARG NODE_VERSION=22.14.0

RUN apt-get update; apt install -y curl python-is-python3 pkg-config build-essential
RUN curl https://get.volta.sh | bash
ENV VOLTA_HOME /root/.volta
ENV PATH /root/.volta/bin:$PATH
RUN volta install node@${NODE_VERSION}

RUN mkdir /app
WORKDIR /app

ENV NODE_ENV production
COPY . .
RUN npm install && npm run build

####

FROM debian:bullseye
LABEL fly_launch_runtime="nodejs"

COPY --from=builder /root/.volta /root/.volta
COPY --from=builder /app /app

WORKDIR /app
ENV NODE_ENV production
ENV PATH /root/.volta/bin:$PATH

CMD [ "npx", "vite", "--host", "0.0.0.0"]

I specifically added the --host option to vite also on the command line. To make sure my app uses this port.

Here is an excerpt from the Fly virtual machine log:

[info][   70.321998] reboot: Restarting system
[info]Out of memory: Killed process
[info]2025-10-10T11:27:17.117593392 [01K76XXR002X5GRTWEMS4J7CS8:main] Running Firecracker v1.12.1
[info]2025-10-10T11:27:17.117785068 [01K76XXR002X5GRTWEMS4J7CS8:main] Listening on API socket ("/fc.sock").
[info] INFO Starting init (commit: fedadb2e)...
[info] INFO Preparing to run: `npx vite --host 0.0.0.0` as root
[info] INFO [fly api proxy] listening at /.fly/api
[info]Machine started in 2.783s
[info]2025/10/10 11:27:21 INFO SSH listening listen_address=[fdaa:1:b0e4:a7b:5a6:fffd:28ad:2]:22
[info]  VITE v7.1.7  ready in 11995 ms
[info]  ➜  Local:   http://localhost:8080/
[info]  ➜  Network: http://172.19.11.122:8080/
[info]  ➜  Network: http://172.19.11.123:8080/

Now it gets more intersting. Output of fly deploy

=> => pushing manifest for registry.fly.io/liquido-frontend-fly:deployment-01K76XWBJQFDY4T8C4PBCZEKNA@sha256:04ce3fbdfe47cbb7f39ad02546fe7855b956b62f61d50c523a66a46c837b7a73                   0.0s
--> Build Summary:  (​)
--> Building image done
image: registry.fly.io/liquido-frontend-fly:deployment-01K76XWBJQFDY4T8C4PBCZEKNA
image size: 169 MB

Watch your deployment at https://fly.io/apps/liquido-frontend-fly/monitoring

-------
Updating existing machines in 'liquido-frontend-fly' with rolling strategy

WARNING The app is not listening on the expected address and will not be reachable by fly-proxy.
You can fix this by configuring your app to listen on the following addresses:
  - 0.0.0.0:8080d lease for 6e827210a70ee8
Found these processes inside the machine with open listening sockets:
  PROCESS        | ADDRESSES                             
-----------------*---------------------------------------
  /.fly/hallpass | [fdaa:1:b0e4:a7b:5a6:fffd:28ad:2]:22  


-------
 ✔ [1/2] Cleared lease for 4d894916a64238
 ✔ [2/2] Cleared lease for 6e827210a70ee8
-------
Checking DNS configuration for liquido-frontend-fly.fly.dev

Visit your newly deployed app at https://liquido-frontend-fly.fly.dev/

Something is going on inside the container. Why is my app not listening on port 8080? According to the server logs it should.

I can SSH into the container with fly ssh console. But that base image is so limited. It’s hard to debug anything in there. No ps, no lsof, no netstat. I also cant install these network debuggin tools.

https://liquido-frontend-fly.fly.dev/ does not load :frowning:

Questions

  • HTTPs outside (https://liquido-frontend-fly.fly.dev/) and the fly proxy forwards that without TLS/HTTPS to the internal port 8080 => is that correct?
  • How can I test more if my application is working correctly inside the container? Or on it? Can I call my app from another Fly container? Kinda internally intranet. Do rule out DNS issues.
  • Any configuration I missed?

Any further ideas?

Is your host config overriding the CLI arg? It looks like you’re running a dev server for production.

It’s taking 12s to start the server?

Ok, seems like this is really just a DNS issue. After waiting for an hour I now receive a very usefull error message when visiting my app:

Blocked request. This host ("liquido-frontend-fly.fly.dev") is not allowed.
To allow this host, add "liquido-frontend-fly.fly.dev" to `server.allowedHosts` in vite.config.js.

This is a vite feature, that it only allows requests from certain host names. But after adding allowedHosts: ["localhost", "127.0.0.1", ".fly.dev"], to my vite.config.js and doing a fly deploy it sadly still doesn’t work.

… seems like I have to wait again for DNS to resolve.

=> Does a fly deploy really re-deploy my container? Is there some kind of --force?
=> Do I need to check in my local changes to my config files first? Or does it use the local state of files when running fly deploylocally?

(About the 12secs: I am on a free XS super small machine. This is just a hobby project. Thanks so much to the Fly team for providing this free tier! :heart:)

This is a production build. vite serve would be the command to locally serve the build with hot reloading/HMR and all the fancy developer stuff. Running just vite --host 0.0.0.0 is the documented way of serving a VUE app in prod.

Is that correct? According to the docs: Command Line Interface | Vite

vite is a short alias for vite dev|serverwhich starts a development server. Starting a web server should not take 11s… most web servers start almost immediately.

My understanding is vite just builds the dist and you’re suppose to server it via some proxy, eg nginx.

Oh you’re right.
Now I get out of memory errors??? Although I already increased my fly machines to 1024MB RAM.

Ok I give up. I’ll try the other way round. I’ll start with a standard empty flye-vue-vite boilerplate and then build up from there.

Thank you very much for your support so far. I’ll keep this thread updated with what I learn.

The OOM error is most likely the dev server (they usually consume a ton for HMR.) A simple node web server on startup should only take 20MB, give or take. You should be fine w/ 256MB for something simple.

1 Like

And yet again you were absolutely right. Starting from scratch with a default VUE application npm create vue@latest and simply calling fly launch on this, creates a different Dockerfile:

[...]
# Final stage for app image
FROM nginx

# Copy built application
COPY --from=build /app/dist /usr/share/nginx/html

# Start the server by default, this can be overwritten at runtime
EXPOSE 80
CMD [ "/usr/sbin/nginx", "-g", "daemon off;" ]

And serving via nginx works like a charm.

1 Like

If anyone else stumbles upon this. I got it working.

HOWTO get VUE and vue-router to work on a fly.io machine.

vite.config.js

export default defineConfig({
	server: {
		host: true,  // listen on all adresses, incl. LAN and public adresses
		port: 8080,
		strictPort: true,   // only use this port. Exit if not available
		allowedHosts: ["localhost", "127.0.0.1", ".fly.dev"],
        },
        plugins: [
             vue(),
	],
})

Dockerfile

# syntax = docker/dockerfile:1

# Adjust NODE_VERSION as desired
ARG NODE_VERSION=22.14.0
FROM node:${NODE_VERSION}-slim AS base

LABEL fly_launch_runtime="Vite"

# Vite app lives here
WORKDIR /app

# Set production environment
ENV NODE_ENV="production"


# Throw-away build stage to reduce size of final image
FROM base AS build

# Install packages needed to build node modules
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3

# Install node modules
COPY package-lock.json package.json ./
RUN npm ci --include=dev

# Copy application code
COPY . .

# Build application
RUN npm run build

# Remove development dependencies
RUN npm prune --omit=dev

# Final stage for app image
FROM nginx:alpine

# Set the desired target directory for the built app
WORKDIR /app

# Copy built application
COPY --from=build /app/dist /app
# overwrite nginx /conf.d/default.conf for VUE webHistoryMode special configs
COPY ./nginx.conf /etc/nginx/conf.d/default.conf  

# Start the server by default, this can be overwritten at runtime
EXPOSE 80
CMD [ "/usr/sbin/nginx", "-g", "daemon off;" ]

nginx.conf

You need a special nginx conf for vue-router webHistoryMode() to work

# NGINX configuration for VUE SPA
# https://router.vuejs.org/guide/essentials/history-mode.html#nginx

# overwrite /etc/nginx/conf.d/default.conf  with this
server {
		listen 80;
		server_name _;

		root /app;
		index index.html;

		# Main SPA route handling for vue-router in webHistoryMode()
		# https://router.vuejs.org/guide/essentials/history-mode.html#nginx
		location / {
				try_files $uri $uri/ /index.html;
		}

		# Optional: Improve caching for static assets (e.g. built JS/CSS files)
		#location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|ttf|svg|mp4|webm)$ {
		#    expires 6M;
		#    access_log off;
		#    add_header Cache-Control "public";
		#}

		# Optional: Error pages
		#error_page 404 /index.html;
		error_page 500 502 503 504 /50x.html;

		location = /50x.html {
				root /app;
		}
}

# Hint do a  /usr/sbin/nginx -s reload  after editing this file

fly.tom

# fly.toml app configuration file generated for my-fly-app-dev on 2025-10-10T17:42:23+02:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = 'my-vue-frontend-spa'
primary_region = 'fra'

[build]

[http_service]
  internal_port = 80
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[vm]]
  memory = '512mb'
  cpu_kind = 'shared'
  cpus = 1
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.