How to deploy Node app to Digital Ocean App Platform
#software-development #node #javascript #typescript #digital-oceanJanuary 01, 2021
Tech Stack
- Node.js
- Express
- PostgreSQL
- Typescript
- Note: this is just my backend code. Frontend is in a different repo.
Issues
The title is actually a little misleading 😅 I’m not walking through the exact process, cause it’s not very complicated and there are a log of existing resources.
But the problems I ran into weren’t well documented, so that’s what I’m documenting here.
Database
The first was that to use a database it was a minimum of $7/month extra for the dev database. I thought it was $5 for server + database, so that was kind of a bummer.
I chose to use the managed database database, which was $15, so I’m at $20/month.
Also, at the moment the database has to be open to all sources because of the floating IP addresses from the App Platform, which is super lame. Hopefully that changes soon.
Community posts about this: https://www.digitalocean.com/community/questions/how-to-add-my-digitalocean-app-as-a-trusted-resource-for-my-managed-database
tsc: command not found
The second thing was when my build script ran, which was
"build": "tsc"
I got an error, tsc: command not found
Apparently I needed to install the dev dependencies, so using
"build": "npm install --only=dev && tsc"
worked.
Here are some community posts discussing this:
SSL Certificate
This one was the greatest pain.
When trying to make a request to the app I kept getting:
Error: self signed certificate in certificate chain
To fix it, first you need to set an environment variable in the app platform.
Go to the Components tab and specify a CA_CERT
environment variable and set it to ${name-of-your-service.CA_CERT}
Here is the DO doc talking about environment variables:
https://www.digitalocean.com/docs/app-platform/how-to/use-environment-variables/
Then you need to reference that when you instantiate the DB connection.
I’m using node-postgres
https://www.npmjs.com/package/pg
const pool = new Pool({
user: process.env.USERNAME,
host: process.env.HOSTNAME,
database: process.env.DATABASE,
password: process.env.PASSWORD,
port: process.env.PORT,
ssl: {
rejectUnauthorized: true,
ca:
process.env.NODE_ENV === PRODUCTION
? process.env.CA_CERT
: fs.readFileSync("ca_cert.crt").toString(),
},
})
Note that I am not using the connectionString
parameter. For some reason that doesn’t work.
I posted a question here, hopefully it gets answered: https://github.com/brianc/node-postgres/issues/2009
Also note that I am separating how I reference the certificate on prod vs dev
process.env.NODE_ENV === PRODUCTION
? process.env.CA_CERT
: fs.readFileSync("ca_cert.crt").toString(),
I have no idea if that is best practice, but locally, you can’t stick the cert in an env variable, so, that’s the best I could come up with.
To get that cert, you need to download the CA certificate from the DO managed database.
When you go to your managed database, there is a button below the connection details.
You have to open the cert with a code editor, I used VS Code.
Then just copy the contents and create a new file in your repo, paste the contents, then reference it like I did above.
Hope that helps.