Updated
—
4 min read
Here's my simple process for deploying a SvelteKit app to a server running Nginx.
I will also show you how to set up SSL, PM2, and a reverse proxy.
Install @sveltejs/adapter-node
for SvelteKit (learn more on SvelteKit adapters here):
npm i -D @sveltejs/adapter-node
Replace @sveltejs/adapter-auto
with @sveltejs/adapter-node
in your svelte.config.js
file:
javascript-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';
export default {
kit: {
adapter: adapter()
}
};
Install dotenv
:
npm i dotenv
According to SvelteKit documentation, in production .env files are not automatically loaded. So you'll need to run node
with the flag -r dotenv/config
to load environment variables.
Now is also a good time to set the port and host in your .env
file:
bashPORT=5173 # or whatever port you want for your reverse proxy
HOST=127.0.0.1
Build your app for production:
npm run build
Here's a basic Nginx server block for SvelteKit and handling ACME challenges for Certbot to auto-renew SSL certificates.
Create a basic server block without SSL and we'll add SSL later.
This server block just serves static files for ACME challenges and redirects HTTP to HTTPS.
bash# Redirect HTTP to HTTPS
# Serve static files for ACME challenges
server {
listen 80;
server_name example.com www.example.com;
location ~ /.well-known/acme-challenge {
root /var/www/certbot/example;
allow all;
}
location / {
return 301 https://example.com$request_uri;
}
}
Replace example.com
with your domain (that is pointed to your server's IP address with an A
record).
Test Nginx config: sudo nginx -t
If everything checks out, restart Nginx: sudo systemctl restart nginx
I've chosen to serve ACME challenges from /var/www/certbot
, where each domain has its own directory, e.g. /var/www/certbot/example
.
Create the directories:
cd /var/www
mkdir certbot
cd certbot
mkdir example # or whatever your domain is
Now that we have a server block and directory for Certbot, we can create the SSL certificate.
sudo certbot certonly --webroot -w /var/www/certbot/example -d example.com -d www.example.com
(Optional) If you want to auto-renew SSL certificates, you can create a cron job:
crontab -e
Then add this line to the bottom of the file:
17 3,15 * * * certbot renew --quiet --post-hook "systemctl restart nginx"
This runs the command certbot renew
twice a day at 3:17 AM and 3:17 PM. It's a best practice to renew certificates at a random time of the day (rather than midnight) to avoid overloading the Let's Encrypt servers.
The --post-hook
flag restarts Nginx after the certificate is renewed.
Now you can update your server block to include SSL:
bash# Redirect HTTP to HTTPS
# Serve static files for ACME challenges
server {
# What we had before...
}
# Configuration for HTTPS
# Reverse proxy for SvelteKit
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5174/; # Make sure the port matches your .env file
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
}
# if ($http_host != "example.com") {
# return 444;
# }
}
# Redirect www to non-www
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
return 301 https://example.com$request_uri;
}
Create a symbolic link: sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled
Then test your Nginx config: sudo nginx -t
If everything checks out, restart Nginx again: sudo systemctl restart nginx
Navigate back to your SvelteKit app directory.
Install PM2 if you haven't already: npm i -g pm2
Then run your app with PM2:
pm2 start node --name "process_name" -- -r dotenv/config build
Replace process_name
with whatever you want to call your process, e.g. svelte_client
.
The flags -r dotenv/config
loads your .env
file.
Lastly, save your PM2 config: pm2 save
.
Your SvelteKit app should now be running and accessible from your domain.
This is a very basic setup, but it should be enough to get you started.
Some next steps may be setting up a firewall, configuring a CDN, or connecting your database.
Meet the Author
Ryan Chiang
Hello, I'm Ryan. I build things and write about them. This is my blog of my learnings, tutorials, and whatever else I feel like writing about.
See what I'm building →.
Thanks for reading! If you want a heads up when I write a new blog post, you can subscribe below: