Skip to content

Instantly share code, notes, and snippets.

@florianguigue
Last active October 28, 2025 16:49
Show Gist options
  • Select an option

  • Save florianguigue/13869fc17053d17a0f9dc3f2ade0a995 to your computer and use it in GitHub Desktop.

Select an option

Save florianguigue/13869fc17053d17a0f9dc3f2ade0a995 to your computer and use it in GitHub Desktop.
Deploy Nuxt 3 App on O2Switch

Deploy Nuxt 3 App on O2Switch

This gist will explain how to easily deploy a Nuxt application on O2Switch host. But if you are trying to deploy on another host which is also using CPanel, then you might be interested in this gist aswell.

Prerequisites

Build your nuxt application

In your package.json of your app, you must have this script:

"scripts": {
    "build": "nuxt build",
    ...
  },

If not, add it then simply run this command to build your Nuxt application:

yarn build or npm run build

This will generate the .output folder containing your application. The content of this folder is what we will put on the server.

Put your files on the server

On CPanel, click on the Files > File Manager link, it will redirect you on another web app from which you'll be able to upload files. Otherwise you can also access this location using a FTP Client like Filezilla. I find this last option easier but both works.

If you decide to use a FTP Client, you'll find the server URL by clicking on Files > FTP Accounts.

File Manager

Now that you're on the server, put the content of the .ouput folder previously generated in a new folder. You can name it as you want, just make sure to keep the path because it will be needed later when we'll be configuring the Node.JS server.

If you did everything corretly, you should now have something like this:

App folder

Create an app loader

One subtility of CPanel and how it works behind when you try to launch a Node server, is that you can't launch ESM JS files. This is quite an issue because you'll probably working with ES modules instead of CommonJS modules.

But don't worry, there is a way to fix this.

The solution is to create an app loader in CommonJS, which will be the new entry point of your application.

Start by creating a new file, we'll name it loader.cjs. The extension .cjs is important if you have specified "type": "module" in your package.json.

async function loadApp() {
  await import("./server/index.mjs");
}

loadApp();

The only thing that this script will do is importing the file that you wanted as your entrypoint, but since it's a CommonJS file, it won't cause any trouble while starting the server.

Now put the file at the root of your app folder, alongside server and public folder on your server file manager. To illustrate, if your nuxt project is in the folder my-app/nuxtApp/, then the file will have the path /home/<YOUR_USERNAME>/my-app/nuxtApp/loader.cjs.

Setup the Node.JS App

On CPanel, click on Software > Setup Node.JS App

Software section

You'll find there the list of all your NodeJS application, if this is your first one, the list is empty. Click on Create Application.

Configure the applciation like this:

  • Node.js version: Select the NodeJs version you used during you development
  • Application mode: Production
  • Application root: Set the path where you put your files on the server
  • Application URL: Select in the dropdown list the domain or sub-domain on which you want the application to be setup
  • Applciation startup file: Choose the app loader file previously created (i.e: loader.cjs)
  • Passenger log file: You can setup a log file if you want. It is totally optional but I suggest you to do it. It's always easier to debug with a log file.

NodeJS Application

When you finished configuring the application, click on Create. The NodeJS server will now start and you application should be available at the address chosen in Application URL.

Thanks for reading and I hope it was useful.

@felixdenoix
Copy link

Thanks a lot for the gist !
Maybe you could add the path for the loader.cjs file for future readers ?

@florianguigue
Copy link
Author

Thanks a lot for the gist ! Maybe you could add the path for the loader.cjs file for future readers ?

You're welcome, happy that it was useful. Regarding your question, I've already mentionned in the Create an app loader section that the file must be put at the root of your folder application. I've added a path exemple like you suggested.

@felixdenoix
Copy link

I guess I've read the gist a bit too quick then ! Thanks nonetheless :)

@mmakria
Copy link

mmakria commented Aug 26, 2025

Salut Florian, merci pour ta contribution. Peux-tu m’expliquer comment tu gères les actions futures avec Git sachant que tu génères l’output en local ? Est ce possible de passer par git clone avec o2switch ?

@florianguigue
Copy link
Author

Salut Florian, merci pour ta contribution. Peux-tu m’expliquer comment tu gères les actions futures avec Git sachant que tu génères l’output en local ? Est ce possible de passer par git clone avec o2switch ?

Salut, je n'utilises plus O2Switch depuis un moment donc je pourrais pas te répondre précisement, mais de mémoire j'avais une Github Actions qui faisait un build de l'application puis qui faisait un transfert FTP sur le serveur o2Switch. Je te met en dessous un exemple du script Github Actions que j'avais mis en place, qui s'éxécutait à chaque push sur la branche master

Ceci dit, comme o2switch propose une fonctionnalité Git Version Control, il est peut être possible de passer par un git clone mais je n'ai pas expérimenté la feature

on:
  push:
    branches: [master]
name: Deploy website
jobs:
  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
      - name: Get latest code
        uses: actions/checkout@v3

      - name: Use Node.js 16
        uses: actions/setup-node@v2
        with:
          node-version: '16'
        
      - name: Build Nuxt
        run: |
          npm install
          npm run build

      - name: Sync files
        uses: SamKirkland/FTP-Deploy-Action@4.3.3
        with:
          server: ${{ secrets.SERVER }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          local-dir: .output/
          server-dir: ./

#  cloudlinux-selector start --json --interpreter nodejs --user [USERNAME] --app-root /home/[USERNAME]/nuxtapp
#  cloudlinux-selector stop --json --interpreter nodejs --user [USERNAME] --app-root /home/[USERNAME]/nuxtapp

@mmakria
Copy link

mmakria commented Aug 27, 2025

Hey Merci beaucoup pour ton retour !

@cappolaris
Copy link

À title de curiosité, tu utilise quoi maintenant à la place de o2switch ?

@florianguigue
Copy link
Author

À title de curiosité, tu utilise quoi maintenant à la place de o2switch ?

Je loue un VPS chez Hostinger et je m'occupe de faire le déploiement moi-même sans passer par des solutions comme cPanel chez o2Switch. Principalement pour plus de flexibilité.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment