<?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>Forem: Dan Steren</title>
    <description>The latest articles on Forem by Dan Steren (@dansteren).</description>
    <link>https://forem.com/dansteren</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%2F288386%2F19d73b4d-1a4c-4afa-8ac6-3aaa03e961f3.png</url>
      <title>Forem: Dan Steren</title>
      <link>https://forem.com/dansteren</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dansteren"/>
    <language>en</language>
    <item>
      <title>Ubuntu 22.04 Hibernate Using Swap File</title>
      <dc:creator>Dan Steren</dc:creator>
      <pubDate>Mon, 25 Nov 2024 05:04:46 +0000</pubDate>
      <link>https://forem.com/dansteren/ubuntu-2204-hibernate-using-swap-file-1ca1</link>
      <guid>https://forem.com/dansteren/ubuntu-2204-hibernate-using-swap-file-1ca1</guid>
      <description>&lt;p&gt;If you're like me, you expect that in 2024 you can close the lid on your laptop and your computer won't be dead when you pick it up the next day. Unfortunately, that's not the case after a default install of Ubuntu. To get this behavior, you need to enable hibernation through a swap partition or file. I've always used a swap file, so this guide will be for a swap file, not a swap partition.&lt;/p&gt;

&lt;p&gt;Because I always forget how to set this up, I'm writing a canonical reference for myself and hopefully it helps you as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;Just follow &lt;a href="https://ubuntuhandbook.org/index.php/2021/08/enable-hibernate-ubuntu-21-10/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;. If it's confusing then come back here as I might have some helpful insight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The way hibernation basically works is that it takes a snapshot of your system and saves it to disk right before shutting down, and then restores your system from that snapshot when you start your computer up again. To do that you need a swap system. So, we need to set that up first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Swap Area
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Check swap setup
&lt;/h3&gt;

&lt;p&gt;Very first we need to see if we even have a swap area. You can check by running this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swapon &lt;span class="nt"&gt;--show&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My output was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME      TYPE SIZE USED PRIO
/swapfile file   2G   0B   -2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we are using a swapfile because it says "/swapfile", not something like "/dev/sdax partition" which would indicate a swap partition. So that's good, but 2GB isn't going to be large enough because it needs to be as big as your memory. So, we need resize the swapfile, or rather, delete the old one and make a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resize your Swapfile
&lt;/h3&gt;

&lt;p&gt;So to make a new swap file we first turn off swap for all processes (so we're not using it while we go through the process):&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;swapoff &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then remove the current swapfile:&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 rm&lt;/span&gt; /swapfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create a new swapfile that is the same size as our memory:&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 dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/swapfile &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1G &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My memory is currently 32 GB, but whatever it is you pass it to the &lt;code&gt;count&lt;/code&gt; flag.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: When looking at the guide in the ubuntu handbook they use a block size (bs) value of 1MiB. When I asked ChatGPT it said the difference only mattered when creating the swapfile and not afterwards. If you have a smaller/older system then using 1MB block size may be easier on your system. You'll just have to multiply your count by 1024 then. But for me the above worked fine so as long as it creates the swap file you're good.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You then need to adjust the permissions so that only the root user can use the swapfile:&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 chmod &lt;/span&gt;600 /swapfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make the file useable as swap:&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;mkswap /swapfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then activate it:&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;swapon /swapfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To ensure the swap file is activated on boot we need to have a line with this contents in the /etc/fstab file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/swapfile none swap sw 0 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should already be there though so check the file first. &lt;strong&gt;If it isn't there already&lt;/strong&gt; you can add it with this command:&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;echo&lt;/span&gt; &lt;span class="s1"&gt;'/swapfile none swap sw 0 0'&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/fstab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mine was already there so I just skipped this step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find the Physical Offset
&lt;/h2&gt;

&lt;p&gt;We then need to find the physical location of the swapfile. We can do so with the following command:&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;filefrag &lt;span class="nt"&gt;-v&lt;/span&gt; /swapfile | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{ if($1=="0:"){ print $4 } }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give a number like &lt;code&gt;226572288..&lt;/code&gt;, you don't want the final &lt;code&gt;..&lt;/code&gt; though, so you'll have to manually grab just the number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update the GRUB Configuration
&lt;/h2&gt;

&lt;p&gt;You'll add the resume and resume_offset parameters to your GRUB configuration to tell the system where to resume from when coming out of hibernation.&lt;/p&gt;

&lt;p&gt;You'll want to open the GRUB configuration file with an editor (vim, nano, vscode, etc.):&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;vim /etc/default/grub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then update that with a line referencing the output of blkid ("/dev/nvme0n1p2") and the physical offset we just found (226572288).&lt;/p&gt;

&lt;h2&gt;
  
  
  Suspend then Hibernate
&lt;/h2&gt;

&lt;p&gt;Ok, so the secret sauce to make it all come together is to use &lt;code&gt;suspend-then-hibernate&lt;/code&gt; rather than &lt;code&gt;suspend&lt;/code&gt;. You do this by editing &lt;code&gt;/etc/systemd/logind.conf&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;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/logind.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find the lines starting with &lt;code&gt;HandleLidSwitch&lt;/code&gt; and &lt;code&gt;HandleLidSwitchExternalPower&lt;/code&gt; in the file. If they don't exist, you can add them. Change or add these lines to specify suspend-then-hibernate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HandleLidSwitch=suspend-then-hibernate
HandleLidSwitchExternalPower=suspend-then-hibernate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to specify the delay before transitioning from suspend to hibernate. This is done by creating or editing a file in /etc/systemd/sleep.conf or overriding the default configuration by creating a file in /etc/systemd/sleep.conf.d/.&lt;/p&gt;

&lt;p&gt;For example, to set a 30-minute delay, create or edit /etc/systemd/sleep.conf:&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;nano /etc/systemd/sleep.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Sleep]
HibernateDelaySec=1800s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, all you should need to do is restart your computer to restart the systemd-logind service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Epilogue
&lt;/h2&gt;

&lt;p&gt;Someone should really automate this whole process. I may get to it one day. Ideally it would be checked into my .dotfiles so I can just have it setup automatically when I get a new linux box. This may be a fun project for you if you're feeling ambitious. I'd love to see what you come up with!&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ubuntuhandbook.org/index.php/2021/08/enable-hibernate-ubuntu-21-10/" rel="noopener noreferrer"&gt;https://ubuntuhandbook.org/index.php/2021/08/enable-hibernate-ubuntu-21-10/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/how-to-enable-hibernate-in-ubuntu-22-04-lts/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/how-to-enable-hibernate-in-ubuntu-22-04-lts/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ubuntu</category>
      <category>hibernate</category>
      <category>swap</category>
    </item>
    <item>
      <title>Adding Postgres to a Node app on DO's App Platform</title>
      <dc:creator>Dan Steren</dc:creator>
      <pubDate>Sun, 20 Dec 2020 07:20:49 +0000</pubDate>
      <link>https://forem.com/dansteren/adding-postgres-to-a-node-app-on-do-s-app-platform-2bjk</link>
      <guid>https://forem.com/dansteren/adding-postgres-to-a-node-app-on-do-s-app-platform-2bjk</guid>
      <description>&lt;p&gt;Source code available at &lt;a href="https://github.com/ardentink/adr-api" rel="noopener noreferrer"&gt;https://github.com/ardentink/adr-api&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Backstory
&lt;/h1&gt;

&lt;p&gt;I'm participating in &lt;a href="https://dev.to/devteam/announcing-the-digitalocean-app-platform-hackathon-on-dev-2i1k"&gt;Digital Ocean's App Platform (DOAP) Hackathon&lt;/a&gt; and am building a graphQL server using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;node&lt;/li&gt;
&lt;li&gt;postgres&lt;/li&gt;
&lt;li&gt;typescript&lt;/li&gt;
&lt;li&gt;graphql&lt;/li&gt;
&lt;li&gt;apollo-server&lt;/li&gt;
&lt;li&gt;type-graphql&lt;/li&gt;
&lt;li&gt;type-orm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my last two posts I mostly rambled 😬 but talked about getting a basic node server deployed on DOAP. However it was just the graphQL server without a database. Today I need to add a persistence layer. I'll be using &lt;a href="https://typeorm.io/" rel="noopener noreferrer"&gt;TypeORM&lt;/a&gt; and Postgres.&lt;/p&gt;

&lt;p&gt;I created a &lt;a href="https://github.com/ardentink/adr-api/pull/1" rel="noopener noreferrer"&gt;PR&lt;/a&gt; for all my changes in the hopes that you could see exactly where my code was before and after this process. I actually ran into some issues with the deploy after committing though so it might be easier to look at &lt;a href="https://github.com/ardentink/adr-api/compare/37b98e497da34ce4cf2651b5f4297501356b636b...669fe890c6c543330fb9772f375d0624d4ef7db8" rel="noopener noreferrer"&gt;this diff&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;The main steps were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Postgres locally&lt;/li&gt;
&lt;li&gt;Add TypeORM and DB migrations&lt;/li&gt;
&lt;li&gt;Create a Postgres component in DOAP&lt;/li&gt;
&lt;li&gt;Add a Job component in DOAP to run migrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Get Postgres working locally
&lt;/h1&gt;

&lt;p&gt;There are a couple ways to get Postgres working locally including installing it directly on my machine. My company uses Docker though and I know that will make things easier in the long run so I'm going to do that instead.&lt;/p&gt;

&lt;p&gt;I'm using a mac (thanks &lt;a href="https://simplenexus.com/sn/careers/" rel="noopener noreferrer"&gt;SimpleNexus&lt;/a&gt;) so the best way to do this is to install the docker desktop app. You can download it directly from &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;, or through &lt;a href="https://brew.sh/" rel="noopener noreferrer"&gt;Homebrew&lt;/a&gt; with &lt;code&gt;brew cask install docker&lt;/code&gt;. Then start it up with &lt;code&gt;open -a Docker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once Docker is running we need to start up our DB container. By looking at the &lt;a href="https://hub.docker.com/_/postgres" rel="noopener noreferrer"&gt;dockerhub page for Postgres&lt;/a&gt; we find that the DB name, username, and password can all be set with environment variables. To do that we create a .env file and set the necessary variables there.&lt;/p&gt;

&lt;p&gt;Then we can use docker-compose to pass all those variables to docker run: &lt;code&gt;docker-compose up -d {your container_name here}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And just like that we have Postgres running on our local machine.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing TypeORM
&lt;/h1&gt;

&lt;p&gt;Getting &lt;a href="https://typeorm.io/#/" rel="noopener noreferrer"&gt;TypeORM&lt;/a&gt; working locally was pretty straightforward. I mostly just followed the guide on their website. I did hit some "gotchas" though so that's what I'll highlight here.&lt;/p&gt;

&lt;p&gt;Because I'm using typescript the ormconfig.json file didn't work for me. There is a whole page on their site dedicated to using different configuration sources. I ended using a &lt;a href="https://typeorm.io/#/using-ormconfig/using-ormconfigjs" rel="noopener noreferrer"&gt;typeorm.js file&lt;/a&gt;. This allowed me to change my folder locations dynamically based on my my environment.&lt;/p&gt;

&lt;p&gt;I don't know if it was how I'm using ts-node to run my files, but basically I wanted my local cli to run the typescript migrations in the src folder and production to run the compiled js migrations in my dist folder. That way I didn't have to run my build step every time I wanted to migrate my local db.&lt;/p&gt;

&lt;p&gt;The other gotcha was that if you want UUIDs to be generated by the DB you need to add in the &lt;code&gt;uuid-ossp&lt;/code&gt; extension. This just requires creating a DB migration with the following SQL statement: &lt;code&gt;CREATE EXTENSION IF NOT EXISTS "uuid-ossp";&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that I updated my model with the entity and column tags, to connect it to my db. Then I ran my migrations and fired things up and everything worked.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding Postgres to DOAP
&lt;/h1&gt;

&lt;p&gt;Very first we need to create a Postgres component:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fazf6s6tnu68obn7nspzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fazf6s6tnu68obn7nspzx.png" alt="Screenshot of DOAP's " width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting your tier and clicking "Create and Attach" DOAP will start provisioning your DB. Once it's fully provisioned DOAP shows you the connection credentials:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbnv1vys6d2mvgmvgxgcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbnv1vys6d2mvgmvgxgcn.png" alt="Screenshot of DB Component connection credentials" width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to get those connection details to our main app now as environment variables. Now you may be tempted to type these out, but DOAP actually has a neat concept called &lt;a href="https://www.digitalocean.com/docs/app-platform/how-to/use-environment-variables/#using-bindable-variables-within-environment-variables" rel="noopener noreferrer"&gt;bindable variables&lt;/a&gt;. These allow you to references variables in other DOAP components without typing raw strings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F40wlpoad35dbqod8ja5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F40wlpoad35dbqod8ja5h.png" alt="Screenshot of bindable variables in use" width="800" height="750"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with those all entered we should be good to deploy all our new code!&lt;/p&gt;

&lt;p&gt;Chances are though that at this point you will get an error when your new code rolls out. Why? The database doesn't know about our models because we haven't run the migrations on our server.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create a Migration Runner
&lt;/h1&gt;

&lt;p&gt;Well that's an easy fix. We just create a Job component and tell it to run the database migrations before each deploy. You can run migrations in TypeORM with the provided command: &lt;code&gt;typeorm migration:run&lt;/code&gt;. I ended up adding this as the "migrate" script in my package.json. Then I had my new Job component use &lt;code&gt;npm run migrate&lt;/code&gt; as my run command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8r3ggg0ub4m66qgz9jm4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8r3ggg0ub4m66qgz9jm4.png" alt="Alt Text" width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And after the container re-builds with those changes... more errors 😢:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fszs1ypatwrkdnupkhbq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fszs1ypatwrkdnupkhbq0.png" alt="Alt Text" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤦🏻‍♂️ I forgot to add all my environment variables to the new container. Once again, this was quickly resolved by adding those.&lt;/p&gt;

&lt;p&gt;And... we hit one last error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj1u8frl0n1xjxp2rb0rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj1u8frl0n1xjxp2rb0rg.png" alt="Alt Text" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time it was complaining about a self-signed certificate. This actually took a little bit of googling to figure out but in the end I ended up on looking at these two issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/typeorm/typeorm/issues/278" rel="noopener noreferrer"&gt;https://github.com/typeorm/typeorm/issues/278&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/brianc/node-postgres/issues/2009" rel="noopener noreferrer"&gt;https://github.com/brianc/node-postgres/issues/2009&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm still not sure if my fix is ok in production or not, but I ended up telling it to not warn about self-signed certs by  setting &lt;code&gt;rejectUnauthorized&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; in my ormconfig.js:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8x9n4ho4fkez4cwzfkly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8x9n4ho4fkez4cwzfkly.png" alt="Alt Text" width="800" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;All in all, adding Posgres and TypeORM was a pretty straightforward process. Definitely better than writing a complex docker-compose or Kubernetes yaml file. I did hit a few more errors than I expected but nothing too bad. Hopefully though this will help you get past any errors you encounter. Good luck!&lt;/p&gt;

</description>
      <category>dohackathon</category>
    </item>
    <item>
      <title>DOAP Day 2</title>
      <dc:creator>Dan Steren</dc:creator>
      <pubDate>Thu, 17 Dec 2020 06:36:42 +0000</pubDate>
      <link>https://forem.com/dansteren/doap-day-2-19o5</link>
      <guid>https://forem.com/dansteren/doap-day-2-19o5</guid>
      <description>&lt;p&gt;I ended my first post saying I couldn't get my backend to build due to using an old codebase as a starting point. I actually kept working for a little bit after I posted though and ended up getting things working! Something super weird was going on with my imports that I still can't figure out... &lt;em&gt;(smh)&lt;/em&gt;... but I've got a workaround that's good enough for now.&lt;/p&gt;

&lt;h1&gt;
  
  
  Initial Deploy to DOAP
&lt;/h1&gt;

&lt;p&gt;So day 2. Now that I have a basic node backend that can actually build, I was able to deploy it in DOAP. I got a little hung up on the env variables and http port. I use the &lt;code&gt;APP_PORT&lt;/code&gt; environment variable in my node server to choose where to host the app, so I wasn't entirely sure if it was supposed to be different than the &lt;code&gt;HTTP Port&lt;/code&gt; setting or not. I ended up setting both to &lt;code&gt;8080&lt;/code&gt; and that did the trick.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr57dg2hxrdh5o4jv7fpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr57dg2hxrdh5o4jv7fpk.png" alt="Screenshot of App Configuration Screen" width="800" height="987"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The actual build process ended up taking about 10 minutes after clicking "Launch Basic App". I think something went wrong during my first attempt because I waited like 15 minutes and it stayed at 17% and never showed any logs. I ended up deleting my app and starting over. Second time only took 10 minutes though and everything worked nice and smoothly!&lt;/p&gt;

&lt;p&gt;So there isn't much to look at, but my server is now up and running at: &lt;a href="https://adr-api-jp4aj.ondigitalocean.app/" rel="noopener noreferrer"&gt;https://adr-api-jp4aj.ondigitalocean.app/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up Apollo Studio
&lt;/h1&gt;

&lt;p&gt;Ever since Graphql Summit 2020 I've been looking forward to using &lt;a href="https://studio.apollographql.com/" rel="noopener noreferrer"&gt;Apollo Studio&lt;/a&gt; and I thought this would be a good time to try it out. So I created an account, selected a deployed schema, and was happy to see that hooking things up was as simple as setting 3 environment variables. Once I added those in DOAP it re-deployed my backend and voila, my schema appeared in apollo studio!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5zmsqd5mg3yq38v1vl88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5zmsqd5mg3yq38v1vl88.png" alt="Alt Text" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a bunch of panes where it wants me to upgrade to a paid plan, but at it's free tier it looks pretty great. I especially love the way you can build queries by just clicking on fields/subfields and slowly building out your query that way. Don't get me wrong, graphiQL and graphQL playground are ok, but I could see where it's easier to click buttons than waiting on an autocomplete and having to know specific field names. I'm looking forward to giving it a try on this project.&lt;/p&gt;

&lt;h1&gt;
  
  
  Next Steps
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Technical Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I think the next hurdle will be to add type-orm to my project and get things working with a DO managed DB. Last time I tried to do a backend I ended up diving into docker, docker-compose and kubernetes. That was certainly a learning experience but I ended up burning myself out trying to figure it all out. Hopefully setting up a managed DB is easier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The other part I need to tackle is building a simple frontend and getting it hosted in DOAP as well. I could add express to my backend and serve my frontend from there. I think instead though I'm going to just create a new repo and serve my site statically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Design Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I need to put together a good list of user stories. I have some rough ideas of how things will work but I think making sure I have the main features is important. I'll probably draw a lot from &lt;a href="https://adr.github.io/" rel="noopener noreferrer"&gt;https://adr.github.io/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I was reading through &lt;a class="mentioned-user" href="https://dev.to/yvesnrb"&gt;@yvesnrb&lt;/a&gt;'s &lt;a href="https://dev.to/yvesnrb/do-hackaton-log-day-1-57eg"&gt;post&lt;/a&gt; and I really liked that he created Figma mockups before he really dove into the code. I need to do the same thing before I start really building the UI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I should probably lay out some basic routes, auth flow, etc. I'm kinda just winging things here.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dohackathon</category>
    </item>
    <item>
      <title>DOAP Day 1</title>
      <dc:creator>Dan Steren</dc:creator>
      <pubDate>Wed, 16 Dec 2020 08:12:01 +0000</pubDate>
      <link>https://forem.com/dansteren/doap-day-1-3h7</link>
      <guid>https://forem.com/dansteren/doap-day-1-3h7</guid>
      <description>&lt;p&gt;First time on Dev.to here so be patient with me. I'm gonna try participating in Digital Ocean's App Platform Hackathon (Which I'll be abbreviating as DOAP from now on) and wanted to document my journey.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Project
&lt;/h1&gt;

&lt;p&gt;I think my goal for this is to build a platform for either storing/managing &lt;a href="https://adr.github.io/" rel="noopener noreferrer"&gt;Architectural Decision Records&lt;/a&gt; or something to do with making municipal code more accessible to constituents. So I'm sitting in either the &lt;code&gt;Program for the People&lt;/code&gt; or &lt;code&gt;Built for Business&lt;/code&gt; category. We'll just see where we end up in the end.&lt;/p&gt;

&lt;h1&gt;
  
  
  Today's Work
&lt;/h1&gt;

&lt;p&gt;So, Day 1... I started the evening just doing some quick reading about the platform, watching some tutorials and doing some maintenance on my Dev.to, DigitalOcean, and GitHub accounts. Of course I also applied for the &lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSdHljGT15tIBAl6awNWh1-s3LCP3HMPPgZX5WE9LgHISp6Oiw/viewform?usp=sf_link" rel="noopener noreferrer"&gt;$50 credit for DigitalOcean&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main thing I learned today is that the very first step to all this is to have a repo that already has some code ready to be deployed. I'm going to go with a node backend so I think the next step is for me to either fork the &lt;a href="https://github.com/digitalocean/sample-nodejs" rel="noopener noreferrer"&gt;Node Sample App&lt;/a&gt;, or to just start a new node project from scratch and hook it up to DO.&lt;/p&gt;

&lt;p&gt;I'm going for a &lt;code&gt;node&lt;/code&gt; + &lt;code&gt;apollo-server&lt;/code&gt; + &lt;code&gt;type-graphl&lt;/code&gt; backend and I happen to have repo that has most of the setup that I want. Unfortunately, it's been a year since I've touched it so it's a little the worse for wear. Additionally it is all hooked up to Postgres and I think that's more than I want at first. So, I spent the evening stripping out all DB stuff and trying to get it to build... and to no avail.&lt;/p&gt;

&lt;p&gt;So, goal for tomorrow? Go back through the docs for all the dependencies and get it to build. Then we can actually start doing something in DO.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ardentink/adr-api" rel="noopener noreferrer"&gt;https://github.com/ardentink/adr-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dohackathon</category>
    </item>
  </channel>
</rss>
