How to deploy a SvelteKit app with the node-adapter

Sean Schertell
5 min readDec 10, 2021


This is a guide to walk you through the whole process from building your SvelteKit app using the Node adapter, to getting a remote server setup to proxy through a web server and serving your through https with automatic redirect. This should work on MacOS or Linux (sorry, Windows users!).

1. Build your local app with node-adapter

From your local machine, we’ll need to install thenode-adapter and update SvelteKit’s config file to use it.

npm i -D @sveltejs/adapter-node@next

Now edit svelte.config.js .

Change this:import adapter from '@sveltejs/adapter-auto';
…to this: import adapter from '@sveltejs/adapter-node';

And this: adapter: adapter(),
…to this: adapter: adapter({ out: 'build' }),

With the node-adapter all set up, we’re ready to build.

npm run build

A new build/ directory should appear at the top level of your app. Make sure it works locally by running node build/index.js. (then CRL+C to quit).

2. Set up the server

I like Digital Ocean and Ubuntu. So I start by logging into my Digital Ocean account and spinning a new droplet with stock Ubuntu 20.04. Then log into the server as the root user. For the hostname, please choose a domain for which you control the DNS and are able to (later) add an A-record. We’ll use for this example.

3. Create a user for this app (allow password login)

Log into your new server as root add the user and home directory into which we’ll upload the app. For this example, the app is called “goodtimes”. So that’s what we’ll name the user.

adduser goodtimes
# ...set the password (and remember it)
# Then just hit return a few times to accept defaults

By default, password login is disabled. Let’s edit the ssh config to fix that.

nano /etc/ssh/sshd_config

Change this line: PasswordAuthentication no
…to: PasswordAuthentication yes

Then restart the ssh service.

service ssh restart

4. Upload your app

We’ve built the Node app locally and we’ve created a remote server with a new user a cozy new directory for our app to live in. So let’s upload the app.

First off, if you’ve never created ssh keys on your local machine, do so now:

ssh-keygen -t rsa -C "" # only if needed!

Once you have ssh keys installed, you can upload your public key to the server using ssh-copy-id.

ssh-copy-id goodtimes@111.222.333.444 # Use your server IP here

Enter the password for the ‘goodtimes’ user and now you will no longer need a password to login from this machine. This is also a requirement for using scp to upload our app.

Important! You must upload the package.json along with the build/ directory!

From your local machine at the top level of your app:

scp -r package.json build goodtimes@111.222.333.444:/home/goodtimes/

Confirm that the upload worked on the server with:
ls /home/goodtimes

5. Install Node / NPM on the server

Since Ubuntu doesn’t offer current apt versions of Node, we’ll use curl to install it from nodesource.

apt update
apt install curl -y
curl -sL | sudo -E bash -
apt install -y nodejs

6. Install dependencies and try running the app

With Node installed on the server and our app already uploaded, let’s see if this works. We’ll start by switching from root to our app user.

su goodtimes
cd ~
npm install
node build/index.js

If all goes well, you should see something like this:
Listening on

…and you should be able to see your site at your server’s IP address like this: http://111.222.333.444:3000

7. Install PM2

Rather than running our app with the Node runtime directly, we’ll use PM2 to manage our Node app with helpful features like restarting the app if it crashes. We’ll need to go back to being the root user for that. First, hit CTL+C to stop the Node process. Then…

exit # revert to root user
npm i -g pm2

8. Install Caddy

While we’re still logged in as root, let’s also install our web server. If you haven’t tried Caddy, you’re in for a treat. It’s a fantastic web server which auto-installs and manages LetsEncrypt SSL certificates and is an absolute joy to configure compared to Nginx or Apache. Since it isn’t available in the apt repository, just copy and paste the below commands (as root!) to install.

apt install -y debian-keyring debian-archive-keyring apt-transport-https && \
curl -1sLf '' | apt-key add - && \
curl -1sLf '' | tee -a /etc/apt/sources.list.d/caddy-stable.list && \
apt update && \
apt install caddy && \
touch /home/Caddyfile

9. Start the app with PM2

Now that we’ve got our Node process manager and our web server installed, let’s switch back to the app user level and start this thing up!

su goodtimes
cd ~
pm2 start build/index.js

You should again be able to see your deployed app running at:
http://111.222.333.444:3000 (but your IP address, of course)

10. Configure and start the web server

Assuming you have a domain name somewhere, log into your DNS control panel and add an A-record for your new app. For this example, we’ll use

As root, edit /home/Caddyfile to proxy all requests to our running node application.

exit # revert to root user
cd /home
nano Caddyfile

This file should be blank. Add the following. {
root * /home/goodtimes/build
reverse_proxy * localhost:3000

…and now while still inside the /home directory, start the web server:
caddy start

Note: If you get a warning about input not being formatted correctly, it’s harmless but can be easily cured with: caddy fmt --overwrite then caddy reload.

You should now be able to see your app running at (in our example), Notice that not only did it auto-install our SSL certs, it even automatically redirects from http to https routes.

Pro Tip: You can easily stop/start/reload caddy with caddy <command> but remember to always use that command from inside the /home directory.

Wanna come (remotely) write some Svelte code with us?

I run a development agency here in San Francisco called Codepilot. We build fully custom web and mobile applications to precise client specifications. Interested in joining us? Get in touch!



Sean Schertell

I love building teams around solving real-word challenges with custom web and mobile applications.