I was working on a SvelteKit application with a SQLite database and Drizzle ORM setup. The runtime used was Bun. In development, there wasn’t much hiccups, but while moving to production, I faced a few problems.
- using
bun:sqlite
, TypeErrors and other stuff! - building the production build
git clone
private repository
While trying to setup bun:sqlite
database, the IDE shows TypeError. For that we need to install bun-types
package and also append "types": ["bun-types"]
to the tsconfig.json
. While initializing the database with the SQLite database file name, make sure the file exists in the root of the project folder. Setting up drizzle was easy-peasy, though for separate file based schemas in a dedicated /schema
folder, we need to have an index.ts
inside that folder and for every new schema, we need to register it inside index.ts
. For example, if we have a new schema named users.ts
, we need to register it as export * from './users'
so that we can import in the client.ts
where we initialize the SQLite database for use in the application.
The files, for drizzle setup looks like —
The run scripts for drizzle are —
To test the setup, I added a few entries to the users
table using drizzle studio. To test the database setup I loaded the users
in +layout.server.ts
as —
So far, all okay. Now, moving to deploying this to DigitalOcean Droplet, we need to spin up a new droplet using the DigitalOcean dashboard. We also need to add a SSH key so that we can connect it from our PC Terminal. To generate an SSH key, go to the terminal and run ssh-keygen
and answer to the prompts given. The public key will be stored in ~/.ssh/id_rsa_something.pub
, cat
the file and put the contents in the form provided by DigitalOcean to add a new SSH key. After that the droplet will spin up. Copy the droplet IP address and ssh into the instance from the terminal by running ssh root@ip_address
. It should login to the droplet instance.
For production build, we need to change the adapter
in svelte.config.js
file and replace @sveltejs/adapter-auto
with svelte-adapter-bun
. After that if we run bun run build
, we’ll get an error [vite]: Rollup failed to resolve import “bun:sqlite”. This is because when we run bun run build
it runs as a node
runtime. But we’re using bun:sqlite
. So, we need to explicitly declare it and run the build as bun --bun run vite build
. This will generate a build
folder inside the project folder. To test if the build and database integration ran well, we can test the build by running bun ./build/index.js
.
Moving to deployment, I’d put the code in a private GitHub repository. So, when I git clone
d into the repository using https, I got https clone deprecation error. Because, GitHub now supports only secured SSH connections for private repositories, so I created an SSH key in my droplet, copied the public key and added it to public SSH keys in GitHub as signature verification. To test if our connection is established, we can run ssh -T git@github.com
, which on being successful will show that we’re logged in successfully as so-and-so-username. After that we can git clone ssh_repo_link
and get the project inside the droplet.
cd
ing to the project and making the necessary installs and setups (.env addition), running the build and starting the server will run the production build at port 3000 which we can see by going to the link http://droplet_ip:3000
. However, we need the server to run even if the the terminal is closed. So, we need to install pm2
for this. But, pm2
supports node by default. So, bun:sqlite
won’t run and it’ll throw error. For this, we need to run pm2 start --interpreter ~/.bun/bin/bun ./build/index.js
which will start the server and keep it running on port 3000 even if we close our terminal.
However, we should be able to go to http://droplet_ip
and see our application, without mentioning the port 3000. For this, Nginx reverse proxying comes to the rescue. Basically, when we go to a website link, the default port is 80. So, proxying our server port 3000 to 80 will let us view the application in the default link. So, we need to install and setup Nginx as —
Next we need to edit the app_name.config
file as —
Next run —
Next we need to enable firewall so that not all ports are available for outside traffic. For this we need to run ufw enable
and to support traffic for port 80, we need to add it to ufw app list
as ufw allow 'Nginx Full'
. Also, we need to run ufw allow ssh
or else we won’t be able to ssh again into the instance once we logout. Finally, we need to run service nginx restart
and then if we check http://droplet_ip
, we can see our application.
That’s it.