Awesome Dart deployment


Deployment with a shared host is always awkward. You need an FTP client, and credentials to access some part of the web directories. Then you need to remotely set up your production database, and it’s just not a very pleasant experience. With Dart, you have very limited options on shared hosts, so it might not even be an option.

Using a VPS, however, opens up possibilities, but might be confusing. Here’s a step-by-step guide to easily provide an amazing dev-deploy experience with Dart.

Set up

I’m going to assume that you have an Ubuntu installation with a non-root user logged in with sudo capabilities. Check out this guide.

1. Installing all the things

Here we go:

sudo apt-get update
  • Nginx:
sudo apt-get install nginx
  • Git:
sudo apt-get install git
  • Dart SDK:
sudo apt-get install apt-transport-https  
sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
sudo apt-get update

2. Setting up the directories

I like my directories to be clean, and to have short, nice names. Therefore, I usually have the following structure:

/www
|-- repos
| `-- my-project-name.git
`-- sites
`-- my-project-name

Let’s set this up!

sudo mkdir /www  
chmod -R 755 /www
cd /www
mkdir sites  
mkdir repos

3. The project

Let’s say we’re deploying a blog made with dart. Let’s call the project my-blog. That means wherever you see me using that name in the code, you’ll want to change it to your own project name.

Let’s create the directories for our project.

mkdir sites/my-blog  
mkdir repos/my-blog.git

4. Git

We’re going to create a bare repository that checks out the master branch into the sites/my-blog directory.

cd /www/repos/my-blog.git  
git init --bare
cd hooks
touch post-receive
chmod +x post-receive

Now, edit the post-receive executable with your favourite command line editor.

#!/bin/sh
git --work-tree=/www/sites/my-blog --git-dir=/www/repos/my-blog.git checkout -f
cd /www/sites/my-blog
pub get
service my-blog restart

Notice the service my-blog restart part — we’ll look into that one later.

On our local machine, we’ll go into our project working directory. Assuming you’re already using Git, we’ll just add the remote:

git remote add live ssh://root@YOUR-VPS-DOMAIN-OR-IP/www/repos/my-blog.git

Notice we’re calling our remote “live”. To push to the remote we’ll do:

git push live master

Looking back on our SSH-session, let’s go into the project root now.

cd /www/sites/my-blog

This folder should now contain the project files, and the packages folder should be present.

5. Nginx

We’re going to configure a new Nginx site, proxying the request to a local host that the Dart file is listening to. So let’s say our Dart app is listening to http://localhost:1337:

sudo touch /etc/nginx/sites-avaiable/my-blog

Inside, we’ll have the following:

server {  
listen 80;
  location / {
proxy_pass http://localhost:1337;
}
}

Note: You’ll have to add some stuff here to use WebSockets. Check out this article

Next, let’s enable the site:

sudo ln -s /etc/nginx/sites-available/my-blog /etc/nginx/site-enabled/my-blog

6. Upstart

Now, we’re going to point a service to our dart file that starts the application. Let’s assume that file is bin/start.dart.

sudo touch /etc/init/my-blog.conf

Inside:

description "My blog"
start on filesystem or runlevel [2345]  
stop on shutdown
respawn
script
    echo $$ > /var/run/my-blog.pid
exec /usr/bin/dart /www/sites/my-blog/bin/start.dart >> /var/log/my-blog.log
end script
pre-start script  
echo "[`date`] Starting" >> /var/log/my-blog.log
end script
pre-stop script  
rm /var/run/my-blog.pid
echo "[`date`] Stopping" >> /var/log/my-blog.log
end script

Now we have our app as a service, that logs its output to /var/log/my-blog.log.

7. Review

What do we have here? What’s the workflow?

When we start this up, we’ll have a running Dart application. If it crashes, it will start up again. It will automatically start on system boot, and automatically stop when the system is shutting down.

If we want to make changes, all we have to do is edit our local repo, and run:

git push live master

And our service will restart with the new changes.

Isn’t this freaking awesome?

8. Flick the switch

Either, you can reboot the server using sudo reboot, or, you can start the services manually:

sudo service nginx restart  
sudo service my-blog restart

If you go to your public URL: http://YOUR-VPS-DOMAIN-OR-IP, you should see your application.

Bonus: Adding another site

Let’s say we have a new site that we want on new.YOUR-DOMAIN.com. Just repeat the steps 3–8, but with one exception:

Your Nginx configurations should point to the specific domains, with the server_name property.

In /etc/nginx/sites-available/my-blog, you should add server_name YOUR-DOMAIN.com; so that it looks like this:

server {  
listen 80;
server_name YOUR-DOMAIN.com;
  location / {
proxy_pass http://localhost:1337;
}
}

And in your new sub-domain app, this should of course be server_name new.YOUR-DOMAIN.com;. Also, the dart apps need to listen to different ports. So just do HttpServer.bind(‘localhost’, 1338); the second time!

Good fun, have luck.

Show your support

Clapping shows how much you appreciated Emil Persson’s story.