# How to do remote development for a Laravel app using Vite

**URL:** <https://community.okteto.com/t/how-to-do-remote-development-for-a-laravel-app-using-vite/1257>\
**Category:** How Do I?\
**Created:** [April 23, 2024, 2:05am UTC](https://community.okteto.com/t/how-to-do-remote-development-for-a-laravel-app-using-vite/1257 "2024-04-23T02:05:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmccorma](https://sea1.discourse-cdn.com/flex019/user_avatar/community.okteto.com/dmccorma/32/133_2.png) [@dmccorma](https://community.okteto.com/u/dmccorma)\
**Post date:** [April 23, 2024, 2:05am UTC](https://community.okteto.com/t/how-to-do-remote-development-for-a-laravel-app-using-vite/1257/1 "2024-04-23T02:05:18Z")

</div>

I’m successfully using Okteto for my legacy vanilla PHP app. We’re working on reimplementing our app from scratch in Laravel, and I’m trying to figure out the best way to develop it in Okteto. The issue I’m running into is how to set up and run the web server/frontend.

In my production web server container, I’d like to avoid having `npm` installed, so my `Dockerfile` is running `npm build` in order to compile the static files, and then copying them into the container:

```auto
FROM node:21 as frontend

ARG APP_PATH
ARG DEV_ENVIRONMENT

COPY --from=composer_base "$APP_PATH" "$APP_PATH"

WORKDIR "$APP_PATH"

RUN npm install && \
    npm run build

###############################

FROM nginx:1.25-alpine as web_server

ARG APP_PATH
ARG DEV_ENVIRONMENT

ENV APP_PATH="$APP_PATH"

WORKDIR "$APP_PATH"

COPY docker/web_server/nginx.conf.template /etc/nginx/templates/default.conf.template

COPY --from=frontend "${APP_PATH}/public" "${APP_PATH}/public"

```

This way, in production, the intention is to just run the `web_server` image, which will serve the statically compiled assets.

For local development, my `docker-compose.yml` file runs both the `web_server` image and also the `frontend` image with an overridden command, to run `npm run dev` and run the `vite` dev server for hot module reloading:

```auto
# ...
  xiam.web:
    build:
      context: .
      target: web_server
      args:
        DEV_ENVIRONMENT: true
    image: xiam/web_server:develop
    container_name: xiam-web
    ports:
      - '${APP_PORT:-80}:80'
    environment:
      FPM_HOST: "xiam-fpm:9000"
    volumes:
      - './public:/app/public'
    networks:
      - xiam
    depends_on:
      - xiam.fpm
      - xiam.frontend

  xiam.frontend:
    build:
      context: .
      target: frontend
      args:
        DEV_ENVIRONMENT: true
    image: xiam/frontend:develop
    container_name: xiam-frontend
    command: ["npm", "run", "dev"]
    ports:
      - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
    volumes:
      - '.:/app'
      - '/app/node_modules/'
    networks:
      - xiam

# ...

```

Both of these are working. However, now I’m trying to build my Okteto manifest to get remote development working in my self-hosted Okteto cluster, and I’m not sure how to achieve the same thing as I’m doing locally in `docker compose`.

I was hoping for some insight from you guys, since Laravel and Vite are also pretty new for me, so I’m not clear on how this should be configured. It looks like Vite detects that there is a dev server running by looking for a file named `hot` in the public directory on the web server container. My first thought was to add a second container to the `web_server` Deployment to run the `frontend` image with the `npm run dev` command. If I could sync both containers back to my local machine, the `hot` file should be synced into the `web_server` container. But based on an earlier discussion thread I found, it looks like Okteto doesn’t support running `okteto up` to multiple containers in the single pod, so that doesn’t seem like a workable solution.

I have some other ideas about other possible approaches, but I was curious if someone with more Laravel/Vite experience might be able to offer some insight. Thanks!

---

<div class="post-metadata">

**Author:** ![dmccorma](https://sea1.discourse-cdn.com/flex019/user_avatar/community.okteto.com/dmccorma/32/133_2.png) [@dmccorma](https://community.okteto.com/u/dmccorma)\
**Post date:** [April 26, 2024, 4:40pm UTC](https://community.okteto.com/t/how-to-do-remote-development-for-a-laravel-app-using-vite/1257/2 "2024-04-26T16:40:01Z")

</div>

I thought I’d come back and share what I was able to get working. I moved the `frontend` container (for running `npm run dev`) to its own, separate deployment in my Helm chart, along with the existing `fpm-server` (for `php-fpm`) and `web-server` (for `nginx`) deployments.

I then set up each of the three deployments as separate sections in the `dev` section of my Okteto manifest:

```auto
dev:
  xiam-fpm-server:
    command: ["php-fpm"]
    reverse:
      - 9003:9003
    sync:
      - ".:/app"
    securityContext:
      runAsUser: 82
      runAsGroup: 82
      fsGroup: 82

  xiam-frontend:
    command: ["npm", "run", "dev"]
    forward:
      - 5173:5173
    sync:
      - ".:/app"

  xiam-web-server:
    command: ["nginx", "-g", "daemon off;"]
    sync:
      - "public:/app/public"
    securityContext:
      runAsUser: 101
      runAsGroup: 101
      fsGroup: 101

```

This got me most of the way there. However, I was getting a mixed-content error, since Okteto serves my site via HTTPS, but the Vite websocket was using plain HTTP via localhost.

This was tricky. I tried setting up a second service and ingress in order to serve the Vite websocket via Okteto’s NGINX proxy, but I wasn’t able to get that working. I was adding the appropriate annotations to my Ingress in order to configure Nginx to support websockets, but it still wasn’t working. I suspect it’s because recent versions of Okteto actually have two nested Nginx proxies, and I probably wasn’t being able to configure both. This wouldn’t have been a great solution anyway, because as far as I’m aware, there isn’t any way for Vite to receive its configuration via environment variables, so I would have had to hardcode my Okteto URL in the Vite config file, which would mean it wouldn’t be usable by multiple developers or even multiple namespaces.

Vite can be configured to serve the websocket using HTTPS directly, but then it has to be configured with the TLS certificate and key files, and, again, hardcoding the configuration.

Fortunately, after hours of research and experimentation, I managed to find a solution that seems to meet my needs. There is a free service called [https://backloop.dev/](https://backloop.dev/) which is designed specifically for this purpose. Any subdomains of \*.backloop.dev resolve to `127.0.0.1`, and they maintain letsencrypt certificates for the wildcard domain so they will be trusted by your browser. They provide an accompanying NPM package to automatically configure the certificates in Vite. So, here is the relevant section of my `vite.config.js` file:

```auto
import backloopHttpsOptions from 'backloop.dev';

export default defineConfig(
	{
		server: {
			https: backloopHttpsOptions,

			hmr: {
				host: 'xiam.backloop.dev'
			},
		},
	});

```

With this configuration, I’m able to open up three terminals, run `okteto up xiam-fpm-server`, `okteto up xiam-web-server`, and `okteto up xiam-frontend`, and get a working development environment with syncing and hot reloading.

In the future I’d like to get the `web-server` and `frontend` components incorporated as `services` under the primary `fpm-server` service, but this wasn’t working for me yet. When I tried to run `okteto up` in that configuration, the dev container failed to come up, with the error, `can't create '/var/okteto/remote/authorized_keys': File exists`. I suspect this is due to the fact that each of my three containers runs as a different user, so there may be a permissions issue with the `persistentVolume` shared by all three development pods. For now, I’m happy to have it working, but I’ll keep pecking away at the combined approach.

---

<div class="post-metadata">

**Author:** ![ramiro](https://sea1.discourse-cdn.com/flex019/user_avatar/community.okteto.com/ramiro/32/6_2.png) [@ramiro](https://community.okteto.com/u/ramiro)\
**Post date:** [April 26, 2024, 5:56pm UTC](https://community.okteto.com/t/how-to-do-remote-development-for-a-laravel-app-using-vite/1257/3 "2024-04-26T17:56:15Z")

</div>

Thanks for contributing your solution @dmccorma! I will try to play with it this weekend and see if I can find some extra optimizations (caveat: I’m a Vite n00b).

---

<div class="post-metadata">

**Author:** ![dmccorma](https://sea1.discourse-cdn.com/flex019/user_avatar/community.okteto.com/dmccorma/32/133_2.png) [@dmccorma](https://community.okteto.com/u/dmccorma)\
**Post date:** [April 26, 2024, 6:19pm UTC](https://community.okteto.com/t/how-to-do-remote-development-for-a-laravel-app-using-vite/1257/4 "2024-04-26T18:19:45Z")

</div>

That’d be great, I’m interested to hear what you find. I am new to Vite as well, which has made this process much more difficult – I’m fumbling around trying to make one unfamiliar piece of software work in another unfamiliar piece of software. At least you’re well versed in Okteto, so at least there’s only one unknown for you 🙂

For my part, I’m working on reworking all of my containers to run under a common userid, to hopefully sidestep any issues Okteto has with services running as different userid’s. By default, Nginx runs under the `nginx` user, which is userid 101 in the `nginx:1.25-alpine` image I’m using as a base, whereas `php-fpm` runs under `www-data`, which is `82` in the `php:8.3-fpm-alpine` image I’m using. I’m experimenting with creating a new user in each one, with a known userid, so that they will all work predictably, even when sharing a common persistent volume.
