<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matt Day</title>
    <description>The latest articles on DEV Community by Matt Day (@emdienn).</description>
    <link>https://dev.to/emdienn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F184405%2F32a63f91-d965-4949-a30c-3ad27a98c71c.png</url>
      <title>DEV Community: Matt Day</title>
      <link>https://dev.to/emdienn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emdienn"/>
    <language>en</language>
    <item>
      <title>Deploy SvelteKit on Dokku in 8 Sort-of Easy Steps</title>
      <dc:creator>Matt Day</dc:creator>
      <pubDate>Wed, 22 Sep 2021 11:33:38 +0000</pubDate>
      <link>https://dev.to/emdienn/deploy-sveltekit-on-dokku-in-8-sort-of-easy-steps-28g2</link>
      <guid>https://dev.to/emdienn/deploy-sveltekit-on-dokku-in-8-sort-of-easy-steps-28g2</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclaimer: I'm not being sponsored by anyone to write this, I'm just a really big fan of the tech in this stack&lt;/em&gt; ❤️&lt;/p&gt;

&lt;p&gt;Have you ever wanted—or needed—to host a webapp, but for one reason or another couldn't use the serverless offerings of Netlify, Vercel, Heroku, Deta et al? Those platforms are undoubtedly awesome, but on occasion, they just don't quite fit the bill.&lt;/p&gt;

&lt;p&gt;Maybe it's because you can't deploy in your region and need to. Maybe the infrastructure your app needs is prohibitively expensive on a serverless stack. Maybe it's because of DBaaS co-location issues, or strict data compliance constraints. (side note, &lt;a href="https://vercel.com"&gt;Vercel&lt;/a&gt; + &lt;a href="https://planetscale.com"&gt;PlanetScale&lt;/a&gt; or &lt;a href="https://supabase.com"&gt;Supabase&lt;/a&gt; = &lt;em&gt;chef kiss&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Whatever your reasons, you find yourself in a situation where you need to explore self-hosting as an option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter &lt;a href="https://dokku.com/"&gt;dokku&lt;/a&gt;.
&lt;/h2&gt;




&lt;blockquote&gt;
&lt;p&gt;"What the heck is dokku?? Like, &lt;a href="https://heroku.com"&gt;Heroku&lt;/a&gt; or something?" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short: yes. It is very much like Heroku. Except for the awesome fact that it's your &lt;strong&gt;very own DIY PaaS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spin up a VM, install Dokku, create your app, &lt;code&gt;git push&lt;/code&gt; your code and...it's done: your app is containerised, launched, stable, and ready to receive traffic, and you can install as many apps as your server can vertically scale for. (Of course, there's a &lt;em&gt;little&lt;/em&gt; more to it than that 😉)&lt;/p&gt;

&lt;p&gt;There are even plugins for Postgres, Redis, Let's Encrypt and more, which helpfully abstract away the provisioning of those services, but not to the exclusion of retaining control if you want 👍&lt;/p&gt;

&lt;p&gt;The real beauty of it, for me, is that each time I make code changes, deployment becomes literally as simple as a &lt;code&gt;git push&lt;/code&gt; and dokku will provision the new container and hot-swap the new version of the app with zero downtime.&lt;/p&gt;

&lt;p&gt;So all the preamble said and done, if you're still with me, here are the 8(ish) sort-of easy steps to follow for a pain-free installation of SvelteKit on dokku.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we're going to do
&lt;/h2&gt;

&lt;p&gt;We're going to deploy dokku onto a VM, and provision the SvelteKit demo app onto it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You'll need a private cloud VM with SSH access. There are so many options; two very popular ones are &lt;a href="https://digitalocean.com"&gt;Digital Ocean&lt;/a&gt; and &lt;a href="https://vultr.com"&gt;Vultr&lt;/a&gt;.
Whatever box you choose, just make sure it's rocking Ubuntu 20.04, and it has at least 1GB RAM.&lt;/li&gt;
&lt;li&gt;You'll need a domain, and a DNS provider who lets you actually modify your records. Personally, I use &lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt; for my DNS management.&lt;/li&gt;
&lt;li&gt;You need to be mostly unafraid of the linux commandline - dokku has no UI 😉&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready?&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Provision your VM
&lt;/h2&gt;

&lt;p&gt;Spin up your server and take note of the public IP address; we'll need that for step 2.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm going to use &lt;code&gt;10.11.12.13&lt;/code&gt; in the examples&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Set up your DNS records
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I'm going to use &lt;code&gt;example.io&lt;/code&gt; for illustrative purposes: substitute your domain and IP as appropriate, and we do this step first because it takes a hot second for the records to propagate/cache.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In your DNS manager, create a wildcard A record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  A   *.example.io  10.11.12.13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This points all subdomain traffic to our dokku server.&lt;/p&gt;

&lt;p&gt;Additionally, if you want to also point the root of your domain to the same server (which you totally can), create a root A record as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  A   example.io  10.11.12.13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: SSH into your VM
&lt;/h2&gt;

&lt;p&gt;Let's get installing! We've got 2 packages we need to install: dokku and &lt;a href="https://buildpacks.io/docs/tools/pack/"&gt;pack&lt;/a&gt;. Pack is what dokku uses to convert your awesome app code into a container.&lt;/p&gt;

&lt;p&gt;First up, go sudo if you aren't already.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install pack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;add-apt-repository ppa:cncf-buildpacks/pack-cli
apt-get update
apt-get &lt;span class="nb"&gt;install &lt;/span&gt;pack-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now install dokku - at time of writing, v0.25.4 is the most recent stable version, but &lt;a href="https://dokku.com/docs/getting-started/installation/#1-install-dokku"&gt;check the docs&lt;/a&gt; for a more recent version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/dokku/dokku/v0.25.4/bootstrap.sh
&lt;span class="nv"&gt;DOKKU_TAG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v0.25.4 bash bootstrap.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will take a few minutes, be patient. Grab a coffee or do some squats or something.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Configure global configurables
&lt;/h2&gt;

&lt;p&gt;First point of order is your root domain, which is easily set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku domains:set-global example.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we nudge dokku to use &lt;code&gt;main&lt;/code&gt; as the default branch name rather than &lt;code&gt;master&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku git:set &lt;span class="nt"&gt;--global&lt;/span&gt; deploy-branch main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third is to configure the buildpack dokku will use to containerize your code. The awesome folks at &lt;a href="https://paketo.io"&gt;packeto.io&lt;/a&gt; have put together a buildback that takes care of this for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku buildpacks:set-property &lt;span class="nt"&gt;--global&lt;/span&gt; stack paketobuildpacks/builder:base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, access: ideally you want to not have to input a password every time you push from your repo, so if you've configured public-private keypair access, run this to give dokku access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/authorized_keys | dokku ssh-keys:add admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Install plugins
&lt;/h2&gt;

&lt;p&gt;There's one plugin we definitely want—Let's Encrypt, so let's install and configure that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
dokku config:set &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nv"&gt;DOKKU_LETSENCRYPT_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mywebmasterinbox@gmailorother.com
dokku letsencrypt:cron-job &lt;span class="nt"&gt;--add&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(The email address you put here doesn't have to be affiliated with your domain in any way, it just has to be an address that you own.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Whether you need to install other plugins depends on what your apps need (check out the &lt;a href="https://dokku.com/docs/community/plugins/#official-plugins"&gt;full list&lt;/a&gt;). For demonstration purposes, let's also install the Postgres plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku plugin:install https://github.com/dokku/dokku-postgres.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Prepare our app!
&lt;/h2&gt;

&lt;p&gt;Before we can push our code to our server, we need a spot into which to push it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku apps:create sveltekit-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Again, name it whatever you wish, this is just for demo purposes)&lt;/p&gt;

&lt;p&gt;Enable HTTPS via Let's Encrypt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku letsencrypt:enable sveltekit-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our demo app this next step is unnecessary, but it illustrates how to provision a postgres database, then link it to our app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dokku postgres:create sveltekit-demo-pg
dokku postgres:link sveltekit-demo-pg sveltekit-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How easy is that! You'll see in the output, an ENV variable for the database URL has been generated - you can now references that variable in your code, and it will be hooked up in production 👍&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Prepare to Deploy
&lt;/h2&gt;

&lt;p&gt;There are a couple of dokku-specific things we need to do to our codebase in your local machine, before we push it.&lt;/p&gt;

&lt;p&gt;If you haven't already cloned the svelte demo, let's do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init svelte@next sveltekit-demo
&lt;span class="c"&gt;# choose Demo, not Skeleton&lt;/span&gt;
&lt;span class="c"&gt;# select the other options as you wish&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;sveltekit-demo
git init
git remote add dokku dokku@example.io:sveltekit-demo
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;code&gt;@sveltejs/adapter-node&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @sveltejs/adapter-node@next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify &lt;code&gt;svelte.config.js&lt;/code&gt; to use the node adapter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; import preprocess from 'svelte-preprocess';
&lt;span class="gi"&gt;+import adapter from '@sveltejs/adapter-node';
&lt;/span&gt;
 const config = {
   preprocess: preprocess(),
   kit: {
&lt;span class="gi"&gt;+    adapter: adapter({
+      out: 'build'
+    }),
&lt;/span&gt;     // hydrate the &amp;lt;div id="svelte"&amp;gt; element in src/app.html
     target: '#svelte'
   }
 };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify the build script in &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; // package.json
 {
   "scripts": {
&lt;span class="gd"&gt;-    "build": "svelte-kit build",
&lt;/span&gt;&lt;span class="gi"&gt;+    "build": "svelte-kit build &amp;amp;&amp;amp; ln -s -f build/index.js server.js",
&lt;/span&gt;   }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create this symlink because packeto expects there to be a launch script called &lt;code&gt;server.js&lt;/code&gt; in the project root. (There &lt;em&gt;is&lt;/em&gt; a config that's supposed to let you change it, but that didn't work for me—this does though!)&lt;/p&gt;

&lt;p&gt;Finally, create a file called &lt;code&gt;project.toml&lt;/code&gt; - this is how we provide pack environment variables and other info specific to the build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# project.toml&lt;/span&gt;
&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;exclude&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s"&gt;"README.md"&lt;/span&gt;
  &lt;span class="c"&gt;#, and/or another other files that are not relevant&lt;/span&gt;
  &lt;span class="c"&gt;# to the build&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[[build.env]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"BP_NODE_RUN_SCRIPTS"&lt;/span&gt;
&lt;span class="py"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"build"&lt;/span&gt;

&lt;span class="nn"&gt;[[build.env]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"NODE_ENV"&lt;/span&gt;
&lt;span class="py"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dev"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first environment variable, &lt;code&gt;BP_NODE_RUN_SCRIPTS&lt;/code&gt;, tells pack to run &lt;code&gt;npm run-script build&lt;/code&gt; after dependencies have been installed. You can run more than one command if you like, eg. &lt;code&gt;"lint,build"&lt;/code&gt; - this var accepts a comma-delimited list of commands to run.&lt;/p&gt;

&lt;p&gt;The second environment variable tells pack to set the build environment to "dev"—namely something other than "production". This is important, because without it, the dev dependencies don't get installed, which means the entire SvelteKit infrastructure is missing, which causes the build to fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Time to Push
&lt;/h2&gt;

&lt;p&gt;Here goes nothing! Commit all your changes and push.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Make dokku compatible"&lt;/span&gt;
git push dokku
&lt;span class="c"&gt;# if your trunk branch is called something other than main,&lt;/span&gt;
&lt;span class="c"&gt;# do this instead&lt;/span&gt;
git push dokku BRANCH_NAME:main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dokku will think for a moment, download the latest packer images from packeto, build your container, compile your svelte app, and launch it. 🚀 🎉 &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9 [BONUS]: Admire your work
&lt;/h2&gt;

&lt;p&gt;You should now be able to navigate to &lt;code&gt;https://sveltekit-demo.[YOUR DOMAIN]&lt;/code&gt; and see your handiwork!&lt;/p&gt;




&lt;h2&gt;
  
  
  Official Docs
&lt;/h2&gt;

&lt;p&gt;These are the ones I found helpful:&lt;/p&gt;

&lt;h3&gt;
  
  
  Dokku
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dokku.com/docs~v0.25.4/getting-started/installation/"&gt;Getting started with Dokku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dokku.com/docs~v0.25.4/deployment/application-deployment/"&gt;Deploying to Dokku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dokku.com/docs~v0.25.4/deployment/methods/git/"&gt;Git Deployment to Dokku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dokku.com/docs~v0.25.4/deployment/builders/cloud-native-buildpacks/"&gt;CloudNative Buildpacks on Dokku&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  BuildPacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://buildpacks.io/docs/app-developer-guide/using-project-descriptor/"&gt;Using Buildpack's project.toml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Packeto
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://paketo.io/docs/howto/nodejs/"&gt;Packeto Node.js Primer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://paketo.io/docs/reference/nodejs-reference/"&gt;Packeto Node.js Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;There are a few ways in which this process could be better (I only learned Dokku even existed yesterday lol), the most prominent of which is deployment directly from Github. Thankfully, Dokku have you covered &lt;a href="https://dokku.com/docs/deployment/continuous-integration/github-actions/"&gt;with a Github Action&lt;/a&gt; there, and there's a Gitlab option too 👍&lt;/p&gt;




&lt;p&gt;The process should be reasonably adaptable to a React/Vue/Angular app - hopefully it helps someone out landing their first self-hosted PaaS!!&lt;/p&gt;

&lt;p&gt;m@&lt;/p&gt;

</description>
      <category>dokku</category>
      <category>svelte</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
