0

I am trying to get a local ddev setup working with the stack:

  • Apache
  • PHP 8.1
  • Laravel 9
  • Vite
  • Soketi for WebSockets

I am confused on how to configure ports on ddev, and which host/port i should use on the frontend.

.ddev/config.yaml

name: laravel-vite-inertia
type: laravel
docroot: public
php_version: "8.1"
webserver_type: apache-fpm
router_http_port: "80"
router_https_port: "443"
xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
database:
  type: mysql
  version: "8.0"
nfs_mount_enabled: false
mutagen_enabled: false
use_dns_when_possible: true
composer_version: "2"
web_environment: []
nodejs_version: "16"

.ddev/docker-compose.vite.yaml

# Override the web container's standard HTTP_EXPOSE and HTTPS_EXPOSE services
# to expose port 3000 of DDEV's web container.
version: '3.6'
services:
  web:
    # ports are a list of exposed *container* ports
    ports:
      - "3000"
      - "6001:6001"
    environment:
      - HTTP_EXPOSE=${DDEV_ROUTER_HTTP_PORT}:80,${DDEV_MAILHOG_PORT}:8025,3001:3000
      - HTTPS_EXPOSE=${DDEV_ROUTER_HTTPS_PORT}:80,${DDEV_MAILHOG_HTTPS_PORT}:8025,3000:3000

/resources/js/app.js

import Echo from 'laravel-echo';
import pusher from 'pusher-js';
let laravelEcho = new Echo({
    broadcaster: 'pusher',
    key: 'app-key',
    wsHost: '127.0.0.1', // <- I assume this is the error?
    wsPort: 6001,
    wssPort: 6001,
    forceTLS: false,
    encrypted: true,
    disableStats: true,
    enabledTransports: ['ws', 'wss'],
});

laravelEcho.channel(`auctions`)
    .listen('AuctionIndexVisited', (e) => {
        console.log('AuctionIndexVisited', e);
    });

laravel .env

#...
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_APP_KEY="app-key"
PUSHER_APP_ID="app-id"
PUSHER_APP_SECRET="app-secret"

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_HOST="${PUSHER_HOST}"
MIX_PUSHER_PORT="${PUSHER_PORT}"

Laravel does broadcasts to soketi. enter image description here

The frontend is not able to connect to the websocket...

enter image description here

Alex
  • 171
  • 2
  • 9
  • I think you'll find that exposing port 3000 via the ddev-router is the same as in https://stackoverflow.com/a/62648435/215713 - see if that sorts it out for you. I assume you want `http://laravel-vite-inertia.ddev.site:3000` to work predictably, right? – rfay May 05 '22 at 16:01
  • Vite works perfectly (which is using Port 3000). My Problem is with the WebSocket and Soketi. – Alex May 05 '22 at 16:02
  • Looks like you have to do the exact same thing with 6001? But your wshost should probably be "0.0.0.0", so it binds to all interfaces? – rfay May 05 '22 at 17:55
  • I don't know about the specific issues you're exploring, but I'm happy to help you with a screenshare/call - the only requirement is that you be willing to write up your full results. You can find me on the DDEV discord, https://discord.gg/hCZFfAMc5k – rfay May 05 '22 at 21:39
  • @rfay thank you for your almost instant replies when it comes to ddev topics. Really appreciate it! It seems the configuration for Port 3000 works flawless. I switched Soketi from 6001 to 3000 and boom! I got my Websocket connection. Basically yes, i try to setup 2 specific ports which are (allowed?) into the web-container since both node processes (vite and soketi) run inside of `ddev ssh`. What I dont understand is why its 3001:3000 on HTTP and 3000:3000 on HTTPS? And Ports just "3000". Why 3001? – Alex May 06 '22 at 07:49
  • Holy sh!t.... I managed to get it to work! Turns out port 6000 is considered "unsafe" (because its usually used by X11). Switching to Port 9000 fixed it. – Alex May 06 '22 at 08:38
  • 1
    I'm glad you have it working. Now please write it all down in an answer for everybody else! – rfay May 06 '22 at 17:36
  • BTW, vite was recently discussed in the context of laravel in DDEV discord in #laravel, https://discord.gg/hCZFfAMc5k – rfay May 06 '22 at 17:42

1 Answers1

2

Fix: Do not use port 6000.

As it turns out, port 6000 is considered "unsafe" because its the the default port for X11.
So I switched to port 9000.

Vite -> Port 3000
Soketi -> Port 9000

My working setup:

.ddev/docker-compose.vite.yaml

# Override the web container's standard HTTP_EXPOSE and HTTPS_EXPOSE services
# to expose port 3000 of DDEV's web container.
version: '3.6'
services:
  web:
    # ports are a list of exposed *container* ports
    ports:
      - "3000"
      - "9000"
    environment:
      - HTTP_EXPOSE=${DDEV_ROUTER_HTTP_PORT}:80,${DDEV_MAILHOG_PORT}:8025,3001:3000,9001:9000
      - HTTPS_EXPOSE=${DDEV_ROUTER_HTTPS_PORT}:80,${DDEV_MAILHOG_HTTPS_PORT}:8025,3000:3000,9000:9000

vite.config.js

import path from "path";
import vue from '@vitejs/plugin-vue';
import vuetify from '@vuetify/vite-plugin';

export default ({command}) => ({
    base: command === 'serve' ? '' : '/dist/',
    publicDir: path.resolve(__dirname, 'resources/copy-to-public'),
    server: {
        host: '0.0.0.0',
        port: 3000,
    },
    plugins: [
        vue(),
        // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
        vuetify({
            autoImport: true,
        }),
    ],
    optimizeDeps: {
        include: [
            "@inertiajs/inertia",
            "@inertiajs/inertia-vue3",
            "axios",
            "vue",
        ],
    },
    build: {
        manifest: true,
        outDir: path.resolve(__dirname, 'public/dist'),
        rollupOptions: {
            input: '/resources/js/app.js',
        }
    },
    resolve: {
        alias: {
            '@': path.resolve(__dirname, 'resources/js'),
        },
        extensions: [
            '.js',
            '.json',
            '.jsx',
            '.mjs',
            '.ts',
            '.tsx',
            '.vue',
        ]
    },
});

Add localhost:3000 to sanctum config.

/config/sanctum.php

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
    Sanctum::currentApplicationUrlWithPort()
))),    

soketi.config.json
-> Caveat: run soketi not inside your root dir! It will read the laravel .env and not work as expected.

{
    "debug": true,
    "ip": "0.0.0.0",
    "address": "0.0.0.0",
    "host": "0.0.0.0",
    "port": 9000,
    "appManager.array.apps": [
        {
            "id": "app-id",
            "key": "app-key",
            "secret": "app-secret",
            "webhooks": [
            ]
        }
    ]
}

I am using soketi as pusher replacement. Part of my app.js:

import Echo from 'laravel-echo';
import pusher from 'pusher-js';
window.laravelEcho = new Echo({
    broadcaster: 'pusher',
    key: "app-key",
    wsHost: "mysite.ddev.site",
    wsPort: 9000,
    wssPort: 9000,
    forceTLS: false,
    encrypted: true,
    disableStats: true,
    enabledTransports: ['ws', 'wss'],
});

/resources/views/app.blade.php

<!doctype html>
<html>
<head>
    <title>Laravel, Vue, Inertia and Vite</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta charset="UTF-8" />
    @include('partials/favicon')
    <link rel="stylesheet" href="/dist/fonts/materialdesignicons.min.css" />
    @production
        @php
            $manifest = json_decode(file_get_contents(
                public_path('dist/manifest.json')
            ), JSON_OBJECT_AS_ARRAY);
        @endphp
        <script type="module" src="/dist/{{ $manifest['resources/js/app.js']['file'] }}"></script>
        <link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}" />
    @else
        <script type="module" src="{{ env('APP_URL') }}:3000/@vite/client"></script>
        <script type="module" src="{{ env('APP_URL') }}:3000/resources/js/app.js"></script>
    @endproduction

    <meta name="csrf-token" content="{{ csrf_token() }}">
    @routes
</head>
<body>
@inertia
</body>
</html>

.env

# Toggle between "production" and "local" for vite
# "production" == vite build
# "local" == vite dev
APP_ENV=local
APP_DEBUG=true

# ....
BROADCAST_DRIVER=pusher
# ....

# Pusher config
PUSHER_HOST=127.0.0.1
PUSHER_APP_HOST=127.0.0.1
PUSHER_PORT=9000
PUSHER_APP_KEY="app-key"
PUSHER_APP_ID="app-id"
PUSHER_APP_SECRET="app-secret"

for vite dev to work.

Part of my package.json

"scripts": {
    "dev": "vite serve",
    "soketi": "cd .. && soketi start --config=html/soketi-config.json",
    "prod": "vite build",
    "build": "vite build"
},    
Alex
  • 171
  • 2
  • 9