Deploy a sveltekit application on virtualmin virtual server using apache

OS type and version AlmaLinux 8.8
Webmin version 2.101
Usermin version 2.001
Virtualmin version 7.7 Pro
Theme version 21.04
Package updates All installed packages are up to date

For the benefit of the community and my future self I am going to document one approach I have succesfully used for deploying a sveltekit (nodejs) application on virtualmin pro using the nodejs script installer as the starting point.

Sveltekit environment / dependencies

I will assume you know how to install all this stuff locally in your dev environment and will also assume you can successfully run a local build process before deploying to your production server.

Production server deployment steps

Step 1 - Install node.js from the available install scripts in your virtual server

  • At the time of writing that is node.js v. 20.6.0
  • I chose the default install config which installs the binaries to public_html/nodejs

Step 2 - Copy source files to server (for production build)

You could optionally simply copy all your build files from your development machine to server. Due to some weird differences between environments I prefer to copy the source files to server and run build there and later remove the source files.

Directories to copy to public_html

  • prisma
  • src
  • static

Omit the prisma schema directory if not using Prisma

Files to copy to public_html

  • .env
  • package.json
  • package-lock.json
  • svelte.config.js
  • vite.config.js

Step 3 - Install dependencies

npm install
npx prisma generate

Step 4 - Build your application

npm run build

Step 5 - Update the host and port of the build/index.js startup script

Update the build/index.js file host and port to match node.js service created by virtualmin script install. Could not currently find an environmental variable to auto handle this at build time. Svelte defaults this to

const host = env('HOST', '');
const port = env('PORT', !path && '3000');

Change it to the port of the service created by the virtualmin Node.js script install


const host = env('HOST', '');
const port = env('PORT', !path && '3001');

Step 6 - Create an application startup script for the node.js server

This could possibly be handled directly in the systemd service created by the install script but I chose to create a separate startup shell script.

Create a file at the path /home/your-virtual-server-path/public_html/nodejs/ with the following contents.

#! /bin/bash
source ${HOME}/.bashrc

cd /home/your-virtual-server-path/public_html/nodejs
export NODE_ENV=production
ORIGIN= node /home/your-virtual-server-path/public_html/build/index.js

Some additional notes on this startup script. The ORIGIN section takes care of the Cross-site POST form submissions are forbidden issue noted here Node servers • Docs • SvelteKit

Setting your startup script to include an origin will solve this issue for your public domain and a form posts error as noted above.

Step 7 - Modify node.js server systemd service to use the startup script created above



  • Click the Service name from the Manage script screen in Virtualmin Pro
  • Update the ExecStart line


ExecStart=/bin/bash /home/your-virtual-server-path/public_html/nodejs/

Step 8 - Modify the Apache directives - startup script does not like the script installed defaults


<Proxy balancer://mongrel3001>
BalancerMember http://localhost:3001
ProxyPass /nodejs balancer://mongrel3001


ProxyPass /
ProxyPassReverse /

click apply changes on both Website and Website SSL apache config after making the changes.

1 Like

Could you elaborate?

My environment is nginx and have a svelte site which is not behaving (or rather it is probably me not quite understanding what is required) no problem running nodejs + express sites (none of which use Prisma)

Usually stuff like running Node 18 in development and 20 on the server or visa versa which can cause dependency install issues.

If you are running into issues you could also try installing node yourself minus the install script and using a manager like pm2. I have done this on another server with a Next.js app, this has pros and cons over using the install script. I try to do as much as possible using the Virtualmin modules/scripts as it makes restoring much simpler and reliable. The virtualmin script creating the service and port for you as well as dealing with the installing node + npm and setting the environment paths all siloed in the current user I think is wonderful.

Thanks for the answer.

I have no problem installing NodeJS and running it under pm2 and always do this outside Virtualmin (especially as Nodejs install is not available as a script) that is easy. I also often have more than one Node version available.

I was specifically interested in the “weird differences in environments” thinking it might be specific to Svelte

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